internal void HandleMessage(FunctionCodeSecondary fcs, bool acd, bool dfc,
                                        int addr, byte[] msg, int userDataStart, int userDataLength)
            {
                PrimaryLinkLayerState newState = primaryState;

                if (dfc)
                {
                    //stop sending ASDUs; only send Status of link requests
                    dontSendMessages = true;

                    switch (primaryState)
                    {
                    case PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK:
                    case PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK:
                        newState = PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK;
                        break;

                    case PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM:
                    //TODO message must be handled and switched to BUSY state later!
                    case PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY:
                        newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY;
                        break;
                    }

                    SetState(LinkLayerState.BUSY);

                    primaryState = newState;
                    return;
                }
                else
                {
                    // unblock transmission of application layer messages
                    dontSendMessages = false;
                }

                switch (fcs)
                {
                case FunctionCodeSecondary.ACK:

                    DebugLog("[SLAVE " + address + "] PLL - received ACK");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK)
                    {
                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;

                        SetState(LinkLayerState.AVAILABLE);
                    }
                    else if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                    {
                        if (sendLinkLayerTestFunction)
                        {
                            sendLinkLayerTestFunction = false;
                        }

                        SetState(LinkLayerState.AVAILABLE);

                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    }
                    else if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND)
                    {
                        /* single char ACK is interpreted as RESP NO DATA */
                        requestClass1Data = false;
                        requestClass2Data = false;

                        SetState(LinkLayerState.AVAILABLE);

                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    }

                    waitingForResponse = false;
                    break;

                case FunctionCodeSecondary.NACK:

                    DebugLog("[SLAVE " + address + "] PLL - received NACK");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                    {
                        SetState(LinkLayerState.BUSY);

                        newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY;
                    }

                    waitingForResponse = false;
                    break;

                case FunctionCodeSecondary.STATUS_OF_LINK_OR_ACCESS_DEMAND:

                    DebugLog("[SLAVE " + address + "] PLL - received STATUS OF LINK");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK)
                    {
                        DebugLog("[SLAVE " + address + "] PLL - SEND RESET REMOTE LINK");

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

                        nextFcb            = true;
                        lastSendTime       = SystemUtils.currentTimeMillis();
                        waitingForResponse = true;
                        newState           = PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK;

                        SetState(LinkLayerState.BUSY);
                    }
                    else
                    {     /* illegal message */
                        newState = PrimaryLinkLayerState.IDLE;

                        SetState(LinkLayerState.ERROR);

                        waitingForResponse = false;
                    }

                    break;

                case FunctionCodeSecondary.RESP_USER_DATA:

                    DebugLog("[SLAVE " + address + "] PLL - received USER DATA");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND)
                    {
                        linkLayerUnbalanced.callbacks.UserData(address, msg, userDataStart, userDataLength);

                        requestClass1Data = false;
                        requestClass2Data = false;

                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;

                        SetState(LinkLayerState.AVAILABLE);
                    }
                    else
                    {     /* illegal message */
                        newState = PrimaryLinkLayerState.IDLE;

                        SetState(LinkLayerState.ERROR);
                    }

                    waitingForResponse = false;

                    break;

                case FunctionCodeSecondary.RESP_NACK_NO_DATA:

                    DebugLog("[SLAVE " + address + "] PLL - received RESP NO DATA");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND)
                    {
                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;

                        requestClass1Data = false;
                        requestClass2Data = false;

                        SetState(LinkLayerState.AVAILABLE);
                    }
                    else
                    {     /* illegal message */
                        newState = PrimaryLinkLayerState.IDLE;

                        SetState(LinkLayerState.ERROR);
                    }

                    waitingForResponse = false;

                    break;

                case FunctionCodeSecondary.LINK_SERVICE_NOT_FUNCTIONING:
                case FunctionCodeSecondary.LINK_SERVICE_NOT_IMPLEMENTED:

                    DebugLog("[SLAVE " + address + "] PLL - link layer service not functioning/not implemented in secondary station ");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                    {
                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;

                        SetState(LinkLayerState.AVAILABLE);
                    }

                    waitingForResponse = false;

                    break;

                default:
                    DebugLog("[SLAVE " + address + "] UNEXPECTED SECONDARY LINK LAYER MESSAGE");
                    break;
                }

                if (acd)
                {
                    if (linkLayerUnbalanced.callbacks != null)
                    {
                        linkLayerUnbalanced.callbacks.AccessDemand(address);
                    }
                }

                DebugLog("[SLAVE " + address + "] PLL RECV - old state: " + primaryState.ToString() + " new state: " + newState.ToString());

                primaryState = newState;
            }
Exemplo n.º 2
0
        public override void HandleMessage(FunctionCodeSecondary fcs, bool dir, bool dfc,
                                           int address, byte[] msg, int userDataStart, int userDataLength)
        {
            PrimaryLinkLayerState newState = primaryState;

            if (dfc)
            {
                //TODO stop sending ASDUs; only send Status of link requests

                switch (primaryState)
                {
                case PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK:
                case PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK:
                    newState = PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK;
                    break;

                case PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM:
                //TODO message must be handled and switched to BUSY state later!
                case PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY:
                    newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY;
                    break;
                }

                SetNewState(LinkLayerState.BUSY);
                primaryState = newState;
                return;
            }

            switch (fcs)
            {
            case FunctionCodeSecondary.ACK:
                //TODO what to do if we are not waiting for a response?
                DebugLog("PLL - received ACK");
                if (primaryState == PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK)
                {
                    newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    SetNewState(LinkLayerState.AVAILABLE);
                }
                else if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                {
                    if (sendLinkLayerTestFunction)
                    {
                        sendLinkLayerTestFunction = false;
                    }

                    newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    SetNewState(LinkLayerState.AVAILABLE);
                }

                waitingForResponse = false;
                break;

            case FunctionCodeSecondary.NACK:
                DebugLog("PLL - received NACK");
                if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                {
                    newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY;
                    SetNewState(LinkLayerState.BUSY);
                }
                break;

            case FunctionCodeSecondary.RESP_USER_DATA:

                newState = PrimaryLinkLayerState.IDLE;
                SetNewState(LinkLayerState.ERROR);

                break;

            case FunctionCodeSecondary.RESP_NACK_NO_DATA:

                newState = PrimaryLinkLayerState.IDLE;
                SetNewState(LinkLayerState.ERROR);

                break;


            case FunctionCodeSecondary.STATUS_OF_LINK_OR_ACCESS_DEMAND:
                DebugLog("PLL - received STATUS OF LINK");
                if (primaryState == PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK)
                {
                    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;
                    SetNewState(LinkLayerState.BUSY);
                }
                else                   /* illegal message */
                {
                    newState = PrimaryLinkLayerState.IDLE;
                    SetNewState(LinkLayerState.ERROR);
                }

                break;

            case FunctionCodeSecondary.LINK_SERVICE_NOT_FUNCTIONING:
            case FunctionCodeSecondary.LINK_SERVICE_NOT_IMPLEMENTED:
                DebugLog("PLL - link layer service not functioning/not implemented in secondary station");

                if (sendLinkLayerTestFunction)
                {
                    sendLinkLayerTestFunction = false;
                }

                if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                {
                    newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    SetNewState(LinkLayerState.AVAILABLE);
                }
                break;

            default:
                DebugLog("UNEXPECTED SECONDARY LINK LAYER MESSAGE");
                break;
            }

            DebugLog("PLL RECV - old state: " + primaryState.ToString() + " new state: " + newState.ToString());

            primaryState = newState;
        }