FUNCTION_BLOCK "FB_Monitoring"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      xInQuitError : Bool;   // Quittierung des Alarms
      stSettings : Struct
         xErrLedIfMachineIsOff : Bool;   // LED-Ausgang aktiv wenn Maschine nicht in "run"
         xSelfQuit : Bool;   // Selbstquittierung wenn Fehler weg
         xStopMachine : Bool;   // Maschine wird gestoppt falls dieser Fehler auftritt
         nErrorType : Int := 1;   // 0: IntError | 1: Error | 2: Warning | 3: Information | 4: Debug
         tDelay : Time;   // Zeitverzögerung bis Fehler geworfen wird
         tBlinkerTime : Time := t#500ms;
      END_STRUCT;
      sInFctnName : String;   // Name der Funktion
      xInSignal : Bool;   // Einfang des Fehlers. Fehler wird geworfen wenn xInSignal = FALSE
      sInPrefix : String[30];   // Anfangstext der Fehlermeldung
      sInAlarmMessage : String;   // Haupttext der Fehlermeldung
      sInSuffix : String[30];   // Endtext der Fehlermeldung
      wInTextListId_Message : Word;
      wInTextListId_Function : Word;
      wInTextListId_Prefix : Word;
      wInTextListId_Suffix : Word;
   END_VAR

   VAR_OUTPUT 
      xOutOk : Bool;   // TRUE = Kein Fehler
      xOutError : Bool;   // TRUE = Error
      xOutLedError : Bool;   // FehlerLED leuchten lassen
      xOutAckReq : Bool;   // TRUE: Quittierung angefordert
      stOutHMI : "UDT_HMI_Monitoring";
   END_VAR

   VAR_IN_OUT 
      InOutMachineState : "UDT_MainState";   // Mit "xStopMachine" des jeweiligen StateMachine verbinden
   END_VAR

   VAR 
      xOk : Bool := true;
      tOffTimer {InstructionName := 'TOF_TIME'; LibVersion := '1.0'} : TOF_TIME;
      fbSetAlarmAndLog : "FB_SetAlarmAndLog";
      FB_Blinker : "FB_Blinker";
   END_VAR


BEGIN
	REGION Blinker 
	    // #FB_Blinker(tInPeriodicTime := #stSettings.tBlinkerTime,
	    //             xInActivate := 1);
	END_REGION
	REGION Aktivieren
	    IF NOT #xOk AND
	        #xInSignal AND
	        (#xInQuitError OR #InOutMachineState.xQuitError OR #stSettings.xSelfQuit) THEN
	        #xOk := TRUE;
	    END_IF;
	END_REGION
	
	REGION Timer
	    IF #stSettings.tDelay > T#0ms THEN
	        #tOffTimer(IN := #xInSignal,
	                   PT := #stSettings.tDelay);
	    END_IF;
	END_REGION
	
	REGION Deaktivieren
	    IF #xOk AND
	        (#stSettings.tDelay = T#0ms AND // kein Delay
	        NOT #xInSignal) OR
	        (#stSettings.tDelay > T#0ms AND // mit Delay-timer
	        NOT #tOffTimer.Q) THEN
	        #xOk := FALSE;
	    END_IF;
	END_REGION
	
	REGION Monitoring
	    #fbSetAlarmAndLog.stSettings.nNoMaxErrors := 1;
	    #fbSetAlarmAndLog.stSettings.nType := #stSettings.nErrorType;
	    #fbSetAlarmAndLog.stSettings.sFctnName := #sInFctnName;
	    #fbSetAlarmAndLog(xInAlarm := NOT #xOk,
	                      nInAlarmNumber := 0,
	                      sInPrefix := #sInPrefix,
	                      sInAlarmMessage := #sInAlarmMessage,
	                      sInSuffix := #sInSuffix,
	                      wInTextListId_Message:= #wInTextListId_Message,
	                      wInTextListId_Function := #wInTextListId_Function,
	                      wInTextListId_Prefix := #wInTextListId_Prefix,
	                      wInTextListId_Suffix := #wInTextListId_Suffix,
	                      stInOutControlUnitCabinet:= #InOutMachineState);
	END_REGION
	
	REGION Ausgang schreiben
	    #xOutLedError :=    ((NOT #xOk AND #xInSignal AND "Clock_1Hz" (* #FB_Blinker.xOutput *)) OR        // Nicht quttiert
	                         (NOT #xOk AND NOT #xInSignal))                             // Quittiert
	    AND (#InOutMachineState.xRunning OR #stSettings.xErrLedIfMachineIsOff);
	    // #InOutMachineState.xError := NOT #xOk;
	    #xOutOk := #xOk;
	    #xOutError := NOT #xOk;
	    
	    #xOutAckReq := NOT #xOk AND #xInSignal;
	    
	    IF NOT #xOk AND
	        #stSettings.xStopMachine THEN
	        #InOutMachineState.xStopMachine := TRUE;
	    END_IF;
	    
	END_REGION
	
	REGION HMI
	    #stOutHMI.xSigOk := #xOk;
	    #stOutHMI.xAckReq := #xOutAckReq;
	END_REGION
	
END_FUNCTION_BLOCK

