public void SendNoReply(int slaveAddress, BufferFrame message)
        {
            if (slaveAddress == linkLayer.GetBroadcastAddress())
            {
                if (nextBroadcastMessage != null)
                {
                    throw new LinkLayerBusyException("Broadcast message pending");
                }
                else
                {
                    nextBroadcastMessage = message;
                }
            }
            else
            {
                SlaveConnection slave = GetSlaveConnection(slaveAddress);

                if (slave != null)
                {
                    if (slave.IsMessageWaitingToSend())
                    {
                        throw new LinkLayerBusyException("Message pending");
                    }
                    else
                    {
                        slave.nextMessage         = message;
                        slave.requireConfirmation = false;
                    }
                }
            }
        }
        private int SendIMessage(BufferFrame asdu)
        {
            byte[] buffer = asdu.GetBuffer();

            int msgSize = asdu.GetMsgSize();              /* ASDU size + ACPI size */

            buffer [0] = 0x68;

            /* set size field */
            buffer [1] = (byte)(msgSize - 2);

            buffer [2] = (byte)((sendCount % 128) * 2);
            buffer [3] = (byte)(sendCount / 128);

            buffer [4] = (byte)((receiveCount % 128) * 2);
            buffer [5] = (byte)(receiveCount / 128);

            try {
                lock (socketStream) {
                    socketStream.Write(buffer, 0, msgSize);
                    DebugLog("SEND I (size = " + msgSize + ") : " + BitConverter.ToString(buffer, 0, msgSize));
                    sendCount = (sendCount + 1) % 32768;
                    unconfirmedReceivedIMessages = 0;
                    timeoutT2Triggered           = false;
                }
            }
            catch (System.IO.IOException) {
                // socket error --> close connection
                running = false;
            }

            return(sendCount);
        }
Esempio n. 3
0
        private void EnqueueUserData(ASDU asdu)
        {
            //TODO problem -> buffer frame needs own buffer so that the message can be stored.
            BufferFrame bf = new BufferFrame(buffer, 0);

            asdu.Encode(bf, parameters);

            linkLayerUnbalanced.SendConfirmed(slaveAddress, bf);
        }
Esempio n. 4
0
        private void EnqueueUserData(ASDU asdu)
        {
            lock (userDataQueue) {
                BufferFrame frame = new BufferFrame(new byte[256], 0);

                asdu.Encode(frame, parameters);

                userDataQueue.Enqueue(frame);
            }
        }
Esempio n. 5
0
            BufferFrame ISecondaryApplicationLayer.GetCLass2Data()
            {
                BufferFrame asdu = DequeueUserDataClass2();

                if (asdu == null)
                {
                    asdu = DequeueUserDataClass1();
                }

                return(asdu);
            }
Esempio n. 6
0
        /// <summary>
        /// Callback function forPrimaryLinkLayerBalanced
        /// </summary>
        /// <returns>The next ASDU to send</returns>
        private BufferFrame GetUserData()
        {
            BufferFrame asdu = null;

            if (IsUserDataAvailable())
            {
                return(DequeueUserData());
            }

            return(asdu);
        }
Esempio n. 7
0
        private void loadFrame(BufferFrame frame)
        {
            using var srcmeta = new ComPtr <IWICMetadataQueryReader>(((WicImageFrame)ctx.ImageFrame).WicMetadataReader);

            frame.Disposal = (GifDisposalMethod)srcmeta.GetValueOrDefault <byte>(Wic.Metadata.Gif.FrameDisposal) == GifDisposalMethod.RestoreBackground ? GifDisposalMethod.RestoreBackground : GifDisposalMethod.Preserve;
            frame.Delay    = srcmeta.GetValueOrDefault <ushort>(Wic.Metadata.Gif.FrameDelay);
            frame.Trans    = srcmeta.GetValueOrDefault <bool>(Wic.Metadata.Gif.TransparencyFlag);
            frame.Area     = ctx.Source.Area;

            var buff = frame.Source;

            fixed(byte *pbuff = buff.Span)
            ctx.Source.CopyPixels(frame.Area, buff.Stride, buff.Span.Length, (IntPtr)pbuff);
        }
        private void SendASDUInternal(ASDU asdu)
        {
            if (isActive)
            {
                lock (waitingASDUsHighPrio) {
                    BufferFrame frame = new BufferFrame(new byte[256], 6);

                    asdu.Encode(frame, alParameters);

                    waitingASDUsHighPrio.Enqueue(frame);
                }

                SendWaitingASDUs();
            }
        }
