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;
            }
Example #2
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;
        }