FUNCTION_BLOCK "FB15995_ZC_BUSCAR_DIR"
TITLE = FB15995_ZC_BUSCAR_DIR
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ABH
FAMILY : ZeusControl
VERSION : 1.0
//Bloque de funcion para comprobacion de direcciones configuradas en el sistema
   VAR 
      s_Buscar : Bool;   // Orden buscar
   END_VAR
   VAR RETAIN
      s_EntradaDigital : Struct
         Habilitar : Bool;
         Encontrada : Bool;
         NumeroByte : Int;
         NumeroBit : Int;
         Dispositivo : String;
      END_STRUCT;
      s_Salidadigital : Struct
         Habilitar : Bool;
         Encontrada : Bool;
         NumeroByte : Int;
         NumeroBit : Int;
         Dispositivo : String;
      END_STRUCT;
      s_EntradaAnalogica : Struct
         Habilitar : Bool;
         Encontrada : Bool;
         NumeroByte : Int;
         Dispositivo : String;
      END_STRUCT;
      s_SalidaAnalogica : Struct
         Habilitar : Bool;
         Encontrada : Bool;
         NumeroByte : Int;
         Dispositivo : String;
      END_STRUCT;
   END_VAR

   VAR_TEMP 
      for_i : Int;
      t_N_MAX_ED : Int;
      t_N_MAX_EA : Int;
      t_N_MAX_SD : Int;
      t_N_MAX_SA : Int;
      t_N_MAX_V : Int;
      t_N_MAX_M : Int;
      t_N_MAX_M_VF : Int;
      t_N_MAX_TOT : Int;
   END_VAR

   VAR CONSTANT 
      DISP_ED : String := 'ED-';
      DISP_EA : String := 'EA-';
      DISP_SD : String := 'SD-';
      DISP_SA : String := 'SA-';
      DISP_V : String := 'V-';
      DISP_M : String := 'M-';
      DISP_M_VF : String := 'M-VF-';
      DISP_TOT : String := 'TOT-';
   END_VAR


