FUNCTION "FC_CarrierManipulator" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_IN_OUT 
      stInOutHMIJamData : "UDT_HMI_JamData";   // Jam Daten HMI
      stInOutHMIJamList : "UDT_Visu_Jam_List";   // Jam Liste HMI
      arInOutJam : Array[*] of "stCarrier";   // Jam SPS
      arInOutHyperJam : Array[*] of "stCarrier";
   END_VAR

   VAR_TEMP 
      tmpEmptyCarr : "stCarrier";
      nCounter : DInt;
      nArrayMax : Int;
      nIdx : Int;
      nStatus : Int;
      xResult : Bool;
   END_VAR

   VAR CONSTANT 
      cFirstAhead : Int := 1;   // Carrier weiterbuchen
      cLastBack : Int := 2;   // Carrier zurückbuchen
      cSwapFirstLast : Int := 3;   // Ersten und letzten Carrier im Jam tauschen
      cDeleteAll : Int := 4;   // Alle Jam Daten löschen (macht Sinn, wenn Jam unklar und man einfach bereinigen will)
      cDeletePos : Int := 5;   // Position, falls bestimmter Carrier gelöscht werden soll (macht Sinn, wenn man Carrier entnimmt)
      cPutToHyperJam : Int := 6;   // Position, falls bestimmter Carrier zum HyperJam soll (macht Sinn, wenn Carrier nicht auffindbar)
   END_VAR


