FUNCTION_BLOCK "FB_Visu_AuslagernAI"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      b_Start : Bool;
      i_Chunk : Int := 500;
   END_VAR

   VAR_OUTPUT 
      r_Progress : Real;
   END_VAR

   VAR_IN_OUT 
      arDatenProLinie : Array[0..12] of "udt_DatenProLinie";
      nGesamtanzahlCarrierLeer : Int;
      nGesamtanzahlCarrierBeladen : Int;
      nGesamtanzahlCarrierAngefordert : Int;
      nGesamtanzahlCarrierLevel : Int;
      arrudt_AngeforderteCarrier : Array[0..26964] of "udt_InfoRequestedCarrier";
   END_VAR

   VAR 
      b_Busy : Bool;
      b_Done : Bool;
      i_IdxAuslagernBlock { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
      i_IdxAuslagernLine { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
      i_IdxAuslagernCarrier { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;
      i_AccAngefordert : Int;
      i_AccLeer : Int;
      i_AccBeladen : Int;
      IndexClear : Int;
      IndexArrayfüllen : Int;
      arrudt_AngeforderteCarrierClear { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'; S7_SetPoint := 'False'} : Array[0..26964] of "udt_InfoRequestedCarrier";
   END_VAR

   VAR_TEMP 
      i_AnzahlDurchlaeufe : Int;
      w_StatusRead : Word;
      di_Total : DInt;
      di_DoneCount : DInt;
   END_VAR

   VAR CONSTANT 
      cPageSize : Int := 10;
      cMaxJam : DInt := 26964;
   END_VAR


BEGIN
	REGION Info
	(* ------------------------------------------------------------------------------------------------
	   Modulname    : FB_Visu_AuslagernAI
	   Date         : 08.10.2025              
	   Author       : Kannler Thomas / Automated-Intelligence
	   Info         : FB für die Visualisierung der Auslagerungsdaten
	                           
	   ChangeLog:   : ThKa 13.10.2025 - Hinzufügen der JamList für alle angeforderten Carrier
	   ---------------------------------------------------------------------------------------------- *)
	END_REGION
	
	REGION Timeslicing für Zählen der Teile in Level 2
	    // Start/Initialisierung
	    IF #b_Start AND NOT #b_Busy THEN
	        #b_Busy := TRUE;
	        #b_Done := FALSE;
	        
	        //Indizess alle initialisieren
	        #i_IdxAuslagernBlock := 1;
	        #i_IdxAuslagernLine := 1;
	        #i_IdxAuslagernCarrier := 1;
	        #i_AccAngefordert := 0;
	        #i_AccLeer := 0;
	        #i_AccBeladen := 0;
	        #IndexArrayfüllen := 0;
	        
	        //Array clearen
	        #arrudt_AngeforderteCarrier := #arrudt_AngeforderteCarrierClear;
	    END_IF;
	    
	    // Timeslice
	    IF #b_Busy THEN
	        #i_AnzahlDurchlaeufe := 0;
	        
	        WHILE (#i_AnzahlDurchlaeufe < #i_Chunk) AND #b_Busy DO
	            //Status einmal lesen (DB-Zugriff minimieren)
	            #w_StatusRead := #arDatenProLinie[#i_IdxAuslagernBlock].udt_DataLine[#i_IdxAuslagernLine].arCarrier[#i_IdxAuslagernCarrier].bStatus;
	            
	            //Zählen
	            //Leere Carrier
	            IF #w_StatusRead.%X0 AND NOT #w_StatusRead.%X1 THEN
	                #i_AccLeer := #i_AccLeer + 1;
	            END_IF;
	            
	            //Beladene Carrier
	            IF #w_StatusRead.%X1 THEN
	                #i_AccBeladen := #i_AccBeladen + 1;
	            END_IF;
	            
	            //Angeforderte Carrier
	            IF #w_StatusRead.%X5 THEN
	                #i_AccAngefordert := #i_AccAngefordert + 1;
	                
	                #IndexArrayfüllen := #IndexArrayfüllen + 1;
	                
	                #arrudt_AngeforderteCarrier[#IndexArrayfüllen].i_Block := #i_IdxAuslagernBlock;
	                #arrudt_AngeforderteCarrier[#IndexArrayfüllen].i_Reihe := #i_IdxAuslagernLine;
	                #arrudt_AngeforderteCarrier[#IndexArrayfüllen].i_Carrier := #i_IdxAuslagernCarrier;
	                #arrudt_AngeforderteCarrier[#IndexArrayfüllen].di_Barcode := #arDatenProLinie[#i_IdxAuslagernBlock].udt_DataLine[#i_IdxAuslagernLine].arCarrier[#i_IdxAuslagernCarrier].nBarcode;
	                #arrudt_AngeforderteCarrier[#IndexArrayfüllen].i_Destination := #arDatenProLinie[#i_IdxAuslagernBlock].udt_DataLine[#i_IdxAuslagernLine].arCarrier[#i_IdxAuslagernCarrier].nDestination;
	                #arrudt_AngeforderteCarrier[#IndexArrayfüllen].w_State := #arDatenProLinie[#i_IdxAuslagernBlock].udt_DataLine[#i_IdxAuslagernLine].arCarrier[#i_IdxAuslagernCarrier].bStatus;
	            END_IF;
	            
	            //Indizess weiterschalten
	            //Durchsuchen der ersten 107 Carrier in der ersten Reihe im ersten Block. 
	            #i_IdxAuslagernCarrier := #i_IdxAuslagernCarrier + 1;
	            
	            //Anschließend durchsuchen der 107 Carrier in der zweiten Reihe im ersten Block...usw.
	            IF #i_IdxAuslagernCarrier > 107 THEN
	                #i_IdxAuslagernCarrier := 1;
	                #i_IdxAuslagernLine := #i_IdxAuslagernLine + 1;
	                
	                //Anschließend durchsuchen der 107 Carrier in der ersten Reihe im zweiten Block...usw.
	                IF #i_IdxAuslagernLine > 21 THEN
	                    #i_IdxAuslagernLine := 1;
	                    #i_IdxAuslagernBlock := #i_IdxAuslagernBlock + 1;
	                    IF #i_IdxAuslagernBlock > 12 THEN
	                        //Hier angekommen wurden alle Carrier in allen Reihen in allen Blöcken ermittelt. Die Anzahl kann nun atomar in den DB geschrieben werden.
	                        #nGesamtanzahlCarrierLeer := #i_AccLeer;
	                        #nGesamtanzahlCarrierBeladen := #i_AccBeladen;
	                        #nGesamtanzahlCarrierAngefordert := #i_AccAngefordert;
	                        
	                        #b_Busy := FALSE;
	                        #b_Done := TRUE;
	                    END_IF;
	                END_IF;
	            END_IF;
	            
	            #i_AnzahlDurchlaeufe := #i_AnzahlDurchlaeufe + 1;
	        END_WHILE;
	        
	        //Anzeige wie viel % das  
	        // Fortschritt fürs HMI (optional)
	        #di_Total := 12 * 21 * 107; // 26964 Carrier
	        #di_DoneCount := (#i_IdxAuslagernBlock - 1) * 21 * 107 + (#i_IdxAuslagernLine - 1) * 107 + (#i_IdxAuslagernCarrier - 1);
	        #r_Progress := 100.0 * DINT_TO_REAL(#di_DoneCount) / DINT_TO_REAL(#di_Total);
	        
	    ELSE
	        // Idle: Done nur 1 Zyklus pulsartig zulassen
	        IF #b_Done THEN
	            #b_Done := FALSE;
	        END_IF;
	        #r_Progress := 0;
	    END_IF;
	    
	    #nGesamtanzahlCarrierLevel := #nGesamtanzahlCarrierLeer + #nGesamtanzahlCarrierBeladen + #nGesamtanzahlCarrierAngefordert;
	END_REGION
	
END_FUNCTION_BLOCK