Esempio n. 9
0
            public void EnqueueUserDataClass2(ASDU asdu)
            {
                lock (userDataClass2Queue) {
                    BufferFrame frame = new BufferFrame(new byte[256], 0);

                    asdu.Encode(frame, parameters);

                    userDataClass2Queue.Enqueue(frame);

                    while (userDataClass2Queue.Count > userDataClass2QueueMaxSize)
                    {
                        userDataClass2Queue.Dequeue();
                    }
                }
            }
Esempio n. 10
0
        private void sendNextAvailableASDU()
        {
            lock (sentASDUs)
            {
                if (isSentBufferFull())
                {
                    return;
                }

                long timestamp;
                int  index;

                asduQueue.LockASDUQueue();
                BufferFrame asdu = asduQueue.GetNextWaitingASDU(out timestamp, out index);

                try
                {
                    if (asdu != null)
                    {
                        int currentIndex = 0;

                        if (oldestSentASDU == -1)
                        {
                            oldestSentASDU = 0;
                            newestSentASDU = 0;
                        }
                        else
                        {
                            currentIndex = (newestSentASDU + 1) % maxSentASDUs;
                        }

                        sentASDUs[currentIndex].entryTime  = timestamp;
                        sentASDUs[currentIndex].queueIndex = index;
                        sentASDUs[currentIndex].seqNo      = SendIMessage(asdu);
                        sentASDUs[currentIndex].sentTime   = SystemUtils.currentTimeMillis();

                        newestSentASDU = currentIndex;

                        PrintSendBuffer();
                    }
                }
                finally
                {
                    asduQueue.UnlockASDUQueue();
                }
            }
        }
Esempio n. 11
0
        public byte[] AsByteArray()
        {
            int expectedSize = parameters.MaxAsduLength - spaceLeft;

            BufferFrame frame = new BufferFrame(new byte[expectedSize], 0);

            Encode(frame, parameters);

            if (frame.GetMsgSize() == expectedSize)
            {
                return(frame.GetBuffer());
            }
            else
            {
                return(null);
            }
        }
        public void SendConfirmed(int slaveAddress, BufferFrame message)
        {
            SlaveConnection slave = GetSlaveConnection(slaveAddress);

            if (slave != null)
            {
                if (slave.nextMessage != null)
                {
                    throw new LinkLayerBusyException("Message pending");
                }
                else
                {
                    slave.nextMessage         = message.Clone();
                    slave.requireConfirmation = true;
                }
            }
        }
Esempio n. 13
0
        private void writeFrame(BufferFrame src)
        {
            using var quant = new OctreeQuantizer();
            using var buffI = new FrameBufferSource(ctx.Source.Width, ctx.Source.Height, PixelFormat.Indexed8Bpp);
            var buffC = EncodeFrame.Source;

            quant.CreateHistorgram(buffC.Span, buffC.Width, buffC.Height, buffC.Stride);
            quant.Quantize(buffC.Span, buffI.Span, buffC.Width, buffC.Height, buffC.Stride, buffI.Stride);
            var palette = quant.Palette;

            using var pal = default(ComPtr <IWICPalette>);
            HRESULT.Check(Wic.Factory->CreatePalette(pal.GetAddressOf()));

            fixed(uint *ppal = palette)
            HRESULT.Check(pal.Get()->InitializeCustom(ppal, (uint)palette.Length));

            ctx.WicContext.DestPalette = pal;
            ctx.Source = buffI;

            using var frm     = new WicImageEncoderFrame(ctx, encoder, src.Area);
            using var frmmeta = default(ComPtr <IWICMetadataQueryWriter>);
            HRESULT.Check(frm.WicEncoderFrame->GetMetadataQueryWriter(frmmeta.GetAddressOf()));

            frmmeta.SetValue(Wic.Metadata.Gif.FrameDisposal, (byte)src.Disposal);
            frmmeta.SetValue(Wic.Metadata.Gif.FrameDelay, (ushort)src.Delay);

            if (src.Area.X != 0)
            {
                frmmeta.SetValue(Wic.Metadata.Gif.FrameLeft, (ushort)src.Area.X);
            }
            if (src.Area.Y != 0)
            {
                frmmeta.SetValue(Wic.Metadata.Gif.FrameTop, (ushort)src.Area.Y);
            }

            frmmeta.SetValue(Wic.Metadata.Gif.TransparencyFlag, true);
            frmmeta.SetValue(Wic.Metadata.Gif.TransparentColorIndex, (byte)(palette.Length - 1));

            frm.WriteSource(ctx, src.Area);

            ctx.WicContext.DestPalette = null;
        }