BEGIN
	REGION Info
	(*
	Funktionen
	
	- Alle carrier daten in einem jam leeren - check
	- bestimmten carrier löschen - check
	
	MUBEA bereits gemacht:
	- Carrier in Hyper-Jam - check
	- Weiterbuchen
	- Zurückbuchen
	- Tauschen (erster und letzter)
	*)
	END_REGION
	
	REGION Array-Grenzen
	    #nArrayMax := DINT_TO_INT(UPPER_BOUND(ARR := #arInOutJam, DIM := 1));
	END_REGION
	
	REGION Befehl ausführen
	    CASE #stInOutHMIJamList.stCarMove.nCommand OF
	        #cDeleteAll:
	            REGION Jam bereinigen
	                IF #stInOutHMIJamList.stCarMove.xStart THEN
	                    IF NOT #arInOutJam[1].bStatus.%X0 OR NOT #stInOutHMIJamData.stStatus.bByte.%X2 OR NOT #stInOutHMIJamData.stStatus.bByte.%X3 THEN
	                        #stInOutHMIJamList.stCarMove.xStart := FALSE;
	                        RETURN;
	                    END_IF;
	                    
	                    FOR #nIdx := 1 TO #nArrayMax DO
	                        IF #arInOutJam[#nIdx].bStatus.%X0 THEN
	                            #arInOutJam[#nIdx] := #tmpEmptyCarr; // Carrierdaten löschen/überschreiben
	                        ELSE
	                            EXIT; //fertig, nichts mehr zu tun
	                        END_IF;
	                    END_FOR;
	                    #stInOutHMIJamList.stCarMove.xStart := FALSE;
	                END_IF;
	            END_REGION
	
	        #cDeletePos:
	            REGION Bestimmten Carrier löschen
	                IF #stInOutHMIJamList.stCarMove.xStart THEN
	                    
	                    IF #stInOutHMIJamList.stCarMove.nPosDeleteCarrier < 1 OR #stInOutHMIJamList.stCarMove.nPosDeleteCarrier > #nArrayMax OR NOT #arInOutJam[1].bStatus.%X0 OR NOT #stInOutHMIJamData.stStatus.bByte.%X2 OR NOT #stInOutHMIJamData.stStatus.bByte.%X3 THEN
	                        //Wenn Positionsangabe zu klein oder zu groß ist, oder in Jam ist gar kein Carrier online, dann beende
	                        #stInOutHMIJamList.stCarMove.nPosDeleteCarrier := 1;
	                        #stInOutHMIJamList.stCarMove.xStart := FALSE;
	                        RETURN;
	                    END_IF;
	                    
	                    //lösche den ausgewählten
	                    #arInOutJam[#stInOutHMIJamList.stCarMove.nPosDeleteCarrier] := #tmpEmptyCarr;
	                    IF #stInOutHMIJamList.stCarMove.nPosDeleteCarrier < #nArrayMax THEN
	                        //Rücke danach auf um Lücke zu beseitigen aber nur wenn es nicht die letzte Stelle war
	                        #nStatus := MOVE_BLK_VARIANT(SRC := #arInOutJam,
	                                                     COUNT := INT_TO_UDINT(#nArrayMax - #stInOutHMIJamList.stCarMove.nPosDeleteCarrier),
	                                                     SRC_INDEX := #stInOutHMIJamList.stCarMove.nPosDeleteCarrier,
	                                                     DEST_INDEX := #stInOutHMIJamList.stCarMove.nPosDeleteCarrier - 1,
	                                                     DEST => #arInOutJam);
	                        //letztes löschen damit dort nichts doppeltes drinsteht
	                        #arInOutJam[#nArrayMax] := #tmpEmptyCarr;
	                    END_IF;
	                    //fertig, setze Startbefehl zurück und Position auf Default
	                    #stInOutHMIJamList.stCarMove.nPosDeleteCarrier := 1;
	                    #stInOutHMIJamList.stCarMove.xStart := FALSE;
	                END_IF;
	            END_REGION
	
	        #cPutToHyperJam:
	            REGION Carrier zum Hyper-Jam
	                
	                IF #stInOutHMIJamList.stCarMove.xStart THEN
	                    IF #stInOutHMIJamList.stCarMove.nPosTransferHj < 1 OR #stInOutHMIJamList.stCarMove.nPosTransferHj > #nArrayMax OR NOT #arInOutJam[1].bStatus.%X0 OR NOT #stInOutHMIJamData.stStatus.bByte.%X2 OR NOT #stInOutHMIJamData.stStatus.bByte.%X3 THEN
	                        //Wenn Positionsangabe zu klein oder zu groß ist, oder in Jam ist gar kein Carrier online, dann beende
	                        #stInOutHMIJamList.stCarMove.nPosTransferHj := 1;
	                        #stInOutHMIJamList.stCarMove.xStart := FALSE;
	                        RETURN;
	                    END_IF;
	                    
	                    IF #arInOutJam[#stInOutHMIJamList.stCarMove.nPosTransferHj].nBarcode > 2 THEN
	                        REGION normale Barcodes
	                            //Füge Carrier am Ende des Hyperjams ein nur wenn nicht Dummy oder BadRead, also nur bei normalem Code
	                            "FC_TSHR_AddAtEnd"(stInTrolley := #arInOutJam[#stInOutHMIJamList.stCarMove.nPosTransferHj],
	                                               nOutCounter => #nCounter,
	                                               xOutResult => #xResult,
	                                               arTSHR := #arInOutHyperJam);
	                            //lösche den ausgewählten
	                            #arInOutJam[#stInOutHMIJamList.stCarMove.nPosTransferHj] := #tmpEmptyCarr;
	                            IF #stInOutHMIJamList.stCarMove.nPosTransferHj < #nArrayMax THEN
	                                //Rücke danach auf um Lücke zu beseitigen aber nur wenn es nicht die letzte Stelle war
	                                #nStatus := MOVE_BLK_VARIANT(SRC := #arInOutJam,
	                                                             COUNT := INT_TO_UDINT(#nArrayMax - #stInOutHMIJamList.stCarMove.nPosTransferHj),
	                                                             SRC_INDEX := #stInOutHMIJamList.stCarMove.nPosTransferHj,
	                                                             DEST_INDEX := #stInOutHMIJamList.stCarMove.nPosTransferHj - 1,
	                                                             DEST => #arInOutJam);
	                                //letztes löschen damit dort nichts doppeltes drinsteht
	                                #arInOutJam[#nArrayMax] := #tmpEmptyCarr;
	                            END_IF;
	                            //fertig, setze Startbefehl zurück und Position auf Default
	                            #stInOutHMIJamList.stCarMove.nPosTransferHj := 1;
	                            #stInOutHMIJamList.stCarMove.xStart := FALSE;
	                        END_REGION
	                    ELSE
	                        REGION Dummy oder unbekannt
	                            //Falls doch Dummy oder unbekannter Barcode, lösche nur
	                            #arInOutJam[#stInOutHMIJamList.stCarMove.nPosTransferHj] := #tmpEmptyCarr;
	                            IF #stInOutHMIJamList.stCarMove.nPosTransferHj < #nArrayMax THEN
	                                //Rücke danach auf um Lücke zu beseitigen aber nur wenn es nicht die letzte Stelle war
	                                #nStatus := MOVE_BLK_VARIANT(SRC := #arInOutJam,
	                                                             COUNT := INT_TO_UDINT(#nArrayMax - #stInOutHMIJamList.stCarMove.nPosTransferHj),
	                                                             SRC_INDEX := #stInOutHMIJamList.stCarMove.nPosTransferHj,
	                                                             DEST_INDEX := #stInOutHMIJamList.stCarMove.nPosTransferHj - 1,
	                                                             DEST => #arInOutJam);
	                                //letztes löschen damit dort nichts doppeltes drinsteht
	                                #arInOutJam[#nArrayMax] := #tmpEmptyCarr;
	                            END_IF;
	                            //fertig, setze Startbefehl zurück und Position auf Default
	                            #stInOutHMIJamList.stCarMove.nPosTransferHj := 1;
	                            #stInOutHMIJamList.stCarMove.xStart := FALSE;
	                        END_REGION
	                    END_IF;
	                END_IF;
	            END_REGION
	
	    END_CASE;
	END_REGION
END_FUNCTION

