{
    S7_Author := "AketzaBarragues";
    S7_BlockComment := "MLC_45W";
    S7_BlockNumber := "6";
    S7_BlockTitle := "MLC_36s";
    S7_EditorMode := "SCL";
    S7_Family := "ZeusControl";
    S7_IECCheck := "TRUE";
    S7_Optimized := "TRUE";
    S7_Version := "1.0"
}
FUNCTION "FC6_ZC_ENT_ESTADO" : Void
    VAR_INPUT
        { S7_MLC := "MLC_p2" }
        Entidad : Int;
        { S7_MLC := "MLC_dt" }
        TipoProceso : Int;
        { S7_MLC := "MLC_tm" }
        CodigoProducto : Int;
    END_VAR
    VAR_OUTPUT
        { S7_MLC := "MLC_4VH" }
        TipoError : Int;
        { S7_MLC := "MLC_42U" }
        DispNumero : Int;
    END_VAR
    VAR_TEMP
        for_i : Int;
        t_DispError : Bool;
        t_DispManual : Bool;
        t_DispNumero : Int;
    END_VAR
    VAR CONSTANT
        DISP_V : Int := 1;
        DISP_M : Int := 2;
        DISP_M_VF : Int := 3;
        DISP_M_SINA : Int := 4;
    END_VAR

    { S7_Language := "SCL" }
    NETWORK
        REGION DESCRIPCION
        (*
        ###### (C)Copyright ZeusControl 2020 - 2026
        
        ---
        ### Información del Sistema
        | Hardware Compatible | Entorno de Ingeniería |
        |---------------------|-----------------------|
        | PLC serie 1200/1500 | TIA Portal 18         |
        
        ---
        > **Restricciones:** Ninguna.
        
        ---
        ### Descripción Funcional
        
        Función para la gestión integral de estados, disponibilidad y supervisión de los dispositivos asociados a una entidad.
        
        Las tareas que realiza son las siguientes:
        
        - **Supervisión de dispositivos:** Escaneo cíclico de los dispositivos vinculados a la entidad (Válvulas, Motores, Variadores y Sinamics) mediante un bucle `FOR`.
        - Verificación de alarmas generales (`Alarmas_General`) y estados de mando manual (`Estado_AutoMan`) en cada equipo.
        - Identificación del tipo de incidencia en las salidas `TipoError` (1 para Error, 2 para Manual) y reporte del índice del dispositivo afectado en `DispNumero`.
        - **Cálculo de disponibilidad:** Determinación del estado `Disponible` basándose en la ausencia de alarmas, mandos manuales, capturas activas y estados de proceso (Producción, CIP, SIP, Standby).
        - Actualización del estado `Capturada` si la entidad tiene una asignación distinta de cero.
        - **Gestión de códigos de estado:** Asignación dinámica del código numérico `CodEstado` según la fase de operación actual (Producción: 1000, CIP: 2000, SIP: 3000, Standby: 4000).
        - Refinamiento del código según el contenido detectado (Producto: +10, Agua: +20, Vacío: +30).
        - Registro de estados de limpieza (Sucia: 10000, Limpia: 11000, Esterilizada: 12000).
        - **Sincronización de producto:** Actualización de la variable `Producto` con el valor de entrada `CodigoProducto` siempre que la entidad tenga un estado activo.
        
        ---
        ### Dependencias Requeridas
        | Tipo | Elementos |
        |------|-----------|
        | FC   | - |
        | FB   | - |
        | DB   | `DB2010_V`, `DB2015_M`, `DB2016_M_VF`, `DB2017_M_SINA`, `DB6_ENTIDAD` |
        | UDT  | - |
            
        ---
        ### Historial de Cambios
        | Versión  | Fecha      | Técnico | Cambios |
        |----------|------------|---------|---------|
        | 00.00.01 | 15.10.2020 | (ABH)   | Primera version. |
        | 00.00.02 | 02.02.2021 | (ABH)   | Modificado para uso como funcion. Se elimina bucle `FOR` para revisar solamente la entidad que se pasa como entrada. |
        | 00.00.03 | 02.12.2022 | (ABH)   | Se modifica el UDT para estandarizacion. |
        | 00.00.01 | 15.10.2025 | (ABH)   | Se añade gestion de codigo de estado. |
        | 00.00.05 | 10.03.2025 | (ABH)   | Se añade gestion de codigo de producto a las entidades. |
        | 00.00.06 | 24.04.2025 | (HCR)   | Se añade gestion de idioma. |
        | 00.00.07 | 11.09.2025 | (ABH)   | Se eliminan las constantes de idioma dentro del `FC`. Se utilizan constantes globales. |
        | 01.00.00 | 26.03.2026 | (ABH)   | Se elimina idioma. Se añaden constantes de tipo de dispositivo. |
        *)
        END_REGION DESCRIPCION
        
        
        //  ==========================================================================================================
        REGION GESTION_ENTIDADES
            
            IF "DB6_ENTIDAD".ENT[#Entidad].Habilitar THEN
                
                //  Asignacion de estado entidad capturada
                "DB6_ENTIDAD".ENT[#Entidad].Estado.Capturada := "DB6_ENTIDAD".ENT[#Entidad].Asignacion <> 0;
                
                //  ==========================================================================================================
                REGION COMPROBACION_DISPOSITIVOS
                    
                    //  Reset de estados
                    "DB6_ENTIDAD".ENT[#Entidad].Alarma.Dispositivo := "DB6_ENTIDAD".ENT[#Entidad].Alarma.Manual := #t_DispError := #t_DispManual := FALSE;
                    
                    //  Comprobacion de estado de dispositivo declarados dentro de la entidad
                    FOR #for_i := 1 TO "N_MAX_ENTIDAD_DISPOSITIVOS" DO
                        
                        //  Se revisan solamente las entidades declaradas
                        IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Tipo <> 0 AND "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <> 0 THEN
                            
                            CASE "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Tipo OF
                                    
                                #DISP_V:
                                    //  ==========================================================================================================
                                    REGION VALVULA
                                        
                                        IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <= "N_MAX_DISP_V" THEN
                                            
                                            //  Comprobacion de errores o dispositivo en manual
                                            #t_DispError := "DB2010_V".V["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Alarmas_General;
                                            #t_DispManual := "DB2010_V".V["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Estado_AutoMan;
                                            
                                            IF #t_DispError OR #t_DispManual THEN
                                                #t_DispNumero := (#DISP_V * 1000) + "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num;
                                            END_IF;
                                            
                                        END_IF;
                                        
                                    END_REGION VALVULA
                                    
                                    
                                #DISP_M:
                                    //  ==========================================================================================================
                                    REGION MOTOR
                                        
                                        IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <= "N_MAX_DISP_M" THEN
                                            
                                            //  Comprobacion de errores o dispositivo en manual
                                            #t_DispError := "DB2015_M".M["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Alarmas_General;
                                            #t_DispManual := "DB2015_M".M["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Estado_AutoMan;
                                            
                                            IF #t_DispError OR #t_DispManual THEN
                                                #t_DispNumero := (#DISP_M * 1000) + "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num;
                                            END_IF;
                                            
                                        END_IF;
                                        
                                    END_REGION MOTOR
                                    
                                    
                                #DISP_M_SINA:
                                    //  ==========================================================================================================
                                    REGION MOTOR_SINAMICS
                                        
                                        IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <= "N_MAX_DISP_M_SINA" THEN
                                            
                                            //  Comprobacion de errores o dispositivo en manual
                                            #t_DispError := "DB2017_M_SINA".M_SINA["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Alarmas_General;
                                            #t_DispManual := "DB2017_M_SINA".M_SINA["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Estado_AutoMan;
                                            
                                            IF #t_DispError OR #t_DispManual THEN
                                                #t_DispNumero := (#DISP_M_SINA * 1000) + "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num;
                                            END_IF;
                                            
                                        END_IF;
                                        
                                    END_REGION MOTOR_SINAMICS
                                    
                                    
                                #DISP_M_VF:
                                    //  ==========================================================================================================
                                    REGION MOTOR_VARIADOR
                                        
                                        IF "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num <= "N_MAX_DISP_M_VF" THEN
                                            
                                            //  Comprobacion de errores o dispositivo en manual
                                            #t_DispError := "DB2016_M_VF".M_VF["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Alarmas_General;
                                            #t_DispManual := "DB2016_M_VF".M_VF["DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num].Estado_AutoMan;
                                            
                                            IF #t_DispError OR #t_DispManual THEN
                                                #t_DispNumero := (#DISP_M_VF * 1000) + "DB6_ENTIDAD".ENT[#Entidad].Dispositivo[#for_i].Num;
                                            END_IF;
                                            
                                        END_IF;
                                    END_REGION MOTOR_VARIADOR
                                    
                                    
                                ELSE
                                    #t_DispError := #t_DispManual := FALSE;
                            END_CASE;
                            
                        END_IF;
                        
                        
                        
                        IF #t_DispError THEN
                            
                            //  Activacion de estado en error
                            "DB6_ENTIDAD".ENT[#Entidad].Alarma.Dispositivo := TRUE;
                            #TipoError := 1;
                            #DispNumero := #t_DispNumero;
                            EXIT;
                            
                        ELSIF #t_DispManual THEN
                            
                            //  Activacion de estado en manual
                            "DB6_ENTIDAD".ENT[#Entidad].Alarma.Manual := TRUE;
                            #TipoError := 2;
                            #DispNumero := #t_DispNumero;
                            EXIT;
                            
                        END_IF;
                        
                    END_FOR;
                    
                END_REGION COMPROBACION_DISPOSITIVOS
                
                
                //  ==========================================================================================================
                REGION ASIGNACION_ESTADOS
                    
                    //  Asignacion de estado disponible
                    "DB6_ENTIDAD".ENT[#Entidad].Estado.Disponible :=
                    ("DB6_ENTIDAD".ENT[#Entidad].Asignacion = 0)
                    AND NOT "DB6_ENTIDAD".ENT[#Entidad].Alarma.Dispositivo
                    AND NOT "DB6_ENTIDAD".ENT[#Entidad].Alarma.Manual
                    AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.EnProduccion
                    AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.EnCIP
                    AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.EnSIP
                    AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.EnStandby
                    AND NOT "DB6_ENTIDAD".ENT[#Entidad].Estado.Capturada;
                    
                    //  Asignacion de codigo de estado
                    "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 0;
                    IF "DB6_ENTIDAD".ENT[#Entidad].Estado.EnProduccion THEN
                        "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 1000;
                    ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.EnCIP THEN
                        "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 2000;
                    ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.EnSIP THEN
                        "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 3000;
                    ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.EnStandby THEN
                        "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 4000;
                    ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.Sucia THEN
                        "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 10000;
                    ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.Limpia THEN
                        "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 11000;
                    ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.Esterilizada THEN
                        "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 12000;
                    END_IF;
                    
                    IF (*ENT[#Entidad].Estado.CodEstado >= 1000 AND *)"DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado <= 4999 THEN
                        IF "DB6_ENTIDAD".ENT[#Entidad].Estado.ConProducto THEN
                            "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado + 10;
                        ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.ConAgua THEN
                            "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado + 20;
                        ELSIF "DB6_ENTIDAD".ENT[#Entidad].Estado.Vacia THEN
                            "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado + 30;
                        END_IF;
                    END_IF;
                    
                    //  Asignacion de codigo de producto
                    IF "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado <> 0 THEN
                        "DB6_ENTIDAD".ENT[#Entidad].Estado.Producto := #CodigoProducto;
                    ELSE
                        "DB6_ENTIDAD".ENT[#Entidad].Estado.CodEstado := 0;
                    END_IF;
                    
                END_REGION ASIGNACION_ESTADOS
                
            ELSE
                "DB6_ENTIDAD".ENT[#Entidad].Estado.Disponible := FALSE;
                "DB6_ENTIDAD".ENT[#Entidad].Asignacion := 0;
                
            END_IF;
            
            
        END_REGION GESTION_ENTIDADES
        
        
    END_NETWORK
END_FUNCTION