Esempio n. 14
0
        public WicAnimatedGifEncoder(PipelineContext ctx, WicImageEncoder enc)
        {
            this.ctx = ctx;
            encoder  = enc;

            lastSource = ctx.Source;
            lastFrame  = ctx.ImageContainer.FrameCount - 1;

            EncodeFrame = new BufferFrame(lastSource.Width, lastSource.Height, lastSource.Format);
            for (int i = 0; i < frames.Length; i++)
            {
                frames[i] = new BufferFrame(lastSource.Width, lastSource.Height, lastSource.Format);
            }

            loadFrame(Current);
            Current.Source.Span.CopyTo(EncodeFrame.Source.Span);

            moveToFrame(1);
            loadFrame(Next !);
        }
Esempio n. 15
0
        private bool sendNextHighPriorityASDU()
        {
            lock (sentASDUs)
            {
                if (isSentBufferFull())
                {
                    return(false);
                }

                BufferFrame asdu = waitingASDUsHighPrio.Dequeue();

                if (asdu != null)
                {
                    int currentIndex = 0;

                    if (oldestSentASDU == -1)
                    {
                        oldestSentASDU = 0;
                        newestSentASDU = 0;
                    }
                    else
                    {
                        currentIndex = (newestSentASDU + 1) % maxSentASDUs;
                    }

                    sentASDUs[currentIndex].queueIndex = -1;
                    sentASDUs[currentIndex].seqNo      = SendIMessage(asdu);
                    sentASDUs[currentIndex].sentTime   = SystemUtils.currentTimeMillis();

                    newestSentASDU = currentIndex;

                    PrintSendBuffer();
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 16
0
        private void writeFrame(BufferFrame src)
        {
            var  curFormat = ctx.Source.Format;
            var  newFormat = PixelFormat.Indexed8Bpp;
            bool alpha     = src.Trans || src.Disposal != GifDisposalMethod.RestoreBackground;

            using var pal = ComHandle.Wrap(Wic.Factory.CreatePalette());
            pal.ComObject.InitializeFromBitmap(wicSource, 256u, alpha);
            ctx.WicContext.DestPalette = pal.ComObject;

            using var conv = ComHandle.Wrap(Wic.Factory.CreateFormatConverter());
            conv.ComObject.Initialize(wicSource, newFormat.FormatGuid, WICBitmapDitherType.WICBitmapDitherTypeErrorDiffusion, pal.ComObject, 25.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
            ctx.Source = conv.ComObject.AsPixelSource($"{nameof(IWICFormatConverter)}: {curFormat.Name}->{newFormat.Name}", false);

            using var frm = new WicImageEncoderFrame(ctx, encoder, src.Area);

            using var frmmeta = ComHandle.Wrap(frm.WicEncoderFrame.GetMetadataQueryWriter());
            var fm = frmmeta.ComObject;

            fm.SetMetadataByName(Wic.Metadata.Gif.FrameDisposal, new PropVariant((byte)src.Disposal));
            fm.SetMetadataByName(Wic.Metadata.Gif.FrameDelay, new PropVariant((ushort)src.Delay));

            if (src.Area.X != 0)
            {
                fm.SetMetadataByName(Wic.Metadata.Gif.FrameLeft, new PropVariant((ushort)src.Area.X));
            }
            if (src.Area.Y != 0)
            {
                fm.SetMetadataByName(Wic.Metadata.Gif.FrameTop, new PropVariant((ushort)src.Area.Y));
            }

            if (alpha)
            {
                fm.SetMetadataByName(Wic.Metadata.Gif.TransparencyFlag, new PropVariant(true));
                fm.SetMetadataByName(Wic.Metadata.Gif.TransparentColorIndex, new PropVariant((byte)(pal.ComObject.GetColorCount() - 1)));
            }

            frm.WriteSource(ctx, src.Area);
        }
Esempio n. 17
0
        private void EnqueueUserData(ASDU asdu)
        {
            if (linkLayerUnbalanced != null)
            {
                //TODO problem -> buffer frame needs own buffer so that the message can be stored.
                BufferFrame frame = new BufferFrame(buffer, 0);

                asdu.Encode(frame, appLayerParameters);

                linkLayerUnbalanced.SendConfirmed(slaveAddress, frame);
            }
            else
            {
                lock (userDataQueue) {
                    BufferFrame frame = new BufferFrame(new byte[256], 0);

                    asdu.Encode(frame, appLayerParameters);

                    userDataQueue.Enqueue(frame);
                }
            }
        }
Esempio n. 18
0
        internal void SendVariableLengthFrameSecondary(FunctionCodeSecondary fc, int address, bool acd, bool dfc, BufferFrame frame)
        {
            buffer [0] = 0x68;             /* START */
            buffer [3] = 0x68;             /* START */

            byte c = (byte)((int)fc & 0x1f);

            if (linkLayerMode == LinkLayerMode.BALANCED)
            {
                if (dir)
                {
                    c += 0x80;
                }
            }

            if (acd)
            {
                c += 0x20;
            }

            if (dfc)
            {
                c += 0x10;
            }

            buffer [4] = c;

            int bufPos = 5;

            if (linkLayerParameters.AddressLength > 0)
            {
                buffer [bufPos++] = (byte)(address % 0x100);

                if (linkLayerParameters.AddressLength > 1)
                {
                    buffer [bufPos++] = (byte)((address / 0x100) % 0x100);
                }
            }

            byte[] userData       = frame.GetBuffer();
            int    userDataLength = frame.GetMsgSize();

            int l = 1 + linkLayerParameters.AddressLength + userDataLength;

            if (l > 255)
            {
                return;
            }

            buffer [1] = (byte)l;
            buffer [2] = (byte)l;

            for (int i = 0; i < userDataLength; i++)
            {
                buffer [bufPos++] = userData[i];
            }

            byte checksum = 0;

            for (int i = 4; i < bufPos; i++)
            {
                checksum += buffer[i];
            }

            buffer [bufPos++] = checksum;

            buffer [bufPos++] = 0x16;             /* END */

            if (sentRawMessageHandler != null)
            {
                sentRawMessageHandler(sentRawMessageHandlerParameter, buffer, bufPos);
            }

            transceiver.SendMessage(buffer, bufPos);
        }
Esempio n. 19
0
        public void SendVariableLengthFramePrimary(FunctionCodePrimary fc, int address, bool fcb, bool fcv, BufferFrame frame)
        {
            buffer [0] = 0x68;             /* START */
            buffer [3] = 0x68;             /* START */

            byte c = (byte)fc;

            if (dir)
            {
                c += 0x80;
            }

            c += 0x40;             // PRM = 1;

            if (fcv)
            {
                c += 0x10;
            }

            if (fcb)
            {
                c += 0x20;
            }

            buffer [4] = c;

            int bufPos = 5;

            if (linkLayerParameters.AddressLength > 0)
            {
                buffer [bufPos++] = (byte)(address % 0x100);

                if (linkLayerParameters.AddressLength > 1)
                {
                    buffer [bufPos++] = (byte)((address / 0x100) % 0x100);
                }
            }

            byte[] userData       = frame.GetBuffer();
            int    userDataLength = frame.GetMsgSize();

            for (int i = 0; i < userDataLength; i++)
            {
                buffer [bufPos++] = userData[i];
            }

            int l = 1 + linkLayerParameters.AddressLength + frame.GetMsgSize();

            if (l > 255)
            {
                return;
            }

            buffer [1] = (byte)l;
            buffer [2] = (byte)l;

            byte checksum = 0;

            for (int i = 4; i < bufPos; i++)
            {
                checksum += buffer[i];
            }

            buffer [bufPos++] = checksum;

            buffer [bufPos++] = 0x16;             /* END */

            if (sentRawMessageHandler != null)
            {
                sentRawMessageHandler(sentRawMessageHandlerParameter, buffer, bufPos);
            }

            transceiver.SendMessage(buffer, bufPos);
        }
        public override void HandleMessage(FunctionCodePrimary fcp, bool isBroadcast, int address, bool fcb, bool fcv, byte[] msg, int userDataStart, int userDataLength)
        {
            // check frame count bit if fcv == true
            if (fcv)
            {
                if (CheckFCB(fcb) == false)
                {
                    return;
                }
            }

            switch (fcp)
            {
            case FunctionCodePrimary.REQUEST_LINK_STATUS:
                DebugLog("SLL - REQUEST LINK STATUS");
                {
                    bool accessDemand = applicationLayer.IsClass1DataAvailable();

                    linkLayer.SendFixedFrameSecondary(FunctionCodeSecondary.STATUS_OF_LINK_OR_ACCESS_DEMAND, linkLayerAddress, accessDemand, false);
                }
                break;

            case FunctionCodePrimary.RESET_REMOTE_LINK:
                DebugLog("SLL - RESET REMOTE LINK");
                {
                    expectedFcb = true;

                    if (linkLayer.linkLayerParameters.UseSingleCharACK)
                    {
                        linkLayer.SendSingleCharACK();
                    }
                    else
                    {
                        linkLayer.SendFixedFrameSecondary(FunctionCodeSecondary.ACK, linkLayerAddress, false, false);
                    }

                    applicationLayer.ResetCUReceived(false);
                }

                break;

            case FunctionCodePrimary.RESET_FCB:
                DebugLog("SLL - RESET FCB");
                {
                    expectedFcb = true;

                    if (linkLayer.linkLayerParameters.UseSingleCharACK)
                    {
                        linkLayer.SendSingleCharACK();
                    }
                    else
                    {
                        linkLayer.SendFixedFrameSecondary(FunctionCodeSecondary.ACK, linkLayerAddress, false, false);
                    }

                    applicationLayer.ResetCUReceived(true);
                }
                break;

            case FunctionCodePrimary.REQUEST_USER_DATA_CLASS_2:
                DebugLog("SLL - REQUEST USER DATA CLASS 2");
                {
                    BufferFrame asdu = applicationLayer.GetCLass2Data();

                    bool accessDemand = applicationLayer.IsClass1DataAvailable();

                    if (asdu != null)
                    {
                        linkLayer.SendVariableLengthFrameSecondary(FunctionCodeSecondary.RESP_USER_DATA, linkLayerAddress, accessDemand, false, asdu);
                    }
                    else
                    {
                        if (linkLayer.linkLayerParameters.UseSingleCharACK && (accessDemand == false))
                        {
                            linkLayer.SendSingleCharACK();
                        }
                        else
                        {
                            linkLayer.SendFixedFrameSecondary(FunctionCodeSecondary.RESP_NACK_NO_DATA, linkLayerAddress, accessDemand, false);
                        }
                    }
                }
                break;

            case FunctionCodePrimary.REQUEST_USER_DATA_CLASS_1:
                DebugLog("SLL - REQUEST USER DATA CLASS 1");
                {
                    BufferFrame asdu = applicationLayer.GetClass1Data();

                    bool accessDemand = applicationLayer.IsClass1DataAvailable();

                    if (asdu != null)
                    {
                        linkLayer.SendVariableLengthFrameSecondary(FunctionCodeSecondary.RESP_USER_DATA, linkLayerAddress, accessDemand, false, asdu);
                    }
                    else
                    {
                        if (linkLayer.linkLayerParameters.UseSingleCharACK && (accessDemand == false))
                        {
                            linkLayer.SendSingleCharACK();
                        }
                        else
                        {
                            linkLayer.SendFixedFrameSecondary(FunctionCodeSecondary.RESP_NACK_NO_DATA, linkLayerAddress, accessDemand, false);
                        }
                    }
                }
                break;

            case FunctionCodePrimary.USER_DATA_CONFIRMED:
                DebugLog("SLL - USER DATA CONFIRMED");
                if (userDataLength > 0)
                {
                    if (applicationLayer.HandleReceivedData(msg, isBroadcast, userDataStart, userDataLength))
                    {
                        bool accessDemand = applicationLayer.IsClass1DataAvailable();

                        linkLayer.SendFixedFrameSecondary(FunctionCodeSecondary.ACK, linkLayerAddress, accessDemand, false);
                    }
                }
                break;

            case FunctionCodePrimary.USER_DATA_NO_REPLY:
                DebugLog("SLL - USER DATA NO REPLY");
                if (userDataLength > 0)
                {
                    applicationLayer.HandleReceivedData(msg, isBroadcast, userDataStart, userDataLength);
                }
                break;

            default:
                DebugLog("SLL - UNEXPECTED LINK LAYER MESSAGE");
                linkLayer.SendFixedFrameSecondary(FunctionCodeSecondary.LINK_SERVICE_NOT_IMPLEMENTED, linkLayerAddress, false, false);
                break;
            }
        }
            public void RunStateMachine()
            {
                PrimaryLinkLayerState newState = primaryState;

                long currentTime = SystemUtils.currentTimeMillis();

                switch (primaryState)
                {
                case PrimaryLinkLayerState.IDLE:

                    waitingForResponse        = false;
                    originalSendTime          = 0;
                    lastSendTime              = 0;
                    sendLinkLayerTestFunction = false;
                    newState = PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK;

                    break;

                case PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK:

                    if (waitingForResponse)
                    {
                        if (currentTime > (lastSendTime + linkLayer.TimeoutForACK))
                        {
                            linkLayer.SendFixedFramePrimary(FunctionCodePrimary.REQUEST_LINK_STATUS, address, false, false);

                            lastSendTime = SystemUtils.currentTimeMillis();
                        }
                    }
                    else
                    {
                        DebugLog("[SLAVE " + address + "] PLL - SEND RESET REMOTE LINK");

                        linkLayer.SendFixedFramePrimary(FunctionCodePrimary.RESET_REMOTE_LINK, address, false, false);

                        lastSendTime       = currentTime;
                        originalSendTime   = lastSendTime;
                        waitingForResponse = true;

                        nextFcb = true;

                        newState = PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK;
                    }

                    break;

                case PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK:

                    if (waitingForResponse)
                    {
                        if (currentTime > (lastSendTime + linkLayer.TimeoutForACK))
                        {
                            waitingForResponse = false;
                            newState           = PrimaryLinkLayerState.IDLE;

                            SetState(LinkLayerState.ERROR);
                        }
                    }
                    else
                    {
                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;

                        SetState(LinkLayerState.AVAILABLE);
                    }

                    break;

                case PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE:

                    if (sendLinkLayerTestFunction)
                    {
                        DebugLog("[SLAVE " + address + "] PLL - SEND TEST LINK");

                        linkLayer.SendFixedFramePrimary(FunctionCodePrimary.TEST_FUNCTION_FOR_LINK, address, nextFcb, true);

                        nextFcb            = !nextFcb;
                        lastSendTime       = currentTime;
                        originalSendTime   = lastSendTime;
                        waitingForResponse = true;

                        newState = PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM;
                    }
                    else if (requestClass1Data || requestClass2Data)
                    {
                        if (requestClass1Data)
                        {
                            DebugLog("[SLAVE " + address + "] PLL - SEND FC 10 - REQ UD 1");

                            linkLayer.SendFixedFramePrimary(FunctionCodePrimary.REQUEST_USER_DATA_CLASS_1, address, nextFcb, true);
                        }
                        else
                        {
                            DebugLog("[SLAVE " + address + "] PLL - SEND FC 11 - REQ UD 2");

                            linkLayer.SendFixedFramePrimary(FunctionCodePrimary.REQUEST_USER_DATA_CLASS_2, address, nextFcb, true);
                        }

                        nextFcb = !nextFcb;

                        lastSendTime       = currentTime;
                        originalSendTime   = lastSendTime;
                        waitingForResponse = true;
                        newState           = PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND;
                    }
                    else
                    {
                        if (dontSendMessages == false)
                        {
                            BufferFrame asdu = nextMessage;

                            if (asdu != null)
                            {
                                DebugLog("[SLAVE " + address + "] PLL - SEND FC 03 - USER DATA CONFIRMED");

                                linkLayer.SendVariableLengthFramePrimary(FunctionCodePrimary.USER_DATA_CONFIRMED, address, nextFcb, true, asdu);

                                lastSentASDU = nextMessage;
                                nextMessage  = null;


                                nextFcb = !nextFcb;

                                lastSendTime       = currentTime;
                                originalSendTime   = lastSendTime;
                                waitingForResponse = true;

                                newState = PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM;
                            }
                        }
                    }

                    break;

                case PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM:

                    if (currentTime > (lastSendTime + linkLayer.TimeoutForACK))
                    {
                        if (currentTime > (originalSendTime + linkLayer.TimeoutRepeat))
                        {
                            DebugLog("[SLAVE " + address + "] TIMEOUT SC: ASDU not confirmed after repeated transmission");
                            newState = PrimaryLinkLayerState.IDLE;

                            SetState(LinkLayerState.ERROR);
                        }
                        else
                        {
                            DebugLog("[SLAVE " + address + "] TIMEOUT SC: 1 ASDU not confirmed");

                            if (sendLinkLayerTestFunction)
                            {
                                DebugLog("[SLAVE " + address + "] PLL - SEND FC 02 - RESET REMOTE LINK [REPEAT]");

                                linkLayer.SendFixedFramePrimary(FunctionCodePrimary.TEST_FUNCTION_FOR_LINK, address, !nextFcb, true);
                            }
                            else
                            {
                                DebugLog("[SLAVE " + address + "] PLL - SEND FC 03 - USER DATA CONFIRMED [REPEAT]");

                                linkLayer.SendVariableLengthFramePrimary(FunctionCodePrimary.USER_DATA_CONFIRMED, address, !nextFcb, true, lastSentASDU);
                            }

                            lastSendTime = currentTime;
                        }
                    }

                    break;

                case PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND:

                    if (currentTime > (lastSendTime + linkLayer.TimeoutForACK))
                    {
                        if (currentTime > (originalSendTime + linkLayer.TimeoutRepeat))
                        {
                            DebugLog("[SLAVE " + address + "] TIMEOUT: ASDU not confirmed after repeated transmission");
                            newState          = PrimaryLinkLayerState.IDLE;
                            requestClass1Data = false;
                            requestClass2Data = false;

                            SetState(LinkLayerState.ERROR);
                        }
                        else
                        {
                            DebugLog("[SLAVE " + address + "] TIMEOUT: ASDU not confirmed");

                            if (requestClass1Data)
                            {
                                DebugLog("[SLAVE " + address + "] PLL - SEND FC 10 - REQ UD 1 [REPEAT]");

                                linkLayer.SendFixedFramePrimary(FunctionCodePrimary.REQUEST_USER_DATA_CLASS_1, address, !nextFcb, true);
                            }
                            else if (requestClass2Data)
                            {
                                DebugLog("[SLAVE " + address + "] PLL - SEND FC 11 - REQ UD 2 [REPEAT]");

                                linkLayer.SendFixedFramePrimary(FunctionCodePrimary.REQUEST_USER_DATA_CLASS_2, address, !nextFcb, true);
                            }

                            lastSendTime = currentTime;
                        }
                    }

                    break;

                case PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY:
                    //TODO - reject new requests from application layer?
                    break;
                }

                if (primaryState != newState)
                {
                    DebugLog("[SLAVE " + address + "] PLL - old state: " + primaryState.ToString() + " new state: " + newState.ToString());
                }

                primaryState = newState;
            }
Esempio n. 22
0
        public override void RunStateMachine()
        {
            PrimaryLinkLayerState newState = primaryState;

            switch (primaryState)
            {
            case PrimaryLinkLayerState.IDLE:

                waitingForResponse        = false;
                originalSendTime          = 0;
                lastSendTime              = 0;
                sendLinkLayerTestFunction = false;
                newState = PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK;

                break;

            case PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK:

                if (waitingForResponse)
                {
                    if (SystemUtils.currentTimeMillis() > (lastSendTime + linkLayer.TimeoutForACK))
                    {
                        linkLayer.SendFixedFramePrimary(FunctionCodePrimary.REQUEST_LINK_STATUS, linkLayerAddressOtherStation, false, false);
                        lastSendTime = SystemUtils.currentTimeMillis();
                    }
                }
                else
                {
                    DebugLog("PLL - SEND RESET REMOTE LINK to address " + linkLayerAddressOtherStation);
                    linkLayer.SendFixedFramePrimary(FunctionCodePrimary.RESET_REMOTE_LINK, linkLayerAddressOtherStation, false, false);
                    lastSendTime       = SystemUtils.currentTimeMillis();
                    waitingForResponse = true;
                    newState           = PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK;
                }

                break;

            case PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK:

                if (waitingForResponse)
                {
                    if (SystemUtils.currentTimeMillis() > (lastSendTime + linkLayer.TimeoutForACK))
                    {
                        waitingForResponse = false;
                        newState           = PrimaryLinkLayerState.IDLE;
                        SetNewState(LinkLayerState.ERROR);
                    }
                }
                else
                {
                    newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    SetNewState(LinkLayerState.AVAILABLE);
                }

                break;

            case PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE:

                if (sendLinkLayerTestFunction)
                {
                    DebugLog("PLL - SEND TEST LINK");
                    linkLayer.SendFixedFramePrimary(FunctionCodePrimary.TEST_FUNCTION_FOR_LINK, linkLayerAddressOtherStation, nextFcb, true);
                    nextFcb          = !nextFcb;
                    lastSendTime     = SystemUtils.currentTimeMillis();
                    originalSendTime = lastSendTime;
                    newState         = PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM;
                }
                else
                {
                    BufferFrame asdu = GetUserData();

                    if (asdu != null)
                    {
                        linkLayer.SendVariableLengthFramePrimary(FunctionCodePrimary.USER_DATA_CONFIRMED, linkLayerAddressOtherStation, nextFcb, true, asdu);

                        nextFcb            = !nextFcb;
                        lastSendASDU       = asdu;
                        lastSendTime       = SystemUtils.currentTimeMillis();
                        originalSendTime   = lastSendTime;
                        waitingForResponse = true;

                        newState = PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM;
                    }
                }

                break;

            case PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM:

                if (SystemUtils.currentTimeMillis() > (lastSendTime + linkLayer.TimeoutForACK))
                {
                    if (SystemUtils.currentTimeMillis() > (originalSendTime + linkLayer.TimeoutRepeat))
                    {
                        DebugLog("TIMEOUT: ASDU not confirmed after repeated transmission");
                        newState = PrimaryLinkLayerState.IDLE;
                        SetNewState(LinkLayerState.ERROR);
                    }
                    else
                    {
                        DebugLog("TIMEOUT: ASDU not confirmed");

                        if (sendLinkLayerTestFunction)
                        {
                            DebugLog("PLL - REPEAT SEND RESET REMOTE LINK");
                            linkLayer.SendFixedFramePrimary(FunctionCodePrimary.TEST_FUNCTION_FOR_LINK, linkLayerAddressOtherStation, !nextFcb, true);
                        }
                        else
                        {
                            DebugLog("PLL - repeat last ASDU");
                            linkLayer.SendVariableLengthFramePrimary(FunctionCodePrimary.USER_DATA_CONFIRMED, linkLayerAddressOtherStation, !nextFcb, true, lastSendASDU);
                        }

                        lastSendTime = SystemUtils.currentTimeMillis();
                    }
                }

                break;

            case PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY:
                //TODO - reject new requests from application layer?
                break;
            }

            if (primaryState != newState)
            {
                DebugLog("PLL - old state: " + primaryState.ToString() + " new state: " + newState.ToString());
            }

            primaryState = newState;
        }