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; }
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; }