{
    S7_Author := "ABH";
    S7_BlockComment := "MLC_3Ln";
    S7_BlockNumber := "15200";
    S7_BlockTitle := "MLC_3aY";
    S7_EditorMode := "SCL";
    S7_Family := "ZeusControl";
    S7_IECCheck := "TRUE";
    S7_Optimized := "TRUE";
    S7_Version := "1.0"
}
FUNCTION_BLOCK "FB15200_ZC_SYNC_RECETA_PANEL"
    VAR_INPUT
        { S7_MLC := "MLC_X3" }
        HabilitarBorrado : Bool := FALSE;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        RutaCarpetaRecetas : String[25] := '\temp\RecetasScada\';
        FechaHoraActual : DTL;
        TiempoRetardoInicio : Time := T#20S;
        TiempoRetardoHmi : Time := T#10S;
        TiempoComprobacion : Time := T#500MS;
        TiempoError : Time := T#8S;
    END_VAR
    VAR_OUTPUT RETAIN
        ErrorImportar : Bool;
        ErrorBorrar : Bool;
    END_VAR
    VAR RETAIN
        s_ExisteRecetaNueva : Bool;
        s_OrdenSincHMI : Bool;
        s_OrdenBorrarHMI : Bool;
        s_EstadoImportar : Int;
        s_EstadoBorrar : Int;
        s_RutaCarpeta : String;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_Iniciar : Bool;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_Etapa : Int;
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        s_EtapaSiguiente : Int;
        { S7_Setpoint := "True" }
        UltimaSincronizacion : DTL;
    END_VAR
    VAR
        {
            S7_Access := "ReadOnly := External";
            S7_Visibility := "Hidden := External"
        }
        TON_OrdenInicio : TON_TIME;
        TON_RetardoImportarHmi : TON_TIME;
        TON_RetardoBorrarHmi : TON_TIME;
        {
            S7_Access := "ReadOnly := External";
            S7_Setpoint := "False";
            S7_Visibility := "Hidden := External"
        }
        TON_EstadoImportar : TON_TIME;
        TON_ErrorImportar : TON_TIME;
        TON_EstadoBorrar : TON_TIME;
        TON_ErrorBorrar : TON_TIME;
    END_VAR
    VAR CONSTANT
        ETAPA_0_REPOSO : Int := 0;
        ETAPA_10_IMPORTAR_ORDEN_HMI : Int := 10;
        ETAPA_20_IMPORTAR_ESPERA_HMI : Int := 20;
        ETAPA_30_IMPORTAR_COMPROBACION : Int := 30;
        ETAPA_40_BORRAR_ORDEN_HMI : Int := 40;
        ETAPA_50_BORRAR_ESPERA_HMI : Int := 50;
        ETAPA_60_BORRAR_COMPROBACION : Int := 60;
    END_VAR

    { S7_Language := "SCL" }
    NETWORK
        REGION DESCRIPCION
        (*
        //=======================================================================
        // (C)Copyright ZeusControl 2022 - 2022
        //=======================================================================
        
        ### Información del Sistema
        | Hardware Compatible | Entorno de Ingeniería |
        |---------------------|-----------------------|
        | PLC serie 1200/1500 | TIA Portal 18         |
          
        ---
        ### Descripción Funcional
        Función central para la gestión de la sincronización de recetas con el HMI. Implementa una máquina de estados que coordina la importación (y borrado opcional) de recetas desde el HMI, gestionando las temporizaciones de espera, las señales de confirmación y los códigos de estado/error, así como el registro de la última sincronización correcta.
        
        > **Restricciones:** Ninguna.
        
        Acciones detalladas:
        - Gestiona los temporizadores generales del bloque: retardo de inicio (`TON_OrdenInicio`), retardos de orden de importar/borrar desde HMI (`TON_RetardoImportarHmi`, `TON_RetardoBorrarHmi`), temporizadores de espera de estado (`TON_EstadoImportar`, `TON_EstadoBorrar`) y temporizadores de error (`TON_ErrorImportar`, `TON_ErrorBorrar`).
        - Estado `ETAPA_0_REPOSO`: si existe receta nueva (`s_ExisteRecetaNueva`) y la etapa actual es reposo, arranca la temporización de inicio. Una vez cumplido el tiempo, se activa `s_Iniciar`, se inicializan los estados de importar/borrar, se carga la `RutaCarpetaRecetas` en `s_RutaCarpeta` y se pasa a la etapa de orden de importar al HMI.
        - Estado `ETAPA_10_IMPORTAR_ORDEN_HMI`: activa la marca `s_OrdenSincHMI` cuando se recibe desde HMI o cuando expira `TON_RetardoImportarHmi`, y transiciona a la etapa de espera de importación.
        - Estado `ETAPA_20_IMPORTAR_ESPERA_HMI`: espera a que finalice la temporización de estado (`TON_EstadoImportar`) o de error (`TON_ErrorImportar`) para pasar a la etapa de comprobación.
        - Estado `ETAPA_30_IMPORTAR_COMPROBACION`: evalúa el código de estado de importación (`s_EstadoImportar`). Si es correcto (`4`), resetea `s_ExisteRecetaNueva` y `ErrorImportar`, registra la `UltimaSincronizacion` y, si está habilitado el borrado (`HabilitarBorrado`), continúa con la etapa de borrado; en caso contrario, vuelve a `ETAPA_0_REPOSO`. Si el estado no es correcto, marca `ErrorImportar` y vuelve a reposo.
        - Estado `ETAPA_40_BORRAR_ORDEN_HMI`: activa `s_OrdenBorrarHMI` cuando se recibe desde HMI o cuando expira `TON_RetardoBorrarHmi`, y transiciona a la etapa de espera de borrado.
        - Estado `ETAPA_50_BORRAR_ESPERA_HMI`: espera a que finalice la temporización de estado (`TON_EstadoBorrar`) o de error (`TON_ErrorBorrar`) para pasar a la etapa de comprobación de borrado.
        - Estado `ETAPA_60_BORRAR_COMPROBACION`: evalúa el código de estado de borrado (`s_EstadoBorrar`). Si es correcto (`4`), resetea `s_ExisteRecetaNueva` y `ErrorBorrar`; si no, activa `ErrorBorrar`. En ambos casos, resetea los flags de estado y orden y vuelve a `ETAPA_0_REPOSO`.
        - En cada ciclo se actualiza la etapa en curso (`s_Etapa := s_EtapaSiguiente`), manteniendo la coherencia de la máquina de estados.
        
        ---
        ### Dependencias Requeridas
        | Tipo | Elementos |
        |------|-----------|
        | FC   | - |
        | FB   | - |
        | DB   | - |
        | UDT  | - |
        
        ---
        ### Historial de Cambios
        | Versión  | Fecha      | Técnico | Cambios |
        |----------|------------|---------|---------|
        | 01.00.00 | 03.11.2022 | (ABH)   | Primera versión. |
        *)
        END_REGION DESCRIPCION
        
        
        //  ==========================================================================================================
        REGION GESTION_TEMPORIZADORES
            
            //  Retardo inicio sincronizacion
            #TON_OrdenInicio(IN := #s_ExisteRecetaNueva AND (#s_Etapa = #ETAPA_0_REPOSO),
                             PT := #TiempoRetardoInicio);
            IF #TON_OrdenInicio.Q THEN
                #s_Iniciar := true;
            END_IF;
            
            //  Retardo orden importar hmi
            #TON_RetardoImportarHmi(IN := (#s_Etapa = #ETAPA_10_IMPORTAR_ORDEN_HMI),
                                    PT := #TiempoRetardoHmi);
            
            //  Retardo estado/error importar
            #TON_EstadoImportar(IN := (#s_Etapa = #ETAPA_20_IMPORTAR_ESPERA_HMI) AND ((#s_EstadoImportar = 4) OR (#s_EstadoImportar = 12)),
                                PT := #TiempoComprobacion);
            #TON_ErrorImportar(IN := (#s_Etapa = #ETAPA_20_IMPORTAR_ESPERA_HMI),
                               PT := #TiempoError);
            
            //  Retardo orden borrar hmi
            #TON_RetardoBorrarHmi(IN := (#s_Etapa = #ETAPA_40_BORRAR_ORDEN_HMI),
                                  PT := #TiempoRetardoHmi);
            
            //  Retardo borrar estado
            #TON_EstadoBorrar(IN := (#s_Etapa = #ETAPA_50_BORRAR_ESPERA_HMI) AND ((#s_EstadoImportar = 4) OR (#s_EstadoImportar = 12)),
                              PT := #TiempoComprobacion);
            #TON_ErrorBorrar(IN := (#s_Etapa = #ETAPA_50_BORRAR_ESPERA_HMI),
                             PT := #TiempoError);
            
        END_REGION GESTION_TEMPORIZADORES
        
        
        //  ==========================================================================================================
        REGION LOGICA
            
            CASE #s_Etapa OF
                    
                #ETAPA_0_REPOSO:
                    #s_RutaCarpeta := '';
                    REGION REPOSO
                        
                        IF #s_Iniciar THEN
                            #s_Iniciar := FALSE;
                            #s_EstadoImportar := 0;
                            #s_EstadoBorrar := 0;
                            #s_RutaCarpeta := #RutaCarpetaRecetas;
                            #s_EtapaSiguiente := #ETAPA_10_IMPORTAR_ORDEN_HMI;
                        END_IF;
                        
                    END_REGION
                    
                    
                #ETAPA_10_IMPORTAR_ORDEN_HMI:
                    
                    REGION IMPORTAR_ORDEN_HMI
                        
                        IF #s_OrdenSincHMI THEN
                            #s_EtapaSiguiente := #ETAPA_20_IMPORTAR_ESPERA_HMI;
                        END_IF;
                        
                        IF #TON_RetardoImportarHmi.Q THEN
                            #s_OrdenSincHMI := TRUE;
                        END_IF;
                        
                    END_REGION
                    
                    
                #ETAPA_20_IMPORTAR_ESPERA_HMI:
                    
                    REGION IMPORTAR_ESPERA_HMI
                        
                        IF #TON_EstadoImportar.Q OR #TON_ErrorImportar.Q THEN
                            #s_EtapaSiguiente := #ETAPA_30_IMPORTAR_COMPROBACION;
                        END_IF;
                        
                    END_REGION
                    
                    
                #ETAPA_30_IMPORTAR_COMPROBACION:
                    
                    REGION IMPORTAR_COMPROBACION
                        
                        //  Si se ejecuta correctamente, reseteamos marca que indica que hay recetas nuevas que sincronizar
                        //  y guardamos la fecha y hora de la ultima sincronizacion
                        IF #s_EstadoImportar = 4 THEN
                            
                            #s_ExisteRecetaNueva :=
                            #ErrorImportar := FALSE;
                            #UltimaSincronizacion := #FechaHoraActual;
                            IF #HabilitarBorrado THEN
                                #s_EtapaSiguiente := #ETAPA_40_BORRAR_ORDEN_HMI;
                            ELSE
                                #s_EtapaSiguiente := #ETAPA_0_REPOSO;
                            END_IF;
                        ELSE
                            #ErrorImportar := TRUE;
                            #s_EtapaSiguiente := #ETAPA_0_REPOSO;
                        END_IF;
                        
                        #s_OrdenSincHMI := FALSE;
                        #s_EstadoImportar := 0;
                        
                        
                    END_REGION
                    
                #ETAPA_40_BORRAR_ORDEN_HMI:
                    
                    REGION BORRAR_ORDEN_HMI
                        
                        IF #s_OrdenBorrarHMI THEN
                            #s_EtapaSiguiente := #ETAPA_50_BORRAR_ESPERA_HMI;
                        END_IF;
                        
                        IF #TON_RetardoBorrarHmi.Q THEN
                            #s_OrdenBorrarHMI := TRUE;
                        END_IF;
                        
                    END_REGION
                    
                    
                #ETAPA_50_BORRAR_ESPERA_HMI:
                    
                    REGION BORRAR_ESPERA_HMI
                        
                        IF #TON_EstadoBorrar.Q OR #TON_ErrorBorrar.Q THEN
                            #s_EtapaSiguiente := #ETAPA_60_BORRAR_COMPROBACION;
                        END_IF;
                        
                    END_REGION
                    
                    
                #ETAPA_60_BORRAR_COMPROBACION:
                    
                    REGION IMPORTAR_COMPROBACION
                        
                        //  Si se ejecuta correctamente, reseteamos marca que indica que hay recetas nuevas que sincronizar
                        //  y guardamos la fecha y hora de la ultima sincronizacion
                        IF #s_EstadoBorrar = 4 THEN
                            
                            #s_ExisteRecetaNueva :=
                            #ErrorBorrar := FALSE;
                            
                        ELSE
                            #ErrorBorrar := TRUE;
                        END_IF;
                        
                        #s_EstadoBorrar := 0;
                        #s_OrdenBorrarHMI := FALSE;
                        #s_EtapaSiguiente := #ETAPA_0_REPOSO;
                        
                    END_REGION
                    
                    
                ELSE
                    
                    #s_EtapaSiguiente := #ETAPA_0_REPOSO;
                    
            END_CASE;
            
            #s_Etapa := #s_EtapaSiguiente;
            
        END_REGION LOGICA
        
        
    END_NETWORK
END_FUNCTION_BLOCK
