FUNCTION_BLOCK "FB_CommunicationWES_ASRS"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_IN_OUT 
      fbInOutSendFIFO : "LGF_FIFO";
      arFifoSendBuffer : Array[1..100] of "UDT_TelegramData_Send";
   END_VAR

   VAR 
      fbTeleHandler : "FB_TCP_LCOM_TeleHandler";
      xReset : Bool;
      xSendTele : Bool;
      stTelegramToSend : "UDT_TelegramData_Send";
      nState : Int;
      xRetVal : Bool;
      stNewTelegram { S7_SetPoint := 'False'} : "UDT_TelegramData";
      stTeleCReqM : "UDT_Telegram_CReqM";
      stTeleCRCanM : "UDT_Telegram_CRCanM";
      rTrigConnectionActive {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG;
      xSendHeartbeat : Bool;
      tOnHeartbeat {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME;
   END_VAR


BEGIN
	REGION Info
	  // Kommunikation zu Fortna WES/ASRS Driver
	    // Telegramme:
	        // Senden:
	            // CRRespM (Abruf Bestätigung/Update)  | Schönenberger -> Fortna WES/ASRS Driver
	            // CSRespM (Einlagern Bestätigung)     | Schönenberger -> Fortna WES/ASRS Driver
	        // Empfangen:
	            // CReqM (Abruf)                       | Fortna WES/ASRS Driver -> Schönenberger
	            // CRCanM (Abruf Cancel)               | Fortna WES/ASRS Driver -> Schönenberger
	END_REGION
	
	REGION Call TeleHandler
	    // hardware identifier of the local interface, PLC tags--Default tag table--System constant default value: PROFINET_interface_1 = 64
	    #fbTeleHandler.stInTcpTypeConfig.connection.interfaceID := "Local~PN-Interface_Customer";
	    //unique connection identifier (W#16#0001...W#16#0FFF)
	    #fbTeleHandler.stInTcpTypeConfig.connection.connectionID := 33;
	    //used protocol: 1=TCP protocol, 2=LCom protocol
	    #fbTeleHandler.stInTcpTypeConfig.connection.comService := "LCOM_TCP_CONNECTION";
	    //FALSE: passive (server), TRUE: active connection establishment (client)
	    #fbTeleHandler.stInTcpTypeConfig.connection.isClient := TRUE;
	    //TRUE: accept requests from all partners, FALSE: only specified partner is allowed in case of server
	    #fbTeleHandler.stInTcpTypeConfig.connection.acceptUnknownPartner := TRUE;
	    //local port number (possible values: 1...49151; caution: some may be reserved for internal use; recommended values: 2000...5000)
	    #fbTeleHandler.stInTcpTypeConfig.connection.localPort := 30635;
	    //partner port number, use only in case of client or specified partner (possible values: 1...49151; recommended values: 2000...5000)
	    #fbTeleHandler.stInTcpTypeConfig.connection.partnerPort := 30635;
	    
	    //partner IP address xxx.xxx.xxx.xxx = [1].[2].[3].[4], use only in case of client or specified partner
	    #fbTeleHandler.stInTcpTypeConfig.connection.partnerIP.ADDR[1] := 172;
	    #fbTeleHandler.stInTcpTypeConfig.connection.partnerIP.ADDR[2] := 22;
	    #fbTeleHandler.stInTcpTypeConfig.connection.partnerIP.ADDR[3] := 160;
	    #fbTeleHandler.stInTcpTypeConfig.connection.partnerIP.ADDR[4] := 21;
	    
	    #fbTeleHandler.stInTcpTypeConfig.connection.connectType := "LCOM_CON_TYPE_IPV4";
	    
	    // Telegramdefinition
	    #fbTeleHandler.stInTelegramDefinition.sStartMarker := '$02';
	    #fbTeleHandler.stInTelegramDefinition.sEndMarker := '$03';
	    #fbTeleHandler.stInTelegramDefinition.sStartMarkerSend := '$02';
	    #fbTeleHandler.stInTelegramDefinition.sEndMarkerSend := '$03';
	    #fbTeleHandler.stInTelegramDefinition.bSeparatorByte := '$1D'; //',';
	    #fbTeleHandler.stInTelegramDefinition.nLength := 0;
	    #fbTeleHandler.stInTelegramDefinition.nTelegramIDDataField := 0;
	    #fbTeleHandler.stInTelegramDefinition.xTelegramIDIsNumber := FALSE;
	    
	    #fbTeleHandler(xInReset := #xReset,
	                   xInOutSendTele := #xSendTele,
	                   stInTelegramSend := #stTelegramToSend,
	                   fbInOutSendFIFO := #fbInOutSendFIFO,
	                   arFifoSendBuffer := #arFifoSendBuffer);
	END_REGION
	
	REGION Reset SequenceNumber
	    #rTrigConnectionActive(CLK := #fbTeleHandler.xOutConnectionActive);
	    
	    IF #rTrigConnectionActive.Q THEN
	        "DB_CommunicationParameters".nSeqNumWESASRS := 0;
	    END_IF;
	END_REGION
	
	REGION Send Heartbeat
	    IF #fbTeleHandler.xOutConnectionActive THEN
	        #xSendHeartbeat := TRUE;
	        
	        IF #tOnHeartbeat.Q THEN
	            #xSendHeartbeat := FALSE;
	            "FC_Send_HB"(sInPLCID := 'GOHPLC03',
	                         nInPartnerType:= 3,
	                         FIFO := "DB_LGF_FIFO_CommWES_ASRS",
	                         BUFFER := "DB_Buffer_CommunicationWES_ASRS".BUFFER,
	                         nInOutSequenceNumber := "DB_CommunicationParameters".nSeqNumWESASRS);
	        END_IF;
	    ELSE
	        #xSendHeartbeat := FALSE;
	    END_IF;
	    
	    #tOnHeartbeat(IN := #xSendHeartbeat,
	                  PT := t#15s);
	END_REGION
	
	
	REGION Empfangen
	    CASE #nState OF
	        0: // Waiting
	            "DB_HandshakeStorage".str_StorageRemoval.udt_HandshakeMESStorage.str_Ctrl.xNewDataAvaible := FALSE;
	            
	            //New Telegram
	            IF #fbTeleHandler.xOutTelegramAvailable THEN
	                #fbTeleHandler.xInGetFirst := TRUE;
	                #nState := 100;
	            END_IF;
	        100: // Get new Telegram
	            #stNewTelegram := #fbTeleHandler.stOutNewTelegram;
	            #fbTeleHandler.xInGetFirst := FALSE;
	            #nState := 200;
	        200: //Analyze Telegram
	            IF #stNewTelegram.arDataString[3] = 'CReqM' THEN
	                #stTeleCReqM.stHeader.sPlcId := #stNewTelegram.arDataString[1];
	                #stTeleCReqM.stHeader.sSeqNum := #stNewTelegram.arDataString[2];
	                #stTeleCReqM.stHeader.sMessageType := #stNewTelegram.arDataString[3];
	                
	                //LPN,Barcode
	                STRG_VAL(IN := #stNewTelegram.arDataString[4],
	                         FORMAT := 0,
	                         P := 1,
	                         OUT => #stTeleCReqM.stPayload.nBarcode);
	                
	                //Location (z.B. 21101)
	                STRG_VAL(IN := #stNewTelegram.arDataString[5],
	                         FORMAT := 0,
	                         P := 1,
	                         OUT => #stTeleCReqM.stPayload.nLocation);
	                
	                //Priorität
	                STRG_VAL(IN := #stNewTelegram.arDataString[6],
	                         FORMAT := 0,
	                         P := 1,
	                         OUT => #stTeleCReqM.stPayload.nPriority);
	                
	                //End-Ziel: AMR oder F2H
	                STRG_VAL(IN := #stNewTelegram.arDataString[7],
	                         FORMAT := 0,
	                         P := 1,
	                         OUT => #stTeleCReqM.stPayload.nDestination);
	                
	                //Reason Code (niu)
	                STRG_VAL(IN := #stNewTelegram.arDataString[8],
	                         FORMAT := 0,
	                         P := 1,
	                         OUT => #stTeleCReqM.stPayload.nReasonCode);
	                
	                //Zeitstempel
	                #stTeleCReqM.stPayload.sTimeStamp := #stNewTelegram.arDataString[9];
	                
	                #nState := 300;
	                
	            ELSIF #stNewTelegram.arDataString[3] = 'CRCanM' THEN
	                #stTeleCRCanM.stHeader.sPlcId := #stNewTelegram.arDataString[1];
	                #stTeleCRCanM.stHeader.sSeqNum := #stNewTelegram.arDataString[2];
	                #stTeleCRCanM.stHeader.sMessageType := #stNewTelegram.arDataString[3];
	                
	                //LPN,Barcode
	                STRG_VAL(IN := #stNewTelegram.arDataString[4],
	                         FORMAT := 0,
	                         P := 1,
	                         OUT => #stTeleCRCanM.stPayload.nBarcode);
	                
	                #stTeleCRCanM.stPayload.sLocation := #stNewTelegram.arDataString[5];
	                #stTeleCRCanM.stPayload.sTimeStamp := #stNewTelegram.arDataString[6];
	                
	                #nState := 0; //todo
	                
	            ELSE //Unknown todo
	                #nState := 0;
	            END_IF;
	        300: //Transfer Telegram to StockRemovalManagement
	            IF NOT "DB_HandshakeStorage".str_StorageRemoval.udt_HandshakeMESStorage.str_Status.xReadingNewData AND
	                NOT "DB_HandshakeStorage".str_StorageRemoval.udt_HandshakeMESStorage.str_Status.xNewDataSaved
	            THEN
	                "DB_HandshakeStorage".str_StorageRemoval.str_TelegramMES.udtIn_DataMES := #stTeleCReqM;
	                "DB_HandshakeStorage".str_StorageRemoval.udt_HandshakeMESStorage.str_Ctrl.xNewDataAvaible := TRUE;
	            END_IF;
	            
	            IF "DB_HandshakeStorage".str_StorageRemoval.udt_HandshakeMESStorage.str_Ctrl.xNewDataAvaible AND 
	                "DB_HandshakeStorage".str_StorageRemoval.udt_HandshakeMESStorage.str_Status.xNewDataSaved
	            THEN
	                #nState := 0;
	            END_IF;
	            
	           
	    END_CASE;
	END_REGION
END_FUNCTION_BLOCK