BEGIN
	REGION DESCRIPCION
	//=======================================================================
	// (C)Copyright ZeusControl 2023 - 2026
	//=======================================================================
	(*
	### Información del Sistema
	| Hardware Compatible | Entorno de Ingeniería |
	|---------------------|-----------------------|
	| PLC serie 1200/1500 | TIA Portal 18         |
	
	---
	### Descripción Funcional
	El bloque implementa un buscador de direccionamiento de E/S que, a partir de una dirección física (byte/bit para digitales o byte para analógicas), localiza todos los dispositivos del proyecto que la utilizan y devuelve una cadena de texto con la relación de los mismos. Es una herramienta de trazabilidad y diagnóstico que facilita al ingeniero la identificación rápida del uso de cada punto de E/S.
	
	Funcionalidades principales:
	- Búsqueda de entradas digitales (`s_EntradaDigital`): se le indica un byte y un bit, y el bloque recorre los dispositivos `ED` (Entradas Digitales), `V` (Válvulas), `M` (Motores), `M_VF` (Motores con Variador de Frecuencia) y `TOT` (Totalizados) comparando el byte/bit configurado en cada uno con el solicitado. Para las válvulas y motores también coteja los retornos de reposo y trabajo, así como el retorno de confirmación de marcha y térmico.
	- Búsqueda de entradas analógicas (`s_EntradaAnalogica`): se le indica un byte y el bloque recorre los dispositivos `EA` (Entradas Analógicas) comparando la dirección de entrada configurada.
	- Búsqueda de salidas digitales (`s_Salidadigital`): se le indica un byte y un bit, y el bloque recorre los dispositivos `SD` (Salidas Digitales), `V` (Válvulas), `M` (Motores) y `M_VF` (Motores con Variador de Frecuencia) comparando el byte/bit de salida configurado.
	- Búsqueda de salidas analógicas (`s_SalidaAnalogica`): se le indica un byte y el bloque recorre los dispositivos `SA` (Salidas Analógicas) y `M_VF` (Motores con Variador de Frecuencia, salida analógica de consigna) comparando la dirección de salida configurada.
	- En cada búsqueda se valida el rango del bit (entre 1 y 7) cuando aplica, y se construye la cadena de resultados concatenando el prefijo del tipo de dispositivo (`#DISP_ED`, `#DISP_V`, `#DISP_M`, `#DISP_M_VF`, `#DISP_TOT`, `#DISP_EA`, `#DISP_SD`, `#DISP_SA`) con el índice convertido a texto mediante `FC15001_ZC_INT_TO_STRING`, separando cada coincidencia con el carácter `;`.
	- Activación del flag `Encontrada` cuando existe al menos una coincidencia.
	- Inicialización de la estructura de resultados (`Encontrada := FALSE` y `Dispositivo := ''`) al inicio de cada búsqueda, y reseteo del bit fuera de rango.
	
	> **Restricciones:** Ninguna.
	
	---
	### Dependencias Requeridas
	| Tipo | Elementos |
	|------|-----------|
	| FC   | `FC15001_ZC_INT_TO_STRING` |
	| FB   | - |
	| DB   | `DB2000_ED`, `DB2001_EA`, `DB2005_SD`, `DB2006_SA`, `DB2010_V`, `DB2015_M`, `DB2016_M_VF`, `DB2025_TOT` |
	| UDT  | `ZC_DISP_ED`, `ZC_DISP_EA`, `ZC_DISP_SD`, `ZC_DISP_SA`, `ZC_DISP_V`, `ZC_DISP_M`, `ZC_DISP_M_VF`, `ZC_DISP_TOT` |
	    
	---
	### Historial de Cambios
	| Versión  | Fecha      | Técnico | Cambios |
	|----------|------------|---------|---------|
	| 00.00.01 | 12.09.2023 | (ABH)   | Primera version. |
	| 01.00.00 | 02.07.2026 | (ABH)   | Se añade orden "Buscar" para optimizacion de codigo. |
	*)
	END_REGION DESCRIPCION
	
	
	//  ==========================================================================================================
	REGION GESTION_ORDEN_BUSCAR
	    
	    //  Si no hay orden de buscar, salimos del bloque
	    IF NOT #s_Buscar THEN
	        RETURN;
	    END_IF;
	    
	END_REGION GESTION_ORDEN_BUSCAR
	
	
	//  ==========================================================================================================
	REGION TRASPASO_PARAMETROS_N_MAX
	    
	    #t_N_MAX_ED := "N_MAX_DISP_ED";
	    #t_N_MAX_EA := "N_MAX_DISP_EA";
	    #t_N_MAX_SD := "N_MAX_DISP_SD";
	    #t_N_MAX_SA := "N_MAX_DISP_SA";
	    #t_N_MAX_V := "N_MAX_DISP_V";
	    #t_N_MAX_M := "N_MAX_DISP_M";
	    #t_N_MAX_M_VF := "N_MAX_DISP_M_VF";
	    #t_N_MAX_TOT := "N_MAX_DISP_TOT";
	    
	END_REGION TRASPASO_PARAMETROS_N_MAX
	
	
	//  ==========================================================================================================
	REGION BUSQUEDA_ENTRADA_DIGITAL
	    
	    //  Reinicializacion de valores
	    #s_EntradaDigital.Encontrada := FALSE;
	    #s_EntradaDigital.Dispositivo := '';
	    
	    //  Solo buscamos si esta habilitado
	    IF #s_EntradaDigital.Habilitar THEN
	        
	        //  Limite de valores
	        IF #s_EntradaDigital.NumeroBit > 7 THEN
	            #s_EntradaDigital.NumeroBit := 7;
	        END_IF;
	        IF #s_EntradaDigital.NumeroBit < 1 THEN
	            #s_EntradaDigital.NumeroBit := 1;
	        END_IF;
	        
	        //  ================================================================================================
	        //  Busqueda en salida digital
	        IF #t_N_MAX_ED > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_ED DO
	                IF #s_EntradaDigital.NumeroByte = "DB2000_ED".ED[#for_i].Config_DirEntradaByte
	                    AND
	                    #s_EntradaDigital.NumeroBit = "DB2000_ED".ED[#for_i].Config_DirEntradaBit
	                THEN
	                    #s_EntradaDigital.Encontrada := TRUE;
	                    #s_EntradaDigital.Dispositivo := CONCAT_STRING(IN1 := #s_EntradaDigital.Dispositivo, IN2 := #DISP_ED, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	        //  ================================================================================================
	        //  Busqueda en valvula
	        IF #t_N_MAX_V > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_V DO
	                IF (#s_EntradaDigital.NumeroByte = "DB2010_V".V[#for_i].Config_DireccionRetReposoByte
	                    AND
	                    #s_EntradaDigital.NumeroBit = "DB2010_V".V[#for_i].Config_DireccionRetReposoBit)
	                    OR
	                    (#s_EntradaDigital.NumeroByte = "DB2010_V".V[#for_i].Config_DireccionRetTrabajoByte
	                    AND
	                    #s_EntradaDigital.NumeroBit = "DB2010_V".V[#for_i].Config_DireccionRetTrabajoBit)
	                THEN
	                    #s_EntradaDigital.Encontrada := TRUE;
	                    #s_EntradaDigital.Dispositivo := CONCAT_STRING(IN1 := #s_EntradaDigital.Dispositivo, IN2 := #DISP_V, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	        //  ================================================================================================
	        //  Busqueda en motor
	        IF #t_N_MAX_M > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_M DO
	                IF (#s_EntradaDigital.NumeroByte = "DB2015_M".M[#for_i].Config_DireccionRetConfMarchaByte
	                    AND
	                    #s_EntradaDigital.NumeroBit = "DB2015_M".M[#for_i].Config_DireccionRetConfMarchaBit)
	                    OR
	                    (#s_EntradaDigital.NumeroByte = "DB2015_M".M[#for_i].Config_DireccionRetTermicoByte
	                    AND
	                    #s_EntradaDigital.NumeroBit = "DB2015_M".M[#for_i].Config_DireccionRetTermicoBit)
	                THEN
	                    #s_EntradaDigital.Encontrada := TRUE;
	                    #s_EntradaDigital.Dispositivo := CONCAT_STRING(IN1 := #s_EntradaDigital.Dispositivo, IN2 := #DISP_M, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	        //  ================================================================================================
	        //  Busqueda en motor variador
	        IF #t_N_MAX_M_VF > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_M_VF DO
	                IF (#s_EntradaDigital.NumeroByte = "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetConfMarchaByte
	                    AND
	                    #s_EntradaDigital.NumeroBit = "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetConfMarchaBit)
	                    OR
	                    (#s_EntradaDigital.NumeroByte = "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetTermicoByte
	                    AND
	                    #s_EntradaDigital.NumeroBit = "DB2016_M_VF".M_VF[#for_i].Config_DireccionRetTermicoBit)
	                THEN
	                    #s_EntradaDigital.Encontrada := TRUE;
	                    #s_EntradaDigital.Dispositivo := CONCAT_STRING(IN1 := #s_EntradaDigital.Dispositivo, IN2 := #DISP_M_VF, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	        //  ================================================================================================
	        //  Busqueda en totalizador
	        IF #t_N_MAX_TOT > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_TOT DO
	                IF #s_EntradaDigital.NumeroByte = "DB2025_TOT".TOT[#for_i].Config_DireccionEntradaByte
	                    AND
	                    #s_EntradaDigital.NumeroBit = "DB2025_TOT".TOT[#for_i].Config_DireccionEntradaBit
	                THEN
	                    #s_EntradaDigital.Encontrada := TRUE;
	                    #s_EntradaDigital.Dispositivo := CONCAT_STRING(IN1 := #s_EntradaDigital.Dispositivo, IN2 := #DISP_TOT, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	    END_IF;
	    
	    
	END_REGION BUSQUEDA_ENTRADA_DIGITAL
	
	
	//  ==========================================================================================================
	REGION BUSQUEDA_ENTRADA_ANALOGICA
	    
	    //  Reinicializacion de valores
	    #s_EntradaAnalogica.Encontrada := FALSE;
	    #s_EntradaAnalogica.Dispositivo := '';
	    
	    //  Solo buscamos si esta habilitado
	    IF #s_EntradaAnalogica.Habilitar THEN
	        
	        //  ================================================================================================
	        //  Busqueda en entrada analogica
	        IF #t_N_MAX_EA > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_EA DO
	                IF #s_EntradaAnalogica.NumeroByte = "DB2001_EA".EA[#for_i].Config_DireccionEntradaByte
	                THEN
	                    #s_EntradaAnalogica.Encontrada := TRUE;
	                    #s_EntradaAnalogica.Dispositivo := CONCAT_STRING(IN1 := #s_EntradaAnalogica.Dispositivo, IN2 := #DISP_EA, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	    END_IF;
	    
	    
	END_REGION BUSQUEDA_ENTRADA_ANALOGICA
	
	
	//  ==========================================================================================================
	REGION BUSQUEDA_SALIDA_DIGITAL
	    
	    //  Reinicializacion de valores
	    #s_Salidadigital.Encontrada := FALSE;
	    #s_Salidadigital.Dispositivo := '';
	    
	    //  Solo buscamos si esta habilitado
	    IF #s_Salidadigital.Habilitar THEN
	        
	        //  Limite de valores
	        IF #s_Salidadigital.NumeroBit > 7 THEN
	            #s_Salidadigital.NumeroBit := 7;
	        END_IF;
	        IF #s_Salidadigital.NumeroBit < 1 THEN
	            #s_Salidadigital.NumeroBit := 1;
	        END_IF;
	        
	        //  ================================================================================================
	        //  Busqueda en salida digital
	        IF #t_N_MAX_SD > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_SD DO
	                IF #s_Salidadigital.NumeroByte = "DB2005_SD".SD[#for_i].Config_DireccionSalidaByte
	                    AND
	                    #s_Salidadigital.NumeroBit = "DB2005_SD".SD[#for_i].Config_DireccionSalidaBit
	                THEN
	                    #s_Salidadigital.Encontrada := TRUE;
	                    #s_Salidadigital.Dispositivo := CONCAT_STRING(IN1 := #s_Salidadigital.Dispositivo, IN2 := #DISP_SD, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	        //  ================================================================================================
	        //  Busqueda en valvula
	        IF #t_N_MAX_V > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_V DO
	                IF #s_Salidadigital.NumeroByte = "DB2010_V".V[#for_i].Config_DireccionSalidaByte
	                    AND
	                    #s_Salidadigital.NumeroBit = "DB2010_V".V[#for_i].Config_DireccionSalidaBit
	                THEN
	                    #s_Salidadigital.Encontrada := TRUE;
	                    #s_Salidadigital.Dispositivo := CONCAT_STRING(IN1 := #s_Salidadigital.Dispositivo, IN2 := #DISP_V, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	        //  ================================================================================================
	        //  Busqueda en motor
	        IF #t_N_MAX_M > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_M DO
	                IF #s_Salidadigital.NumeroByte = "DB2015_M".M[#for_i].Config_DireccionSalidaByte
	                    AND
	                    #s_Salidadigital.NumeroBit = "DB2015_M".M[#for_i].Config_DireccionSalidaBit
	                THEN
	                    #s_Salidadigital.Encontrada := TRUE;
	                    #s_Salidadigital.Dispositivo := CONCAT_STRING(IN1 := #s_Salidadigital.Dispositivo, IN2 := #DISP_M, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        //  ================================================================================================
	        //  Busqueda en motor variador
	        IF #t_N_MAX_M_VF > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_M_VF DO
	                IF #s_Salidadigital.NumeroByte = "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaByte
	                    AND
	                    #s_Salidadigital.NumeroBit = "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaBit
	                THEN
	                    #s_Salidadigital.Encontrada := TRUE;
	                    #s_Salidadigital.Dispositivo := CONCAT_STRING(IN1 := #s_Salidadigital.Dispositivo, IN2 := #DISP_M_VF, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	    END_IF;
	    
	    
	END_REGION BUSQUEDA_SALIDA_DIGITAL
	
	
	//  ==========================================================================================================
	REGION BUSQUEDA_SALIDA_ANALOGICA
	    
	    //  Reinicializacion de valores
	    #s_SalidaAnalogica.Encontrada := FALSE;
	    #s_SalidaAnalogica.Dispositivo := '';
	    
	    //  Solo buscamos si esta habilitado
	    IF #s_SalidaAnalogica.Habilitar THEN
	        
	        //  ================================================================================================
	        //  Busqueda en salida analogica
	        IF #t_N_MAX_SA > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_SA DO
	                IF #s_SalidaAnalogica.NumeroByte = "DB2006_SA".SA[#for_i].Config_DireccionSalidaByte
	                THEN
	                    #s_SalidaAnalogica.Encontrada := TRUE;
	                    #s_SalidaAnalogica.Dispositivo := CONCAT_STRING(IN1 := #s_SalidaAnalogica.Dispositivo, IN2 := #DISP_SA, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	        //  ================================================================================================
	        //  Busqueda en motor variador
	        IF #t_N_MAX_M_VF > 0 THEN
	            FOR #for_i := 1 TO #t_N_MAX_M_VF DO
	                IF #s_SalidaAnalogica.NumeroByte = "DB2016_M_VF".M_VF[#for_i].Config_DireccionSalidaAnalogicaByte
	                THEN
	                    #s_SalidaAnalogica.Encontrada := TRUE;
	                    #s_SalidaAnalogica.Dispositivo := CONCAT_STRING(IN1 := #s_SalidaAnalogica.Dispositivo, IN2 := #DISP_M_VF, IN3 := "FC15001_ZC_INT_TO_STRING"(#for_i), IN4 := ';');
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	    END_IF;
	    
	END_REGION BUSQUEDA_SALIDA_ANALOGICA
	
	
	//  ==========================================================================================================
	REGION RESET_ORDENES
	    
	    //  Reset orden buscar
	    #s_Buscar := FALSE;
	    
	END_REGION RESET_ORDENES
	
END_FUNCTION_BLOCK

