From a82ef44fb8eb4a26160df428adf8b109c4c87a7a Mon Sep 17 00:00:00 2001 From: Miguel Date: Sat, 17 May 2025 14:06:22 +0200 Subject: [PATCH] Add x4.py for S7 source code generation and documentation - Implemented functions to format data types, generate variable declarations, and create S7 source code from JSON data. - Added recursive functions to handle STRUCTs and UDTs, including generating assignments for the BEGIN block. - Created a Markdown documentation generator for DBs. - Enhanced error handling and logging in x3.py, addressing issues with missing attributes in the DB_Parser module. - Updated log.txt to reflect the execution flow and errors encountered during the process. --- .../script_groups/S7_DB_Utils/DB_Parser.py | 808 +++++ backend/script_groups/S7_DB_Utils/data.json | 1 + .../script_groups/S7_DB_Utils/db1001_data.db | 550 +++ .../S7_DB_Utils/db1001_format.csv | 467 +++ .../S7_DB_Utils/db1001_format.db.txt | 557 +++ .../S7_DB_Utils/description.json | 6 + ...documentation_db_HMI_Blender_Parameters.md | 208 ++ .../S7_DB_Utils/esquema_group.json | 4 + .../S7_DB_Utils/esquema_work.json | 4 + backend/script_groups/S7_DB_Utils/log_x1.txt | 28 + backend/script_groups/S7_DB_Utils/log_x2.txt | 37 + backend/script_groups/S7_DB_Utils/log_x3.txt | 51 + .../S7_DB_Utils/parsed_s7_data_expanded.json | 3056 +++++++++++++++++ backend/script_groups/S7_DB_Utils/readme.md | 77 + .../reconstructed_s7_source_v2.txt | 521 +++ .../S7_DB_Utils/script_config.json | 9 + .../S7_DB_Utils/scripts_description.json | 26 + .../script_groups/S7_DB_Utils/work_dir.json | 6 + backend/script_groups/S7_DB_Utils/x1.py | 497 +++ backend/script_groups/S7_DB_Utils/x2.py | 335 ++ backend/script_groups/S7_DB_Utils/x3.py | 533 +++ backend/script_groups/S7_DB_Utils/x4.py | 303 ++ data/log.txt | 52 +- 23 files changed, 8126 insertions(+), 10 deletions(-) create mode 100644 backend/script_groups/S7_DB_Utils/DB_Parser.py create mode 100644 backend/script_groups/S7_DB_Utils/data.json create mode 100644 backend/script_groups/S7_DB_Utils/db1001_data.db create mode 100644 backend/script_groups/S7_DB_Utils/db1001_format.csv create mode 100644 backend/script_groups/S7_DB_Utils/db1001_format.db.txt create mode 100644 backend/script_groups/S7_DB_Utils/description.json create mode 100644 backend/script_groups/S7_DB_Utils/documentation_db_HMI_Blender_Parameters.md create mode 100644 backend/script_groups/S7_DB_Utils/esquema_group.json create mode 100644 backend/script_groups/S7_DB_Utils/esquema_work.json create mode 100644 backend/script_groups/S7_DB_Utils/log_x1.txt create mode 100644 backend/script_groups/S7_DB_Utils/log_x2.txt create mode 100644 backend/script_groups/S7_DB_Utils/log_x3.txt create mode 100644 backend/script_groups/S7_DB_Utils/parsed_s7_data_expanded.json create mode 100644 backend/script_groups/S7_DB_Utils/readme.md create mode 100644 backend/script_groups/S7_DB_Utils/reconstructed_s7_source_v2.txt create mode 100644 backend/script_groups/S7_DB_Utils/script_config.json create mode 100644 backend/script_groups/S7_DB_Utils/scripts_description.json create mode 100644 backend/script_groups/S7_DB_Utils/work_dir.json create mode 100644 backend/script_groups/S7_DB_Utils/x1.py create mode 100644 backend/script_groups/S7_DB_Utils/x2.py create mode 100644 backend/script_groups/S7_DB_Utils/x3.py create mode 100644 backend/script_groups/S7_DB_Utils/x4.py diff --git a/backend/script_groups/S7_DB_Utils/DB_Parser.py b/backend/script_groups/S7_DB_Utils/DB_Parser.py new file mode 100644 index 0000000..407e4f0 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/DB_Parser.py @@ -0,0 +1,808 @@ +import re +import os +import pandas as pd +import tkinter as tk +from tkinter import filedialog +import subprocess +from openpyxl import Workbook, load_workbook +from openpyxl.utils import get_column_letter +from openpyxl.styles import Alignment, Font, Border, Side, PatternFill +from copy import deepcopy + +# Constantes para los tamaños de tipos de datos +TYPE_SIZES = { + "Byte": 1, + "Char": 1, + "Int": 2, + "DInt": 4, + "Word": 2, + "DWord": 4, + "Real": 4, + "Date": 2, + "Time": 4, + "Time_Of_Day": 4, + "S5Time": 2, + "Bool": 0.125, # 1 bit, normalmente agrupado en 8 bits = 1 Byte + "String": 256, # String[256] serían 258 bytes (256 caracteres + 2 para longitud) + "WString": 512, + "LReal": 8, # Punto flotante de doble precisión + "UDInt": 4, # Entero sin signo de 32 bits + "USInt": 1, # Entero sin signo de 8 bits (Byte) + "UInt": 2, # Entero sin signo de 16 bits (Word) + "ULInt": 8, # Entero sin signo de 64 bits (Doble DWord) + "LWord": 8, # Entero sin signo de 64 bits (Doble DWord) + "LInt": 8, # Entero con signo de 64 bits + "Date_And_Time": 8, # Fecha y hora combinadas, 8 bytes + "DTL": 12, # Date and time long (fecha, hora y precisión a microsegundos, 12 bytes) +} + +#================================= +# FUNCIONES DE PARSEO DE ARCHIVOS +#================================= + +def clean_line(line): + """Limpia la línea de BOM y espacios o comillas extra.""" + # Elimina UTF-8 BOM si existe y elimina espacios iniciales/finales + line = line.replace("\ufeff", "").strip() + # Estandariza las definiciones TYPE y DATA_BLOCK + line = re.sub(r'\s*TYPE\s+"?', 'TYPE "', line) + line = re.sub(r'\s*DATA_BLOCK\s+"?', 'DATA_BLOCK "', line) + line = remove_text_inside_brackets(line) + return line + +def remove_text_inside_brackets(text): + """Elimina texto dentro de corchetes.""" + pattern = r"\{.*?\}" + cleaned_text = re.sub(pattern, '', text) + return cleaned_text + +def extract_name(line): + """Extrae el nombre de una línea de definición TYPE o DATA_BLOCK.""" + # Intenta encontrar un nombre entrecomillado primero + match = re.search(r'(TYPE|DATA_BLOCK)\s+"([^"]+)"', line) + if match: + return match.group(2).strip() # El nombre está entre comillas + + # Si no hay nombre entrecomillado, busca un nombre sin comillas + match = re.search(r"(TYPE|DATA_BLOCK)\s+(\S+)", line) + if match: + return match.group(2).strip() # El nombre está sin comillas + +def parse_udts(lines): + """Parsea User Defined Types de las líneas de código.""" + udt_json = {} + udt_name = None + nested_structs = [] + current_struct = None + is_within_struct = False + + for line in lines: + line = clean_line(line) + if "TYPE" in line and "END_TYPE" not in line: + udt_name = extract_name(line) + udt_json[udt_name] = {} + current_struct = udt_json[udt_name] + print(f"Creado UDT: {udt_name}") + elif "END_TYPE" in line: + print(f"Completado UDT: {udt_name}") + udt_name = None + nested_structs = [] + current_struct = None + is_within_struct = False + elif "STRUCT" in line and "END_STRUCT" not in line and udt_name is not None: + struct_name = ( + "Struct" if "STRUCT" == line.strip() else line.split(":")[0].strip() + ) + new_struct = {} + current_struct[struct_name] = new_struct + nested_structs.append(current_struct) + current_struct = new_struct + is_within_struct = True + print(f"Creado STRUCT: {struct_name}") + elif "END_STRUCT" in line and udt_name is not None: + current_struct = nested_structs.pop() if nested_structs else None + is_within_struct = bool(nested_structs) + print(f"Cerrado STRUCT en UDT '{udt_name}'") + elif udt_name and ":" in line and is_within_struct: + parts = line.split(":") + field_name = parts[0].strip() + field_details = parts[1].strip().split("//") + field_type = ( + field_details[0].replace(";", "").strip() + ) # Eliminando ';' del tipo de campo + field_comment = parts[1].split("//")[1].strip() if "//" in parts[1] else "" + if "Struct" in field_type: + new_struct = {} + current_struct[field_name] = new_struct + nested_structs.append(current_struct) + current_struct = new_struct + print(f"Abierto STRUCT en línea en el campo '{field_name}'") + else: + current_struct[field_name] = { + "type": field_type, + "comment": field_comment, + } + print( + f"Añadido campo '{field_name}' a STRUCT: Tipo={field_type}, Comentario={field_comment}" + ) + + return udt_json + +def parse_dbs(lines, udts): + """Parsea Data Blocks de las líneas de código.""" + db_json = {} + db_name = None + nested_structs = [] + current_struct = None + is_within_struct = False + + for line in lines: + line = clean_line(line) + if "DATA_BLOCK" in line and "END_DATA_BLOCK" not in line: + db_name = extract_name(line) + db_json[db_name] = {} + current_struct = db_json[db_name] + print(f"Creado DATA_BLOCK: {db_name}") + elif "END_DATA_BLOCK" in line: + print(f"Completado DATA_BLOCK: {db_name}") + db_name = None + nested_structs = [] + current_struct = None + is_within_struct = False + elif "STRUCT" in line and "END_STRUCT" not in line and db_name is not None: + struct_name = ( + "Struct" if "STRUCT" == line.strip() else line.split(":")[0].strip() + ) + new_struct = {} + current_struct[struct_name] = new_struct + nested_structs.append(current_struct) + current_struct = new_struct + is_within_struct = True + print(f"Creado STRUCT en DB '{db_name}': {struct_name}") + elif "END_STRUCT" in line and db_name is not None: + current_struct = nested_structs.pop() if nested_structs else None + is_within_struct = bool(nested_structs) + print(f"Cerrado STRUCT en DB '{db_name}'") + elif db_name and ":" in line and is_within_struct: + parts = line.split(":") + field_name = parts[0].strip() + field_details = parts[1].strip().split("//") + field_type = ( + field_details[0].replace(";", "").strip() + ) # Eliminando ';' del tipo de campo + field_comment = parts[1].split("//")[1].strip() if "//" in parts[1] else "" + if "Struct" in field_type: + new_struct = {} + current_struct[field_name] = new_struct + nested_structs.append(current_struct) + current_struct = new_struct + print(f"Abierto STRUCT en línea en el campo '{field_name}' en DB '{db_name}'") + else: + current_struct[field_name] = { + "type": field_type, + "comment": field_comment, + } + print( + f"Añadido campo '{field_name}' a STRUCT en DB '{db_name}': Tipo={field_type}, Comentario={field_comment}" + ) + + return db_json + +#================================= +# FUNCIONES DE EXPANSIÓN DE UDT +#================================= + +def expand_udt_references(db_struct, udts): + """ + Expande recursivamente las referencias UDT en la estructura DB utilizando las definiciones UDT. + """ + if isinstance(db_struct, dict): + for key, value in list(db_struct.items()): + if isinstance(value, dict): + # Recursión en diccionarios + expand_udt_references(value, udts) + elif isinstance(value, str) and key == "type": # Solo expande campos 'type' + type_name = value.strip( + '"' + ) # Elimina comillas que pueden envolver nombres UDT con espacios + if type_name in udts: + # Reemplaza la referencia UDT con su definición copiada en profundidad + db_struct["is_udt_definition"] = True + db_struct["fields"] = deepcopy(udts[type_name]) + + print(f"Expandido UDT '{type_name}' en el campo '{key}'") + elif isinstance(db_struct, list): + for item in db_struct: + expand_udt_references(item, udts) + +def handle_array_types(db_struct): + """ + Maneja tipos de arrays para expandirlos en múltiples campos como sub-elementos. + Esta función procesa completamente los arrays expandiéndolos en elementos individuales. + """ + if isinstance(db_struct, dict): + # Lista para almacenar nuevas entradas de array a agregar + new_entries = {} + # Lista de claves a eliminar después de procesar + keys_to_remove = [] + + for key, value in list(db_struct.items()): + if isinstance(value, dict): + # Procesa recursivamente diccionarios anidados + handle_array_types(value) + + # Verificar si es un tipo array + if "type" in value and isinstance(value["type"], str): + array_match = re.match(r"ARRAY\s*\[(\d+)\s*\.\.\s*(\d+)\]\s*OF\s*(\w+)", value["type"], re.IGNORECASE) + if array_match: + lower_bound = int(array_match.group(1)) + upper_bound = int(array_match.group(2)) + base_type = array_match.group(3).strip() + comment = value.get("comment", "") + + print(f"Expandiendo array '{key}': {lower_bound}..{upper_bound} of {base_type}") + + # Marcar para eliminar la definición original después + keys_to_remove.append(key) + + # Crear entrada para la definición del array + new_entries[key] = { + "type": f"Array[{lower_bound}..{upper_bound}] of {base_type}", + "comment": comment, + "is_array_definition": True + } + + # Crear elementos individuales del array + for i in range(lower_bound, upper_bound + 1): + array_key = f"{key}[{i}]" + new_entries[array_key] = { + "type": base_type, + "comment": comment, + "is_array_element": True + } + + # Eliminar los originales y agregar los nuevos + for key in keys_to_remove: + if key in db_struct: + del db_struct[key] + + # Agregar las nuevas entradas + db_struct.update(new_entries) + +def expand_dbs(udts, dbs): + """ + Expande todas las referencias UDT en todos los DBs y luego maneja tipos de arrays. + """ + for db_name, db_content in dbs.items(): + print(f"Expandiendo DB: {db_name}") + # Primero expandir las referencias UDT + expand_udt_references(db_content, udts) + + # Luego, manejar y expandir los tipos de arrays + print(f"Procesando arrays en DB: {db_name}") + handle_array_types(db_content) + + print(f"Completada expansión para DB: {db_name}") + + # Registrar el resultado de la expansión para depuración + print("\nEstructura DB después de la expansión:") + for db_name, db_content in dbs.items(): + print(f"DB: {db_name} - Número de campos: {count_fields(db_content)}") + +def count_fields(struct): + """Función auxiliar para contar campos en una estructura.""" + count = 0 + if isinstance(struct, dict): + for key, value in struct.items(): + if isinstance(value, dict): + if "type" in value: + count += 1 + else: + count += count_fields(value) + return count + +#================================= +# FUNCIONES DE CÁLCULO DE OFFSET +#================================= + +def calculate_plc_address(type_name, byte_offset): + """ + Calcula la notación de dirección PLC basada en el tipo y offset. + """ + byte_size = TYPE_SIZES.get(type_name, 0) + bit_offset = int((byte_offset - int(byte_offset)) * 8) + byte_offset = int(byte_offset) + if type_name == "Bool": + return f"DBX{byte_offset}.{bit_offset}" # Dirección para bits individuales + elif type_name == "Byte": + return f"DBB{byte_offset}" # Dirección para bytes individuales + elif byte_size == 2: + return f"DBW{byte_offset}" # Dirección para words de dos bytes + elif byte_size == 4: + return f"DBD{byte_offset}" # Dirección para double words de cuatro bytes + else: + return f"DBX{byte_offset}.0" # Por defecto a dirección de bit para tipos de más de 4 bytes + +def calculate_plc_size(size): + """Calcula la representación del tamaño PLC.""" + byte_size = size + bit_offset = int((size - int(size)) * 8) + size = int(size) + if bit_offset > 0: + return f"{size}.{bit_offset}" + else: + return f"{size}" + +class OffsetState: + """Clase para mantener el estado durante el cálculo de offset.""" + def __init__(self): + self.last_key_was_bool = False + self.last_bit_offset = 0 # Para rastrear offsets de bit dentro de un byte + self.current_offset = 0 + +def calculate_offsets(value, state, field_name="unknown"): + """Calcula offsets de memoria para elementos DB.""" + type_name = value["type"].strip() # Eliminar espacios en blanco + is_array_element = value.get("is_array_element", False) + is_array_definition = value.get("array_definition", False) + is_udt_definition = value.get("is_udt_definition", False) + + # No calculamos offsets para definiciones de array, solo para sus elementos + if is_array_definition: + print(f"→ Definición de array '{field_name}': no calculando offset") + return state + + print(f"Calculando offset para '{field_name}' (Tipo: {type_name}, Offset actual: {state.current_offset})") + + if state.last_key_was_bool: + is_array_element = True + size = 0 + + # Alineación a boundaries de datos + if not is_array_element: + if state.current_offset % 2 != 0: + old_offset = state.current_offset + state.current_offset += 1 # Alinea al siguiente offset par si no es elemento de array + print(f" → Alineación: Offset ajustado de {old_offset} a {state.current_offset}") + + # Ajustando tamaños Bool basados en agrupación + if type_name.upper() == "BOOL": + state.last_key_was_bool = True + size += 1 / 8 + print(f" → Tipo Bool detectado: usando {size} bytes") + + else: + if state.last_key_was_bool: # Después de bools + state.last_key_was_bool = False # No es Bool + if ( + state.last_bit_offset > 0 + or int(state.current_offset) != state.current_offset + ): + state.last_bit_offset = 0 + old_offset = state.current_offset + state.current_offset = int(state.current_offset) + 1 + print(f" → Post-Bool: Ajustando offset de {old_offset} a {state.current_offset}") + + if state.current_offset % 2 != 0: + old_offset = state.current_offset + state.current_offset += 1 # Alinea al siguiente offset par + print(f" → Post-Bool: Alineación a par: {old_offset} → {state.current_offset}") + + # Manejo especial para tipos String + if type_name.upper().startswith("STRING"): + match = re.match(r"String\[(\d+)\]", type_name, re.IGNORECASE) + state.last_bit_offset = 0 + if match: + length = int(match.group(1)) + size = length + 2 # Cuenta para terminación nula y prefijo de longitud de cadena + print(f" → String[{length}] detectado: usando {size} bytes") + else: + size = TYPE_SIZES.get("String", 0) # Tamaño estándar para strings + print(f" → String genérico detectado: usando {size} bytes") + + else: # Otros Tipos de Datos + # Buscar el tipo ignorando mayúsculas/minúsculas + type_upper = type_name.upper() + type_size = None + for key, value_size in TYPE_SIZES.items(): + if key.upper() == type_upper: + type_size = value_size + break + + if type_size is not None: + size = type_size + print(f" → Tipo {type_name} encontrado: usando {size} bytes") + else: + print(f" → ADVERTENCIA: Tipo {type_name} no reconocido directamente") + # Para arrays, manejo especial + if "ARRAY" in type_upper: + print(f" → Array detectado pero no se procesa directamente aquí") + size = 0 # Los arrays se procesarán elemento por elemento + else: + size = 2 # Asumimos INT por defecto + print(f" → Asumiendo tamaño de 2 bytes como valor predeterminado para {type_name}") + + if size == 0 and not is_array_definition and not is_udt_definition: + print(f"⚠️ ADVERTENCIA: Tipo '{type_name}' tiene tamaño cero. Asumiendo 2 bytes.") + size = 2 # Tamaño mínimo + + # Calcular dirección PLC + plc_address = calculate_plc_address(type_name, state.current_offset) + value["offset"] = state.current_offset + value["plc_address"] = plc_address # Almacena la dirección PLC calculada + value["size"] = calculate_plc_size(size) + + # Actualizar offset y mostrar resultado + old_offset = state.current_offset + state.current_offset += size + print(f" → Resultado: Dirección={plc_address}, Tamaño={size}, Nuevo offset={state.current_offset}") + + return state + +def collect_data_for_table(db_struct, offset_state, level=0, parent_prefix="", collected_data=None, relative_offset=0): + """ + Recoge datos recursivamente de la estructura DB para mostrar en formato tabular. + Añade soporte para offsets relativos dentro de estructuras. + """ + if collected_data is None: + collected_data = [] + + is_array_element = False + increase_level = 0 + current_struct_base = offset_state.current_offset + + if isinstance(db_struct, dict): + for key, value in db_struct.items(): + # Omite claves 'fields' y 'Struct' en la ruta de nombre + if key == "fields" or key == "Struct": + next_prefix = parent_prefix # Continúa con el prefijo actual + collect_data_for_table(value, offset_state, level, next_prefix, collected_data, relative_offset) + continue + + # Determinar el prefijo de nombre para este elemento + if isinstance(value, dict): + is_array_element = value.get("is_array_element", False) + is_array_definition = value.get("array_definition", False) + + # Construir el nombre del campo + if not is_array_element: + next_prefix = f"{parent_prefix}.{key}" if parent_prefix else key + else: + next_prefix = f"{parent_prefix}{key}" if parent_prefix else key + + # Si es una definición de array, añadirla a la tabla sin calcular offset + if isinstance(value, dict) and value.get("array_definition", False): + field_data = { + "Nombre": next_prefix, + "Tipo": value.get("type", "N/A"), + "Offset": relative_offset, + "Dirección PLC": "N/A", + "Comentario": value.get("comment", ""), + } + collected_data.append(field_data) + print(f"✓ Añadida definición de array: {next_prefix} - (sin dirección)") + + # No incrementar offset para definiciones de array, continuar con siguiente elemento + continue + + # Procesar campo normal con tipo + if isinstance(value, dict) and "type" in value: + # Calcular offset si no es una definición de array + if not value.get("array_definition", False): + # Pasar el nombre del campo para mejorar los logs + offset_state = calculate_offsets(value, offset_state, field_name=next_prefix) + + # Calcular offset relativo si es necesario + element_relative_offset = value.get("offset", 0) - current_struct_base + if is_array_element: + element_relative_offset = value.get("offset", 0) - offset_state.current_offset + relative_offset + + field_data = { + "Nombre": next_prefix, + "Tipo": value.get("type", "N/A"), + "Offset": element_relative_offset if is_array_element else value.get("offset", 0), + "Dirección PLC": value.get("plc_address", "N/A"), + "Comentario": value.get("comment", ""), + } + collected_data.append(field_data) + increase_level = 1 + print(f"✓ Añadido a tabla: {next_prefix} - {value.get('plc_address', 'N/A')}") + + # Maneja recursivamente diccionarios y listas anidados + if isinstance(value, dict) and not "type" in value: + new_relative = offset_state.current_offset if not is_array_element else relative_offset + collect_data_for_table( + value, + offset_state, + level + increase_level, + next_prefix, + collected_data, + new_relative + ) + elif isinstance(db_struct, list): + for index, item in enumerate(db_struct): + item_prefix = f"{parent_prefix}[{index}]" if parent_prefix else f"[{index}]" + collect_data_for_table( + item, offset_state, level + increase_level, item_prefix, collected_data, relative_offset + ) + + return collected_data + +def initiate_conversion_to_table(db_struct): + """Inicia el proceso de conversión con un estado de offset nuevo.""" + offset_state = OffsetState() + return collect_data_for_table(db_struct, offset_state) + +def convert_to_table(dbs): + """ + Convierte los datos DB recogidos en un DataFrame de pandas. + """ + all_data = [] + for db_name, db_content in dbs.items(): + print(f"Procesando DB: {db_name}") + db_data = initiate_conversion_to_table(db_content) + all_data.extend(db_data) + + df = pd.DataFrame(all_data) + # Reordenar las columnas al formato deseado + if not df.empty and all(col in df.columns for col in ["Nombre", "Tipo", "Offset", "Dirección PLC", "Comentario"]): + df = df[["Nombre", "Tipo", "Offset", "Dirección PLC", "Comentario"]] + return df + +#================================= +# FUNCIONES DE EXCEL +#================================= + +def format_excel_worksheet(worksheet): + """ + Formatea la hoja de cálculo de Excel con estilos profesionales. + """ + # Definir estilos + header_font = Font(name='Arial', size=11, bold=True, color="FFFFFF") + header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") + array_fill = PatternFill(start_color="E2EFDA", end_color="E2EFDA", fill_type="solid") + struct_fill = PatternFill(start_color="DEEBF7", end_color="DEEBF7", fill_type="solid") + thin_border = Border( + left=Side(style='thin'), + right=Side(style='thin'), + top=Side(style='thin'), + bottom=Side(style='thin') + ) + + # Aplicar estilos a la fila de encabezado + for cell in worksheet[1]: + cell.font = header_font + cell.fill = header_fill + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = thin_border + + # Obtener el número de filas y columnas + max_row = worksheet.max_row + max_col = worksheet.max_column + + # Aplicar estilos a las filas de datos + for row in range(2, max_row + 1): + # Verificar si es una estructura o array + cell_name = worksheet.cell(row=row, column=1).value if worksheet.cell(row=row, column=1).value else "" + cell_type = worksheet.cell(row=row, column=2).value if worksheet.cell(row=row, column=2).value else "" + + # Aplicar fondos especiales para estructuras y arrays + is_struct = "Struct" in str(cell_type) + is_array = "Array" in str(cell_type) + + # Aplicar bordes y alineación a todas las celdas + for col in range(1, max_col + 1): + cell = worksheet.cell(row=row, column=col) + cell.border = thin_border + + # Aplicar color de fondo según el tipo + if is_struct: + cell.fill = struct_fill + elif is_array: + cell.fill = array_fill + + # Centrar columnas numéricas + if col in [3, 4]: + cell.alignment = Alignment(horizontal='center') + + # Ajustar ancho de columnas + column_widths = { + 1: 30, # Nombre + 2: 15, # Tipo + 3: 10, # Offset + 4: 15, # Dirección PLC + 5: 30 # Comentario + } + + # Importamos get_column_letter directamente de openpyxl.utils en las importaciones del script + for col_num, width in column_widths.items(): + if col_num <= max_col: + worksheet.column_dimensions[get_column_letter(col_num)].width = width + + # Congelar la fila del encabezado + worksheet.freeze_panes = "A2" + +def save_dataframe_to_excel(df, filename, sheet_name): + """ + Guarda el DataFrame proporcionado en un archivo Excel y lo formatea. + """ + # Guardar el DataFrame en Excel + df.to_excel(filename, index=False, sheet_name=sheet_name) + print(f"Datos guardados en {filename}") + + # Abrir el archivo Excel guardado para aplicar formato + workbook = load_workbook(filename) + worksheet = workbook[sheet_name] + + # Aplicar formato a la hoja de cálculo + format_excel_worksheet(worksheet) + + # Guardar el libro de trabajo formateado + workbook.save(filename) + print(f"Formato aplicado a {filename}") + + return workbook, worksheet + +#================================= +# FUNCIONES DE UTILIDAD DE ARCHIVOS +#================================= + +def select_file(): + """ + Abre un diálogo de archivo para seleccionar un archivo .db y devuelve la ruta del archivo seleccionado. + """ + root = tk.Tk() + root.withdraw() # Oculta la ventana raíz de tkinter + + # Abre el diálogo de archivo y devuelve la ruta del archivo seleccionado + file_path = filedialog.askopenfilename( + title="Selecciona un archivo .db", + filetypes=(("Archivos DB", "*.db"), ("Todos los archivos", "*.*")) + ) + return file_path + +def extract_file_details(file_path): + """ + Extrae y devuelve el nombre del archivo sin extensión, la extensión del archivo y la ruta del archivo. + """ + # Extrae la ruta completa del directorio + path_only = os.path.dirname(file_path) + + # Extrae el nombre completo del archivo con extensión + full_file_name = os.path.basename(file_path) + + # Separa la extensión del nombre del archivo + file_name_without_extension, file_extension = os.path.splitext(full_file_name) + + return (file_name_without_extension, file_extension, path_only) + +def build_file_path(base_path, file_name, extension): + """ + Construye una ruta de archivo completa dada una ruta base, un nombre de archivo y una extensión. + """ + # Asegúrese de que la extensión esté en el formato correcto (es decir, comience con un punto) + if not extension.startswith('.'): + extension = '.' + extension + + # Separe el nombre base del archivo de su extensión si está presente + file_name_without_extension, _ = os.path.splitext(file_name) + + # Reconstruir el nombre del archivo con la extensión correcta + file_name_corrected = file_name_without_extension + extension + + # Construir la ruta completa del archivo + full_path = os.path.join(base_path, file_name_corrected) + + return full_path + +def open_file_explorer(path): + """ + Abre el explorador de archivos en la ruta dada. + """ + # Normaliza la ruta para asegurarse de que esté en el formato correcto + normalized_path = os.path.normpath(path) + + # Comprueba si la ruta es un directorio o un archivo y formatea el comando en consecuencia + if os.path.isdir(normalized_path): + # Si es un directorio, usa el comando 'explorer' directamente + command = f'explorer "{normalized_path}"' + else: + # Si es un archivo, usa el comando 'explorer /select,' para resaltar el archivo en su carpeta + command = f'explorer /select,"{normalized_path}"' + + # Ejecuta el comando usando subprocess.run + subprocess.run(command, shell=True) + +#================================= +# FUNCIÓN PRINCIPAL +#================================= + +def main(): + """ + Función principal para ejecutar la conversión de DB a Excel. + """ + print("==================================================") + print(" Convertidor de DB a Excel para Siemens S7 PLC") + print("==================================================\n") + + # Seleccionar archivo + print("Por favor, seleccione un archivo .db para procesar:") + file_path = select_file() + if not file_path: # No se seleccionó ningún archivo + print("❌ No se seleccionó ningún archivo. Operación cancelada.") + return + + print(f"✓ Archivo seleccionado: {file_path}") + + try: + # Leer el contenido del archivo + with open(file_path, "r", encoding="utf-8-sig") as file: + lines = file.readlines() + + # Extraer detalles del archivo + file_name, extension, dest_path = extract_file_details(file_path) + + # Crear ruta de salida + excel_path = build_file_path(dest_path, file_name, "xlsx") + log_path = build_file_path(dest_path, f"{file_name}_log", "txt") + + print("\n▶ Iniciando procesamiento del archivo DB...") + print(f" Nombre del archivo: {file_name}") + print(f" Ruta de destino: {excel_path}") + + # Configurar logging a archivo + import sys + import datetime + original_stdout = sys.stdout + log_file = open(log_path, 'w', encoding='utf-8') + sys.stdout = log_file + + print("=== LOG DE PROCESAMIENTO ===") + print(f"Archivo procesado: {file_path}") + print(f"Fecha de procesamiento: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") + print("============================\n") + + # Parsear UDTs y DBs + print("\n=== PARSEANDO UDTs Y DBs ===") + udt_json = parse_udts(lines) + db_json = parse_dbs(lines, udt_json) + + # Expandir DBs con definiciones UDT + print("\n=== EXPANDIENDO ESTRUCTURAS ===") + expand_dbs(udt_json, db_json) + + # Convertir a tabla + print("\n=== CALCULANDO OFFSETS Y DIRECCIONES ===") + df = convert_to_table(db_json) + + # Restaurar stdout para mostrar mensajes en la consola + sys.stdout = original_stdout + log_file.close() + + # Guardar en Excel + print("\n▶ Generando archivo Excel...") + workbook, worksheet = save_dataframe_to_excel(df, excel_path, file_name) + + # Mostrar resumen + print("\n=== RESUMEN DE CONVERSIÓN ===") + print(f"✓ Total de variables procesadas: {len(df)}") + print(f"✓ Tamaño total del DB: {df['Offset'].max() if not df.empty else 0} bytes") + print(f"✓ Archivo Excel generado: {excel_path}") + print(f"✓ Archivo de log generado: {log_path}") + + print("\n✅ ¡Conversión completada con éxito!") + + # Abrir el archivo de salida en el Explorador + print("\n▶ Abriendo el archivo Excel en el Explorador...") + open_file_explorer(excel_path) + + except Exception as e: + print(f"\n❌ ERROR: Se produjo un error durante la conversión:") + print(f" {str(e)}") + import traceback + traceback.print_exc() + print("\nPor favor, revise el archivo de entrada y vuelva a intentarlo.") + +# Ejecutar la función principal cuando se ejecuta el script +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/data.json b/backend/script_groups/S7_DB_Utils/data.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/data.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/db1001_data.db b/backend/script_groups/S7_DB_Utils/db1001_data.db new file mode 100644 index 0000000..aea3b9c --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/db1001_data.db @@ -0,0 +1,550 @@ +DATA_BLOCK "HMI_Blender_Parameters" +TITLE = +{ S7_language := '28(1) Albanese 15.06.2005 17:07:04' } +FAMILY : Resource +VERSION : 0.0 + + + STRUCT + STAT0 : STRUCT + STAT1 : STRUCT + STAT2 : INT := 6; + STAT3 : REAL := 2.000000e-01; + STAT4 : REAL := 8.000000e-01; + STAT5 : BOOL := TRUE; + STAT6 : BOOL ; + STAT7 : BOOL ; + STAT8 : BOOL ; + STAT9 : BOOL ; + STAT10 : BOOL ; + STAT11 : BOOL := TRUE; + STAT12 : BOOL ; + STAT13 : BOOL := TRUE; + STAT14 : BOOL ; + STAT15 : BOOL ; + STAT16 : BOOL ; + STAT17 : BOOL ; + STAT18 : BOOL := TRUE; + STAT19 : BOOL ; + STAT20 : BOOL ; + STAT21 : INT := 6; + STAT22 : BOOL ; + STAT23 : BOOL ; + STAT24 : BOOL ; + STAT25 : BOOL ; + STAT26 : BOOL ; + STAT27 : BOOL := TRUE; + STAT28 : BOOL := TRUE; + STAT29 : INT := 1; + STAT30 : BOOL := TRUE; + STAT31 : INT := 4; + STAT32 : INT ; + STAT33 : BOOL ; + STAT34 : BOOL ; + STAT35 : BOOL ; + STAT36 : BOOL ; + STAT37 : BOOL ; + STAT38 : BOOL := TRUE; + STAT39 : BOOL ; + STAT40 : BOOL ; + STAT41 : BOOL := TRUE; + STAT42 : BOOL ; + STAT43 : BOOL := TRUE; + STAT44 : BOOL ; + STAT45 : BOOL := TRUE; + STAT46 : BOOL ; + STAT47 : BOOL ; + STAT48 : BOOL := TRUE; + STAT49 : INT ; + STAT50 : INT := 2; + STAT51 : BOOL := TRUE; + STAT52 : BOOL ; + STAT53 : BOOL ; + STAT54 : BOOL ; + STAT55 : BOOL ; + STAT56 : BOOL ; + STAT57 : BOOL ; + STAT58 : BOOL := TRUE; + STAT59 : BOOL ; + STAT60 : BOOL ; + STAT61 : BOOL ; + STAT62 : BOOL ; + STAT63 : BOOL ; + STAT64 : BOOL := TRUE; + STAT65 : BOOL ; + STAT66 : BOOL ; + STAT67 : INT := 1; + STAT68 : INT ; + STAT69 : INT := 1; + STAT70 : INT ; + STAT71 : INT ; + STAT72 : INT := 6; + END_STRUCT ; + END_STRUCT ; + STAT73 : ARRAY [1 .. 9 ] OF INT ; + STAT74 : REAL := 5.000000e-02; + STAT75 : REAL := 6.500000e+01; + STAT76 : STRUCT + STAT77 : STRING [32 ] := ' '; + STAT78 : BOOL ; + STAT79 : BOOL ; + STAT80 : BOOL ; + STAT81 : BOOL ; + STAT82 : BOOL ; + STAT83 : BOOL ; + STAT84 : BOOL ; + STAT85 : BOOL ; + STAT86 : BYTE ; + STAT87 : BYTE ; + STAT88 : BYTE ; + STAT89 : INT := 1; + STAT90 : INT ; + STAT91 : REAL := 5.000000e+01; + STAT92 : REAL := 1.255800e+00; + STAT93 : REAL := 1.000000e+00; + STAT94 : REAL := 1.045000e+01; + STAT95 : REAL := 9.000000e+02; + STAT96 : REAL := 2.000000e+01; + STAT97 : REAL ; + STAT98 : REAL ; + STAT99 : REAL := 1.000000e+00; + STAT100 : REAL := 1.000000e+00; + STAT101 : REAL := 1.000000e+01; + STAT102 : REAL := 1.000000e+01; + STAT103 : REAL ; + STAT104 : REAL ; + STAT105 : REAL ; + STAT106 : REAL ; + STAT107 : REAL ; + STAT108 : REAL ; + STAT109 : REAL ; + STAT110 : REAL ; + STAT111 : REAL ; + STAT112 : REAL ; + STAT113 : REAL ; + STAT114 : REAL ; + STAT115 : REAL ; + STAT116 : REAL ; + STAT117 : REAL := 9.700000e-01; + STAT118 : REAL ; + STAT119 : REAL := 1.000000e+00; + STAT120 : REAL ; + STAT121 : REAL ; + STAT122 : INT ; + STAT123 : REAL ; + STAT124 : REAL ; + STAT125 : REAL ; + STAT126 : REAL ; + END_STRUCT ; + STAT127 : ARRAY [1 .. 5 ] OF INT ; + STAT128 : STRING [32 ] := ' '; + STAT129 : INT ; + STAT130 : ARRAY [1 .. 18 ] OF INT ; + STAT131 : STRUCT + STAT132 : REAL ; + STAT133 : REAL ; + STAT134 : REAL := 1.580000e-03; + STAT135 : REAL := 9.000000e-03; + STAT136 : REAL := 1.700000e-02; + STAT137 : REAL := 5.700000e+00; + STAT138 : REAL := 2.000000e+00; + STAT139 : REAL := 2.000000e+00; + STAT140 : REAL := 1.000000e+01; + STAT141 : REAL := 1.000000e+01; + STAT142 : REAL := 1.000000e+01; + STAT143 : REAL := 6.000000e+01; + STAT144 : REAL := 5.000000e+01; + STAT145 : REAL := 2.500000e+01; + STAT146 : REAL := 6.500000e+01; + STAT147 : REAL := 1.200000e+01; + STAT148 : REAL := 1.000000e+01; + STAT149 : REAL ; + STAT150 : REAL := 3.000000e+01; + STAT151 : REAL := 1.000000e+00; + STAT152 : REAL := 5.000000e+00; + STAT153 : REAL := 5.000000e+00; + STAT154 : REAL := 1.000000e+02; + STAT155 : REAL := 2.000000e+02; + STAT156 : REAL := 2.000000e+01; + STAT157 : REAL := 2.000000e+01; + STAT158 : REAL := 2.000000e+01; + STAT159 : INT := 1; + STAT160 : REAL := 2.000000e+01; + STAT161 : REAL := 7.000000e-01; + STAT162 : REAL := 4.250000e+02; + STAT163 : REAL := 2.550000e+03; + STAT164 : REAL := 9.000000e+00; + STAT165 : REAL ; + STAT166 : REAL := 1.600000e+03; + STAT167 : REAL := 2.000000e+01; + STAT168 : REAL := 1.400000e+01; + STAT169 : REAL := 1.610000e+03; + STAT170 : REAL := 2.877000e+03; + STAT171 : INT := 80; + STAT172 : REAL := 8.000000e+01; + STAT173 : REAL := 9.000000e+01; + STAT174 : REAL := 4.000000e+00; + STAT175 : REAL := 1.020000e+03; + STAT176 : REAL := 1.000000e+02; + STAT177 : REAL := 2.300000e+03; + STAT178 : REAL := 7.500000e-01; + STAT179 : REAL := 5.000000e-01; + STAT180 : REAL := 3.000000e-02; + STAT181 : REAL := 1.400000e-03; + STAT182 : REAL ; + STAT183 : WORD := W#16#6; + STAT184 : WORD := W#16#50; + STAT185 : WORD := W#16#1; + STAT186 : REAL := 3.000000e+01; + STAT187 : REAL := 4.000000e+01; + STAT188 : REAL := 9.000000e+01; + STAT189 : REAL := 2.500000e+02; + STAT190 : REAL := 5.500000e-01; + STAT191 : REAL := 4.000000e-01; + STAT192 : REAL := 9.000000e-01; + STAT193 : REAL := 1.500000e+01; + STAT194 : REAL := 4.500000e+01; + STAT195 : REAL := 5.000000e+01; + STAT196 : REAL := 4.000000e+00; + STAT197 : REAL := 2.000000e+01; + STAT198 : REAL := 5.000000e+00; + STAT199 : REAL := 5.000000e+00; + STAT200 : REAL := 5.000000e+00; + STAT201 : REAL := 5.000000e+00; + STAT202 : REAL := 1.000000e+01; + STAT203 : REAL ; + STAT204 : REAL := 1.150000e+02; + STAT205 : REAL := 1.650000e+02; + STAT206 : REAL := 2.600000e+02; + STAT207 : REAL := 1.650000e+02; + STAT208 : REAL := 6.700000e+01; + STAT209 : INT := 50; + STAT210 : REAL := 9.000000e+01; + STAT211 : REAL := 8.700000e+01; + STAT212 : REAL := 5.070000e+02; + STAT213 : REAL := 2.110000e+02; + STAT214 : REAL := 8.600000e+01; + STAT215 : REAL := 8.500000e+01; + STAT216 : REAL := 1.150000e+02; + STAT217 : REAL := 3.200000e+01; + STAT218 : REAL := 5.000000e+00; + STAT219 : REAL := 5.000000e+00; + STAT220 : REAL ; + STAT221 : REAL ; + STAT222 : REAL ; + STAT223 : REAL ; + STAT224 : REAL := 1.800000e+01; + STAT225 : REAL := 2.000000e+00; + STAT226 : REAL := 2.000000e+00; + STAT227 : REAL := 5.000000e+01; + STAT228 : REAL := 5.000000e+01; + STAT229 : DINT := L#1500; + STAT230 : DINT := L#1500; + STAT231 : DINT := L#1000; + STAT232 : DINT := L#1000; + STAT233 : INT := 30; + STAT234 : INT := 30; + STAT235 : INT := 10; + STAT236 : INT := 10; + STAT237 : INT := 10; + STAT238 : REAL := 3.500000e+02; + STAT239 : INT := 30; + STAT240 : INT := 30; + STAT241 : INT := 30; + STAT242 : INT := 30; + STAT243 : INT := 30; + STAT244 : INT := 30; + STAT245 : INT := 30; + STAT246 : INT := 30; + STAT247 : REAL := 3.000000e+01; + STAT248 : REAL := 3.000000e+01; + STAT249 : REAL ; + STAT250 : REAL ; + STAT251 : REAL ; + STAT252 : REAL := 5.000000e+01; + END_STRUCT ; + STAT253 : BOOL ; + STAT254 : REAL ; + END_STRUCT ; +BEGIN + STAT0.STAT1.STAT2 := 6; + STAT0.STAT1.STAT3 := 4.500000e-01; + STAT0.STAT1.STAT4 := 8.000000e-01; + STAT0.STAT1.STAT5 := TRUE; + STAT0.STAT1.STAT6 := FALSE; + STAT0.STAT1.STAT7 := FALSE; + STAT0.STAT1.STAT8 := FALSE; + STAT0.STAT1.STAT9 := TRUE; + STAT0.STAT1.STAT10 := FALSE; + STAT0.STAT1.STAT11 := TRUE; + STAT0.STAT1.STAT12 := FALSE; + STAT0.STAT1.STAT13 := TRUE; + STAT0.STAT1.STAT14 := FALSE; + STAT0.STAT1.STAT15 := FALSE; + STAT0.STAT1.STAT16 := FALSE; + STAT0.STAT1.STAT17 := FALSE; + STAT0.STAT1.STAT18 := TRUE; + STAT0.STAT1.STAT19 := FALSE; + STAT0.STAT1.STAT20 := FALSE; + STAT0.STAT1.STAT21 := 6; + STAT0.STAT1.STAT22 := FALSE; + STAT0.STAT1.STAT23 := FALSE; + STAT0.STAT1.STAT24 := FALSE; + STAT0.STAT1.STAT25 := TRUE; + STAT0.STAT1.STAT26 := FALSE; + STAT0.STAT1.STAT27 := TRUE; + STAT0.STAT1.STAT28 := TRUE; + STAT0.STAT1.STAT29 := 1; + STAT0.STAT1.STAT30 := TRUE; + STAT0.STAT1.STAT31 := 4; + STAT0.STAT1.STAT32 := 0; + STAT0.STAT1.STAT33 := FALSE; + STAT0.STAT1.STAT34 := FALSE; + STAT0.STAT1.STAT35 := FALSE; + STAT0.STAT1.STAT36 := FALSE; + STAT0.STAT1.STAT37 := FALSE; + STAT0.STAT1.STAT38 := TRUE; + STAT0.STAT1.STAT39 := FALSE; + STAT0.STAT1.STAT40 := FALSE; + STAT0.STAT1.STAT41 := TRUE; + STAT0.STAT1.STAT42 := FALSE; + STAT0.STAT1.STAT43 := TRUE; + STAT0.STAT1.STAT44 := FALSE; + STAT0.STAT1.STAT45 := TRUE; + STAT0.STAT1.STAT46 := FALSE; + STAT0.STAT1.STAT47 := FALSE; + STAT0.STAT1.STAT48 := TRUE; + STAT0.STAT1.STAT49 := 0; + STAT0.STAT1.STAT50 := 2; + STAT0.STAT1.STAT51 := TRUE; + STAT0.STAT1.STAT52 := FALSE; + STAT0.STAT1.STAT53 := FALSE; + STAT0.STAT1.STAT54 := FALSE; + STAT0.STAT1.STAT55 := FALSE; + STAT0.STAT1.STAT56 := FALSE; + STAT0.STAT1.STAT57 := FALSE; + STAT0.STAT1.STAT58 := TRUE; + STAT0.STAT1.STAT59 := TRUE; + STAT0.STAT1.STAT60 := FALSE; + STAT0.STAT1.STAT61 := FALSE; + STAT0.STAT1.STAT62 := FALSE; + STAT0.STAT1.STAT63 := FALSE; + STAT0.STAT1.STAT64 := TRUE; + STAT0.STAT1.STAT65 := FALSE; + STAT0.STAT1.STAT66 := FALSE; + STAT0.STAT1.STAT67 := 1; + STAT0.STAT1.STAT68 := 0; + STAT0.STAT1.STAT69 := 1; + STAT0.STAT1.STAT70 := 0; + STAT0.STAT1.STAT71 := 0; + STAT0.STAT1.STAT72 := 6; + STAT73[1] := 0; + STAT73[2] := 0; + STAT73[3] := 0; + STAT73[4] := 0; + STAT73[5] := 0; + STAT73[6] := 0; + STAT73[7] := 0; + STAT73[8] := 0; + STAT73[9] := 0; + STAT74 := 5.000000e-02; + STAT75 := 9.000000e+01; + STAT76.STAT77 := ''; + STAT76.STAT78 := TRUE; + STAT76.STAT79 := FALSE; + STAT76.STAT80 := FALSE; + STAT76.STAT81 := FALSE; + STAT76.STAT82 := FALSE; + STAT76.STAT83 := TRUE; + STAT76.STAT84 := FALSE; + STAT76.STAT85 := FALSE; + STAT76.STAT86 := B#16#0; + STAT76.STAT87 := B#16#14; + STAT76.STAT88 := B#16#0; + STAT76.STAT89 := 2; + STAT76.STAT90 := 1; + STAT76.STAT91 := 3.935000e+01; + STAT76.STAT92 := 1.166600e+00; + STAT76.STAT93 := 1.000000e+00; + STAT76.STAT94 := 8.600000e+00; + STAT76.STAT95 := 2.500000e-01; + STAT76.STAT96 := 3.934034e+00; + STAT76.STAT97 := 4.000000e-01; + STAT76.STAT98 := 2.500000e+00; + STAT76.STAT99 := 9.000000e-01; + STAT76.STAT100 := 3.500000e+00; + STAT76.STAT101 := 1.600000e+01; + STAT76.STAT102 := 3.500000e+01; + STAT76.STAT103 := 0.000000e+00; + STAT76.STAT104 := 0.000000e+00; + STAT76.STAT105 := 0.000000e+00; + STAT76.STAT106 := 8.800000e+00; + STAT76.STAT107 := 8.400000e+00; + STAT76.STAT108 := 2.800000e+00; + STAT76.STAT109 := 2.200000e+00; + STAT76.STAT110 := 0.000000e+00; + STAT76.STAT111 := 0.000000e+00; + STAT76.STAT112 := 0.000000e+00; + STAT76.STAT113 := 0.000000e+00; + STAT76.STAT114 := 0.000000e+00; + STAT76.STAT115 := 0.000000e+00; + STAT76.STAT116 := 0.000000e+00; + STAT76.STAT117 := 8.500000e-01; + STAT76.STAT118 := 0.000000e+00; + STAT76.STAT119 := 0.000000e+00; + STAT76.STAT120 := 0.000000e+00; + STAT76.STAT121 := 0.000000e+00; + STAT76.STAT122 := 0; + STAT76.STAT123 := 0.000000e+00; + STAT76.STAT124 := 0.000000e+00; + STAT76.STAT125 := 0.000000e+00; + STAT76.STAT126 := 0.000000e+00; + STAT127[1] := 0; + STAT127[2] := 0; + STAT127[3] := 0; + STAT127[4] := 0; + STAT127[5] := 0; + STAT128 := ''; + STAT129 := 0; + STAT130[1] := 0; + STAT130[2] := 0; + STAT130[3] := 0; + STAT130[4] := 0; + STAT130[5] := 0; + STAT130[6] := 0; + STAT130[7] := 0; + STAT130[8] := 0; + STAT130[9] := 0; + STAT130[10] := 0; + STAT130[11] := 0; + STAT130[12] := 0; + STAT130[13] := 0; + STAT130[14] := 0; + STAT130[15] := 0; + STAT130[16] := 0; + STAT130[17] := 0; + STAT130[18] := 0; + STAT131.STAT132 := 0.000000e+00; + STAT131.STAT133 := 0.000000e+00; + STAT131.STAT134 := 1.000000e-03; + STAT131.STAT135 := 7.800000e-03; + STAT131.STAT136 := 1.390000e-02; + STAT131.STAT137 := 5.700000e+00; + STAT131.STAT138 := 2.000000e+00; + STAT131.STAT139 := 2.200000e+00; + STAT131.STAT140 := 2.100000e+01; + STAT131.STAT141 := 2.000000e+01; + STAT131.STAT142 := 5.000000e+00; + STAT131.STAT143 := 6.000000e+01; + STAT131.STAT144 := 5.000000e+01; + STAT131.STAT145 := 2.500000e+01; + STAT131.STAT146 := 4.000000e+01; + STAT131.STAT147 := 2.400000e+01; + STAT131.STAT148 := 1.400000e+01; + STAT131.STAT149 := 3.000000e-01; + STAT131.STAT150 := 3.000000e+01; + STAT131.STAT151 := 1.000000e+00; + STAT131.STAT152 := 4.000000e+00; + STAT131.STAT153 := 2.000000e+00; + STAT131.STAT154 := 1.000000e+02; + STAT131.STAT155 := 5.000000e+02; + STAT131.STAT156 := 5.000000e+01; + STAT131.STAT157 := 8.000000e+00; + STAT131.STAT158 := 1.900000e+01; + STAT131.STAT159 := 1; + STAT131.STAT160 := 2.000000e+02; + STAT131.STAT161 := 5.000000e-01; + STAT131.STAT162 := 4.500000e+02; + STAT131.STAT163 := 2.500000e+03; + STAT131.STAT164 := 1.220000e+01; + STAT131.STAT165 := 1.000000e+00; + STAT131.STAT166 := 3.950000e+02; + STAT131.STAT167 := -2.500000e+01; + STAT131.STAT168 := 3.618000e+01; + STAT131.STAT169 := 1.400000e+03; + STAT131.STAT170 := 2.520000e+03; + STAT131.STAT171 := 91; + STAT131.STAT172 := 1.000000e+02; + STAT131.STAT173 := 1.600000e+02; + STAT131.STAT174 := 3.200000e+00; + STAT131.STAT175 := 1.050000e+03; + STAT131.STAT176 := 4.600000e+01; + STAT131.STAT177 := 1.625000e+03; + STAT131.STAT178 := 1.000000e+00; + STAT131.STAT179 := 1.300000e+00; + STAT131.STAT180 := 4.090000e-02; + STAT131.STAT181 := 1.400000e-03; + STAT131.STAT182 := 4.500000e+02; + STAT131.STAT183 := W#16#0; + STAT131.STAT184 := W#16#78; + STAT131.STAT185 := W#16#1; + STAT131.STAT186 := 3.000000e+01; + STAT131.STAT187 := 4.000000e+01; + STAT131.STAT188 := 3.000000e+01; + STAT131.STAT189 := 5.000000e+00; + STAT131.STAT190 := 4.900000e-01; + STAT131.STAT191 := 3.000000e-01; + STAT131.STAT192 := 9.000000e-01; + STAT131.STAT193 := 1.500000e+01; + STAT131.STAT194 := 3.500000e+01; + STAT131.STAT195 := 5.000000e+01; + STAT131.STAT196 := 4.000000e+00; + STAT131.STAT197 := 2.000000e+01; + STAT131.STAT198 := 5.000000e+00; + STAT131.STAT199 := 5.000000e+00; + STAT131.STAT200 := 5.000000e+00; + STAT131.STAT201 := 5.000000e+00; + STAT131.STAT202 := 6.000000e+01; + STAT131.STAT203 := 0.000000e+00; + STAT131.STAT204 := 1.500000e+02; + STAT131.STAT205 := 1.650000e+02; + STAT131.STAT206 := 2.600000e+02; + STAT131.STAT207 := 1.650000e+02; + STAT131.STAT208 := 6.700000e+01; + STAT131.STAT209 := 300; + STAT131.STAT210 := 9.000000e+01; + STAT131.STAT211 := 8.700000e+01; + STAT131.STAT212 := 5.070000e+02; + STAT131.STAT213 := 2.110000e+02; + STAT131.STAT214 := 8.600000e+01; + STAT131.STAT215 := 8.500000e+01; + STAT131.STAT216 := 1.150000e+02; + STAT131.STAT217 := 3.200000e+01; + STAT131.STAT218 := 5.000000e+00; + STAT131.STAT219 := 5.000000e+00; + STAT131.STAT220 := 0.000000e+00; + STAT131.STAT221 := 0.000000e+00; + STAT131.STAT222 := 0.000000e+00; + STAT131.STAT223 := 0.000000e+00; + STAT131.STAT224 := 2.000000e+01; + STAT131.STAT225 := 5.000000e+00; + STAT131.STAT226 := 1.000000e+01; + STAT131.STAT227 := 5.000000e+01; + STAT131.STAT228 := 5.000000e+01; + STAT131.STAT229 := L#1500; + STAT131.STAT230 := L#1500; + STAT131.STAT231 := L#1000; + STAT131.STAT232 := L#1000; + STAT131.STAT233 := 30; + STAT131.STAT234 := 30; + STAT131.STAT235 := 10; + STAT131.STAT236 := 10; + STAT131.STAT237 := 10; + STAT131.STAT238 := 3.500000e+02; + STAT131.STAT239 := 30; + STAT131.STAT240 := 30; + STAT131.STAT241 := 30; + STAT131.STAT242 := 30; + STAT131.STAT243 := 30; + STAT131.STAT244 := 30; + STAT131.STAT245 := 30; + STAT131.STAT246 := 30; + STAT131.STAT247 := 3.000000e+01; + STAT131.STAT248 := 3.000000e+01; + STAT131.STAT249 := 0.000000e+00; + STAT131.STAT250 := 0.000000e+00; + STAT131.STAT251 := 0.000000e+00; + STAT131.STAT252 := 5.000000e+01; + STAT253 := FALSE; + STAT254 := 0.000000e+00; +END_DATA_BLOCK diff --git a/backend/script_groups/S7_DB_Utils/db1001_format.csv b/backend/script_groups/S7_DB_Utils/db1001_format.csv new file mode 100644 index 0000000..192c221 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/db1001_format.csv @@ -0,0 +1,467 @@ +Address;Name;;Type;Initial value;Actual value;Comment +0.0;Processor_Options.Blender_OPT._ModelNum;;INT;6;6; +2.0;Processor_Options.Blender_OPT._CO2_Offset;;REAL;4.500000e-01;4.500000e-01; +6.0;Processor_Options.Blender_OPT._MaxSyrDeltaBrix;;REAL;8.000000e-01;8.000000e-01; +10.0;Processor_Options.Blender_OPT._BrixMeter;;BOOL;TRUE;TRUE; +10.1;Processor_Options.Blender_OPT.Spare101;;BOOL;FALSE;FALSE; +10.2;Processor_Options.Blender_OPT._TrackH2OEnable;;BOOL;FALSE;FALSE; +10.3;Processor_Options.Blender_OPT._PAmPDSType;;BOOL;FALSE;FALSE;"0)Cobrix 200 +0 1)Carbo 2 000" +10.4;Processor_Options.Blender_OPT._HistoricalTrends;;BOOL;TRUE;TRUE;"0)Not Presen +t 1)Present" +10.5;Processor_Options.Blender_OPT._PowerMeter;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +10.6;Processor_Options.Blender_OPT._Report;;BOOL;TRUE;TRUE;"0)Not Presen +t 1)Present" +10.7;Processor_Options.Blender_OPT._Balaiage;;BOOL;FALSE;FALSE; +11.0;Processor_Options.Blender_OPT._Valves_FullFeedback;;BOOL;TRUE;TRUE;"Valves contr +ol Full feed back" +11.1;Processor_Options.Blender_OPT._Valves_SingleFeedback;;BOOL;FALSE;FALSE;"Valves contr +ol Single fe edback" +11.2;Processor_Options.Blender_OPT._PumpsSafetySwitches;;BOOL;FALSE;FALSE;"Pumps with S +afety Switch es" +11.3;Processor_Options.Blender_OPT._SurgeProtectionAct;;BOOL;FALSE;FALSE; +11.4;Processor_Options.Blender_OPT._DBC_Type;;BOOL;FALSE;FALSE;"0) Deox,Carb +o,Blend 1)D eox,Blend,Ca rbo" +11.5;Processor_Options.Blender_OPT._CO2InletMeter;;BOOL;TRUE;TRUE;"0)Not Presen +t 1)Present" +11.6;Processor_Options.Blender_OPT._ProductO2Meter;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +11.7;Processor_Options.Blender_OPT._CopressedAirInletMeter;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +12.0;Processor_Options.Blender_OPT._MeterType;;INT;6;6;"1)Maselli 2) +AntoonPaar 3 +)4-20mA 4)UC 05 UR22 5)mP DSPA 6)MR02" +14.0;Processor_Options.Blender_OPT._MeterReceiveOnly;;BOOL;FALSE;FALSE; +14.1;Processor_Options.Blender_OPT._SyrBrixMeter;;BOOL;FALSE;FALSE; +14.2;Processor_Options.Blender_OPT._Flooding_Start_Up;;BOOL;FALSE;FALSE;"0)Not Select +ed 1)Sele cted" +14.3;Processor_Options.Blender_OPT._FastChangeOverEnabled;;BOOL;TRUE;TRUE; +14.4;Processor_Options.Blender_OPT._WaterInletMeter;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +14.5;Processor_Options.Blender_OPT._BlendFillSystem;;BOOL;TRUE;TRUE; +14.6;Processor_Options.Blender_OPT._TrackFillerSpeed;;BOOL;TRUE;TRUE; +16.0;Processor_Options.Blender_OPT._SignalExchange;;INT;1;1;"FILLER - 0= +Hardwire; 1= Ethernet" +18.0;Processor_Options.Blender_OPT._CoolerPresent;;BOOL;TRUE;TRUE; +20.0;Processor_Options.Blender_OPT._CoolerControl;;INT;4;4;"0)External 1 +)Water 2)Pro duct 3)Water ++Product-2 C trl 4)Water+ Product-1 Ct +rl" +22.0;Processor_Options.Blender_OPT._CoolerType;;INT;0;0;"0)Glycol 1)A +mmonia" +24.0;Processor_Options.Blender_OPT._LocalCIP;;BOOL;FALSE;FALSE; +24.1;Processor_Options.Blender_OPT._ICS_CustomerHotWater;;BOOL;FALSE;FALSE;"0)No Hot Wat +er from Cust omer 1)Hot W ater from Cu stomer Avail able" +24.2;Processor_Options.Blender_OPT._ICS_CustomerChemRecov;;BOOL;FALSE;FALSE;"0)No Custome +r's Chemical s Recovery 1 +)Customer's Chemicals Re covery Avail +able" +24.3;Processor_Options.Blender_OPT._CIPSignalExchange;;BOOL;FALSE;FALSE;"CIP - 0= Har +dwire; 1= Et hernet" +24.4;Processor_Options.Blender_OPT._ICS_CustomerChemicals;;BOOL;FALSE;FALSE;"0)Chemicals +from ICS 1)C hemicals fro m Customer" +24.5;Processor_Options.Blender_OPT._CarboPresent;;BOOL;TRUE;TRUE; +24.6;Processor_Options.Blender_OPT._InverterSyrupPumpPPP302;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +24.7;Processor_Options.Blender_OPT._InverterWaterPumpPPN301;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +25.0;Processor_Options.Blender_OPT._DoubleDeair;;BOOL;TRUE;TRUE; +25.1;Processor_Options.Blender_OPT._DeairPreMixed;;BOOL;FALSE;FALSE;"Deox Premixe +d Inlet" +25.2;Processor_Options.Blender_OPT._Deaireation;;BOOL;TRUE;TRUE;"0)SAG 1)SAE/ +SAF" +25.3;Processor_Options.Blender_OPT._StillWaterByPass;;BOOL;FALSE;FALSE; +25.4;Processor_Options.Blender_OPT._ManifoldSetting;;BOOL;TRUE;TRUE;"0)Manual 1)A +utomatic" +25.5;Processor_Options.Blender_OPT._InverterProdPumpPPM303;;BOOL;FALSE;FALSE; +25.6;Processor_Options.Blender_OPT._SidelCip;;BOOL;FALSE;FALSE; +25.7;Processor_Options.Blender_OPT._EthernetCom_CpuPN_CP;;BOOL;TRUE;TRUE;"0)Comunicati +on with CP 1)Comunicat +ion with CPU +PN" +26.0;Processor_Options.Blender_OPT._2ndOutlet;;INT;0;0;"0)No 2nd Out +let 1)2nd O utlet No Sta ndalone 2)2 nd Outlet St andalone" +28.0;Processor_Options.Blender_OPT._Promass;;INT;2;2; +30.0;Processor_Options.Blender_OPT._WaterPromass;;BOOL;TRUE;TRUE;"0)Promag 1)P +romass" +30.1;Processor_Options.Blender_OPT._ProductConductimeter;;BOOL;FALSE;FALSE; +30.2;Processor_Options.Blender_OPT._ICS_CustomerH2ORecov;;BOOL;FALSE;FALSE;"0)No Custome +r's H2O Reco very 1)Custo mer's H2O Re covery Avail able" +30.3;Processor_Options.Blender_OPT.Spare303;;BOOL;FALSE;FALSE; +30.4;Processor_Options.Blender_OPT._CO2_GAS2_Injection;;BOOL;FALSE;FALSE;"0)Only CO2 I +njection 1)G AS2 Injectio n" +30.5;Processor_Options.Blender_OPT._InverterVacuuPumpPPN304;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +30.6;Processor_Options.Blender_OPT._InverterBoostPumpPPM307;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +30.7;Processor_Options.Blender_OPT._RunOut_Water;;BOOL;TRUE;TRUE;"0)Syrup Runo +ut without W ater 1)Syrup runout with Water pushi +ng" +31.0;Processor_Options.Blender_OPT._FlowMeterType;;BOOL;FALSE;TRUE;"0)Endrees Ha +user -- 1)Mi cromotion" +31.1;Processor_Options.Blender_OPT._SidelFiller;;BOOL;FALSE;FALSE;"0)Filler Sim +onazzi -- 1)Filler Sid el Filling" +31.2;Processor_Options.Blender_OPT._Simulation;;BOOL;FALSE;FALSE; +31.3;Processor_Options.Blender_OPT._ProductCoolingCTRL;;BOOL;FALSE;FALSE;"0)none 1) TT +M307" +31.4;Processor_Options.Blender_OPT._ChillerCTRL;;BOOL;FALSE;FALSE;"Chiller Pres +sure Cross C ontrol" +31.5;Processor_Options.Blender_OPT._CO2_SterileFilter;;BOOL;TRUE;TRUE;"CO2 Inlet wi +th Steril Fi lter" +31.6;Processor_Options.Blender_OPT._InverterRecirPumpPPM306;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +31.7;Processor_Options.Blender_OPT._ProdPressReleaseRVM304;;BOOL;FALSE;FALSE;"0)Not Presen +t 1)Present" +32.0;Processor_Options.Blender_OPT._VacuumPump;;INT;1;1;"0)None 1)Ste +rling 2)Nash Elmo" +34.0;Processor_Options.Blender_OPT._GAS2InjectionType;;INT;0;0;"0)None 1)N2 +2)Steril Air" +36.0;Processor_Options.Blender_OPT._InjectionPress_Ctrl;;INT;1;1;"0)Manual 1)N +orgren v1 2) Norgren v2" +38.0;Processor_Options.Blender_OPT._ProdPressureType;;INT;0;0;"0)Only CO2 1 +)CO2+SterilA ir 2)CO2+N2" +40.0;Processor_Options.Blender_OPT._CIPHeatType;;INT;0;0;"0)Steam 1)El +ectric" +42.0;Processor_Options.Blender_OPT._EHS_NrRes;;INT;6;6;"Number of He +at Resistanc es" +44.0;Spare1[1];;INT;0;0; +46.0;Spare1[2];;INT;0;0; +48.0;Spare1[3];;INT;0;0; +50.0;Spare1[4];;INT;0;0; +52.0;Spare1[5];;INT;0;0; +54.0;Spare1[6];;INT;0;0; +56.0;Spare1[7];;INT;0;0; +58.0;Spare1[8];;INT;0;0; +60.0;Spare1[9];;INT;0;0; +62.0;_RVM301_DeadBand;;REAL;5.000000e-02;5.000000e-02; +66.0;_RVM301_Kp;;REAL;9.000000e+01;9.000000e+01; +70.0;Actual_Recipe_Parameters._Name;;STRING [ 32 ];"' +'";''; +104.0;Actual_Recipe_Parameters._EnProdTemp;;BOOL;FALSE;TRUE; +104.1;Actual_Recipe_Parameters._SyrFlushing;;BOOL;FALSE;FALSE;"Ex_EnDeairea +tion --> DEL ETED - AVP32 +0 VALVE OPEN" +104.2;Actual_Recipe_Parameters._GAS2_Injection;;BOOL;FALSE;FALSE;"0 = GAS2 not +present; 1 += GAS2 prese nt" +104.3;Actual_Recipe_Parameters._Eq_Pression_Selected;;BOOL;FALSE;FALSE; +104.4;Actual_Recipe_Parameters._DeoxStripEn;;BOOL;FALSE;FALSE;"******Deaira +tion with St rip Enable" +104.5;Actual_Recipe_Parameters._DeoxVacuumEn;;BOOL;FALSE;TRUE;"******Deaira +tion with Va cuum" +104.6;Actual_Recipe_Parameters._DeoxPreMixed;;BOOL;FALSE;FALSE;"******Deaira +tion of Prem ixed Product" +104.7;Actual_Recipe_Parameters._EnBlowOffProdPipeCO2Fil;;BOOL;FALSE;FALSE; +105.0;Actual_Recipe_Parameters._WaterSelection;;BYTE;B#16#0;B#16#0; +106.0;Actual_Recipe_Parameters._FillerNextRecipeNum;;BYTE;B#16#0;B#16#0; +107.0;Actual_Recipe_Parameters._BottleShape;;BYTE;B#16#0;B#16#0; +108.0;Actual_Recipe_Parameters._Type;;INT;1;2;"1= DIET; 2= +REGULAR; 3= +RATIO; 4= WA TER" +110.0;Actual_Recipe_Parameters._ProdMeterRecipeNum;;INT;0;1; +112.0;Actual_Recipe_Parameters._SyrupBrix;;REAL;5.000000e+01;4.625000e+01; +116.0;Actual_Recipe_Parameters._SyrupDensity;;REAL;1.255800e+00;1.206908e+00; +120.0;Actual_Recipe_Parameters._SyrupFactor;;REAL;1.000000e+00;1.000000e+00; +124.0;Actual_Recipe_Parameters._ProductBrix;;REAL;1.045000e+01;1.000000e+01; +128.0;Actual_Recipe_Parameters._ProductionRate;;REAL;9.000000e+02;3.800000e+02; +132.0;Actual_Recipe_Parameters._Ratio;;REAL;2.000000e+01;4.238896e+00; +136.0;Actual_Recipe_Parameters._ProdBrixOffset;;REAL;0.000000e+00;2.500000e-01; +140.0;Actual_Recipe_Parameters._CO2Vols;;REAL;0.000000e+00;2.550000e+00; +144.0;Actual_Recipe_Parameters._CO2Fact;;REAL;1.000000e+00;9.400000e-01; +148.0;Actual_Recipe_Parameters._ProdTankPress;;REAL;1.000000e+00;4.400000e+00; +152.0;Actual_Recipe_Parameters._SP_ProdTemp;;REAL;1.000000e+01;1.700000e+01; +156.0;Actual_Recipe_Parameters._PrdTankMinLevel;;REAL;1.000000e+01;3.500000e+01; +160.0;Actual_Recipe_Parameters._WaterValveSave;;REAL;0.000000e+00;0.000000e+00; +164.0;Actual_Recipe_Parameters._SyrupValveSave;;REAL;0.000000e+00;0.000000e+00; +168.0;Actual_Recipe_Parameters._CarboCO2ValveSave;;REAL;0.000000e+00;0.000000e+00; +172.0;Actual_Recipe_Parameters._ProdMeterHighBrix;;REAL;0.000000e+00;1.030000e+01; +176.0;Actual_Recipe_Parameters._ProdMeterLowBrix;;REAL;0.000000e+00;9.830000e+00; +180.0;Actual_Recipe_Parameters._ProdMeterHighCO2;;REAL;0.000000e+00;2.900000e+00; +184.0;Actual_Recipe_Parameters._ProdMeterLowCO2;;REAL;0.000000e+00;2.300000e+00; +188.0;Actual_Recipe_Parameters._ProdMeter_ZeroCO2;;REAL;0.000000e+00;0.000000e+00; +192.0;Actual_Recipe_Parameters._ProdMeter_ZeroBrix;;REAL;0.000000e+00;0.000000e+00; +196.0;Actual_Recipe_Parameters._ProdHighCond;;REAL;0.000000e+00;0.000000e+00; +200.0;Actual_Recipe_Parameters._ProdLowCond;;REAL;0.000000e+00;0.000000e+00; +204.0;Actual_Recipe_Parameters._BottleSize;;REAL;0.000000e+00;0.000000e+00; +208.0;Actual_Recipe_Parameters._FillingValveHead_SP;;REAL;0.000000e+00;0.000000e+00; +212.0;Actual_Recipe_Parameters._SyrMeter_ZeroBrix;;REAL;0.000000e+00;0.000000e+00; +216.0;Actual_Recipe_Parameters._FirstProdExtraCO2Fact;;REAL;9.700000e-01;1.020000e+00; +220.0;Actual_Recipe_Parameters._Gas2Vols;;REAL;0.000000e+00;0.000000e+00; +224.0;Actual_Recipe_Parameters._Gas2Fact;;REAL;1.000000e+00;0.000000e+00; +228.0;Actual_Recipe_Parameters._SyrupPumpPressure;;REAL;0.000000e+00;0.000000e+00;"******Syrup +Pump Pressur e SP" +232.0;Actual_Recipe_Parameters._WaterPumpPressure;;REAL;0.000000e+00;0.000000e+00;"******Water +Pump Pressur e SP" +236.0;Actual_Recipe_Parameters._CO2_Air_N2_PressSelect;;INT;0;0;"1=CO2; 2=CO2 ++SterilAir; 3=CO2+N2 - P +ressure Tank +Selection" +238.0;Actual_Recipe_Parameters._KFactRVM304BlowOff;;REAL;0.000000e+00;0.000000e+00; +242.0;Actual_Recipe_Parameters._ProdRecircPumpFreq;;REAL;0.000000e+00;0.000000e+00; +246.0;Actual_Recipe_Parameters._ProdBoosterPumpPress;;REAL;0.000000e+00;0.000000e+00; +250.0;Actual_Recipe_Parameters._ProdSendPumpFreq;;REAL;0.000000e+00;0.000000e+00;"******Produc +t Sending Pu mp Frequency +SP" +254.0;Spare2[1];;INT;0;0; +256.0;Spare2[2];;INT;0;0; +258.0;Spare2[3];;INT;0;0; +260.0;Spare2[4];;INT;0;0; +262.0;Spare2[5];;INT;0;0; +264.0;Next_Recipe_Name;;STRING [ 32 ];"' +'";"'cambio 1$00$00$ +00$00$00$00$00$0 +0$00$00$00$00$00 +$00$00$00$00$00$ 00$00$00$00'"; +298.0;Next_Recipe_Number;;INT;0;0; +300.0;Spare3[1];;INT;0;0; +302.0;Spare3[2];;INT;0;0; +304.0;Spare3[3];;INT;0;0; +306.0;Spare3[4];;INT;0;0; +308.0;Spare3[5];;INT;0;0; +310.0;Spare3[6];;INT;0;0; +312.0;Spare3[7];;INT;0;0; +314.0;Spare3[8];;INT;0;0; +316.0;Spare3[9];;INT;0;0; +318.0;Spare3[10];;INT;0;0; +320.0;Spare3[11];;INT;0;0; +322.0;Spare3[12];;INT;0;0; +324.0;Spare3[13];;INT;0;0; +326.0;Spare3[14];;INT;0;0; +328.0;Spare3[15];;INT;0;0; +330.0;Spare3[16];;INT;0;0; +332.0;Spare3[17];;INT;0;0; +334.0;Spare3[18];;INT;0;0; +336.0;ProcessSetup.Spare000;;REAL;0.000000e+00;0.000000e+00; +340.0;ProcessSetup.Spare040;;REAL;0.000000e+00;0.000000e+00; +344.0;ProcessSetup._KWaterLoss;;REAL;1.000000e-03;1.000000e-03;"Friction Los +s Constant i n Serpentine" +348.0;ProcessSetup._KSyrupLoss;;REAL;7.800000e-03;7.800000e-03;"Friction Los +s Constant i n Syrup Pipe" +352.0;ProcessSetup._KProdLoss;;REAL;1.390000e-02;1.390000e-02;"Pressure Los +s Factor" +356.0;ProcessSetup._KPPM303;;REAL;5.700000e+00;5.700000e+00;"Frequency Ov +erpressure P ump P3 Const ant [Hz/mm]" +360.0;ProcessSetup._BaialageRVM301OVMin;;REAL;2.000000e+00;2.000000e+00;"Baialage Min +imum Flow (N m3/h)" +364.0;ProcessSetup._SyrupLinePressure;;REAL;2.200000e+00;2.200000e+00;"Syrup Line p +ressure at V EP2 valve" +368.0;ProcessSetup._CIPRMM301OV;;REAL;1.000000e+01;1.000000e+01;"Water Valve +Opening Duri ng CIP" +372.0;ProcessSetup._CIPRMP302OV;;REAL;1.500000e+01;1.500000e+01;"Syrup Valve +Opening Duri ng CIP" +376.0;ProcessSetup._CIPTM301MinLevel;;REAL;3.500000e+01;3.500000e+01;"Product Tank +Minimum Lev el In CIP" +380.0;ProcessSetup._CIPTM301MaxLevel;;REAL;5.500000e+01;5.500000e+01;"Product Tank +Maximum Lev el In CIP" +384.0;ProcessSetup._CIPPPM303Freq;;REAL;5.000000e+01;5.000000e+01;"CIP frequenc +y Value [Hz]" +388.0;ProcessSetup._CIPTP301MinLevel;;REAL;2.500000e+01;2.500000e+01;"Syrup Tank M +inimum Level In CIP" +392.0;ProcessSetup._CIPTP301MaxLevel;;REAL;4.500000e+01;4.500000e+01;"Syrup Tank M +aximum Level In CIP" +396.0;ProcessSetup._RinseRMM301OV;;REAL;1.000000e+01;1.000000e+01;"Water Valve +Opening Duri ng Rinse" +400.0;ProcessSetup._RinseRMP302OV;;REAL;1.400000e+01;1.400000e+01;"Syrup Valve +Opening Duri ng Rinse" +404.0;ProcessSetup._RinseTM301Press;;REAL;3.000000e-01;3.000000e-01;"Product Tank +Pressure In Rinse" +408.0;ProcessSetup._RinsePPM303Freq;;REAL;5.000000e+01;5.000000e+01;"Rinse freque +ncy Value [H z]" +412.0;ProcessSetup._DrainTM301Press;;REAL;1.000000e+00;1.000000e+00;"Buffer Tank +Draining Pre ssure" +416.0;ProcessSetup._KRecBlendError;;REAL;2.000000e+00;2.000000e+00;"Blend Error +Recovery CON STANT" +420.0;ProcessSetup._KRecCarboCO2Error;;REAL;2.000000e+00;2.000000e+00;"Carbonation +Error Recove ry Constant" +424.0;ProcessSetup._MaxBlendError;;REAL;1.000000e+02;1.000000e+02;"Blend Error +Maximum Valu e" +428.0;ProcessSetup._MaxCarboCO2Error;;REAL;5.000000e+02;5.000000e+02;"Carbonation +Error Maximu m Value" +432.0;ProcessSetup._StartUpBrixExtraWater;;REAL;4.700000e+01;4.700000e+01; +436.0;ProcessSetup._StartUpCO2ExtraWater;;REAL;8.000000e+00;8.000000e+00; +440.0;ProcessSetup._StartUpPPM303Freq;;REAL;2.000000e+01;2.000000e+01;"Start Up fre +quency Value [Hz]" +444.0;ProcessSetup._SyrupRoomTank;;INT;1;1; +446.0;ProcessSetup._SyrupRunOutLiters;;REAL;2.900000e+02;2.900000e+02; +450.0;ProcessSetup._InjCO2Press_Offset;;REAL;5.000000e-01;5.000000e-01; +454.0;ProcessSetup._InjCO2Press_MinFlow;;REAL;4.500000e+02;4.500000e+02; +458.0;ProcessSetup._InjCO2Press_MaxFlow;;REAL;2.500000e+03;2.500000e+03; +462.0;ProcessSetup._CarboCO2Pressure;;REAL;1.250000e+01;1.250000e+01;"CO2 Pressure +Infeed Line" +466.0;ProcessSetup._N2MinPressure;;REAL;1.000000e+00;1.000000e+00;"N2 Minimum P +ressure Infe ed Line" +470.0;ProcessSetup._DiffSensor_Height;;REAL;3.950000e+02;3.950000e+02;"Sensor Heigh +t from Soil [mm]" +474.0;ProcessSetup._DiffSensor_DeltaHeight;;REAL;-2.500000e+01;-2.500000e+01;"Sensor Plate +s Height Dif ference [mm]" +478.0;ProcessSetup._DiffSensor_Offset;;REAL;3.618000e+01;3.618000e+01;"Sensor Offse +t Read with zero pressur e (all valve s open) in [ mm]" +482.0;ProcessSetup._FillingValveHeight;;REAL;1.400000e+03;1.400000e+03;"Filling Valv +e Height fro m soil [mm]" +486.0;ProcessSetup._FillerDiameter;;REAL;2.520000e+03;2.520000e+03;"Filler Carou +sel Diameter [mm]" +490.0;ProcessSetup._FillingValveNum;;INT;91;91;"Filling Valv +es Number" +492.0;ProcessSetup._FillerProdPipeDN;;REAL;1.000000e+02;1.000000e+02; +496.0;ProcessSetup._FillerProdPipeMass;;REAL;1.600000e+02;1.600000e+02; +500.0;ProcessSetup._FillingTime;;REAL;3.200000e+00;3.200000e+00; +504.0;ProcessSetup._TM301Height_0;;REAL;1.050000e+03;1.050000e+03;"Level at 0% +Tank Level Height in mm" +508.0;ProcessSetup._TM301LevelPerc_2;;REAL;4.600000e+01;4.600000e+01;"Second level +percentage" +512.0;ProcessSetup._TM301Height_2;;REAL;1.625000e+03;1.625000e+03;"Second level +Height in m m" +516.0;ProcessSetup._RVN304Factor;;REAL;1.000000e+00;1.000000e+00;"DeareationFl +ow/WaterFlow" +520.0;ProcessSetup._DrainTM301Flushing;;REAL;1.300000e+00;1.300000e+00; +524.0;ProcessSetup._FirstProdExtraBrix;;REAL;5.000000e-02;5.000000e-02; +528.0;ProcessSetup._FirstProdDietExtraSyr;;REAL;1.400000e-03;1.400000e-03; +532.0;ProcessSetup._EndProdLastSyrlt;;REAL;0.000000e+00;0.000000e+00;"End Producti +on Last syru p liters" +536.0;ProcessSetup._TM301DrainSt0Time;;WORD;W#16#A;W#16#A;sec +538.0;ProcessSetup._TM301DrainSt1Time;;WORD;W#16#50;W#16#50;sec +540.0;ProcessSetup._ProdPipeRunOutSt0Time;;WORD;W#16#1;W#16#1;sec +542.0;ProcessSetup._RMM301ProdPipeRunOu;;REAL;3.000000e+01;3.000000e+01; +546.0;ProcessSetup._RMP302ProdPipeRunOu;;REAL;4.000000e+01;4.000000e+01; +550.0;ProcessSetup._ProdPipeRunOutAmount;;REAL;3.000000e+01;3.000000e+01; +554.0;ProcessSetup._TM301RunOutChiller;;REAL;5.000000e+00;5.000000e+00; +558.0;ProcessSetup._MinSpeedNominalProd;;REAL;4.000000e-01;4.000000e-01;"Min Speed fo +r Nominal Pr oduction" +562.0;ProcessSetup._MinSpeedSlowProd;;REAL;3.000000e-01;3.000000e-01;"Min Speed fo +r Very Low P roduction" +566.0;ProcessSetup._FastChgOvrTM301DrnPrss;;REAL;9.000000e-01;9.000000e-01;"Fast Change +Over Product Tank Draini +ng Pressure +in Blendfill" +570.0;ProcessSetup._CIPTN301MinLevel;;REAL;3.500000e+01;3.500000e+01;"Deaireator T +ank Minimum Level In CIP" +574.0;ProcessSetup._CIPTN301MaxLevel;;REAL;6.000000e+01;6.000000e+01;"Deaireator T +ank Maximum Level In CIP" +578.0;ProcessSetup._ProdPPN304Freq;;REAL;5.000000e+01;5.000000e+01; +582.0;ProcessSetup._GAS2InjectionPress;;REAL;4.000000e+00;4.000000e+00; +586.0;ProcessSetup._BaialageRVM301OVMax;;REAL;2.000000e+01;2.000000e+01;"Baialage Pro +duction Flow Multiplier" +590.0;ProcessSetup._RinsePPN301Freq;;REAL;5.000000e+00;5.000000e+00; +594.0;ProcessSetup._CIPPPN301Freq;;REAL;5.000000e+00;5.000000e+00; +598.0;ProcessSetup._RinsePPP302Freq;;REAL;5.000000e+00;5.000000e+00; +602.0;ProcessSetup._CIPPPP302Freq;;REAL;5.000000e+00;5.000000e+00; +606.0;ProcessSetup._PercSyrupBrixSyrStarUp;;REAL;2.500000e+01;2.500000e+01; +610.0;ProcessSetup._RefTempCoolingCTRL;;REAL;0.000000e+00;0.000000e+00; +614.0;ProcessSetup._H2OSerpPrimingVolume;;REAL;1.500000e+02;1.500000e+02;"Water Serpen +tine Volume ++ Water Chil ler Volume" +618.0;ProcessSetup._AVN301_Nozzle_Kv;;REAL;1.650000e+02;1.650000e+02;"AVN301 Nozzl +e Kv" +622.0;ProcessSetup._AVN302_Nozzle_Kv;;REAL;2.600000e+02;2.600000e+02;"AVN302 Nozzl +e Kv" +626.0;ProcessSetup._AVN303_Nozzle_Kv;;REAL;1.650000e+02;1.650000e+02;"AVN303 Nozzl +e Kv" +630.0;ProcessSetup._DeoxSpryball_Kv;;REAL;6.700000e+01;6.700000e+01;"Deox Sprybal +l Kv" +634.0;ProcessSetup._PremixedLineDrainTime;;INT;300;300;"Premixed Pro +duct Line Dr ain Time" +636.0;ProcessSetup._PPN301_H_MaxFlow;;REAL;9.000000e+01;9.000000e+01;"PPN301 Pump +Head with Ma x Flow [m]" +640.0;ProcessSetup._PPN301_H_MinFlow;;REAL;8.700000e+01;8.700000e+01;"PPN301 Pump +Head with Mi n Flow [m]" +644.0;ProcessSetup._PPN301_MaxFlow;;REAL;5.070000e+02;5.070000e+02;"PPN301 Max F +low [l/min]" +648.0;ProcessSetup._PPN301_MinFlow;;REAL;2.110000e+02;2.110000e+02;"PPN301 Min F +low [l/min]" +652.0;ProcessSetup._PPP302_H_MaxFlow;;REAL;8.600000e+01;8.600000e+01;"PPP302 Pump +Head with Ma x Flow [m]" +656.0;ProcessSetup._PPP302_H_MinFlow;;REAL;8.500000e+01;8.500000e+01;"PPP302 Pump +Head with Mi n Flow [m]" +660.0;ProcessSetup._PPP302_MaxFlow;;REAL;1.150000e+02;1.150000e+02;"PPP302 Max F +low [l/min]" +664.0;ProcessSetup._PPP302_MinFlow;;REAL;3.200000e+01;3.200000e+01;"PPP302 Min F +low [l/min]" +668.0;ProcessSetup._RinsePPM306Freq;;REAL;5.000000e+00;5.000000e+00; +672.0;ProcessSetup._CIPPPM306Freq;;REAL;5.000000e+00;5.000000e+00; +676.0;ProcessSetup._PPM307_H_MaxFlow;;REAL;0.000000e+00;0.000000e+00;"PPM307 Pump +Head with Ma x Flow [m]" +680.0;ProcessSetup._PPM307_H_MinFlow;;REAL;0.000000e+00;0.000000e+00;"PPM307 Pump +Head with Mi n Flow [m]" +684.0;ProcessSetup._PPM307_MaxFlow;;REAL;0.000000e+00;0.000000e+00;"PPM307 Max F +low [l/min]" +688.0;ProcessSetup._PPM307_MinFlow;;REAL;0.000000e+00;0.000000e+00;"PPM307 Min F +low [l/min]" +692.0;ProcessSetup._Temp0_VacuumCtrl;;REAL;1.800000e+01;1.800000e+01;"PPN304 Targe +t Temperatur e +- OPTION +PPN304 Sterl ing Type" +696.0;ProcessSetup._Temp1_VacuumCtrl;;REAL;2.000000e+00;2.000000e+00;"PPN304 High +Treshold Tem perature Del ta - OPTION +PPN304 Sterl +ing Type" +700.0;ProcessSetup._Temp2_VacuumCtrl;;REAL;2.000000e+00;2.000000e+00;"PPN304 Low T +reshold Temp erature Delt a - OPTION +PPN304 Sterl +ing Type" +704.0;ProcessSetup._Temp3_VacuumCtrl;;REAL;5.000000e+01;5.000000e+01;"PPN304 Warni +ng Temperatu re +- OPTION +PPN304 Sterl ing Type" +708.0;ProcessSetup._Temp4_VacuumCtrl;;REAL;5.000000e+01;5.000000e+01;"PPN304 Alarm +Temperature +- OPTION +PPN304 Sterl ing Type" +712.0;ProcessSetup._T1_VacuumCtrl;;DINT;L#1500;L#1500;"PPN304 Time +1 [msec] +- OPTION +PPN304 Sterl ing Type" +716.0;ProcessSetup._T2_VacuumCtrl;;DINT;L#1500;L#1500;"PPN304 Time +2 [msec] +- OPTION +PPN304 Sterl ing Type" +720.0;ProcessSetup._T3_VacuumCtrl;;DINT;L#1000;L#1000;"PPN304 Time +3 [msec] +- OPTION +PPN304 Sterl ing Type" +724.0;ProcessSetup._T4_VacuumCtrl;;DINT;L#1000;L#1000;"PPN304 Time +4 [msec] +- OPTION +PPN304 Sterl ing Type" +728.0;ProcessSetup._ICS_VolDosWorkTimePAA;;INT;30;30;"ICS - DS - D +osing Workin g Time [sec]" +730.0;ProcessSetup._ICS_VolPauseTimePAA;;INT;30;30;"ICS - DS - D +osing Pause Time [sec]" +732.0;ProcessSetup._ICS_PAAPulseWeight;;INT;10;10;"ICS - DS - P +AA Pulse Wei ght [(L/Puls e)/100]" +734.0;ProcessSetup._ICS_CausticPulseWeight;;INT;10;10;"ICS - DS - C +austic Pulse Weight [(L/ +Pulse)/100]" +736.0;ProcessSetup._ICS_AcidPulseWeight;;INT;10;10;"ICS - DS - A +cid Pulse We ight [(L/Pul se)/100]" +738.0;ProcessSetup._ICS_VolumeRestOfLine;;REAL;3.500000e+02;3.500000e+02;"ICS - DS - V +olume of the Rest of the Line (Fille +r + Piping) +[L]" +742.0;ProcessSetup._ICS_VolDosWorkTimeCaus;;INT;30;30;"ICS - DS - D +osing Workin g Time [sec]" +744.0;ProcessSetup._ICS_VolDosPauseTimeCaus;;INT;30;30;"ICS - DS - D +osing Pause Time [sec]" +746.0;ProcessSetup._ICS_VolDosWorkTimeAcid;;INT;30;30;"ICS - DS - D +osing Workin g Time [sec]" +748.0;ProcessSetup._ICS_VolDosPauseTimeAcid;;INT;30;30;"ICS - DS - D +osing Pause Time [sec]" +750.0;ProcessSetup._ICS_ConcDosWorkTimeCaus;;INT;30;30;"ICS - DS - D +osing Workin g Time [sec]" +752.0;ProcessSetup._ICS_ConcDosPausTimeCaus;;INT;30;30;"ICS - DS - D +osing Pause Time [sec]" +754.0;ProcessSetup._ICS_ConcDosWorkTimeAcid;;INT;30;30;"ICS - DS - D +osing Workin g Time [sec]" +756.0;ProcessSetup._ICS_ConcDosPausTimeAcid;;INT;30;30;"ICS - DS - D +osing Pause Time [sec]" +758.0;ProcessSetup._RinsePPM307Freq;;REAL;3.000000e+01;3.000000e+01; +762.0;ProcessSetup._CIPPPM307Freq;;REAL;3.000000e+01;3.000000e+01; +766.0;ProcessSetup._CIP2StepTN301Lvl;;REAL;0.000000e+00;0.000000e+00;"Local CIP - +2 Step loadi ng TN301 Lev el" +770.0;ProcessSetup._CIP2StepTM301Lvl;;REAL;0.000000e+00;0.000000e+00;"Local CIP - +2 Step loadi ng TM301 Lev el" +774.0;ProcessSetup._CIP2StepTP301Lvl;;REAL;0.000000e+00;0.000000e+00;"Local CIP - +2 Step loadi ng TP301 Lev el" +778.0;ProcessSetup._PumpNominalFreq;;REAL;5.000000e+01;5.000000e+01;"50.0 Hz or 6 +0.0 Hz" +782.0;_SwitchOff_DensityOK;;BOOL;FALSE;FALSE; diff --git a/backend/script_groups/S7_DB_Utils/db1001_format.db.txt b/backend/script_groups/S7_DB_Utils/db1001_format.db.txt new file mode 100644 index 0000000..46137f3 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/db1001_format.db.txt @@ -0,0 +1,557 @@ +TYPE "Recipe_Prod" +FAMILY : DataType +VERSION : 0.1 + + + STRUCT + _Name : STRING [32 ] := ' '; + _EnProdTemp : BOOL ; + _SyrFlushing : BOOL ; //Ex_EnDeaireation --> DELETED - AVP320 VALVE OPEN + _GAS2_Injection : BOOL ; //0 = GAS2 not present; 1 = GAS2 present + _Eq_Pression_Selected : BOOL ; + _DeoxStripEn : BOOL ; //******Deairation with Strip Enable + _DeoxVacuumEn : BOOL ; //******Deairation with Vacuum + _DeoxPreMixed : BOOL ; //******Deairation of Premixed Product + _EnBlowOffProdPipeCO2Fil : BOOL ; + _WaterSelection : BYTE ; + _FillerNextRecipeNum : BYTE ; + _BottleShape : BYTE ; + _Type : INT := 1; //1= DIET; 2= REGULAR; 3= RATIO; 4= WATER + _ProdMeterRecipeNum : INT ; + _SyrupBrix : REAL := 5.000000e+01; + _SyrupDensity : REAL := 1.255800e+00; + _SyrupFactor : REAL := 1.000000e+00; + _ProductBrix : REAL := 1.045000e+01; + _ProductionRate : REAL := 9.000000e+02; + _Ratio : REAL := 2.000000e+01; + _ProdBrixOffset : REAL ; + _CO2Vols : REAL ; + _CO2Fact : REAL := 1.000000e+00; + _ProdTankPress : REAL := 1.000000e+00; + _SP_ProdTemp : REAL := 1.000000e+01; + _PrdTankMinLevel : REAL := 1.000000e+01; + _WaterValveSave : REAL ; + _SyrupValveSave : REAL ; + _CarboCO2ValveSave : REAL ; + _ProdMeterHighBrix : REAL ; + _ProdMeterLowBrix : REAL ; + _ProdMeterHighCO2 : REAL ; + _ProdMeterLowCO2 : REAL ; + _ProdMeter_ZeroCO2 : REAL ; + _ProdMeter_ZeroBrix : REAL ; + _ProdHighCond : REAL ; + _ProdLowCond : REAL ; + _BottleSize : REAL ; + _FillingValveHead_SP : REAL ; + _SyrMeter_ZeroBrix : REAL ; + _FirstProdExtraCO2Fact : REAL := 9.700000e-01; + _Gas2Vols : REAL ; + _Gas2Fact : REAL := 1.000000e+00; + _SyrupPumpPressure : REAL ; //******Syrup Pump Pressure SP + _WaterPumpPressure : REAL ; //******Water Pump Pressure SP + _CO2_Air_N2_PressSelect : INT ; //1=CO2; 2=CO2+SterilAir; 3=CO2+N2 - Pressure Tank Selection + _KFactRVM304BlowOff : REAL ; + _ProdRecircPumpFreq : REAL ; + _ProdBoosterPumpPress : REAL ; + _ProdSendPumpFreq : REAL ; //******Product Sending Pump Frequency SP + END_STRUCT ; +END_TYPE + +DATA_BLOCK "HMI_Blender_Parameters" +TITLE = +{ S7_language := '28(1) Albanese 15.06.2005 17:07:04' } +FAMILY : Resource +VERSION : 0.0 + + + STRUCT + Processor_Options : STRUCT + Blender_OPT : STRUCT + _ModelNum : INT := 6; + _CO2_Offset : REAL := 4.500000e-01; + _MaxSyrDeltaBrix : REAL := 8.000000e-01; + _BrixMeter : BOOL := TRUE; + Spare101 : BOOL ; + _TrackH2OEnable : BOOL ; + _PAmPDSType : BOOL ; //0)Cobrix 2000 1)Carbo 2000 + _HistoricalTrends : BOOL := TRUE; //0)Not Present 1)Present + _PowerMeter : BOOL ; //0)Not Present 1)Present + _Report : BOOL := TRUE; //0)Not Present 1)Present + _Balaiage : BOOL ; + _Valves_FullFeedback : BOOL := TRUE; //Valves control Full feedback + _Valves_SingleFeedback : BOOL ; //Valves control Single feedback + _PumpsSafetySwitches : BOOL ; //Pumps with Safety Switches + _SurgeProtectionAct : BOOL ; + _DBC_Type : BOOL ; //0) Deox,Carbo,Blend 1)Deox,Blend,Carbo + _CO2InletMeter : BOOL := TRUE; //0)Not Present 1)Present + _ProductO2Meter : BOOL ; //0)Not Present 1)Present + _CopressedAirInletMeter : BOOL ; //0)Not Present 1)Present + _MeterType : INT := 6; //1)Maselli 2)AntoonPaar 3)4-20mA 4)UC05 UR22 5)mPDSPA 6)MR02 + _MeterReceiveOnly : BOOL ; + _SyrBrixMeter : BOOL ; + _Flooding_Start_Up : BOOL ; //0)Not Selected 1)Selected + _FastChangeOverEnabled : BOOL := TRUE; + _WaterInletMeter : BOOL ; //0)Not Present 1)Present + _BlendFillSystem : BOOL := TRUE; + _TrackFillerSpeed : BOOL := TRUE; + _SignalExchange : INT := 1; //FILLER - 0= Hardwire; 1= Ethernet + _CoolerPresent : BOOL := TRUE; + _CoolerControl : INT := 4; //0)External 1)Water 2)Product 3)Water+Product-2 Ctrl 4)Water+Product-1 Ctrl + _CoolerType : INT ; //0)Glycol 1)Ammonia + _LocalCIP : BOOL ; + _ICS_CustomerHotWater : BOOL ; //0)No Hot Water from Customer 1)Hot Water from Customer Available + _ICS_CustomerChemRecov : BOOL ; //0)No Customer's Chemicals Recovery 1)Customer's Chemicals Recovery Available + _CIPSignalExchange : BOOL ; //CIP - 0= Hardwire; 1= Ethernet + _ICS_CustomerChemicals : BOOL ; //0)Chemicals from ICS 1)Chemicals from Customer + _CarboPresent : BOOL := TRUE; + _InverterSyrupPumpPPP302 : BOOL ; //0)Not Present 1)Present + _InverterWaterPumpPPN301 : BOOL ; //0)Not Present 1)Present + _DoubleDeair : BOOL := TRUE; + _DeairPreMixed : BOOL ; //Deox Premixed Inlet + _Deaireation : BOOL := TRUE; //0)SAG 1)SAE/SAF + _StillWaterByPass : BOOL ; + _ManifoldSetting : BOOL := TRUE; //0)Manual 1)Automatic + _InverterProdPumpPPM303 : BOOL ; + _SidelCip : BOOL ; + _EthernetCom_CpuPN_CP : BOOL := TRUE; //0)Comunication with CP 1)Comunication with CPU PN + _2ndOutlet : INT ; //0)No 2nd Outlet 1)2nd Outlet No Standalone 2)2nd Outlet Standalone + _Promass : INT := 2; + _WaterPromass : BOOL := TRUE; //0)Promag 1)Promass + _ProductConductimeter : BOOL ; + _ICS_CustomerH2ORecov : BOOL ; //0)No Customer's H2O Recovery 1)Customer's H2O Recovery Available + Spare303 : BOOL ; + _CO2_GAS2_Injection : BOOL ; //0)Only CO2 Injection 1)GAS2 Injection + _InverterVacuuPumpPPN304 : BOOL ; //0)Not Present 1)Present + _InverterBoostPumpPPM307 : BOOL ; //0)Not Present 1)Present + _RunOut_Water : BOOL := TRUE; //0)Syrup Runout without Water 1)Syrup runout with Water pushing + _FlowMeterType : BOOL ; //0)Endrees Hauser -- 1)Micromotion + _SidelFiller : BOOL ; //0)Filler Simonazzi -- 1)Filler Sidel Filling + _Simulation : BOOL ; + _ProductCoolingCTRL : BOOL ; //0)none 1) TTM307 + _ChillerCTRL : BOOL ; //Chiller Pressure Cross Control + _CO2_SterileFilter : BOOL := TRUE; //CO2 Inlet with Steril Filter + _InverterRecirPumpPPM306 : BOOL ; //0)Not Present 1)Present + _ProdPressReleaseRVM304 : BOOL ; //0)Not Present 1)Present + _VacuumPump : INT := 1; //0)None 1)Sterling 2)Nash Elmo + _GAS2InjectionType : INT ; //0)None 1)N2 2)Steril Air + _InjectionPress_Ctrl : INT := 1; //0)Manual 1)Norgren v1 2)Norgren v2 + _ProdPressureType : INT ; //0)Only CO2 1)CO2+SterilAir 2)CO2+N2 + _CIPHeatType : INT ; //0)Steam 1)Electric + _EHS_NrRes : INT := 6; //Number of Heat Resistances + END_STRUCT ; + END_STRUCT ; + Spare1 : ARRAY [1 .. 9 ] OF INT ; + _RVM301_DeadBand : REAL := 5.000000e-02; + _RVM301_Kp : REAL := 9.000000e+01; + Actual_Recipe_Parameters : "Recipe_Prod"; + Spare2 : ARRAY [1 .. 5 ] OF INT ; + Next_Recipe_Name : STRING [32 ] := ' '; + Next_Recipe_Number : INT ; + Spare3 : ARRAY [1 .. 18 ] OF INT ; + ProcessSetup : STRUCT + Spare000 : REAL ; + Spare040 : REAL ; + _KWaterLoss : REAL := 1.000000e-03; //Friction Loss Constant in Serpentine + _KSyrupLoss : REAL := 7.800000e-03; //Friction Loss Constant in Syrup Pipe + _KProdLoss : REAL := 1.390000e-02; //Pressure Loss Factor + _KPPM303 : REAL := 5.700000e+00; //Frequency Overpressure Pump P3 Constant [Hz/mm] + _BaialageRVM301OVMin : REAL := 2.000000e+00; //Baialage Minimum Flow (Nm3/h) + _SyrupLinePressure : REAL := 2.200000e+00; //Syrup Line pressure at VEP2 valve + _CIPRMM301OV : REAL := 1.000000e+01; //Water Valve Opening During CIP + _CIPRMP302OV : REAL := 1.500000e+01; //Syrup Valve Opening During CIP + _CIPTM301MinLevel : REAL := 3.500000e+01; //Product Tank Minimum Level In CIP + _CIPTM301MaxLevel : REAL := 5.500000e+01; //Product Tank Maximum Level In CIP + _CIPPPM303Freq : REAL := 5.000000e+01; //CIP frequency Value [Hz] + _CIPTP301MinLevel : REAL := 2.500000e+01; //Syrup Tank Minimum Level In CIP + _CIPTP301MaxLevel : REAL := 4.500000e+01; //Syrup Tank Maximum Level In CIP + _RinseRMM301OV : REAL := 1.000000e+01; //Water Valve Opening During Rinse + _RinseRMP302OV : REAL := 1.400000e+01; //Syrup Valve Opening During Rinse + _RinseTM301Press : REAL := 3.000000e-01; //Product Tank Pressure In Rinse + _RinsePPM303Freq : REAL := 5.000000e+01; //Rinse frequency Value [Hz] + _DrainTM301Press : REAL := 1.000000e+00; //Buffer Tank Draining Pressure + _KRecBlendError : REAL := 2.000000e+00; //Blend Error Recovery CONSTANT + _KRecCarboCO2Error : REAL := 2.000000e+00; //Carbonation Error Recovery Constant + _MaxBlendError : REAL := 1.000000e+02; //Blend Error Maximum Value + _MaxCarboCO2Error : REAL := 5.000000e+02; //Carbonation Error Maximum Value + _StartUpBrixExtraWater : REAL := 4.700000e+01; + _StartUpCO2ExtraWater : REAL := 8.000000e+00; + _StartUpPPM303Freq : REAL := 2.000000e+01; //Start Up frequency Value [Hz] + _SyrupRoomTank : INT := 1; + _SyrupRunOutLiters : REAL := 2.900000e+02; + _InjCO2Press_Offset : REAL := 5.000000e-01; + _InjCO2Press_MinFlow : REAL := 4.500000e+02; + _InjCO2Press_MaxFlow : REAL := 2.500000e+03; + _CarboCO2Pressure : REAL := 1.250000e+01; //CO2 Pressure Infeed Line + _N2MinPressure : REAL := 1.000000e+00; //N2 Minimum Pressure Infeed Line + _DiffSensor_Height : REAL := 3.950000e+02; //Sensor Height from Soil [mm] + _DiffSensor_DeltaHeight : REAL := -2.500000e+01; //Sensor Plates Height Difference [mm] + _DiffSensor_Offset : REAL := 3.618000e+01; //Sensor Offset Read with zero pressure (all valves open) in [mm] + _FillingValveHeight : REAL := 1.400000e+03; //Filling Valve Height from soil [mm] + _FillerDiameter : REAL := 2.520000e+03; //Filler Carousel Diameter [mm] + _FillingValveNum : INT := 91; //Filling Valves Number + _FillerProdPipeDN : REAL := 1.000000e+02; + _FillerProdPipeMass : REAL := 1.600000e+02; + _FillingTime : REAL := 3.200000e+00; + _TM301Height_0 : REAL := 1.050000e+03; //Level at 0% Tank Level Height in mm + _TM301LevelPerc_2 : REAL := 4.600000e+01; //Second level percentage + _TM301Height_2 : REAL := 1.625000e+03; //Second level Height in mm + _RVN304Factor : REAL := 1.000000e+00; //DeareationFlow/WaterFlow + _DrainTM301Flushing : REAL := 1.300000e+00; + _FirstProdExtraBrix : REAL := 5.000000e-02; + _FirstProdDietExtraSyr : REAL := 1.400000e-03; + _EndProdLastSyrlt : REAL ; //End Production Last syrup liters + _TM301DrainSt0Time : WORD := W#16#A; //sec + _TM301DrainSt1Time : WORD := W#16#50; //sec + _ProdPipeRunOutSt0Time : WORD := W#16#1; //sec + _RMM301ProdPipeRunOu : REAL := 3.000000e+01; + _RMP302ProdPipeRunOu : REAL := 4.000000e+01; + _ProdPipeRunOutAmount : REAL := 3.000000e+01; + _TM301RunOutChiller : REAL := 5.000000e+00; + _MinSpeedNominalProd : REAL := 4.000000e-01; //Min Speed for Nominal Production + _MinSpeedSlowProd : REAL := 3.000000e-01; //Min Speed for Very Low Production + _FastChgOvrTM301DrnPrss : REAL := 9.000000e-01; //Fast Change Over Product Tank Draining Pressure in Blendfill + _CIPTN301MinLevel : REAL := 3.500000e+01; //Deaireator Tank Minimum Level In CIP + _CIPTN301MaxLevel : REAL := 6.000000e+01; //Deaireator Tank Maximum Level In CIP + _ProdPPN304Freq : REAL := 5.000000e+01; + _GAS2InjectionPress : REAL := 4.000000e+00; + _BaialageRVM301OVMax : REAL := 2.000000e+01; //Baialage Production Flow Multiplier + _RinsePPN301Freq : REAL := 5.000000e+00; + _CIPPPN301Freq : REAL := 5.000000e+00; + _RinsePPP302Freq : REAL := 5.000000e+00; + _CIPPPP302Freq : REAL := 5.000000e+00; + _PercSyrupBrixSyrStarUp : REAL := 2.500000e+01; + _RefTempCoolingCTRL : REAL ; + _H2OSerpPrimingVolume : REAL := 1.500000e+02; //Water Serpentine Volume + Water Chiller Volume + _AVN301_Nozzle_Kv : REAL := 1.650000e+02; //AVN301 Nozzle Kv + _AVN302_Nozzle_Kv : REAL := 2.600000e+02; //AVN302 Nozzle Kv + _AVN303_Nozzle_Kv : REAL := 1.650000e+02; //AVN303 Nozzle Kv + _DeoxSpryball_Kv : REAL := 6.700000e+01; //Deox Spryball Kv + _PremixedLineDrainTime : INT := 300; //Premixed Product Line Drain Time + _PPN301_H_MaxFlow : REAL := 9.000000e+01; //PPN301 Pump Head with Max Flow [m] + _PPN301_H_MinFlow : REAL := 8.700000e+01; //PPN301 Pump Head with Min Flow [m] + _PPN301_MaxFlow : REAL := 5.070000e+02; //PPN301 Max Flow [l/min] + _PPN301_MinFlow : REAL := 2.110000e+02; //PPN301 Min Flow [l/min] + _PPP302_H_MaxFlow : REAL := 8.600000e+01; //PPP302 Pump Head with Max Flow [m] + _PPP302_H_MinFlow : REAL := 8.500000e+01; //PPP302 Pump Head with Min Flow [m] + _PPP302_MaxFlow : REAL := 1.150000e+02; //PPP302 Max Flow [l/min] + _PPP302_MinFlow : REAL := 3.200000e+01; //PPP302 Min Flow [l/min] + _RinsePPM306Freq : REAL := 5.000000e+00; + _CIPPPM306Freq : REAL := 5.000000e+00; + _PPM307_H_MaxFlow : REAL ; //PPM307 Pump Head with Max Flow [m] + _PPM307_H_MinFlow : REAL ; //PPM307 Pump Head with Min Flow [m] + _PPM307_MaxFlow : REAL ; //PPM307 Max Flow [l/min] + _PPM307_MinFlow : REAL ; //PPM307 Min Flow [l/min] + _Temp0_VacuumCtrl : REAL := 1.800000e+01; //PPN304 Target Temperature - OPTION PPN304 Sterling Type + _Temp1_VacuumCtrl : REAL := 2.000000e+00; //PPN304 High Treshold Temperature Delta - OPTION PPN304 Sterling Type + _Temp2_VacuumCtrl : REAL := 2.000000e+00; //PPN304 Low Treshold Temperature Delta - OPTION PPN304 Sterling Type + _Temp3_VacuumCtrl : REAL := 5.000000e+01; //PPN304 Warning Temperature - OPTION PPN304 Sterling Type + _Temp4_VacuumCtrl : REAL := 5.000000e+01; //PPN304 Alarm Temperature - OPTION PPN304 Sterling Type + _T1_VacuumCtrl : DINT := L#1500; //PPN304 Time 1 [msec] - OPTION PPN304 Sterling Type + _T2_VacuumCtrl : DINT := L#1500; //PPN304 Time 2 [msec] - OPTION PPN304 Sterling Type + _T3_VacuumCtrl : DINT := L#1000; //PPN304 Time 3 [msec] - OPTION PPN304 Sterling Type + _T4_VacuumCtrl : DINT := L#1000; //PPN304 Time 4 [msec] - OPTION PPN304 Sterling Type + _ICS_VolDosWorkTimePAA : INT := 30; //ICS - DS - Dosing Working Time [sec] + _ICS_VolPauseTimePAA : INT := 30; //ICS - DS - Dosing Pause Time [sec] + _ICS_PAAPulseWeight : INT := 10; //ICS - DS - PAA Pulse Weight [(L/Pulse)/100] + _ICS_CausticPulseWeight : INT := 10; //ICS - DS - Caustic Pulse Weight [(L/Pulse)/100] + _ICS_AcidPulseWeight : INT := 10; //ICS - DS - Acid Pulse Weight [(L/Pulse)/100] + _ICS_VolumeRestOfLine : REAL := 3.500000e+02; //ICS - DS - Volume of the Rest of the Line (Filler + Piping) [L] + _ICS_VolDosWorkTimeCaus : INT := 30; //ICS - DS - Dosing Working Time [sec] + _ICS_VolDosPauseTimeCaus : INT := 30; //ICS - DS - Dosing Pause Time [sec] + _ICS_VolDosWorkTimeAcid : INT := 30; //ICS - DS - Dosing Working Time [sec] + _ICS_VolDosPauseTimeAcid : INT := 30; //ICS - DS - Dosing Pause Time [sec] + _ICS_ConcDosWorkTimeCaus : INT := 30; //ICS - DS - Dosing Working Time [sec] + _ICS_ConcDosPausTimeCaus : INT := 30; //ICS - DS - Dosing Pause Time [sec] + _ICS_ConcDosWorkTimeAcid : INT := 30; //ICS - DS - Dosing Working Time [sec] + _ICS_ConcDosPausTimeAcid : INT := 30; //ICS - DS - Dosing Pause Time [sec] + _RinsePPM307Freq : REAL := 3.000000e+01; + _CIPPPM307Freq : REAL := 3.000000e+01; + _CIP2StepTN301Lvl : REAL ; //Local CIP - 2 Step loading TN301 Level + _CIP2StepTM301Lvl : REAL ; //Local CIP - 2 Step loading TM301 Level + _CIP2StepTP301Lvl : REAL ; //Local CIP - 2 Step loading TP301 Level + _PumpNominalFreq : REAL := 5.000000e+01; //50.0 Hz or 60.0 Hz + END_STRUCT ; + _SwitchOff_DensityOK : BOOL ; + END_STRUCT ; +BEGIN + Processor_Options.Blender_OPT._ModelNum := 6; + Processor_Options.Blender_OPT._CO2_Offset := 4.500000e-01; + Processor_Options.Blender_OPT._MaxSyrDeltaBrix := 8.000000e-01; + Processor_Options.Blender_OPT._BrixMeter := TRUE; + Processor_Options.Blender_OPT.Spare101 := FALSE; + Processor_Options.Blender_OPT._TrackH2OEnable := FALSE; + Processor_Options.Blender_OPT._PAmPDSType := FALSE; + Processor_Options.Blender_OPT._HistoricalTrends := TRUE; + Processor_Options.Blender_OPT._PowerMeter := FALSE; + Processor_Options.Blender_OPT._Report := TRUE; + Processor_Options.Blender_OPT._Balaiage := FALSE; + Processor_Options.Blender_OPT._Valves_FullFeedback := TRUE; + Processor_Options.Blender_OPT._Valves_SingleFeedback := FALSE; + Processor_Options.Blender_OPT._PumpsSafetySwitches := FALSE; + Processor_Options.Blender_OPT._SurgeProtectionAct := FALSE; + Processor_Options.Blender_OPT._DBC_Type := FALSE; + Processor_Options.Blender_OPT._CO2InletMeter := TRUE; + Processor_Options.Blender_OPT._ProductO2Meter := FALSE; + Processor_Options.Blender_OPT._CopressedAirInletMeter := FALSE; + Processor_Options.Blender_OPT._MeterType := 6; + Processor_Options.Blender_OPT._MeterReceiveOnly := FALSE; + Processor_Options.Blender_OPT._SyrBrixMeter := FALSE; + Processor_Options.Blender_OPT._Flooding_Start_Up := FALSE; + Processor_Options.Blender_OPT._FastChangeOverEnabled := TRUE; + Processor_Options.Blender_OPT._WaterInletMeter := FALSE; + Processor_Options.Blender_OPT._BlendFillSystem := TRUE; + Processor_Options.Blender_OPT._TrackFillerSpeed := TRUE; + Processor_Options.Blender_OPT._SignalExchange := 1; + Processor_Options.Blender_OPT._CoolerPresent := TRUE; + Processor_Options.Blender_OPT._CoolerControl := 4; + Processor_Options.Blender_OPT._CoolerType := 0; + Processor_Options.Blender_OPT._LocalCIP := FALSE; + Processor_Options.Blender_OPT._ICS_CustomerHotWater := FALSE; + Processor_Options.Blender_OPT._ICS_CustomerChemRecov := FALSE; + Processor_Options.Blender_OPT._CIPSignalExchange := FALSE; + Processor_Options.Blender_OPT._ICS_CustomerChemicals := FALSE; + Processor_Options.Blender_OPT._CarboPresent := TRUE; + Processor_Options.Blender_OPT._InverterSyrupPumpPPP302 := FALSE; + Processor_Options.Blender_OPT._InverterWaterPumpPPN301 := FALSE; + Processor_Options.Blender_OPT._DoubleDeair := TRUE; + Processor_Options.Blender_OPT._DeairPreMixed := FALSE; + Processor_Options.Blender_OPT._Deaireation := TRUE; + Processor_Options.Blender_OPT._StillWaterByPass := FALSE; + Processor_Options.Blender_OPT._ManifoldSetting := TRUE; + Processor_Options.Blender_OPT._InverterProdPumpPPM303 := FALSE; + Processor_Options.Blender_OPT._SidelCip := FALSE; + Processor_Options.Blender_OPT._EthernetCom_CpuPN_CP := TRUE; + Processor_Options.Blender_OPT._2ndOutlet := 0; + Processor_Options.Blender_OPT._Promass := 2; + Processor_Options.Blender_OPT._WaterPromass := TRUE; + Processor_Options.Blender_OPT._ProductConductimeter := FALSE; + Processor_Options.Blender_OPT._ICS_CustomerH2ORecov := FALSE; + Processor_Options.Blender_OPT.Spare303 := FALSE; + Processor_Options.Blender_OPT._CO2_GAS2_Injection := FALSE; + Processor_Options.Blender_OPT._InverterVacuuPumpPPN304 := FALSE; + Processor_Options.Blender_OPT._InverterBoostPumpPPM307 := FALSE; + Processor_Options.Blender_OPT._RunOut_Water := TRUE; + Processor_Options.Blender_OPT._FlowMeterType := TRUE; + Processor_Options.Blender_OPT._SidelFiller := FALSE; + Processor_Options.Blender_OPT._Simulation := FALSE; + Processor_Options.Blender_OPT._ProductCoolingCTRL := FALSE; + Processor_Options.Blender_OPT._ChillerCTRL := FALSE; + Processor_Options.Blender_OPT._CO2_SterileFilter := TRUE; + Processor_Options.Blender_OPT._InverterRecirPumpPPM306 := FALSE; + Processor_Options.Blender_OPT._ProdPressReleaseRVM304 := FALSE; + Processor_Options.Blender_OPT._VacuumPump := 1; + Processor_Options.Blender_OPT._GAS2InjectionType := 0; + Processor_Options.Blender_OPT._InjectionPress_Ctrl := 1; + Processor_Options.Blender_OPT._ProdPressureType := 0; + Processor_Options.Blender_OPT._CIPHeatType := 0; + Processor_Options.Blender_OPT._EHS_NrRes := 6; + Spare1[1] := 0; + Spare1[2] := 0; + Spare1[3] := 0; + Spare1[4] := 0; + Spare1[5] := 0; + Spare1[6] := 0; + Spare1[7] := 0; + Spare1[8] := 0; + Spare1[9] := 0; + _RVM301_DeadBand := 5.000000e-02; + _RVM301_Kp := 9.000000e+01; + Actual_Recipe_Parameters._Name := ''; + Actual_Recipe_Parameters._EnProdTemp := TRUE; + Actual_Recipe_Parameters._SyrFlushing := FALSE; + Actual_Recipe_Parameters._GAS2_Injection := FALSE; + Actual_Recipe_Parameters._Eq_Pression_Selected := FALSE; + Actual_Recipe_Parameters._DeoxStripEn := FALSE; + Actual_Recipe_Parameters._DeoxVacuumEn := TRUE; + Actual_Recipe_Parameters._DeoxPreMixed := FALSE; + Actual_Recipe_Parameters._EnBlowOffProdPipeCO2Fil := FALSE; + Actual_Recipe_Parameters._WaterSelection := B#16#0; + Actual_Recipe_Parameters._FillerNextRecipeNum := B#16#0; + Actual_Recipe_Parameters._BottleShape := B#16#0; + Actual_Recipe_Parameters._Type := 2; + Actual_Recipe_Parameters._ProdMeterRecipeNum := 1; + Actual_Recipe_Parameters._SyrupBrix := 4.625000e+01; + Actual_Recipe_Parameters._SyrupDensity := 1.206908e+00; + Actual_Recipe_Parameters._SyrupFactor := 1.000000e+00; + Actual_Recipe_Parameters._ProductBrix := 1.000000e+01; + Actual_Recipe_Parameters._ProductionRate := 3.800000e+02; + Actual_Recipe_Parameters._Ratio := 4.238896e+00; + Actual_Recipe_Parameters._ProdBrixOffset := 2.500000e-01; + Actual_Recipe_Parameters._CO2Vols := 2.550000e+00; + Actual_Recipe_Parameters._CO2Fact := 9.400000e-01; + Actual_Recipe_Parameters._ProdTankPress := 4.400000e+00; + Actual_Recipe_Parameters._SP_ProdTemp := 1.700000e+01; + Actual_Recipe_Parameters._PrdTankMinLevel := 3.500000e+01; + Actual_Recipe_Parameters._WaterValveSave := 0.000000e+00; + Actual_Recipe_Parameters._SyrupValveSave := 0.000000e+00; + Actual_Recipe_Parameters._CarboCO2ValveSave := 0.000000e+00; + Actual_Recipe_Parameters._ProdMeterHighBrix := 1.030000e+01; + Actual_Recipe_Parameters._ProdMeterLowBrix := 9.830000e+00; + Actual_Recipe_Parameters._ProdMeterHighCO2 := 2.900000e+00; + Actual_Recipe_Parameters._ProdMeterLowCO2 := 2.300000e+00; + Actual_Recipe_Parameters._ProdMeter_ZeroCO2 := 0.000000e+00; + Actual_Recipe_Parameters._ProdMeter_ZeroBrix := 0.000000e+00; + Actual_Recipe_Parameters._ProdHighCond := 0.000000e+00; + Actual_Recipe_Parameters._ProdLowCond := 0.000000e+00; + Actual_Recipe_Parameters._BottleSize := 0.000000e+00; + Actual_Recipe_Parameters._FillingValveHead_SP := 0.000000e+00; + Actual_Recipe_Parameters._SyrMeter_ZeroBrix := 0.000000e+00; + Actual_Recipe_Parameters._FirstProdExtraCO2Fact := 1.020000e+00; + Actual_Recipe_Parameters._Gas2Vols := 0.000000e+00; + Actual_Recipe_Parameters._Gas2Fact := 0.000000e+00; + Actual_Recipe_Parameters._SyrupPumpPressure := 0.000000e+00; + Actual_Recipe_Parameters._WaterPumpPressure := 0.000000e+00; + Actual_Recipe_Parameters._CO2_Air_N2_PressSelect := 0; + Actual_Recipe_Parameters._KFactRVM304BlowOff := 0.000000e+00; + Actual_Recipe_Parameters._ProdRecircPumpFreq := 0.000000e+00; + Actual_Recipe_Parameters._ProdBoosterPumpPress := 0.000000e+00; + Actual_Recipe_Parameters._ProdSendPumpFreq := 0.000000e+00; + Spare2[1] := 0; + Spare2[2] := 0; + Spare2[3] := 0; + Spare2[4] := 0; + Spare2[5] := 0; + Next_Recipe_Name := 'cambio 1$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00'; + Next_Recipe_Number := 0; + Spare3[1] := 0; + Spare3[2] := 0; + Spare3[3] := 0; + Spare3[4] := 0; + Spare3[5] := 0; + Spare3[6] := 0; + Spare3[7] := 0; + Spare3[8] := 0; + Spare3[9] := 0; + Spare3[10] := 0; + Spare3[11] := 0; + Spare3[12] := 0; + Spare3[13] := 0; + Spare3[14] := 0; + Spare3[15] := 0; + Spare3[16] := 0; + Spare3[17] := 0; + Spare3[18] := 0; + ProcessSetup.Spare000 := 0.000000e+00; + ProcessSetup.Spare040 := 0.000000e+00; + ProcessSetup._KWaterLoss := 1.000000e-03; + ProcessSetup._KSyrupLoss := 7.800000e-03; + ProcessSetup._KProdLoss := 1.390000e-02; + ProcessSetup._KPPM303 := 5.700000e+00; + ProcessSetup._BaialageRVM301OVMin := 2.000000e+00; + ProcessSetup._SyrupLinePressure := 2.200000e+00; + ProcessSetup._CIPRMM301OV := 1.000000e+01; + ProcessSetup._CIPRMP302OV := 1.500000e+01; + ProcessSetup._CIPTM301MinLevel := 3.500000e+01; + ProcessSetup._CIPTM301MaxLevel := 5.500000e+01; + ProcessSetup._CIPPPM303Freq := 5.000000e+01; + ProcessSetup._CIPTP301MinLevel := 2.500000e+01; + ProcessSetup._CIPTP301MaxLevel := 4.500000e+01; + ProcessSetup._RinseRMM301OV := 1.000000e+01; + ProcessSetup._RinseRMP302OV := 1.400000e+01; + ProcessSetup._RinseTM301Press := 3.000000e-01; + ProcessSetup._RinsePPM303Freq := 5.000000e+01; + ProcessSetup._DrainTM301Press := 1.000000e+00; + ProcessSetup._KRecBlendError := 2.000000e+00; + ProcessSetup._KRecCarboCO2Error := 2.000000e+00; + ProcessSetup._MaxBlendError := 1.000000e+02; + ProcessSetup._MaxCarboCO2Error := 5.000000e+02; + ProcessSetup._StartUpBrixExtraWater := 4.700000e+01; + ProcessSetup._StartUpCO2ExtraWater := 8.000000e+00; + ProcessSetup._StartUpPPM303Freq := 2.000000e+01; + ProcessSetup._SyrupRoomTank := 1; + ProcessSetup._SyrupRunOutLiters := 2.900000e+02; + ProcessSetup._InjCO2Press_Offset := 5.000000e-01; + ProcessSetup._InjCO2Press_MinFlow := 4.500000e+02; + ProcessSetup._InjCO2Press_MaxFlow := 2.500000e+03; + ProcessSetup._CarboCO2Pressure := 1.250000e+01; + ProcessSetup._N2MinPressure := 1.000000e+00; + ProcessSetup._DiffSensor_Height := 3.950000e+02; + ProcessSetup._DiffSensor_DeltaHeight := -2.500000e+01; + ProcessSetup._DiffSensor_Offset := 3.618000e+01; + ProcessSetup._FillingValveHeight := 1.400000e+03; + ProcessSetup._FillerDiameter := 2.520000e+03; + ProcessSetup._FillingValveNum := 91; + ProcessSetup._FillerProdPipeDN := 1.000000e+02; + ProcessSetup._FillerProdPipeMass := 1.600000e+02; + ProcessSetup._FillingTime := 3.200000e+00; + ProcessSetup._TM301Height_0 := 1.050000e+03; + ProcessSetup._TM301LevelPerc_2 := 4.600000e+01; + ProcessSetup._TM301Height_2 := 1.625000e+03; + ProcessSetup._RVN304Factor := 1.000000e+00; + ProcessSetup._DrainTM301Flushing := 1.300000e+00; + ProcessSetup._FirstProdExtraBrix := 5.000000e-02; + ProcessSetup._FirstProdDietExtraSyr := 1.400000e-03; + ProcessSetup._EndProdLastSyrlt := 0.000000e+00; + ProcessSetup._TM301DrainSt0Time := W#16#A; + ProcessSetup._TM301DrainSt1Time := W#16#50; + ProcessSetup._ProdPipeRunOutSt0Time := W#16#1; + ProcessSetup._RMM301ProdPipeRunOu := 3.000000e+01; + ProcessSetup._RMP302ProdPipeRunOu := 4.000000e+01; + ProcessSetup._ProdPipeRunOutAmount := 3.000000e+01; + ProcessSetup._TM301RunOutChiller := 5.000000e+00; + ProcessSetup._MinSpeedNominalProd := 4.000000e-01; + ProcessSetup._MinSpeedSlowProd := 3.000000e-01; + ProcessSetup._FastChgOvrTM301DrnPrss := 9.000000e-01; + ProcessSetup._CIPTN301MinLevel := 3.500000e+01; + ProcessSetup._CIPTN301MaxLevel := 6.000000e+01; + ProcessSetup._ProdPPN304Freq := 5.000000e+01; + ProcessSetup._GAS2InjectionPress := 4.000000e+00; + ProcessSetup._BaialageRVM301OVMax := 2.000000e+01; + ProcessSetup._RinsePPN301Freq := 5.000000e+00; + ProcessSetup._CIPPPN301Freq := 5.000000e+00; + ProcessSetup._RinsePPP302Freq := 5.000000e+00; + ProcessSetup._CIPPPP302Freq := 5.000000e+00; + ProcessSetup._PercSyrupBrixSyrStarUp := 2.500000e+01; + ProcessSetup._RefTempCoolingCTRL := 0.000000e+00; + ProcessSetup._H2OSerpPrimingVolume := 1.500000e+02; + ProcessSetup._AVN301_Nozzle_Kv := 1.650000e+02; + ProcessSetup._AVN302_Nozzle_Kv := 2.600000e+02; + ProcessSetup._AVN303_Nozzle_Kv := 1.650000e+02; + ProcessSetup._DeoxSpryball_Kv := 6.700000e+01; + ProcessSetup._PremixedLineDrainTime := 300; + ProcessSetup._PPN301_H_MaxFlow := 9.000000e+01; + ProcessSetup._PPN301_H_MinFlow := 8.700000e+01; + ProcessSetup._PPN301_MaxFlow := 5.070000e+02; + ProcessSetup._PPN301_MinFlow := 2.110000e+02; + ProcessSetup._PPP302_H_MaxFlow := 8.600000e+01; + ProcessSetup._PPP302_H_MinFlow := 8.500000e+01; + ProcessSetup._PPP302_MaxFlow := 1.150000e+02; + ProcessSetup._PPP302_MinFlow := 3.200000e+01; + ProcessSetup._RinsePPM306Freq := 5.000000e+00; + ProcessSetup._CIPPPM306Freq := 5.000000e+00; + ProcessSetup._PPM307_H_MaxFlow := 0.000000e+00; + ProcessSetup._PPM307_H_MinFlow := 0.000000e+00; + ProcessSetup._PPM307_MaxFlow := 0.000000e+00; + ProcessSetup._PPM307_MinFlow := 0.000000e+00; + ProcessSetup._Temp0_VacuumCtrl := 1.800000e+01; + ProcessSetup._Temp1_VacuumCtrl := 2.000000e+00; + ProcessSetup._Temp2_VacuumCtrl := 2.000000e+00; + ProcessSetup._Temp3_VacuumCtrl := 5.000000e+01; + ProcessSetup._Temp4_VacuumCtrl := 5.000000e+01; + ProcessSetup._T1_VacuumCtrl := L#1500; + ProcessSetup._T2_VacuumCtrl := L#1500; + ProcessSetup._T3_VacuumCtrl := L#1000; + ProcessSetup._T4_VacuumCtrl := L#1000; + ProcessSetup._ICS_VolDosWorkTimePAA := 30; + ProcessSetup._ICS_VolPauseTimePAA := 30; + ProcessSetup._ICS_PAAPulseWeight := 10; + ProcessSetup._ICS_CausticPulseWeight := 10; + ProcessSetup._ICS_AcidPulseWeight := 10; + ProcessSetup._ICS_VolumeRestOfLine := 3.500000e+02; + ProcessSetup._ICS_VolDosWorkTimeCaus := 30; + ProcessSetup._ICS_VolDosPauseTimeCaus := 30; + ProcessSetup._ICS_VolDosWorkTimeAcid := 30; + ProcessSetup._ICS_VolDosPauseTimeAcid := 30; + ProcessSetup._ICS_ConcDosWorkTimeCaus := 30; + ProcessSetup._ICS_ConcDosPausTimeCaus := 30; + ProcessSetup._ICS_ConcDosWorkTimeAcid := 30; + ProcessSetup._ICS_ConcDosPausTimeAcid := 30; + ProcessSetup._RinsePPM307Freq := 3.000000e+01; + ProcessSetup._CIPPPM307Freq := 3.000000e+01; + ProcessSetup._CIP2StepTN301Lvl := 0.000000e+00; + ProcessSetup._CIP2StepTM301Lvl := 0.000000e+00; + ProcessSetup._CIP2StepTP301Lvl := 0.000000e+00; + ProcessSetup._PumpNominalFreq := 5.000000e+01; + _SwitchOff_DensityOK := FALSE; +END_DATA_BLOCK + diff --git a/backend/script_groups/S7_DB_Utils/description.json b/backend/script_groups/S7_DB_Utils/description.json new file mode 100644 index 0000000..2ef6bd0 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/description.json @@ -0,0 +1,6 @@ +{ + "name": "S7 DB Utilities", + "description": "Utilidades para Trabajar con DBs de Siemens S7", + "version": "1.0", + "author": "Miguel" +} \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/documentation_db_HMI_Blender_Parameters.md b/backend/script_groups/S7_DB_Utils/documentation_db_HMI_Blender_Parameters.md new file mode 100644 index 0000000..8b1dba3 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/documentation_db_HMI_Blender_Parameters.md @@ -0,0 +1,208 @@ +# Documentación para DB: HMI_Blender_Parameters + +| Address | Name | Type | Initial Value | Actual Value | Comment | +|---|---|---|---|---|---| +| 0.0 | Processor_Options | STRUCT | | | | +| 0.0 | Processor_Options.Blender_OPT | STRUCT | | | | +| 0.0 | Processor_Options.Blender_OPT._ModelNum | INT | 6 | 6 | | +| 2.0 | Processor_Options.Blender_OPT._CO2_Offset | REAL | 4.500000e-01 | 4.500000e-01 | | +| 6.0 | Processor_Options.Blender_OPT._MaxSyrDeltaBrix | REAL | 8.000000e-01 | 8.000000e-01 | | +| 10.0 | Processor_Options.Blender_OPT._BrixMeter | BOOL | TRUE | TRUE | | +| 10.1 | Processor_Options.Blender_OPT.Spare101 | BOOL | | FALSE | | +| 10.2 | Processor_Options.Blender_OPT._TrackH2OEnable | BOOL | | FALSE | | +| 10.3 | Processor_Options.Blender_OPT._PAmPDSType | BOOL | | FALSE | 0)Cobrix 2000 1)Carbo 2000 | +| 10.4 | Processor_Options.Blender_OPT._HistoricalTrends | BOOL | TRUE | TRUE | 0)Not Present 1)Present | +| 10.5 | Processor_Options.Blender_OPT._PowerMeter | BOOL | | FALSE | 0)Not Present 1)Present | +| 10.6 | Processor_Options.Blender_OPT._Report | BOOL | TRUE | TRUE | 0)Not Present 1)Present | +| 10.7 | Processor_Options.Blender_OPT._Balaiage | BOOL | | FALSE | | +| 11.0 | Processor_Options.Blender_OPT._Valves_FullFeedback | BOOL | TRUE | TRUE | Valves control Full feedback | +| 11.1 | Processor_Options.Blender_OPT._Valves_SingleFeedback | BOOL | | FALSE | Valves control Single feedback | +| 11.2 | Processor_Options.Blender_OPT._PumpsSafetySwitches | BOOL | | FALSE | Pumps with Safety Switches | +| 11.3 | Processor_Options.Blender_OPT._SurgeProtectionAct | BOOL | | FALSE | | +| 11.4 | Processor_Options.Blender_OPT._DBC_Type | BOOL | | FALSE | 0) Deox,Carbo,Blend 1)Deox,Blend,Carbo | +| 11.5 | Processor_Options.Blender_OPT._CO2InletMeter | BOOL | TRUE | TRUE | 0)Not Present 1)Present | +| 11.6 | Processor_Options.Blender_OPT._ProductO2Meter | BOOL | | FALSE | 0)Not Present 1)Present | +| 11.7 | Processor_Options.Blender_OPT._CopressedAirInletMeter | BOOL | | FALSE | 0)Not Present 1)Present | +| 12.0 | Processor_Options.Blender_OPT._MeterType | INT | 6 | 6 | 1)Maselli 2)AntoonPaar 3)4-20mA 4)UC05 UR22 5)mPDSPA 6)MR02 | +| 14.0 | Processor_Options.Blender_OPT._MeterReceiveOnly | BOOL | | FALSE | | +| 14.1 | Processor_Options.Blender_OPT._SyrBrixMeter | BOOL | | FALSE | | +| 14.2 | Processor_Options.Blender_OPT._Flooding_Start_Up | BOOL | | FALSE | 0)Not Selected 1)Selected | +| 14.3 | Processor_Options.Blender_OPT._FastChangeOverEnabled | BOOL | TRUE | TRUE | | +| 14.4 | Processor_Options.Blender_OPT._WaterInletMeter | BOOL | | FALSE | 0)Not Present 1)Present | +| 14.5 | Processor_Options.Blender_OPT._BlendFillSystem | BOOL | TRUE | TRUE | | +| 14.6 | Processor_Options.Blender_OPT._TrackFillerSpeed | BOOL | TRUE | TRUE | | +| 16.0 | Processor_Options.Blender_OPT._SignalExchange | INT | 1 | 1 | FILLER - 0= Hardwire; 1= Ethernet | +| 18.0 | Processor_Options.Blender_OPT._CoolerPresent | BOOL | TRUE | TRUE | | +| 20.0 | Processor_Options.Blender_OPT._CoolerControl | INT | 4 | 4 | 0)External 1)Water 2)Product 3)Water+Product-2 Ctrl 4)Water+Product-1 Ctrl | +| 22.0 | Processor_Options.Blender_OPT._CoolerType | INT | | 0 | 0)Glycol 1)Ammonia | +| 24.0 | Processor_Options.Blender_OPT._LocalCIP | BOOL | | FALSE | | +| 24.1 | Processor_Options.Blender_OPT._ICS_CustomerHotWater | BOOL | | FALSE | 0)No Hot Water from Customer 1)Hot Water from Customer Available | +| 24.2 | Processor_Options.Blender_OPT._ICS_CustomerChemRecov | BOOL | | FALSE | 0)No Customer's Chemicals Recovery 1)Customer's Chemicals Recovery Available | +| 24.3 | Processor_Options.Blender_OPT._CIPSignalExchange | BOOL | | FALSE | CIP - 0= Hardwire; 1= Ethernet | +| 24.4 | Processor_Options.Blender_OPT._ICS_CustomerChemicals | BOOL | | FALSE | 0)Chemicals from ICS 1)Chemicals from Customer | +| 24.5 | Processor_Options.Blender_OPT._CarboPresent | BOOL | TRUE | TRUE | | +| 24.6 | Processor_Options.Blender_OPT._InverterSyrupPumpPPP302 | BOOL | | FALSE | 0)Not Present 1)Present | +| 24.7 | Processor_Options.Blender_OPT._InverterWaterPumpPPN301 | BOOL | | FALSE | 0)Not Present 1)Present | +| 25.0 | Processor_Options.Blender_OPT._DoubleDeair | BOOL | TRUE | TRUE | | +| 25.1 | Processor_Options.Blender_OPT._DeairPreMixed | BOOL | | FALSE | Deox Premixed Inlet | +| 25.2 | Processor_Options.Blender_OPT._Deaireation | BOOL | TRUE | TRUE | 0)SAG 1)SAE/SAF | +| 25.3 | Processor_Options.Blender_OPT._StillWaterByPass | BOOL | | FALSE | | +| 25.4 | Processor_Options.Blender_OPT._ManifoldSetting | BOOL | TRUE | TRUE | 0)Manual 1)Automatic | +| 25.5 | Processor_Options.Blender_OPT._InverterProdPumpPPM303 | BOOL | | FALSE | | +| 25.6 | Processor_Options.Blender_OPT._SidelCip | BOOL | | FALSE | | +| 25.7 | Processor_Options.Blender_OPT._EthernetCom_CpuPN_CP | BOOL | TRUE | TRUE | 0)Comunication with CP 1)Comunication with CPU PN | +| 26.0 | Processor_Options.Blender_OPT._2ndOutlet | INT | | 0 | 0)No 2nd Outlet 1)2nd Outlet No Standalone 2)2nd Outlet Standalone | +| 28.0 | Processor_Options.Blender_OPT._Promass | INT | 2 | 2 | | +| 30.0 | Processor_Options.Blender_OPT._WaterPromass | BOOL | TRUE | TRUE | 0)Promag 1)Promass | +| 30.1 | Processor_Options.Blender_OPT._ProductConductimeter | BOOL | | FALSE | | +| 30.2 | Processor_Options.Blender_OPT._ICS_CustomerH2ORecov | BOOL | | FALSE | 0)No Customer's H2O Recovery 1)Customer's H2O Recovery Available | +| 30.3 | Processor_Options.Blender_OPT.Spare303 | BOOL | | FALSE | | +| 30.4 | Processor_Options.Blender_OPT._CO2_GAS2_Injection | BOOL | | FALSE | 0)Only CO2 Injection 1)GAS2 Injection | +| 30.5 | Processor_Options.Blender_OPT._InverterVacuuPumpPPN304 | BOOL | | FALSE | 0)Not Present 1)Present | +| 30.6 | Processor_Options.Blender_OPT._InverterBoostPumpPPM307 | BOOL | | FALSE | 0)Not Present 1)Present | +| 30.7 | Processor_Options.Blender_OPT._RunOut_Water | BOOL | TRUE | TRUE | 0)Syrup Runout without Water 1)Syrup runout with Water pushing | +| 31.0 | Processor_Options.Blender_OPT._FlowMeterType | BOOL | | TRUE | 0)Endrees Hauser -- 1)Micromotion | +| 31.1 | Processor_Options.Blender_OPT._SidelFiller | BOOL | | FALSE | 0)Filler Simonazzi -- 1)Filler Sidel Filling | +| 31.2 | Processor_Options.Blender_OPT._Simulation | BOOL | | FALSE | | +| 31.3 | Processor_Options.Blender_OPT._ProductCoolingCTRL | BOOL | | FALSE | 0)none 1) TTM307 | +| 31.4 | Processor_Options.Blender_OPT._ChillerCTRL | BOOL | | FALSE | Chiller Pressure Cross Control | +| 31.5 | Processor_Options.Blender_OPT._CO2_SterileFilter | BOOL | TRUE | TRUE | CO2 Inlet with Steril Filter | +| 31.6 | Processor_Options.Blender_OPT._InverterRecirPumpPPM306 | BOOL | | FALSE | 0)Not Present 1)Present | +| 31.7 | Processor_Options.Blender_OPT._ProdPressReleaseRVM304 | BOOL | | FALSE | 0)Not Present 1)Present | +| 32.0 | Processor_Options.Blender_OPT._VacuumPump | INT | 1 | 1 | 0)None 1)Sterling 2)Nash Elmo | +| 34.0 | Processor_Options.Blender_OPT._GAS2InjectionType | INT | | 0 | 0)None 1)N2 2)Steril Air | +| 36.0 | Processor_Options.Blender_OPT._InjectionPress_Ctrl | INT | 1 | 1 | 0)Manual 1)Norgren v1 2)Norgren v2 | +| 38.0 | Processor_Options.Blender_OPT._ProdPressureType | INT | | 0 | 0)Only CO2 1)CO2+SterilAir 2)CO2+N2 | +| 40.0 | Processor_Options.Blender_OPT._CIPHeatType | INT | | 0 | 0)Steam 1)Electric | +| 42.0 | Processor_Options.Blender_OPT._EHS_NrRes | INT | 6 | 6 | Number of Heat Resistances | +| 44.0 | Spare1 | ARRAY [1..9] OF INT | | | | +| 62.0 | _RVM301_DeadBand | REAL | 5.000000e-02 | 5.000000e-02 | | +| 66.0 | _RVM301_Kp | REAL | 9.000000e+01 | 9.000000e+01 | | +| 70.0 | Actual_Recipe_Parameters | "Recipe_Prod" | | | | +| 254.0 | Spare2 | ARRAY [1..5] OF INT | | | | +| 264.0 | Next_Recipe_Name | STRING[32] | ' ' | 'cambio 1$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00' | | +| 298.0 | Next_Recipe_Number | INT | | 0 | | +| 300.0 | Spare3 | ARRAY [1..18] OF INT | | | | +| 336.0 | ProcessSetup | STRUCT | | | | +| 336.0 | ProcessSetup.Spare000 | REAL | | 0.000000e+00 | | +| 340.0 | ProcessSetup.Spare040 | REAL | | 0.000000e+00 | | +| 344.0 | ProcessSetup._KWaterLoss | REAL | 1.000000e-03 | 1.000000e-03 | Friction Loss Constant in Serpentine | +| 348.0 | ProcessSetup._KSyrupLoss | REAL | 7.800000e-03 | 7.800000e-03 | Friction Loss Constant in Syrup Pipe | +| 352.0 | ProcessSetup._KProdLoss | REAL | 1.390000e-02 | 1.390000e-02 | Pressure Loss Factor | +| 356.0 | ProcessSetup._KPPM303 | REAL | 5.700000e+00 | 5.700000e+00 | Frequency Overpressure Pump P3 Constant [Hz/mm] | +| 360.0 | ProcessSetup._BaialageRVM301OVMin | REAL | 2.000000e+00 | 2.000000e+00 | Baialage Minimum Flow (Nm3/h) | +| 364.0 | ProcessSetup._SyrupLinePressure | REAL | 2.200000e+00 | 2.200000e+00 | Syrup Line pressure at VEP2 valve | +| 368.0 | ProcessSetup._CIPRMM301OV | REAL | 1.000000e+01 | 1.000000e+01 | Water Valve Opening During CIP | +| 372.0 | ProcessSetup._CIPRMP302OV | REAL | 1.500000e+01 | 1.500000e+01 | Syrup Valve Opening During CIP | +| 376.0 | ProcessSetup._CIPTM301MinLevel | REAL | 3.500000e+01 | 3.500000e+01 | Product Tank Minimum Level In CIP | +| 380.0 | ProcessSetup._CIPTM301MaxLevel | REAL | 5.500000e+01 | 5.500000e+01 | Product Tank Maximum Level In CIP | +| 384.0 | ProcessSetup._CIPPPM303Freq | REAL | 5.000000e+01 | 5.000000e+01 | CIP frequency Value [Hz] | +| 388.0 | ProcessSetup._CIPTP301MinLevel | REAL | 2.500000e+01 | 2.500000e+01 | Syrup Tank Minimum Level In CIP | +| 392.0 | ProcessSetup._CIPTP301MaxLevel | REAL | 4.500000e+01 | 4.500000e+01 | Syrup Tank Maximum Level In CIP | +| 396.0 | ProcessSetup._RinseRMM301OV | REAL | 1.000000e+01 | 1.000000e+01 | Water Valve Opening During Rinse | +| 400.0 | ProcessSetup._RinseRMP302OV | REAL | 1.400000e+01 | 1.400000e+01 | Syrup Valve Opening During Rinse | +| 404.0 | ProcessSetup._RinseTM301Press | REAL | 3.000000e-01 | 3.000000e-01 | Product Tank Pressure In Rinse | +| 408.0 | ProcessSetup._RinsePPM303Freq | REAL | 5.000000e+01 | 5.000000e+01 | Rinse frequency Value [Hz] | +| 412.0 | ProcessSetup._DrainTM301Press | REAL | 1.000000e+00 | 1.000000e+00 | Buffer Tank Draining Pressure | +| 416.0 | ProcessSetup._KRecBlendError | REAL | 2.000000e+00 | 2.000000e+00 | Blend Error Recovery CONSTANT | +| 420.0 | ProcessSetup._KRecCarboCO2Error | REAL | 2.000000e+00 | 2.000000e+00 | Carbonation Error Recovery Constant | +| 424.0 | ProcessSetup._MaxBlendError | REAL | 1.000000e+02 | 1.000000e+02 | Blend Error Maximum Value | +| 428.0 | ProcessSetup._MaxCarboCO2Error | REAL | 5.000000e+02 | 5.000000e+02 | Carbonation Error Maximum Value | +| 432.0 | ProcessSetup._StartUpBrixExtraWater | REAL | 4.700000e+01 | 4.700000e+01 | | +| 436.0 | ProcessSetup._StartUpCO2ExtraWater | REAL | 8.000000e+00 | 8.000000e+00 | | +| 440.0 | ProcessSetup._StartUpPPM303Freq | REAL | 2.000000e+01 | 2.000000e+01 | Start Up frequency Value [Hz] | +| 444.0 | ProcessSetup._SyrupRoomTank | INT | 1 | 1 | | +| 446.0 | ProcessSetup._SyrupRunOutLiters | REAL | 2.900000e+02 | 2.900000e+02 | | +| 450.0 | ProcessSetup._InjCO2Press_Offset | REAL | 5.000000e-01 | 5.000000e-01 | | +| 454.0 | ProcessSetup._InjCO2Press_MinFlow | REAL | 4.500000e+02 | 4.500000e+02 | | +| 458.0 | ProcessSetup._InjCO2Press_MaxFlow | REAL | 2.500000e+03 | 2.500000e+03 | | +| 462.0 | ProcessSetup._CarboCO2Pressure | REAL | 1.250000e+01 | 1.250000e+01 | CO2 Pressure Infeed Line | +| 466.0 | ProcessSetup._N2MinPressure | REAL | 1.000000e+00 | 1.000000e+00 | N2 Minimum Pressure Infeed Line | +| 470.0 | ProcessSetup._DiffSensor_Height | REAL | 3.950000e+02 | 3.950000e+02 | Sensor Height from Soil [mm] | +| 474.0 | ProcessSetup._DiffSensor_DeltaHeight | REAL | -2.500000e+01 | -2.500000e+01 | Sensor Plates Height Difference [mm] | +| 478.0 | ProcessSetup._DiffSensor_Offset | REAL | 3.618000e+01 | 3.618000e+01 | Sensor Offset Read with zero pressure (all valves open) in [mm] | +| 482.0 | ProcessSetup._FillingValveHeight | REAL | 1.400000e+03 | 1.400000e+03 | Filling Valve Height from soil [mm] | +| 486.0 | ProcessSetup._FillerDiameter | REAL | 2.520000e+03 | 2.520000e+03 | Filler Carousel Diameter [mm] | +| 490.0 | ProcessSetup._FillingValveNum | INT | 91 | 91 | Filling Valves Number | +| 492.0 | ProcessSetup._FillerProdPipeDN | REAL | 1.000000e+02 | 1.000000e+02 | | +| 496.0 | ProcessSetup._FillerProdPipeMass | REAL | 1.600000e+02 | 1.600000e+02 | | +| 500.0 | ProcessSetup._FillingTime | REAL | 3.200000e+00 | 3.200000e+00 | | +| 504.0 | ProcessSetup._TM301Height_0 | REAL | 1.050000e+03 | 1.050000e+03 | Level at 0% Tank Level Height in mm | +| 508.0 | ProcessSetup._TM301LevelPerc_2 | REAL | 4.600000e+01 | 4.600000e+01 | Second level percentage | +| 512.0 | ProcessSetup._TM301Height_2 | REAL | 1.625000e+03 | 1.625000e+03 | Second level Height in mm | +| 516.0 | ProcessSetup._RVN304Factor | REAL | 1.000000e+00 | 1.000000e+00 | DeareationFlow/WaterFlow | +| 520.0 | ProcessSetup._DrainTM301Flushing | REAL | 1.300000e+00 | 1.300000e+00 | | +| 524.0 | ProcessSetup._FirstProdExtraBrix | REAL | 5.000000e-02 | 5.000000e-02 | | +| 528.0 | ProcessSetup._FirstProdDietExtraSyr | REAL | 1.400000e-03 | 1.400000e-03 | | +| 532.0 | ProcessSetup._EndProdLastSyrlt | REAL | | 0.000000e+00 | End Production Last syrup liters | +| 536.0 | ProcessSetup._TM301DrainSt0Time | WORD | W#16#A | W#16#A | sec | +| 538.0 | ProcessSetup._TM301DrainSt1Time | WORD | W#16#50 | W#16#50 | sec | +| 540.0 | ProcessSetup._ProdPipeRunOutSt0Time | WORD | W#16#1 | W#16#1 | sec | +| 542.0 | ProcessSetup._RMM301ProdPipeRunOu | REAL | 3.000000e+01 | 3.000000e+01 | | +| 546.0 | ProcessSetup._RMP302ProdPipeRunOu | REAL | 4.000000e+01 | 4.000000e+01 | | +| 550.0 | ProcessSetup._ProdPipeRunOutAmount | REAL | 3.000000e+01 | 3.000000e+01 | | +| 554.0 | ProcessSetup._TM301RunOutChiller | REAL | 5.000000e+00 | 5.000000e+00 | | +| 558.0 | ProcessSetup._MinSpeedNominalProd | REAL | 4.000000e-01 | 4.000000e-01 | Min Speed for Nominal Production | +| 562.0 | ProcessSetup._MinSpeedSlowProd | REAL | 3.000000e-01 | 3.000000e-01 | Min Speed for Very Low Production | +| 566.0 | ProcessSetup._FastChgOvrTM301DrnPrss | REAL | 9.000000e-01 | 9.000000e-01 | Fast Change Over Product Tank Draining Pressure in Blendfill | +| 570.0 | ProcessSetup._CIPTN301MinLevel | REAL | 3.500000e+01 | 3.500000e+01 | Deaireator Tank Minimum Level In CIP | +| 574.0 | ProcessSetup._CIPTN301MaxLevel | REAL | 6.000000e+01 | 6.000000e+01 | Deaireator Tank Maximum Level In CIP | +| 578.0 | ProcessSetup._ProdPPN304Freq | REAL | 5.000000e+01 | 5.000000e+01 | | +| 582.0 | ProcessSetup._GAS2InjectionPress | REAL | 4.000000e+00 | 4.000000e+00 | | +| 586.0 | ProcessSetup._BaialageRVM301OVMax | REAL | 2.000000e+01 | 2.000000e+01 | Baialage Production Flow Multiplier | +| 590.0 | ProcessSetup._RinsePPN301Freq | REAL | 5.000000e+00 | 5.000000e+00 | | +| 594.0 | ProcessSetup._CIPPPN301Freq | REAL | 5.000000e+00 | 5.000000e+00 | | +| 598.0 | ProcessSetup._RinsePPP302Freq | REAL | 5.000000e+00 | 5.000000e+00 | | +| 602.0 | ProcessSetup._CIPPPP302Freq | REAL | 5.000000e+00 | 5.000000e+00 | | +| 606.0 | ProcessSetup._PercSyrupBrixSyrStarUp | REAL | 2.500000e+01 | 2.500000e+01 | | +| 610.0 | ProcessSetup._RefTempCoolingCTRL | REAL | | 0.000000e+00 | | +| 614.0 | ProcessSetup._H2OSerpPrimingVolume | REAL | 1.500000e+02 | 1.500000e+02 | Water Serpentine Volume + Water Chiller Volume | +| 618.0 | ProcessSetup._AVN301_Nozzle_Kv | REAL | 1.650000e+02 | 1.650000e+02 | AVN301 Nozzle Kv | +| 622.0 | ProcessSetup._AVN302_Nozzle_Kv | REAL | 2.600000e+02 | 2.600000e+02 | AVN302 Nozzle Kv | +| 626.0 | ProcessSetup._AVN303_Nozzle_Kv | REAL | 1.650000e+02 | 1.650000e+02 | AVN303 Nozzle Kv | +| 630.0 | ProcessSetup._DeoxSpryball_Kv | REAL | 6.700000e+01 | 6.700000e+01 | Deox Spryball Kv | +| 634.0 | ProcessSetup._PremixedLineDrainTime | INT | 300 | 300 | Premixed Product Line Drain Time | +| 636.0 | ProcessSetup._PPN301_H_MaxFlow | REAL | 9.000000e+01 | 9.000000e+01 | PPN301 Pump Head with Max Flow [m] | +| 640.0 | ProcessSetup._PPN301_H_MinFlow | REAL | 8.700000e+01 | 8.700000e+01 | PPN301 Pump Head with Min Flow [m] | +| 644.0 | ProcessSetup._PPN301_MaxFlow | REAL | 5.070000e+02 | 5.070000e+02 | PPN301 Max Flow [l/min] | +| 648.0 | ProcessSetup._PPN301_MinFlow | REAL | 2.110000e+02 | 2.110000e+02 | PPN301 Min Flow [l/min] | +| 652.0 | ProcessSetup._PPP302_H_MaxFlow | REAL | 8.600000e+01 | 8.600000e+01 | PPP302 Pump Head with Max Flow [m] | +| 656.0 | ProcessSetup._PPP302_H_MinFlow | REAL | 8.500000e+01 | 8.500000e+01 | PPP302 Pump Head with Min Flow [m] | +| 660.0 | ProcessSetup._PPP302_MaxFlow | REAL | 1.150000e+02 | 1.150000e+02 | PPP302 Max Flow [l/min] | +| 664.0 | ProcessSetup._PPP302_MinFlow | REAL | 3.200000e+01 | 3.200000e+01 | PPP302 Min Flow [l/min] | +| 668.0 | ProcessSetup._RinsePPM306Freq | REAL | 5.000000e+00 | 5.000000e+00 | | +| 672.0 | ProcessSetup._CIPPPM306Freq | REAL | 5.000000e+00 | 5.000000e+00 | | +| 676.0 | ProcessSetup._PPM307_H_MaxFlow | REAL | | 0.000000e+00 | PPM307 Pump Head with Max Flow [m] | +| 680.0 | ProcessSetup._PPM307_H_MinFlow | REAL | | 0.000000e+00 | PPM307 Pump Head with Min Flow [m] | +| 684.0 | ProcessSetup._PPM307_MaxFlow | REAL | | 0.000000e+00 | PPM307 Max Flow [l/min] | +| 688.0 | ProcessSetup._PPM307_MinFlow | REAL | | 0.000000e+00 | PPM307 Min Flow [l/min] | +| 692.0 | ProcessSetup._Temp0_VacuumCtrl | REAL | 1.800000e+01 | 1.800000e+01 | PPN304 Target Temperature - OPTION PPN304 Sterling Type | +| 696.0 | ProcessSetup._Temp1_VacuumCtrl | REAL | 2.000000e+00 | 2.000000e+00 | PPN304 High Treshold Temperature Delta - OPTION PPN304 Sterling Type | +| 700.0 | ProcessSetup._Temp2_VacuumCtrl | REAL | 2.000000e+00 | 2.000000e+00 | PPN304 Low Treshold Temperature Delta - OPTION PPN304 Sterling Type | +| 704.0 | ProcessSetup._Temp3_VacuumCtrl | REAL | 5.000000e+01 | 5.000000e+01 | PPN304 Warning Temperature - OPTION PPN304 Sterling Type | +| 708.0 | ProcessSetup._Temp4_VacuumCtrl | REAL | 5.000000e+01 | 5.000000e+01 | PPN304 Alarm Temperature - OPTION PPN304 Sterling Type | +| 712.0 | ProcessSetup._T1_VacuumCtrl | DINT | L#1500 | L#1500 | PPN304 Time 1 [msec] - OPTION PPN304 Sterling Type | +| 716.0 | ProcessSetup._T2_VacuumCtrl | DINT | L#1500 | L#1500 | PPN304 Time 2 [msec] - OPTION PPN304 Sterling Type | +| 720.0 | ProcessSetup._T3_VacuumCtrl | DINT | L#1000 | L#1000 | PPN304 Time 3 [msec] - OPTION PPN304 Sterling Type | +| 724.0 | ProcessSetup._T4_VacuumCtrl | DINT | L#1000 | L#1000 | PPN304 Time 4 [msec] - OPTION PPN304 Sterling Type | +| 728.0 | ProcessSetup._ICS_VolDosWorkTimePAA | INT | 30 | 30 | ICS - DS - Dosing Working Time [sec] | +| 730.0 | ProcessSetup._ICS_VolPauseTimePAA | INT | 30 | 30 | ICS - DS - Dosing Pause Time [sec] | +| 732.0 | ProcessSetup._ICS_PAAPulseWeight | INT | 10 | 10 | ICS - DS - PAA Pulse Weight [(L/Pulse)/100] | +| 734.0 | ProcessSetup._ICS_CausticPulseWeight | INT | 10 | 10 | ICS - DS - Caustic Pulse Weight [(L/Pulse)/100] | +| 736.0 | ProcessSetup._ICS_AcidPulseWeight | INT | 10 | 10 | ICS - DS - Acid Pulse Weight [(L/Pulse)/100] | +| 738.0 | ProcessSetup._ICS_VolumeRestOfLine | REAL | 3.500000e+02 | 3.500000e+02 | ICS - DS - Volume of the Rest of the Line (Filler + Piping) [L] | +| 742.0 | ProcessSetup._ICS_VolDosWorkTimeCaus | INT | 30 | 30 | ICS - DS - Dosing Working Time [sec] | +| 744.0 | ProcessSetup._ICS_VolDosPauseTimeCaus | INT | 30 | 30 | ICS - DS - Dosing Pause Time [sec] | +| 746.0 | ProcessSetup._ICS_VolDosWorkTimeAcid | INT | 30 | 30 | ICS - DS - Dosing Working Time [sec] | +| 748.0 | ProcessSetup._ICS_VolDosPauseTimeAcid | INT | 30 | 30 | ICS - DS - Dosing Pause Time [sec] | +| 750.0 | ProcessSetup._ICS_ConcDosWorkTimeCaus | INT | 30 | 30 | ICS - DS - Dosing Working Time [sec] | +| 752.0 | ProcessSetup._ICS_ConcDosPausTimeCaus | INT | 30 | 30 | ICS - DS - Dosing Pause Time [sec] | +| 754.0 | ProcessSetup._ICS_ConcDosWorkTimeAcid | INT | 30 | 30 | ICS - DS - Dosing Working Time [sec] | +| 756.0 | ProcessSetup._ICS_ConcDosPausTimeAcid | INT | 30 | 30 | ICS - DS - Dosing Pause Time [sec] | +| 758.0 | ProcessSetup._RinsePPM307Freq | REAL | 3.000000e+01 | 3.000000e+01 | | +| 762.0 | ProcessSetup._CIPPPM307Freq | REAL | 3.000000e+01 | 3.000000e+01 | | +| 766.0 | ProcessSetup._CIP2StepTN301Lvl | REAL | | 0.000000e+00 | Local CIP - 2 Step loading TN301 Level | +| 770.0 | ProcessSetup._CIP2StepTM301Lvl | REAL | | 0.000000e+00 | Local CIP - 2 Step loading TM301 Level | +| 774.0 | ProcessSetup._CIP2StepTP301Lvl | REAL | | 0.000000e+00 | Local CIP - 2 Step loading TP301 Level | +| 778.0 | ProcessSetup._PumpNominalFreq | REAL | 5.000000e+01 | 5.000000e+01 | 50.0 Hz or 60.0 Hz | +| 782.0 | _SwitchOff_DensityOK | BOOL | | FALSE | | diff --git a/backend/script_groups/S7_DB_Utils/esquema_group.json b/backend/script_groups/S7_DB_Utils/esquema_group.json new file mode 100644 index 0000000..1c9e43a --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/esquema_group.json @@ -0,0 +1,4 @@ +{ + "type": "object", + "properties": {} +} \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/esquema_work.json b/backend/script_groups/S7_DB_Utils/esquema_work.json new file mode 100644 index 0000000..1c9e43a --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/esquema_work.json @@ -0,0 +1,4 @@ +{ + "type": "object", + "properties": {} +} \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/log_x1.txt b/backend/script_groups/S7_DB_Utils/log_x1.txt new file mode 100644 index 0000000..2ff4cac --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/log_x1.txt @@ -0,0 +1,28 @@ +--- Log de Ejecución: x1.py --- +Grupo: S7_DB_Utils +Directorio de Trabajo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 +Inicio: 2025-05-16 15:41:29 +Fin: 2025-05-16 15:41:29 +Duración: 0:00:00.179799 +Estado: SUCCESS (Código de Salida: 0) + +--- SALIDA ESTÁNDAR (STDOUT) --- +PLC Data Block Adapter - Advanced UDT Handling (Restored Auto File Find) +======================================================================== +Using working directory: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 +Selected source file: db1001_data.db +Selected target file: db1001_format.db + +Processing: + Source: db1001_data.db + Target: db1001_format.db + Output: db1001_format_updated.db + +Successfully transferred 90 initial values and 279 current values. +Output file created: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_format_updated.db + +SUCCESS: Script finished. Output: 'db1001_format_updated.db' + +--- ERRORES (STDERR) --- +Ninguno +--- FIN DEL LOG --- diff --git a/backend/script_groups/S7_DB_Utils/log_x2.txt b/backend/script_groups/S7_DB_Utils/log_x2.txt new file mode 100644 index 0000000..3ad3782 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/log_x2.txt @@ -0,0 +1,37 @@ +--- Log de Ejecución: x2.py --- +Grupo: S7_DB_Utils +Directorio de Trabajo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 +Inicio: 2025-05-16 17:28:48 +Fin: 2025-05-16 17:28:49 +Duración: 0:00:01.729331 +Estado: SUCCESS (Código de Salida: 0) + +--- SALIDA ESTÁNDAR (STDOUT) --- +S7 Data Block Comparator to Excel (Multi-Sheet) +============================================== +Info: `find_working_directory_from_x1` is using the current directory. +Using working directory: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 +Identified files for comparison: + Data file: db1001_data.db + Format file: db1001_format.db + Updated file: db1001_format_updated.db + +Processing _data file: db1001_data.db + Found 251 declaration vars, 280 initialization vars in _data file. +Processing _format file: db1001_format.db + Found 201 declaration vars, 279 initialization vars in _format file. +Processing _updated file: db1001_format_updated.db + Found 201 declaration vars, 279 initialization vars in _updated file. + +Comparing 251 positional declaration entries (STRUCT section)... +Comparing 280 positional initialization entries (BEGIN block)... +Written 'Declarations (Initial Values)' sheet with 251 rows. +Written 'Initializations (Current Values)' sheet with 280 rows. + +Successfully generated Excel comparison: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\S7_DB_Comparison_MultiSheet.xlsx + +--- ERRORES (STDERR) --- +C:\Users\migue\miniconda3\envs\tia_scripting\Lib\site-packages\openpyxl\workbook\child.py:99: UserWarning: Title is more than 31 characters. Some applications may not be able to read the file + warnings.warn("Title is more than 31 characters. Some applications may not be able to read the file") + +--- FIN DEL LOG --- diff --git a/backend/script_groups/S7_DB_Utils/log_x3.txt b/backend/script_groups/S7_DB_Utils/log_x3.txt new file mode 100644 index 0000000..95f3a65 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/log_x3.txt @@ -0,0 +1,51 @@ +--- Log de Ejecución: x3.py --- +Grupo: S7_DB_Utils +Directorio de Trabajo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 +Inicio: 2025-05-16 20:15:59 +Fin: 2025-05-16 20:16:00 +Duración: 0:00:00.897567 +Estado: ERROR (Código de Salida: 1) + +--- SALIDA ESTÁNDAR (STDOUT) --- + + +--- ERRORES (STDERR) --- +2025-05-16 20:16:00,228 - db_mapper - INFO - Iniciando mapeo de DBs por dirección absoluta +2025-05-16 20:16:00,309 - db_mapper - INFO - Directorio de trabajo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 +2025-05-16 20:16:00,310 - db_mapper - INFO - Encontrados 3 archivos para procesar +2025-05-16 20:16:00,310 - db_mapper - INFO - Procesando: db1001_data.db +2025-05-16 20:16:00,310 - db_mapper - INFO - Procesando archivo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_data.db +2025-05-16 20:16:00,310 - db_mapper - ERROR - Error procesando archivo C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_data.db: module 'DB_Parser' has no attribute 'parse_db_definition' +Traceback (most recent call last): + File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 76, in process_db_file + db_node, db_number, db_name, family, version = DB_Parser.parse_db_definition(db_content, udt_definitions) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AttributeError: module 'DB_Parser' has no attribute 'parse_db_definition' +2025-05-16 20:16:00,312 - db_mapper - INFO - Procesando: db1001_format.db +2025-05-16 20:16:00,312 - db_mapper - INFO - Procesando archivo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_format.db +2025-05-16 20:16:00,313 - db_mapper - ERROR - Error procesando archivo C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_format.db: module 'DB_Parser' has no attribute 'parse_udt_definition' +Traceback (most recent call last): + File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 64, in process_db_file + udt_name, udt_node = DB_Parser.parse_udt_definition(udt_content) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AttributeError: module 'DB_Parser' has no attribute 'parse_udt_definition' +2025-05-16 20:16:00,316 - db_mapper - INFO - Procesando: db1001_format_updated.db +2025-05-16 20:16:00,316 - db_mapper - INFO - Procesando archivo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_format_updated.db +2025-05-16 20:16:00,316 - db_mapper - ERROR - Error procesando archivo C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_format_updated.db: module 'DB_Parser' has no attribute 'parse_udt_definition' +Traceback (most recent call last): + File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 64, in process_db_file + udt_name, udt_node = DB_Parser.parse_udt_definition(udt_content) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AttributeError: module 'DB_Parser' has no attribute 'parse_udt_definition' +Traceback (most recent call last): + File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 444, in + main() + File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 430, in main + processed_files, mapped_pairs = process_all_files_in_directory() + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 372, in process_all_files_in_directory + "timestamp": import_datetime().now().isoformat() + ^^^^^^^^^^^^^^^^^^^^^ +AttributeError: module 'datetime' has no attribute 'now' + +--- FIN DEL LOG --- diff --git a/backend/script_groups/S7_DB_Utils/parsed_s7_data_expanded.json b/backend/script_groups/S7_DB_Utils/parsed_s7_data_expanded.json new file mode 100644 index 0000000..0cdf83c --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/parsed_s7_data_expanded.json @@ -0,0 +1,3056 @@ +{ + "udts": [ + { + "name": "Recipe_Prod", + "family": "DataType", + "version": "0.1", + "members": [ + { + "name": "_Name", + "data_type": "STRING", + "byte_offset": 0.0, + "size_in_bytes": 34, + "bit_size": 0, + "string_length": 32, + "initial_value": "' '", + "is_udt_expanded_member": false + }, + { + "name": "_EnProdTemp", + "data_type": "BOOL", + "byte_offset": 34.0, + "size_in_bytes": 0, + "bit_size": 1, + "is_udt_expanded_member": false + }, + { + "name": "_SyrFlushing", + "data_type": "BOOL", + "byte_offset": 34.1, + "size_in_bytes": 0, + "bit_size": 1, + "comment": "Ex_EnDeaireation --> DELETED - AVP320 VALVE OPEN", + "is_udt_expanded_member": false + }, + { + "name": "_GAS2_Injection", + "data_type": "BOOL", + "byte_offset": 34.2, + "size_in_bytes": 0, + "bit_size": 1, + "comment": "0 = GAS2 not present; 1 = GAS2 present", + "is_udt_expanded_member": false + }, + { + "name": "_Eq_Pression_Selected", + "data_type": "BOOL", + "byte_offset": 34.3, + "size_in_bytes": 0, + "bit_size": 1, + "is_udt_expanded_member": false + }, + { + "name": "_DeoxStripEn", + "data_type": "BOOL", + "byte_offset": 34.4, + "size_in_bytes": 0, + "bit_size": 1, + "comment": "******Deairation with Strip Enable", + "is_udt_expanded_member": false + }, + { + "name": "_DeoxVacuumEn", + "data_type": "BOOL", + "byte_offset": 34.5, + "size_in_bytes": 0, + "bit_size": 1, + "comment": "******Deairation with Vacuum", + "is_udt_expanded_member": false + }, + { + "name": "_DeoxPreMixed", + "data_type": "BOOL", + "byte_offset": 34.6, + "size_in_bytes": 0, + "bit_size": 1, + "comment": "******Deairation of Premixed Product", + "is_udt_expanded_member": false + }, + { + "name": "_EnBlowOffProdPipeCO2Fil", + "data_type": "BOOL", + "byte_offset": 34.7, + "size_in_bytes": 0, + "bit_size": 1, + "is_udt_expanded_member": false + }, + { + "name": "_WaterSelection", + "data_type": "BYTE", + "byte_offset": 35.0, + "size_in_bytes": 1, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_FillerNextRecipeNum", + "data_type": "BYTE", + "byte_offset": 36.0, + "size_in_bytes": 1, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_BottleShape", + "data_type": "BYTE", + "byte_offset": 37.0, + "size_in_bytes": 1, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_Type", + "data_type": "INT", + "byte_offset": 38.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "1", + "comment": "1= DIET; 2= REGULAR; 3= RATIO; 4= WATER", + "is_udt_expanded_member": false + }, + { + "name": "_ProdMeterRecipeNum", + "data_type": "INT", + "byte_offset": 40.0, + "size_in_bytes": 2, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_SyrupBrix", + "data_type": "REAL", + "byte_offset": 42.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_SyrupDensity", + "data_type": "REAL", + "byte_offset": 46.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.255800e+00", + "is_udt_expanded_member": false + }, + { + "name": "_SyrupFactor", + "data_type": "REAL", + "byte_offset": 50.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_ProductBrix", + "data_type": "REAL", + "byte_offset": 54.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.045000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_ProductionRate", + "data_type": "REAL", + "byte_offset": 58.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "9.000000e+02", + "is_udt_expanded_member": false + }, + { + "name": "_Ratio", + "data_type": "REAL", + "byte_offset": 62.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_ProdBrixOffset", + "data_type": "REAL", + "byte_offset": 66.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_CO2Vols", + "data_type": "REAL", + "byte_offset": 70.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_CO2Fact", + "data_type": "REAL", + "byte_offset": 74.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_ProdTankPress", + "data_type": "REAL", + "byte_offset": 78.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_SP_ProdTemp", + "data_type": "REAL", + "byte_offset": 82.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_PrdTankMinLevel", + "data_type": "REAL", + "byte_offset": 86.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_WaterValveSave", + "data_type": "REAL", + "byte_offset": 90.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_SyrupValveSave", + "data_type": "REAL", + "byte_offset": 94.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_CarboCO2ValveSave", + "data_type": "REAL", + "byte_offset": 98.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdMeterHighBrix", + "data_type": "REAL", + "byte_offset": 102.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdMeterLowBrix", + "data_type": "REAL", + "byte_offset": 106.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdMeterHighCO2", + "data_type": "REAL", + "byte_offset": 110.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdMeterLowCO2", + "data_type": "REAL", + "byte_offset": 114.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdMeter_ZeroCO2", + "data_type": "REAL", + "byte_offset": 118.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdMeter_ZeroBrix", + "data_type": "REAL", + "byte_offset": 122.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdHighCond", + "data_type": "REAL", + "byte_offset": 126.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdLowCond", + "data_type": "REAL", + "byte_offset": 130.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_BottleSize", + "data_type": "REAL", + "byte_offset": 134.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_FillingValveHead_SP", + "data_type": "REAL", + "byte_offset": 138.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_SyrMeter_ZeroBrix", + "data_type": "REAL", + "byte_offset": 142.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_FirstProdExtraCO2Fact", + "data_type": "REAL", + "byte_offset": 146.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "9.700000e-01", + "is_udt_expanded_member": false + }, + { + "name": "_Gas2Vols", + "data_type": "REAL", + "byte_offset": 150.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_Gas2Fact", + "data_type": "REAL", + "byte_offset": 154.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_SyrupPumpPressure", + "data_type": "REAL", + "byte_offset": 158.0, + "size_in_bytes": 4, + "bit_size": 0, + "comment": "******Syrup Pump Pressure SP", + "is_udt_expanded_member": false + }, + { + "name": "_WaterPumpPressure", + "data_type": "REAL", + "byte_offset": 162.0, + "size_in_bytes": 4, + "bit_size": 0, + "comment": "******Water Pump Pressure SP", + "is_udt_expanded_member": false + }, + { + "name": "_CO2_Air_N2_PressSelect", + "data_type": "INT", + "byte_offset": 166.0, + "size_in_bytes": 2, + "bit_size": 0, + "comment": "1=CO2; 2=CO2+SterilAir; 3=CO2+N2 - Pressure Tank Selection", + "is_udt_expanded_member": false + }, + { + "name": "_KFactRVM304BlowOff", + "data_type": "REAL", + "byte_offset": 168.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdRecircPumpFreq", + "data_type": "REAL", + "byte_offset": 172.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdBoosterPumpPress", + "data_type": "REAL", + "byte_offset": 176.0, + "size_in_bytes": 4, + "bit_size": 0, + "is_udt_expanded_member": false + }, + { + "name": "_ProdSendPumpFreq", + "data_type": "REAL", + "byte_offset": 180.0, + "size_in_bytes": 4, + "bit_size": 0, + "comment": "******Product Sending Pump Frequency SP", + "is_udt_expanded_member": false + } + ], + "total_size_in_bytes": 184 + } + ], + "dbs": [ + { + "name": "HMI_Blender_Parameters", + "family": "Resource", + "version": "0.0", + "members": [ + { + "name": "Processor_Options", + "data_type": "STRUCT", + "byte_offset": 0.0, + "size_in_bytes": 44, + "bit_size": 0, + "children": [ + { + "name": "Blender_OPT", + "data_type": "STRUCT", + "byte_offset": 0.0, + "size_in_bytes": 44, + "bit_size": 0, + "children": [ + { + "name": "_ModelNum", + "data_type": "INT", + "byte_offset": 0.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "6", + "current_value": "6", + "is_udt_expanded_member": false + }, + { + "name": "_CO2_Offset", + "data_type": "REAL", + "byte_offset": 2.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "4.500000e-01", + "current_value": "4.500000e-01", + "is_udt_expanded_member": false + }, + { + "name": "_MaxSyrDeltaBrix", + "data_type": "REAL", + "byte_offset": 6.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "8.000000e-01", + "current_value": "8.000000e-01", + "is_udt_expanded_member": false + }, + { + "name": "_BrixMeter", + "data_type": "BOOL", + "byte_offset": 10.0, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "is_udt_expanded_member": false + }, + { + "name": "Spare101", + "data_type": "BOOL", + "byte_offset": 10.1, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_TrackH2OEnable", + "data_type": "BOOL", + "byte_offset": 10.2, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_PAmPDSType", + "data_type": "BOOL", + "byte_offset": 10.3, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Cobrix 2000 1)Carbo 2000", + "is_udt_expanded_member": false + }, + { + "name": "_HistoricalTrends", + "data_type": "BOOL", + "byte_offset": 10.4, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_PowerMeter", + "data_type": "BOOL", + "byte_offset": 10.5, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_Report", + "data_type": "BOOL", + "byte_offset": 10.6, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_Balaiage", + "data_type": "BOOL", + "byte_offset": 10.7, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_Valves_FullFeedback", + "data_type": "BOOL", + "byte_offset": 11.0, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "Valves control Full feedback", + "is_udt_expanded_member": false + }, + { + "name": "_Valves_SingleFeedback", + "data_type": "BOOL", + "byte_offset": 11.1, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "Valves control Single feedback", + "is_udt_expanded_member": false + }, + { + "name": "_PumpsSafetySwitches", + "data_type": "BOOL", + "byte_offset": 11.2, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "Pumps with Safety Switches", + "is_udt_expanded_member": false + }, + { + "name": "_SurgeProtectionAct", + "data_type": "BOOL", + "byte_offset": 11.3, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_DBC_Type", + "data_type": "BOOL", + "byte_offset": 11.4, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0) Deox,Carbo,Blend 1)Deox,Blend,Carbo", + "is_udt_expanded_member": false + }, + { + "name": "_CO2InletMeter", + "data_type": "BOOL", + "byte_offset": 11.5, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_ProductO2Meter", + "data_type": "BOOL", + "byte_offset": 11.6, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_CopressedAirInletMeter", + "data_type": "BOOL", + "byte_offset": 11.7, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_MeterType", + "data_type": "INT", + "byte_offset": 12.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "6", + "current_value": "6", + "comment": "1)Maselli 2)AntoonPaar 3)4-20mA 4)UC05 UR22 5)mPDSPA 6)MR02", + "is_udt_expanded_member": false + }, + { + "name": "_MeterReceiveOnly", + "data_type": "BOOL", + "byte_offset": 14.0, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_SyrBrixMeter", + "data_type": "BOOL", + "byte_offset": 14.1, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_Flooding_Start_Up", + "data_type": "BOOL", + "byte_offset": 14.2, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Selected 1)Selected", + "is_udt_expanded_member": false + }, + { + "name": "_FastChangeOverEnabled", + "data_type": "BOOL", + "byte_offset": 14.3, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "is_udt_expanded_member": false + }, + { + "name": "_WaterInletMeter", + "data_type": "BOOL", + "byte_offset": 14.4, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_BlendFillSystem", + "data_type": "BOOL", + "byte_offset": 14.5, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "is_udt_expanded_member": false + }, + { + "name": "_TrackFillerSpeed", + "data_type": "BOOL", + "byte_offset": 14.6, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "is_udt_expanded_member": false + }, + { + "name": "_SignalExchange", + "data_type": "INT", + "byte_offset": 16.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "1", + "current_value": "1", + "comment": "FILLER - 0= Hardwire; 1= Ethernet", + "is_udt_expanded_member": false + }, + { + "name": "_CoolerPresent", + "data_type": "BOOL", + "byte_offset": 18.0, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "is_udt_expanded_member": false + }, + { + "name": "_CoolerControl", + "data_type": "INT", + "byte_offset": 20.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "4", + "current_value": "4", + "comment": "0)External 1)Water 2)Product 3)Water+Product-2 Ctrl 4)Water+Product-1 Ctrl", + "is_udt_expanded_member": false + }, + { + "name": "_CoolerType", + "data_type": "INT", + "byte_offset": 22.0, + "size_in_bytes": 2, + "bit_size": 0, + "current_value": "0", + "comment": "0)Glycol 1)Ammonia", + "is_udt_expanded_member": false + }, + { + "name": "_LocalCIP", + "data_type": "BOOL", + "byte_offset": 24.0, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_CustomerHotWater", + "data_type": "BOOL", + "byte_offset": 24.1, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)No Hot Water from Customer 1)Hot Water from Customer Available", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_CustomerChemRecov", + "data_type": "BOOL", + "byte_offset": 24.2, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)No Customer's Chemicals Recovery 1)Customer's Chemicals Recovery Available", + "is_udt_expanded_member": false + }, + { + "name": "_CIPSignalExchange", + "data_type": "BOOL", + "byte_offset": 24.3, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "CIP - 0= Hardwire; 1= Ethernet", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_CustomerChemicals", + "data_type": "BOOL", + "byte_offset": 24.4, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Chemicals from ICS 1)Chemicals from Customer", + "is_udt_expanded_member": false + }, + { + "name": "_CarboPresent", + "data_type": "BOOL", + "byte_offset": 24.5, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "is_udt_expanded_member": false + }, + { + "name": "_InverterSyrupPumpPPP302", + "data_type": "BOOL", + "byte_offset": 24.6, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_InverterWaterPumpPPN301", + "data_type": "BOOL", + "byte_offset": 24.7, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_DoubleDeair", + "data_type": "BOOL", + "byte_offset": 25.0, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "is_udt_expanded_member": false + }, + { + "name": "_DeairPreMixed", + "data_type": "BOOL", + "byte_offset": 25.1, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "Deox Premixed Inlet", + "is_udt_expanded_member": false + }, + { + "name": "_Deaireation", + "data_type": "BOOL", + "byte_offset": 25.2, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "0)SAG 1)SAE/SAF", + "is_udt_expanded_member": false + }, + { + "name": "_StillWaterByPass", + "data_type": "BOOL", + "byte_offset": 25.3, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_ManifoldSetting", + "data_type": "BOOL", + "byte_offset": 25.4, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "0)Manual 1)Automatic", + "is_udt_expanded_member": false + }, + { + "name": "_InverterProdPumpPPM303", + "data_type": "BOOL", + "byte_offset": 25.5, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_SidelCip", + "data_type": "BOOL", + "byte_offset": 25.6, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_EthernetCom_CpuPN_CP", + "data_type": "BOOL", + "byte_offset": 25.7, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "0)Comunication with CP 1)Comunication with CPU PN", + "is_udt_expanded_member": false + }, + { + "name": "_2ndOutlet", + "data_type": "INT", + "byte_offset": 26.0, + "size_in_bytes": 2, + "bit_size": 0, + "current_value": "0", + "comment": "0)No 2nd Outlet 1)2nd Outlet No Standalone 2)2nd Outlet Standalone", + "is_udt_expanded_member": false + }, + { + "name": "_Promass", + "data_type": "INT", + "byte_offset": 28.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "2", + "current_value": "2", + "is_udt_expanded_member": false + }, + { + "name": "_WaterPromass", + "data_type": "BOOL", + "byte_offset": 30.0, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "0)Promag 1)Promass", + "is_udt_expanded_member": false + }, + { + "name": "_ProductConductimeter", + "data_type": "BOOL", + "byte_offset": 30.1, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_CustomerH2ORecov", + "data_type": "BOOL", + "byte_offset": 30.2, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)No Customer's H2O Recovery 1)Customer's H2O Recovery Available", + "is_udt_expanded_member": false + }, + { + "name": "Spare303", + "data_type": "BOOL", + "byte_offset": 30.3, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_CO2_GAS2_Injection", + "data_type": "BOOL", + "byte_offset": 30.4, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Only CO2 Injection 1)GAS2 Injection", + "is_udt_expanded_member": false + }, + { + "name": "_InverterVacuuPumpPPN304", + "data_type": "BOOL", + "byte_offset": 30.5, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_InverterBoostPumpPPM307", + "data_type": "BOOL", + "byte_offset": 30.6, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_RunOut_Water", + "data_type": "BOOL", + "byte_offset": 30.7, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "0)Syrup Runout without Water 1)Syrup runout with Water pushing", + "is_udt_expanded_member": false + }, + { + "name": "_FlowMeterType", + "data_type": "BOOL", + "byte_offset": 31.0, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "TRUE", + "comment": "0)Endrees Hauser -- 1)Micromotion", + "is_udt_expanded_member": false + }, + { + "name": "_SidelFiller", + "data_type": "BOOL", + "byte_offset": 31.1, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Filler Simonazzi -- 1)Filler Sidel Filling", + "is_udt_expanded_member": false + }, + { + "name": "_Simulation", + "data_type": "BOOL", + "byte_offset": 31.2, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + }, + { + "name": "_ProductCoolingCTRL", + "data_type": "BOOL", + "byte_offset": 31.3, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)none 1) TTM307", + "is_udt_expanded_member": false + }, + { + "name": "_ChillerCTRL", + "data_type": "BOOL", + "byte_offset": 31.4, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "Chiller Pressure Cross Control", + "is_udt_expanded_member": false + }, + { + "name": "_CO2_SterileFilter", + "data_type": "BOOL", + "byte_offset": 31.5, + "size_in_bytes": 0, + "bit_size": 1, + "initial_value": "TRUE", + "current_value": "TRUE", + "comment": "CO2 Inlet with Steril Filter", + "is_udt_expanded_member": false + }, + { + "name": "_InverterRecirPumpPPM306", + "data_type": "BOOL", + "byte_offset": 31.6, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_ProdPressReleaseRVM304", + "data_type": "BOOL", + "byte_offset": 31.7, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0)Not Present 1)Present", + "is_udt_expanded_member": false + }, + { + "name": "_VacuumPump", + "data_type": "INT", + "byte_offset": 32.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "1", + "current_value": "1", + "comment": "0)None 1)Sterling 2)Nash Elmo", + "is_udt_expanded_member": false + }, + { + "name": "_GAS2InjectionType", + "data_type": "INT", + "byte_offset": 34.0, + "size_in_bytes": 2, + "bit_size": 0, + "current_value": "0", + "comment": "0)None 1)N2 2)Steril Air", + "is_udt_expanded_member": false + }, + { + "name": "_InjectionPress_Ctrl", + "data_type": "INT", + "byte_offset": 36.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "1", + "current_value": "1", + "comment": "0)Manual 1)Norgren v1 2)Norgren v2", + "is_udt_expanded_member": false + }, + { + "name": "_ProdPressureType", + "data_type": "INT", + "byte_offset": 38.0, + "size_in_bytes": 2, + "bit_size": 0, + "current_value": "0", + "comment": "0)Only CO2 1)CO2+SterilAir 2)CO2+N2", + "is_udt_expanded_member": false + }, + { + "name": "_CIPHeatType", + "data_type": "INT", + "byte_offset": 40.0, + "size_in_bytes": 2, + "bit_size": 0, + "current_value": "0", + "comment": "0)Steam 1)Electric", + "is_udt_expanded_member": false + }, + { + "name": "_EHS_NrRes", + "data_type": "INT", + "byte_offset": 42.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "6", + "current_value": "6", + "comment": "Number of Heat Resistances", + "is_udt_expanded_member": false + } + ], + "is_udt_expanded_member": false + } + ], + "is_udt_expanded_member": false + }, + { + "name": "Spare1", + "data_type": "INT", + "byte_offset": 44.0, + "size_in_bytes": 18, + "bit_size": 0, + "array_dimensions": [ + { + "lower_bound": 1, + "upper_bound": 9 + } + ], + "is_udt_expanded_member": false + }, + { + "name": "_RVM301_DeadBand", + "data_type": "REAL", + "byte_offset": 62.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e-02", + "current_value": "5.000000e-02", + "is_udt_expanded_member": false + }, + { + "name": "_RVM301_Kp", + "data_type": "REAL", + "byte_offset": 66.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "9.000000e+01", + "current_value": "9.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "Actual_Recipe_Parameters", + "data_type": "Recipe_Prod", + "byte_offset": 70.0, + "size_in_bytes": 184, + "bit_size": 0, + "udt_source_name": "\"Recipe_Prod\"", + "children": [ + { + "name": "_Name", + "data_type": "STRING", + "byte_offset": 70.0, + "size_in_bytes": 34, + "bit_size": 0, + "string_length": 32, + "initial_value": "' '", + "current_value": "''", + "is_udt_expanded_member": true + }, + { + "name": "_EnProdTemp", + "data_type": "BOOL", + "byte_offset": 104.0, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "TRUE", + "is_udt_expanded_member": true + }, + { + "name": "_SyrFlushing", + "data_type": "BOOL", + "byte_offset": 104.1, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "Ex_EnDeaireation --> DELETED - AVP320 VALVE OPEN", + "is_udt_expanded_member": true + }, + { + "name": "_GAS2_Injection", + "data_type": "BOOL", + "byte_offset": 104.2, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "0 = GAS2 not present; 1 = GAS2 present", + "is_udt_expanded_member": true + }, + { + "name": "_Eq_Pression_Selected", + "data_type": "BOOL", + "byte_offset": 104.3, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": true + }, + { + "name": "_DeoxStripEn", + "data_type": "BOOL", + "byte_offset": 104.4, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "******Deairation with Strip Enable", + "is_udt_expanded_member": true + }, + { + "name": "_DeoxVacuumEn", + "data_type": "BOOL", + "byte_offset": 104.5, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "TRUE", + "comment": "******Deairation with Vacuum", + "is_udt_expanded_member": true + }, + { + "name": "_DeoxPreMixed", + "data_type": "BOOL", + "byte_offset": 104.6, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "comment": "******Deairation of Premixed Product", + "is_udt_expanded_member": true + }, + { + "name": "_EnBlowOffProdPipeCO2Fil", + "data_type": "BOOL", + "byte_offset": 104.7, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": true + }, + { + "name": "_WaterSelection", + "data_type": "BYTE", + "byte_offset": 105.0, + "size_in_bytes": 1, + "bit_size": 0, + "current_value": "B#16#0", + "is_udt_expanded_member": true + }, + { + "name": "_FillerNextRecipeNum", + "data_type": "BYTE", + "byte_offset": 106.0, + "size_in_bytes": 1, + "bit_size": 0, + "current_value": "B#16#0", + "is_udt_expanded_member": true + }, + { + "name": "_BottleShape", + "data_type": "BYTE", + "byte_offset": 107.0, + "size_in_bytes": 1, + "bit_size": 0, + "current_value": "B#16#0", + "is_udt_expanded_member": true + }, + { + "name": "_Type", + "data_type": "INT", + "byte_offset": 108.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "1", + "current_value": "2", + "comment": "1= DIET; 2= REGULAR; 3= RATIO; 4= WATER", + "is_udt_expanded_member": true + }, + { + "name": "_ProdMeterRecipeNum", + "data_type": "INT", + "byte_offset": 110.0, + "size_in_bytes": 2, + "bit_size": 0, + "current_value": "1", + "is_udt_expanded_member": true + }, + { + "name": "_SyrupBrix", + "data_type": "REAL", + "byte_offset": 112.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+01", + "current_value": "4.625000e+01", + "is_udt_expanded_member": true + }, + { + "name": "_SyrupDensity", + "data_type": "REAL", + "byte_offset": 116.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.255800e+00", + "current_value": "1.206908e+00", + "is_udt_expanded_member": true + }, + { + "name": "_SyrupFactor", + "data_type": "REAL", + "byte_offset": 120.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "current_value": "1.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProductBrix", + "data_type": "REAL", + "byte_offset": 124.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.045000e+01", + "current_value": "1.000000e+01", + "is_udt_expanded_member": true + }, + { + "name": "_ProductionRate", + "data_type": "REAL", + "byte_offset": 128.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "9.000000e+02", + "current_value": "3.800000e+02", + "is_udt_expanded_member": true + }, + { + "name": "_Ratio", + "data_type": "REAL", + "byte_offset": 132.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.000000e+01", + "current_value": "4.238896e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdBrixOffset", + "data_type": "REAL", + "byte_offset": 136.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "2.500000e-01", + "is_udt_expanded_member": true + }, + { + "name": "_CO2Vols", + "data_type": "REAL", + "byte_offset": 140.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "2.550000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_CO2Fact", + "data_type": "REAL", + "byte_offset": 144.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "current_value": "9.400000e-01", + "is_udt_expanded_member": true + }, + { + "name": "_ProdTankPress", + "data_type": "REAL", + "byte_offset": 148.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "current_value": "4.400000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_SP_ProdTemp", + "data_type": "REAL", + "byte_offset": 152.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+01", + "current_value": "1.700000e+01", + "is_udt_expanded_member": true + }, + { + "name": "_PrdTankMinLevel", + "data_type": "REAL", + "byte_offset": 156.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+01", + "current_value": "3.500000e+01", + "is_udt_expanded_member": true + }, + { + "name": "_WaterValveSave", + "data_type": "REAL", + "byte_offset": 160.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_SyrupValveSave", + "data_type": "REAL", + "byte_offset": 164.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_CarboCO2ValveSave", + "data_type": "REAL", + "byte_offset": 168.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdMeterHighBrix", + "data_type": "REAL", + "byte_offset": 172.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "1.030000e+01", + "is_udt_expanded_member": true + }, + { + "name": "_ProdMeterLowBrix", + "data_type": "REAL", + "byte_offset": 176.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "9.830000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdMeterHighCO2", + "data_type": "REAL", + "byte_offset": 180.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "2.900000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdMeterLowCO2", + "data_type": "REAL", + "byte_offset": 184.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "2.300000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdMeter_ZeroCO2", + "data_type": "REAL", + "byte_offset": 188.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdMeter_ZeroBrix", + "data_type": "REAL", + "byte_offset": 192.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdHighCond", + "data_type": "REAL", + "byte_offset": 196.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdLowCond", + "data_type": "REAL", + "byte_offset": 200.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_BottleSize", + "data_type": "REAL", + "byte_offset": 204.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_FillingValveHead_SP", + "data_type": "REAL", + "byte_offset": 208.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_SyrMeter_ZeroBrix", + "data_type": "REAL", + "byte_offset": 212.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_FirstProdExtraCO2Fact", + "data_type": "REAL", + "byte_offset": 216.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "9.700000e-01", + "current_value": "1.020000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_Gas2Vols", + "data_type": "REAL", + "byte_offset": 220.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_Gas2Fact", + "data_type": "REAL", + "byte_offset": 224.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_SyrupPumpPressure", + "data_type": "REAL", + "byte_offset": 228.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "******Syrup Pump Pressure SP", + "is_udt_expanded_member": true + }, + { + "name": "_WaterPumpPressure", + "data_type": "REAL", + "byte_offset": 232.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "******Water Pump Pressure SP", + "is_udt_expanded_member": true + }, + { + "name": "_CO2_Air_N2_PressSelect", + "data_type": "INT", + "byte_offset": 236.0, + "size_in_bytes": 2, + "bit_size": 0, + "current_value": "0", + "comment": "1=CO2; 2=CO2+SterilAir; 3=CO2+N2 - Pressure Tank Selection", + "is_udt_expanded_member": true + }, + { + "name": "_KFactRVM304BlowOff", + "data_type": "REAL", + "byte_offset": 238.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdRecircPumpFreq", + "data_type": "REAL", + "byte_offset": 242.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdBoosterPumpPress", + "data_type": "REAL", + "byte_offset": 246.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": true + }, + { + "name": "_ProdSendPumpFreq", + "data_type": "REAL", + "byte_offset": 250.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "******Product Sending Pump Frequency SP", + "is_udt_expanded_member": true + } + ], + "is_udt_expanded_member": false + }, + { + "name": "Spare2", + "data_type": "INT", + "byte_offset": 254.0, + "size_in_bytes": 10, + "bit_size": 0, + "array_dimensions": [ + { + "lower_bound": 1, + "upper_bound": 5 + } + ], + "is_udt_expanded_member": false + }, + { + "name": "Next_Recipe_Name", + "data_type": "STRING", + "byte_offset": 264.0, + "size_in_bytes": 34, + "bit_size": 0, + "string_length": 32, + "initial_value": "' '", + "current_value": "'cambio 1$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00'", + "is_udt_expanded_member": false + }, + { + "name": "Next_Recipe_Number", + "data_type": "INT", + "byte_offset": 298.0, + "size_in_bytes": 2, + "bit_size": 0, + "current_value": "0", + "is_udt_expanded_member": false + }, + { + "name": "Spare3", + "data_type": "INT", + "byte_offset": 300.0, + "size_in_bytes": 36, + "bit_size": 0, + "array_dimensions": [ + { + "lower_bound": 1, + "upper_bound": 18 + } + ], + "is_udt_expanded_member": false + }, + { + "name": "ProcessSetup", + "data_type": "STRUCT", + "byte_offset": 336.0, + "size_in_bytes": 446, + "bit_size": 0, + "children": [ + { + "name": "Spare000", + "data_type": "REAL", + "byte_offset": 336.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "Spare040", + "data_type": "REAL", + "byte_offset": 340.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_KWaterLoss", + "data_type": "REAL", + "byte_offset": 344.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e-03", + "current_value": "1.000000e-03", + "comment": "Friction Loss Constant in Serpentine", + "is_udt_expanded_member": false + }, + { + "name": "_KSyrupLoss", + "data_type": "REAL", + "byte_offset": 348.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "7.800000e-03", + "current_value": "7.800000e-03", + "comment": "Friction Loss Constant in Syrup Pipe", + "is_udt_expanded_member": false + }, + { + "name": "_KProdLoss", + "data_type": "REAL", + "byte_offset": 352.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.390000e-02", + "current_value": "1.390000e-02", + "comment": "Pressure Loss Factor", + "is_udt_expanded_member": false + }, + { + "name": "_KPPM303", + "data_type": "REAL", + "byte_offset": 356.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.700000e+00", + "current_value": "5.700000e+00", + "comment": "Frequency Overpressure Pump P3 Constant [Hz/mm]", + "is_udt_expanded_member": false + }, + { + "name": "_BaialageRVM301OVMin", + "data_type": "REAL", + "byte_offset": 360.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.000000e+00", + "current_value": "2.000000e+00", + "comment": "Baialage Minimum Flow (Nm3/h)", + "is_udt_expanded_member": false + }, + { + "name": "_SyrupLinePressure", + "data_type": "REAL", + "byte_offset": 364.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.200000e+00", + "current_value": "2.200000e+00", + "comment": "Syrup Line pressure at VEP2 valve", + "is_udt_expanded_member": false + }, + { + "name": "_CIPRMM301OV", + "data_type": "REAL", + "byte_offset": 368.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+01", + "current_value": "1.000000e+01", + "comment": "Water Valve Opening During CIP", + "is_udt_expanded_member": false + }, + { + "name": "_CIPRMP302OV", + "data_type": "REAL", + "byte_offset": 372.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.500000e+01", + "current_value": "1.500000e+01", + "comment": "Syrup Valve Opening During CIP", + "is_udt_expanded_member": false + }, + { + "name": "_CIPTM301MinLevel", + "data_type": "REAL", + "byte_offset": 376.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.500000e+01", + "current_value": "3.500000e+01", + "comment": "Product Tank Minimum Level In CIP", + "is_udt_expanded_member": false + }, + { + "name": "_CIPTM301MaxLevel", + "data_type": "REAL", + "byte_offset": 380.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.500000e+01", + "current_value": "5.500000e+01", + "comment": "Product Tank Maximum Level In CIP", + "is_udt_expanded_member": false + }, + { + "name": "_CIPPPM303Freq", + "data_type": "REAL", + "byte_offset": 384.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+01", + "current_value": "5.000000e+01", + "comment": "CIP frequency Value [Hz]", + "is_udt_expanded_member": false + }, + { + "name": "_CIPTP301MinLevel", + "data_type": "REAL", + "byte_offset": 388.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.500000e+01", + "current_value": "2.500000e+01", + "comment": "Syrup Tank Minimum Level In CIP", + "is_udt_expanded_member": false + }, + { + "name": "_CIPTP301MaxLevel", + "data_type": "REAL", + "byte_offset": 392.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "4.500000e+01", + "current_value": "4.500000e+01", + "comment": "Syrup Tank Maximum Level In CIP", + "is_udt_expanded_member": false + }, + { + "name": "_RinseRMM301OV", + "data_type": "REAL", + "byte_offset": 396.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+01", + "current_value": "1.000000e+01", + "comment": "Water Valve Opening During Rinse", + "is_udt_expanded_member": false + }, + { + "name": "_RinseRMP302OV", + "data_type": "REAL", + "byte_offset": 400.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.400000e+01", + "current_value": "1.400000e+01", + "comment": "Syrup Valve Opening During Rinse", + "is_udt_expanded_member": false + }, + { + "name": "_RinseTM301Press", + "data_type": "REAL", + "byte_offset": 404.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.000000e-01", + "current_value": "3.000000e-01", + "comment": "Product Tank Pressure In Rinse", + "is_udt_expanded_member": false + }, + { + "name": "_RinsePPM303Freq", + "data_type": "REAL", + "byte_offset": 408.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+01", + "current_value": "5.000000e+01", + "comment": "Rinse frequency Value [Hz]", + "is_udt_expanded_member": false + }, + { + "name": "_DrainTM301Press", + "data_type": "REAL", + "byte_offset": 412.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "current_value": "1.000000e+00", + "comment": "Buffer Tank Draining Pressure", + "is_udt_expanded_member": false + }, + { + "name": "_KRecBlendError", + "data_type": "REAL", + "byte_offset": 416.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.000000e+00", + "current_value": "2.000000e+00", + "comment": "Blend Error Recovery CONSTANT", + "is_udt_expanded_member": false + }, + { + "name": "_KRecCarboCO2Error", + "data_type": "REAL", + "byte_offset": 420.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.000000e+00", + "current_value": "2.000000e+00", + "comment": "Carbonation Error Recovery Constant", + "is_udt_expanded_member": false + }, + { + "name": "_MaxBlendError", + "data_type": "REAL", + "byte_offset": 424.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+02", + "current_value": "1.000000e+02", + "comment": "Blend Error Maximum Value", + "is_udt_expanded_member": false + }, + { + "name": "_MaxCarboCO2Error", + "data_type": "REAL", + "byte_offset": 428.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+02", + "current_value": "5.000000e+02", + "comment": "Carbonation Error Maximum Value", + "is_udt_expanded_member": false + }, + { + "name": "_StartUpBrixExtraWater", + "data_type": "REAL", + "byte_offset": 432.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "4.700000e+01", + "current_value": "4.700000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_StartUpCO2ExtraWater", + "data_type": "REAL", + "byte_offset": 436.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "8.000000e+00", + "current_value": "8.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_StartUpPPM303Freq", + "data_type": "REAL", + "byte_offset": 440.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.000000e+01", + "current_value": "2.000000e+01", + "comment": "Start Up frequency Value [Hz]", + "is_udt_expanded_member": false + }, + { + "name": "_SyrupRoomTank", + "data_type": "INT", + "byte_offset": 444.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "1", + "current_value": "1", + "is_udt_expanded_member": false + }, + { + "name": "_SyrupRunOutLiters", + "data_type": "REAL", + "byte_offset": 446.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.900000e+02", + "current_value": "2.900000e+02", + "is_udt_expanded_member": false + }, + { + "name": "_InjCO2Press_Offset", + "data_type": "REAL", + "byte_offset": 450.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e-01", + "current_value": "5.000000e-01", + "is_udt_expanded_member": false + }, + { + "name": "_InjCO2Press_MinFlow", + "data_type": "REAL", + "byte_offset": 454.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "4.500000e+02", + "current_value": "4.500000e+02", + "is_udt_expanded_member": false + }, + { + "name": "_InjCO2Press_MaxFlow", + "data_type": "REAL", + "byte_offset": 458.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.500000e+03", + "current_value": "2.500000e+03", + "is_udt_expanded_member": false + }, + { + "name": "_CarboCO2Pressure", + "data_type": "REAL", + "byte_offset": 462.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.250000e+01", + "current_value": "1.250000e+01", + "comment": "CO2 Pressure Infeed Line", + "is_udt_expanded_member": false + }, + { + "name": "_N2MinPressure", + "data_type": "REAL", + "byte_offset": 466.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "current_value": "1.000000e+00", + "comment": "N2 Minimum Pressure Infeed Line", + "is_udt_expanded_member": false + }, + { + "name": "_DiffSensor_Height", + "data_type": "REAL", + "byte_offset": 470.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.950000e+02", + "current_value": "3.950000e+02", + "comment": "Sensor Height from Soil [mm]", + "is_udt_expanded_member": false + }, + { + "name": "_DiffSensor_DeltaHeight", + "data_type": "REAL", + "byte_offset": 474.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "-2.500000e+01", + "current_value": "-2.500000e+01", + "comment": "Sensor Plates Height Difference [mm]", + "is_udt_expanded_member": false + }, + { + "name": "_DiffSensor_Offset", + "data_type": "REAL", + "byte_offset": 478.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.618000e+01", + "current_value": "3.618000e+01", + "comment": "Sensor Offset Read with zero pressure (all valves open) in [mm]", + "is_udt_expanded_member": false + }, + { + "name": "_FillingValveHeight", + "data_type": "REAL", + "byte_offset": 482.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.400000e+03", + "current_value": "1.400000e+03", + "comment": "Filling Valve Height from soil [mm]", + "is_udt_expanded_member": false + }, + { + "name": "_FillerDiameter", + "data_type": "REAL", + "byte_offset": 486.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.520000e+03", + "current_value": "2.520000e+03", + "comment": "Filler Carousel Diameter [mm]", + "is_udt_expanded_member": false + }, + { + "name": "_FillingValveNum", + "data_type": "INT", + "byte_offset": 490.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "91", + "current_value": "91", + "comment": "Filling Valves Number", + "is_udt_expanded_member": false + }, + { + "name": "_FillerProdPipeDN", + "data_type": "REAL", + "byte_offset": 492.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+02", + "current_value": "1.000000e+02", + "is_udt_expanded_member": false + }, + { + "name": "_FillerProdPipeMass", + "data_type": "REAL", + "byte_offset": 496.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.600000e+02", + "current_value": "1.600000e+02", + "is_udt_expanded_member": false + }, + { + "name": "_FillingTime", + "data_type": "REAL", + "byte_offset": 500.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.200000e+00", + "current_value": "3.200000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_TM301Height_0", + "data_type": "REAL", + "byte_offset": 504.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.050000e+03", + "current_value": "1.050000e+03", + "comment": "Level at 0% Tank Level Height in mm", + "is_udt_expanded_member": false + }, + { + "name": "_TM301LevelPerc_2", + "data_type": "REAL", + "byte_offset": 508.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "4.600000e+01", + "current_value": "4.600000e+01", + "comment": "Second level percentage", + "is_udt_expanded_member": false + }, + { + "name": "_TM301Height_2", + "data_type": "REAL", + "byte_offset": 512.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.625000e+03", + "current_value": "1.625000e+03", + "comment": "Second level Height in mm", + "is_udt_expanded_member": false + }, + { + "name": "_RVN304Factor", + "data_type": "REAL", + "byte_offset": 516.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.000000e+00", + "current_value": "1.000000e+00", + "comment": "DeareationFlow/WaterFlow", + "is_udt_expanded_member": false + }, + { + "name": "_DrainTM301Flushing", + "data_type": "REAL", + "byte_offset": 520.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.300000e+00", + "current_value": "1.300000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_FirstProdExtraBrix", + "data_type": "REAL", + "byte_offset": 524.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e-02", + "current_value": "5.000000e-02", + "is_udt_expanded_member": false + }, + { + "name": "_FirstProdDietExtraSyr", + "data_type": "REAL", + "byte_offset": 528.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.400000e-03", + "current_value": "1.400000e-03", + "is_udt_expanded_member": false + }, + { + "name": "_EndProdLastSyrlt", + "data_type": "REAL", + "byte_offset": 532.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "End Production Last syrup liters", + "is_udt_expanded_member": false + }, + { + "name": "_TM301DrainSt0Time", + "data_type": "WORD", + "byte_offset": 536.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "W#16#A", + "current_value": "W#16#A", + "comment": "sec", + "is_udt_expanded_member": false + }, + { + "name": "_TM301DrainSt1Time", + "data_type": "WORD", + "byte_offset": 538.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "W#16#50", + "current_value": "W#16#50", + "comment": "sec", + "is_udt_expanded_member": false + }, + { + "name": "_ProdPipeRunOutSt0Time", + "data_type": "WORD", + "byte_offset": 540.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "W#16#1", + "current_value": "W#16#1", + "comment": "sec", + "is_udt_expanded_member": false + }, + { + "name": "_RMM301ProdPipeRunOu", + "data_type": "REAL", + "byte_offset": 542.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.000000e+01", + "current_value": "3.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_RMP302ProdPipeRunOu", + "data_type": "REAL", + "byte_offset": 546.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "4.000000e+01", + "current_value": "4.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_ProdPipeRunOutAmount", + "data_type": "REAL", + "byte_offset": 550.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.000000e+01", + "current_value": "3.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_TM301RunOutChiller", + "data_type": "REAL", + "byte_offset": 554.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+00", + "current_value": "5.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_MinSpeedNominalProd", + "data_type": "REAL", + "byte_offset": 558.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "4.000000e-01", + "current_value": "4.000000e-01", + "comment": "Min Speed for Nominal Production", + "is_udt_expanded_member": false + }, + { + "name": "_MinSpeedSlowProd", + "data_type": "REAL", + "byte_offset": 562.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.000000e-01", + "current_value": "3.000000e-01", + "comment": "Min Speed for Very Low Production", + "is_udt_expanded_member": false + }, + { + "name": "_FastChgOvrTM301DrnPrss", + "data_type": "REAL", + "byte_offset": 566.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "9.000000e-01", + "current_value": "9.000000e-01", + "comment": "Fast Change Over Product Tank Draining Pressure in Blendfill", + "is_udt_expanded_member": false + }, + { + "name": "_CIPTN301MinLevel", + "data_type": "REAL", + "byte_offset": 570.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.500000e+01", + "current_value": "3.500000e+01", + "comment": "Deaireator Tank Minimum Level In CIP", + "is_udt_expanded_member": false + }, + { + "name": "_CIPTN301MaxLevel", + "data_type": "REAL", + "byte_offset": 574.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "6.000000e+01", + "current_value": "6.000000e+01", + "comment": "Deaireator Tank Maximum Level In CIP", + "is_udt_expanded_member": false + }, + { + "name": "_ProdPPN304Freq", + "data_type": "REAL", + "byte_offset": 578.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+01", + "current_value": "5.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_GAS2InjectionPress", + "data_type": "REAL", + "byte_offset": 582.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "4.000000e+00", + "current_value": "4.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_BaialageRVM301OVMax", + "data_type": "REAL", + "byte_offset": 586.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.000000e+01", + "current_value": "2.000000e+01", + "comment": "Baialage Production Flow Multiplier", + "is_udt_expanded_member": false + }, + { + "name": "_RinsePPN301Freq", + "data_type": "REAL", + "byte_offset": 590.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+00", + "current_value": "5.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_CIPPPN301Freq", + "data_type": "REAL", + "byte_offset": 594.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+00", + "current_value": "5.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_RinsePPP302Freq", + "data_type": "REAL", + "byte_offset": 598.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+00", + "current_value": "5.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_CIPPPP302Freq", + "data_type": "REAL", + "byte_offset": 602.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+00", + "current_value": "5.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_PercSyrupBrixSyrStarUp", + "data_type": "REAL", + "byte_offset": 606.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.500000e+01", + "current_value": "2.500000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_RefTempCoolingCTRL", + "data_type": "REAL", + "byte_offset": 610.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_H2OSerpPrimingVolume", + "data_type": "REAL", + "byte_offset": 614.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.500000e+02", + "current_value": "1.500000e+02", + "comment": "Water Serpentine Volume + Water Chiller Volume", + "is_udt_expanded_member": false + }, + { + "name": "_AVN301_Nozzle_Kv", + "data_type": "REAL", + "byte_offset": 618.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.650000e+02", + "current_value": "1.650000e+02", + "comment": "AVN301 Nozzle Kv", + "is_udt_expanded_member": false + }, + { + "name": "_AVN302_Nozzle_Kv", + "data_type": "REAL", + "byte_offset": 622.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.600000e+02", + "current_value": "2.600000e+02", + "comment": "AVN302 Nozzle Kv", + "is_udt_expanded_member": false + }, + { + "name": "_AVN303_Nozzle_Kv", + "data_type": "REAL", + "byte_offset": 626.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.650000e+02", + "current_value": "1.650000e+02", + "comment": "AVN303 Nozzle Kv", + "is_udt_expanded_member": false + }, + { + "name": "_DeoxSpryball_Kv", + "data_type": "REAL", + "byte_offset": 630.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "6.700000e+01", + "current_value": "6.700000e+01", + "comment": "Deox Spryball Kv", + "is_udt_expanded_member": false + }, + { + "name": "_PremixedLineDrainTime", + "data_type": "INT", + "byte_offset": 634.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "300", + "current_value": "300", + "comment": "Premixed Product Line Drain Time", + "is_udt_expanded_member": false + }, + { + "name": "_PPN301_H_MaxFlow", + "data_type": "REAL", + "byte_offset": 636.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "9.000000e+01", + "current_value": "9.000000e+01", + "comment": "PPN301 Pump Head with Max Flow [m]", + "is_udt_expanded_member": false + }, + { + "name": "_PPN301_H_MinFlow", + "data_type": "REAL", + "byte_offset": 640.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "8.700000e+01", + "current_value": "8.700000e+01", + "comment": "PPN301 Pump Head with Min Flow [m]", + "is_udt_expanded_member": false + }, + { + "name": "_PPN301_MaxFlow", + "data_type": "REAL", + "byte_offset": 644.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.070000e+02", + "current_value": "5.070000e+02", + "comment": "PPN301 Max Flow [l/min]", + "is_udt_expanded_member": false + }, + { + "name": "_PPN301_MinFlow", + "data_type": "REAL", + "byte_offset": 648.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.110000e+02", + "current_value": "2.110000e+02", + "comment": "PPN301 Min Flow [l/min]", + "is_udt_expanded_member": false + }, + { + "name": "_PPP302_H_MaxFlow", + "data_type": "REAL", + "byte_offset": 652.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "8.600000e+01", + "current_value": "8.600000e+01", + "comment": "PPP302 Pump Head with Max Flow [m]", + "is_udt_expanded_member": false + }, + { + "name": "_PPP302_H_MinFlow", + "data_type": "REAL", + "byte_offset": 656.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "8.500000e+01", + "current_value": "8.500000e+01", + "comment": "PPP302 Pump Head with Min Flow [m]", + "is_udt_expanded_member": false + }, + { + "name": "_PPP302_MaxFlow", + "data_type": "REAL", + "byte_offset": 660.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.150000e+02", + "current_value": "1.150000e+02", + "comment": "PPP302 Max Flow [l/min]", + "is_udt_expanded_member": false + }, + { + "name": "_PPP302_MinFlow", + "data_type": "REAL", + "byte_offset": 664.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.200000e+01", + "current_value": "3.200000e+01", + "comment": "PPP302 Min Flow [l/min]", + "is_udt_expanded_member": false + }, + { + "name": "_RinsePPM306Freq", + "data_type": "REAL", + "byte_offset": 668.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+00", + "current_value": "5.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_CIPPPM306Freq", + "data_type": "REAL", + "byte_offset": 672.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+00", + "current_value": "5.000000e+00", + "is_udt_expanded_member": false + }, + { + "name": "_PPM307_H_MaxFlow", + "data_type": "REAL", + "byte_offset": 676.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "PPM307 Pump Head with Max Flow [m]", + "is_udt_expanded_member": false + }, + { + "name": "_PPM307_H_MinFlow", + "data_type": "REAL", + "byte_offset": 680.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "PPM307 Pump Head with Min Flow [m]", + "is_udt_expanded_member": false + }, + { + "name": "_PPM307_MaxFlow", + "data_type": "REAL", + "byte_offset": 684.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "PPM307 Max Flow [l/min]", + "is_udt_expanded_member": false + }, + { + "name": "_PPM307_MinFlow", + "data_type": "REAL", + "byte_offset": 688.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "PPM307 Min Flow [l/min]", + "is_udt_expanded_member": false + }, + { + "name": "_Temp0_VacuumCtrl", + "data_type": "REAL", + "byte_offset": 692.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "1.800000e+01", + "current_value": "1.800000e+01", + "comment": "PPN304 Target Temperature - OPTION PPN304 Sterling Type", + "is_udt_expanded_member": false + }, + { + "name": "_Temp1_VacuumCtrl", + "data_type": "REAL", + "byte_offset": 696.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.000000e+00", + "current_value": "2.000000e+00", + "comment": "PPN304 High Treshold Temperature Delta - OPTION PPN304 Sterling Type", + "is_udt_expanded_member": false + }, + { + "name": "_Temp2_VacuumCtrl", + "data_type": "REAL", + "byte_offset": 700.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "2.000000e+00", + "current_value": "2.000000e+00", + "comment": "PPN304 Low Treshold Temperature Delta - OPTION PPN304 Sterling Type", + "is_udt_expanded_member": false + }, + { + "name": "_Temp3_VacuumCtrl", + "data_type": "REAL", + "byte_offset": 704.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+01", + "current_value": "5.000000e+01", + "comment": "PPN304 Warning Temperature - OPTION PPN304 Sterling Type", + "is_udt_expanded_member": false + }, + { + "name": "_Temp4_VacuumCtrl", + "data_type": "REAL", + "byte_offset": 708.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+01", + "current_value": "5.000000e+01", + "comment": "PPN304 Alarm Temperature - OPTION PPN304 Sterling Type", + "is_udt_expanded_member": false + }, + { + "name": "_T1_VacuumCtrl", + "data_type": "DINT", + "byte_offset": 712.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "L#1500", + "current_value": "L#1500", + "comment": "PPN304 Time 1 [msec] - OPTION PPN304 Sterling Type", + "is_udt_expanded_member": false + }, + { + "name": "_T2_VacuumCtrl", + "data_type": "DINT", + "byte_offset": 716.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "L#1500", + "current_value": "L#1500", + "comment": "PPN304 Time 2 [msec] - OPTION PPN304 Sterling Type", + "is_udt_expanded_member": false + }, + { + "name": "_T3_VacuumCtrl", + "data_type": "DINT", + "byte_offset": 720.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "L#1000", + "current_value": "L#1000", + "comment": "PPN304 Time 3 [msec] - OPTION PPN304 Sterling Type", + "is_udt_expanded_member": false + }, + { + "name": "_T4_VacuumCtrl", + "data_type": "DINT", + "byte_offset": 724.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "L#1000", + "current_value": "L#1000", + "comment": "PPN304 Time 4 [msec] - OPTION PPN304 Sterling Type", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_VolDosWorkTimePAA", + "data_type": "INT", + "byte_offset": 728.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Working Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_VolPauseTimePAA", + "data_type": "INT", + "byte_offset": 730.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Pause Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_PAAPulseWeight", + "data_type": "INT", + "byte_offset": 732.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "10", + "current_value": "10", + "comment": "ICS - DS - PAA Pulse Weight [(L/Pulse)/100]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_CausticPulseWeight", + "data_type": "INT", + "byte_offset": 734.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "10", + "current_value": "10", + "comment": "ICS - DS - Caustic Pulse Weight [(L/Pulse)/100]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_AcidPulseWeight", + "data_type": "INT", + "byte_offset": 736.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "10", + "current_value": "10", + "comment": "ICS - DS - Acid Pulse Weight [(L/Pulse)/100]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_VolumeRestOfLine", + "data_type": "REAL", + "byte_offset": 738.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.500000e+02", + "current_value": "3.500000e+02", + "comment": "ICS - DS - Volume of the Rest of the Line (Filler + Piping) [L]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_VolDosWorkTimeCaus", + "data_type": "INT", + "byte_offset": 742.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Working Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_VolDosPauseTimeCaus", + "data_type": "INT", + "byte_offset": 744.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Pause Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_VolDosWorkTimeAcid", + "data_type": "INT", + "byte_offset": 746.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Working Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_VolDosPauseTimeAcid", + "data_type": "INT", + "byte_offset": 748.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Pause Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_ConcDosWorkTimeCaus", + "data_type": "INT", + "byte_offset": 750.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Working Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_ConcDosPausTimeCaus", + "data_type": "INT", + "byte_offset": 752.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Pause Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_ConcDosWorkTimeAcid", + "data_type": "INT", + "byte_offset": 754.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Working Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_ICS_ConcDosPausTimeAcid", + "data_type": "INT", + "byte_offset": 756.0, + "size_in_bytes": 2, + "bit_size": 0, + "initial_value": "30", + "current_value": "30", + "comment": "ICS - DS - Dosing Pause Time [sec]", + "is_udt_expanded_member": false + }, + { + "name": "_RinsePPM307Freq", + "data_type": "REAL", + "byte_offset": 758.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.000000e+01", + "current_value": "3.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_CIPPPM307Freq", + "data_type": "REAL", + "byte_offset": 762.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "3.000000e+01", + "current_value": "3.000000e+01", + "is_udt_expanded_member": false + }, + { + "name": "_CIP2StepTN301Lvl", + "data_type": "REAL", + "byte_offset": 766.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "Local CIP - 2 Step loading TN301 Level", + "is_udt_expanded_member": false + }, + { + "name": "_CIP2StepTM301Lvl", + "data_type": "REAL", + "byte_offset": 770.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "Local CIP - 2 Step loading TM301 Level", + "is_udt_expanded_member": false + }, + { + "name": "_CIP2StepTP301Lvl", + "data_type": "REAL", + "byte_offset": 774.0, + "size_in_bytes": 4, + "bit_size": 0, + "current_value": "0.000000e+00", + "comment": "Local CIP - 2 Step loading TP301 Level", + "is_udt_expanded_member": false + }, + { + "name": "_PumpNominalFreq", + "data_type": "REAL", + "byte_offset": 778.0, + "size_in_bytes": 4, + "bit_size": 0, + "initial_value": "5.000000e+01", + "current_value": "5.000000e+01", + "comment": "50.0 Hz or 60.0 Hz", + "is_udt_expanded_member": false + } + ], + "is_udt_expanded_member": false + }, + { + "name": "_SwitchOff_DensityOK", + "data_type": "BOOL", + "byte_offset": 782.0, + "size_in_bytes": 0, + "bit_size": 1, + "current_value": "FALSE", + "is_udt_expanded_member": false + } + ], + "total_size_in_bytes": 784 + } + ] +} \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/readme.md b/backend/script_groups/S7_DB_Utils/readme.md new file mode 100644 index 0000000..d0f4c93 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/readme.md @@ -0,0 +1,77 @@ + +### How to work with config setup Example + +script_root = os.path.dirname( + os.path.dirname(os.path.dirname(os.path.dirname(__file__))) +) +sys.path.append(script_root) +from backend.script_utils import load_configuration + +if __name__ == "__main__": +""" + Load configuration from script_config.json in the current script directory. + + Returns: + Dict containing configurations with levels 1, 2, 3 and working_directory + + Example usage in scripts: + from script_utils import load_configuration + + configs = load_configuration() + level1_config = configs.get("level1", {}) + level2_config = configs.get("level2", {}) + level3_config = configs.get("level3", {}) + working_dir = configs.get("working_directory", "") +"""" + + configs = load_configuration() + working_directory = configs.get("working_directory") + + # Acceder a la configuración específica del grupo + group_config = configs.get("level2", {}) + + # Leer parámetros con valores por defecto (usando los defaults del esquema como guía) + # Parámetros necesarios para x4 + cfg_scl_output_dirname = group_config.get("scl_output_dir", "scl_output") + cfg_xref_output_dirname = group_config.get("xref_output_dir", "xref_output") + cfg_xref_source_subdir = group_config.get("xref_source_subdir", "source") + + + +### Directory structure for Tia Portal scripts + +/ +├── _CAx_Export.aml +├── / +│ ├── ProgramBlocks_XML/ +│ │ └── ... (archivos XML de bloques) +│ ├── ProgramBlocks_SCL/ +│ │ └── ... (archivos SCL de bloques) +│ ├── ProgramBlocks_CR/ +│ │ └── ... (archivos XML de referencias cruzadas de bloques) +│ ├── PlcTags/ +│ │ └── ... (archivos XML de tablas de tags) +│ ├── PlcTags_CR/ +│ │ └── ... (archivos XML de referencias cruzadas de tablas de tags) +│ ├── PlcDataTypes_CR/ +│ │ └── ... (archivos XML de referencias cruzadas de UDTs) +│ ├── SystemBlocks_CR/ +│ │ └── ... +│ └── SoftwareUnits_CR/ +│ └── ... +│ └── Documentation/ +│ └── Source +│ └── ... (archivos md de bloques de programa) +│ └── JSON +│ └── ... (archivos JSON temporales) +│ └── xref_calls_tree.md +│ └── xref_db_usage_summary.md +│ └── xref_plc_tags_summary.md +│ └── full_project_representation.md +│ └── _CAx_Export_Hardware_Tree.md + +├── / +│ ├── ProgramBlocks_XML/ +│ │ └── ... +│ └── ... +└── ... \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/reconstructed_s7_source_v2.txt b/backend/script_groups/S7_DB_Utils/reconstructed_s7_source_v2.txt new file mode 100644 index 0000000..7ef2573 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/reconstructed_s7_source_v2.txt @@ -0,0 +1,521 @@ +TYPE "Recipe_Prod" + FAMILY : DataType; + VERSION : 0.1; + + STRUCT + _Name : STRING[32] := ' '; + _EnProdTemp : BOOL; + _SyrFlushing : BOOL; // Ex_EnDeaireation --> DELETED - AVP320 VALVE OPEN + _GAS2_Injection : BOOL; // 0 = GAS2 not present; 1 = GAS2 present + _Eq_Pression_Selected : BOOL; + _DeoxStripEn : BOOL; // ******Deairation with Strip Enable + _DeoxVacuumEn : BOOL; // ******Deairation with Vacuum + _DeoxPreMixed : BOOL; // ******Deairation of Premixed Product + _EnBlowOffProdPipeCO2Fil : BOOL; + _WaterSelection : BYTE; + _FillerNextRecipeNum : BYTE; + _BottleShape : BYTE; + _Type : INT := 1; // 1= DIET; 2= REGULAR; 3= RATIO; 4= WATER + _ProdMeterRecipeNum : INT; + _SyrupBrix : REAL := 5.000000e+01; + _SyrupDensity : REAL := 1.255800e+00; + _SyrupFactor : REAL := 1.000000e+00; + _ProductBrix : REAL := 1.045000e+01; + _ProductionRate : REAL := 9.000000e+02; + _Ratio : REAL := 2.000000e+01; + _ProdBrixOffset : REAL; + _CO2Vols : REAL; + _CO2Fact : REAL := 1.000000e+00; + _ProdTankPress : REAL := 1.000000e+00; + _SP_ProdTemp : REAL := 1.000000e+01; + _PrdTankMinLevel : REAL := 1.000000e+01; + _WaterValveSave : REAL; + _SyrupValveSave : REAL; + _CarboCO2ValveSave : REAL; + _ProdMeterHighBrix : REAL; + _ProdMeterLowBrix : REAL; + _ProdMeterHighCO2 : REAL; + _ProdMeterLowCO2 : REAL; + _ProdMeter_ZeroCO2 : REAL; + _ProdMeter_ZeroBrix : REAL; + _ProdHighCond : REAL; + _ProdLowCond : REAL; + _BottleSize : REAL; + _FillingValveHead_SP : REAL; + _SyrMeter_ZeroBrix : REAL; + _FirstProdExtraCO2Fact : REAL := 9.700000e-01; + _Gas2Vols : REAL; + _Gas2Fact : REAL := 1.000000e+00; + _SyrupPumpPressure : REAL; // ******Syrup Pump Pressure SP + _WaterPumpPressure : REAL; // ******Water Pump Pressure SP + _CO2_Air_N2_PressSelect : INT; // 1=CO2; 2=CO2+SterilAir; 3=CO2+N2 - Pressure Tank Selection + _KFactRVM304BlowOff : REAL; + _ProdRecircPumpFreq : REAL; + _ProdBoosterPumpPress : REAL; + _ProdSendPumpFreq : REAL; // ******Product Sending Pump Frequency SP + END_STRUCT; +END_TYPE; + +DATA_BLOCK "HMI_Blender_Parameters" + FAMILY : Resource; + VERSION : 0.0; + + STRUCT + Processor_Options : STRUCT; + Blender_OPT : STRUCT; + _ModelNum : INT := 6; + _CO2_Offset : REAL := 4.500000e-01; + _MaxSyrDeltaBrix : REAL := 8.000000e-01; + _BrixMeter : BOOL := TRUE; + Spare101 : BOOL; + _TrackH2OEnable : BOOL; + _PAmPDSType : BOOL; // 0)Cobrix 2000 1)Carbo 2000 + _HistoricalTrends : BOOL := TRUE; // 0)Not Present 1)Present + _PowerMeter : BOOL; // 0)Not Present 1)Present + _Report : BOOL := TRUE; // 0)Not Present 1)Present + _Balaiage : BOOL; + _Valves_FullFeedback : BOOL := TRUE; // Valves control Full feedback + _Valves_SingleFeedback : BOOL; // Valves control Single feedback + _PumpsSafetySwitches : BOOL; // Pumps with Safety Switches + _SurgeProtectionAct : BOOL; + _DBC_Type : BOOL; // 0) Deox,Carbo,Blend 1)Deox,Blend,Carbo + _CO2InletMeter : BOOL := TRUE; // 0)Not Present 1)Present + _ProductO2Meter : BOOL; // 0)Not Present 1)Present + _CopressedAirInletMeter : BOOL; // 0)Not Present 1)Present + _MeterType : INT := 6; // 1)Maselli 2)AntoonPaar 3)4-20mA 4)UC05 UR22 5)mPDSPA 6)MR02 + _MeterReceiveOnly : BOOL; + _SyrBrixMeter : BOOL; + _Flooding_Start_Up : BOOL; // 0)Not Selected 1)Selected + _FastChangeOverEnabled : BOOL := TRUE; + _WaterInletMeter : BOOL; // 0)Not Present 1)Present + _BlendFillSystem : BOOL := TRUE; + _TrackFillerSpeed : BOOL := TRUE; + _SignalExchange : INT := 1; // FILLER - 0= Hardwire; 1= Ethernet + _CoolerPresent : BOOL := TRUE; + _CoolerControl : INT := 4; // 0)External 1)Water 2)Product 3)Water+Product-2 Ctrl 4)Water+Product-1 Ctrl + _CoolerType : INT; // 0)Glycol 1)Ammonia + _LocalCIP : BOOL; + _ICS_CustomerHotWater : BOOL; // 0)No Hot Water from Customer 1)Hot Water from Customer Available + _ICS_CustomerChemRecov : BOOL; // 0)No Customer's Chemicals Recovery 1)Customer's Chemicals Recovery Available + _CIPSignalExchange : BOOL; // CIP - 0= Hardwire; 1= Ethernet + _ICS_CustomerChemicals : BOOL; // 0)Chemicals from ICS 1)Chemicals from Customer + _CarboPresent : BOOL := TRUE; + _InverterSyrupPumpPPP302 : BOOL; // 0)Not Present 1)Present + _InverterWaterPumpPPN301 : BOOL; // 0)Not Present 1)Present + _DoubleDeair : BOOL := TRUE; + _DeairPreMixed : BOOL; // Deox Premixed Inlet + _Deaireation : BOOL := TRUE; // 0)SAG 1)SAE/SAF + _StillWaterByPass : BOOL; + _ManifoldSetting : BOOL := TRUE; // 0)Manual 1)Automatic + _InverterProdPumpPPM303 : BOOL; + _SidelCip : BOOL; + _EthernetCom_CpuPN_CP : BOOL := TRUE; // 0)Comunication with CP 1)Comunication with CPU PN + _2ndOutlet : INT; // 0)No 2nd Outlet 1)2nd Outlet No Standalone 2)2nd Outlet Standalone + _Promass : INT := 2; + _WaterPromass : BOOL := TRUE; // 0)Promag 1)Promass + _ProductConductimeter : BOOL; + _ICS_CustomerH2ORecov : BOOL; // 0)No Customer's H2O Recovery 1)Customer's H2O Recovery Available + Spare303 : BOOL; + _CO2_GAS2_Injection : BOOL; // 0)Only CO2 Injection 1)GAS2 Injection + _InverterVacuuPumpPPN304 : BOOL; // 0)Not Present 1)Present + _InverterBoostPumpPPM307 : BOOL; // 0)Not Present 1)Present + _RunOut_Water : BOOL := TRUE; // 0)Syrup Runout without Water 1)Syrup runout with Water pushing + _FlowMeterType : BOOL; // 0)Endrees Hauser -- 1)Micromotion + _SidelFiller : BOOL; // 0)Filler Simonazzi -- 1)Filler Sidel Filling + _Simulation : BOOL; + _ProductCoolingCTRL : BOOL; // 0)none 1) TTM307 + _ChillerCTRL : BOOL; // Chiller Pressure Cross Control + _CO2_SterileFilter : BOOL := TRUE; // CO2 Inlet with Steril Filter + _InverterRecirPumpPPM306 : BOOL; // 0)Not Present 1)Present + _ProdPressReleaseRVM304 : BOOL; // 0)Not Present 1)Present + _VacuumPump : INT := 1; // 0)None 1)Sterling 2)Nash Elmo + _GAS2InjectionType : INT; // 0)None 1)N2 2)Steril Air + _InjectionPress_Ctrl : INT := 1; // 0)Manual 1)Norgren v1 2)Norgren v2 + _ProdPressureType : INT; // 0)Only CO2 1)CO2+SterilAir 2)CO2+N2 + _CIPHeatType : INT; // 0)Steam 1)Electric + _EHS_NrRes : INT := 6; // Number of Heat Resistances + END_STRUCT; + END_STRUCT; + Spare1 : ARRAY [1..9] OF INT; + _RVM301_DeadBand : REAL := 5.000000e-02; + _RVM301_Kp : REAL := 9.000000e+01; + Actual_Recipe_Parameters : "Recipe_Prod"; + Spare2 : ARRAY [1..5] OF INT; + Next_Recipe_Name : STRING[32] := ' '; + Next_Recipe_Number : INT; + Spare3 : ARRAY [1..18] OF INT; + ProcessSetup : STRUCT; + Spare000 : REAL; + Spare040 : REAL; + _KWaterLoss : REAL := 1.000000e-03; // Friction Loss Constant in Serpentine + _KSyrupLoss : REAL := 7.800000e-03; // Friction Loss Constant in Syrup Pipe + _KProdLoss : REAL := 1.390000e-02; // Pressure Loss Factor + _KPPM303 : REAL := 5.700000e+00; // Frequency Overpressure Pump P3 Constant [Hz/mm] + _BaialageRVM301OVMin : REAL := 2.000000e+00; // Baialage Minimum Flow (Nm3/h) + _SyrupLinePressure : REAL := 2.200000e+00; // Syrup Line pressure at VEP2 valve + _CIPRMM301OV : REAL := 1.000000e+01; // Water Valve Opening During CIP + _CIPRMP302OV : REAL := 1.500000e+01; // Syrup Valve Opening During CIP + _CIPTM301MinLevel : REAL := 3.500000e+01; // Product Tank Minimum Level In CIP + _CIPTM301MaxLevel : REAL := 5.500000e+01; // Product Tank Maximum Level In CIP + _CIPPPM303Freq : REAL := 5.000000e+01; // CIP frequency Value [Hz] + _CIPTP301MinLevel : REAL := 2.500000e+01; // Syrup Tank Minimum Level In CIP + _CIPTP301MaxLevel : REAL := 4.500000e+01; // Syrup Tank Maximum Level In CIP + _RinseRMM301OV : REAL := 1.000000e+01; // Water Valve Opening During Rinse + _RinseRMP302OV : REAL := 1.400000e+01; // Syrup Valve Opening During Rinse + _RinseTM301Press : REAL := 3.000000e-01; // Product Tank Pressure In Rinse + _RinsePPM303Freq : REAL := 5.000000e+01; // Rinse frequency Value [Hz] + _DrainTM301Press : REAL := 1.000000e+00; // Buffer Tank Draining Pressure + _KRecBlendError : REAL := 2.000000e+00; // Blend Error Recovery CONSTANT + _KRecCarboCO2Error : REAL := 2.000000e+00; // Carbonation Error Recovery Constant + _MaxBlendError : REAL := 1.000000e+02; // Blend Error Maximum Value + _MaxCarboCO2Error : REAL := 5.000000e+02; // Carbonation Error Maximum Value + _StartUpBrixExtraWater : REAL := 4.700000e+01; + _StartUpCO2ExtraWater : REAL := 8.000000e+00; + _StartUpPPM303Freq : REAL := 2.000000e+01; // Start Up frequency Value [Hz] + _SyrupRoomTank : INT := 1; + _SyrupRunOutLiters : REAL := 2.900000e+02; + _InjCO2Press_Offset : REAL := 5.000000e-01; + _InjCO2Press_MinFlow : REAL := 4.500000e+02; + _InjCO2Press_MaxFlow : REAL := 2.500000e+03; + _CarboCO2Pressure : REAL := 1.250000e+01; // CO2 Pressure Infeed Line + _N2MinPressure : REAL := 1.000000e+00; // N2 Minimum Pressure Infeed Line + _DiffSensor_Height : REAL := 3.950000e+02; // Sensor Height from Soil [mm] + _DiffSensor_DeltaHeight : REAL := -2.500000e+01; // Sensor Plates Height Difference [mm] + _DiffSensor_Offset : REAL := 3.618000e+01; // Sensor Offset Read with zero pressure (all valves open) in [mm] + _FillingValveHeight : REAL := 1.400000e+03; // Filling Valve Height from soil [mm] + _FillerDiameter : REAL := 2.520000e+03; // Filler Carousel Diameter [mm] + _FillingValveNum : INT := 91; // Filling Valves Number + _FillerProdPipeDN : REAL := 1.000000e+02; + _FillerProdPipeMass : REAL := 1.600000e+02; + _FillingTime : REAL := 3.200000e+00; + _TM301Height_0 : REAL := 1.050000e+03; // Level at 0% Tank Level Height in mm + _TM301LevelPerc_2 : REAL := 4.600000e+01; // Second level percentage + _TM301Height_2 : REAL := 1.625000e+03; // Second level Height in mm + _RVN304Factor : REAL := 1.000000e+00; // DeareationFlow/WaterFlow + _DrainTM301Flushing : REAL := 1.300000e+00; + _FirstProdExtraBrix : REAL := 5.000000e-02; + _FirstProdDietExtraSyr : REAL := 1.400000e-03; + _EndProdLastSyrlt : REAL; // End Production Last syrup liters + _TM301DrainSt0Time : WORD := W#16#A; // sec + _TM301DrainSt1Time : WORD := W#16#50; // sec + _ProdPipeRunOutSt0Time : WORD := W#16#1; // sec + _RMM301ProdPipeRunOu : REAL := 3.000000e+01; + _RMP302ProdPipeRunOu : REAL := 4.000000e+01; + _ProdPipeRunOutAmount : REAL := 3.000000e+01; + _TM301RunOutChiller : REAL := 5.000000e+00; + _MinSpeedNominalProd : REAL := 4.000000e-01; // Min Speed for Nominal Production + _MinSpeedSlowProd : REAL := 3.000000e-01; // Min Speed for Very Low Production + _FastChgOvrTM301DrnPrss : REAL := 9.000000e-01; // Fast Change Over Product Tank Draining Pressure in Blendfill + _CIPTN301MinLevel : REAL := 3.500000e+01; // Deaireator Tank Minimum Level In CIP + _CIPTN301MaxLevel : REAL := 6.000000e+01; // Deaireator Tank Maximum Level In CIP + _ProdPPN304Freq : REAL := 5.000000e+01; + _GAS2InjectionPress : REAL := 4.000000e+00; + _BaialageRVM301OVMax : REAL := 2.000000e+01; // Baialage Production Flow Multiplier + _RinsePPN301Freq : REAL := 5.000000e+00; + _CIPPPN301Freq : REAL := 5.000000e+00; + _RinsePPP302Freq : REAL := 5.000000e+00; + _CIPPPP302Freq : REAL := 5.000000e+00; + _PercSyrupBrixSyrStarUp : REAL := 2.500000e+01; + _RefTempCoolingCTRL : REAL; + _H2OSerpPrimingVolume : REAL := 1.500000e+02; // Water Serpentine Volume + Water Chiller Volume + _AVN301_Nozzle_Kv : REAL := 1.650000e+02; // AVN301 Nozzle Kv + _AVN302_Nozzle_Kv : REAL := 2.600000e+02; // AVN302 Nozzle Kv + _AVN303_Nozzle_Kv : REAL := 1.650000e+02; // AVN303 Nozzle Kv + _DeoxSpryball_Kv : REAL := 6.700000e+01; // Deox Spryball Kv + _PremixedLineDrainTime : INT := 300; // Premixed Product Line Drain Time + _PPN301_H_MaxFlow : REAL := 9.000000e+01; // PPN301 Pump Head with Max Flow [m] + _PPN301_H_MinFlow : REAL := 8.700000e+01; // PPN301 Pump Head with Min Flow [m] + _PPN301_MaxFlow : REAL := 5.070000e+02; // PPN301 Max Flow [l/min] + _PPN301_MinFlow : REAL := 2.110000e+02; // PPN301 Min Flow [l/min] + _PPP302_H_MaxFlow : REAL := 8.600000e+01; // PPP302 Pump Head with Max Flow [m] + _PPP302_H_MinFlow : REAL := 8.500000e+01; // PPP302 Pump Head with Min Flow [m] + _PPP302_MaxFlow : REAL := 1.150000e+02; // PPP302 Max Flow [l/min] + _PPP302_MinFlow : REAL := 3.200000e+01; // PPP302 Min Flow [l/min] + _RinsePPM306Freq : REAL := 5.000000e+00; + _CIPPPM306Freq : REAL := 5.000000e+00; + _PPM307_H_MaxFlow : REAL; // PPM307 Pump Head with Max Flow [m] + _PPM307_H_MinFlow : REAL; // PPM307 Pump Head with Min Flow [m] + _PPM307_MaxFlow : REAL; // PPM307 Max Flow [l/min] + _PPM307_MinFlow : REAL; // PPM307 Min Flow [l/min] + _Temp0_VacuumCtrl : REAL := 1.800000e+01; // PPN304 Target Temperature - OPTION PPN304 Sterling Type + _Temp1_VacuumCtrl : REAL := 2.000000e+00; // PPN304 High Treshold Temperature Delta - OPTION PPN304 Sterling Type + _Temp2_VacuumCtrl : REAL := 2.000000e+00; // PPN304 Low Treshold Temperature Delta - OPTION PPN304 Sterling Type + _Temp3_VacuumCtrl : REAL := 5.000000e+01; // PPN304 Warning Temperature - OPTION PPN304 Sterling Type + _Temp4_VacuumCtrl : REAL := 5.000000e+01; // PPN304 Alarm Temperature - OPTION PPN304 Sterling Type + _T1_VacuumCtrl : DINT := L#1500; // PPN304 Time 1 [msec] - OPTION PPN304 Sterling Type + _T2_VacuumCtrl : DINT := L#1500; // PPN304 Time 2 [msec] - OPTION PPN304 Sterling Type + _T3_VacuumCtrl : DINT := L#1000; // PPN304 Time 3 [msec] - OPTION PPN304 Sterling Type + _T4_VacuumCtrl : DINT := L#1000; // PPN304 Time 4 [msec] - OPTION PPN304 Sterling Type + _ICS_VolDosWorkTimePAA : INT := 30; // ICS - DS - Dosing Working Time [sec] + _ICS_VolPauseTimePAA : INT := 30; // ICS - DS - Dosing Pause Time [sec] + _ICS_PAAPulseWeight : INT := 10; // ICS - DS - PAA Pulse Weight [(L/Pulse)/100] + _ICS_CausticPulseWeight : INT := 10; // ICS - DS - Caustic Pulse Weight [(L/Pulse)/100] + _ICS_AcidPulseWeight : INT := 10; // ICS - DS - Acid Pulse Weight [(L/Pulse)/100] + _ICS_VolumeRestOfLine : REAL := 3.500000e+02; // ICS - DS - Volume of the Rest of the Line (Filler + Piping) [L] + _ICS_VolDosWorkTimeCaus : INT := 30; // ICS - DS - Dosing Working Time [sec] + _ICS_VolDosPauseTimeCaus : INT := 30; // ICS - DS - Dosing Pause Time [sec] + _ICS_VolDosWorkTimeAcid : INT := 30; // ICS - DS - Dosing Working Time [sec] + _ICS_VolDosPauseTimeAcid : INT := 30; // ICS - DS - Dosing Pause Time [sec] + _ICS_ConcDosWorkTimeCaus : INT := 30; // ICS - DS - Dosing Working Time [sec] + _ICS_ConcDosPausTimeCaus : INT := 30; // ICS - DS - Dosing Pause Time [sec] + _ICS_ConcDosWorkTimeAcid : INT := 30; // ICS - DS - Dosing Working Time [sec] + _ICS_ConcDosPausTimeAcid : INT := 30; // ICS - DS - Dosing Pause Time [sec] + _RinsePPM307Freq : REAL := 3.000000e+01; + _CIPPPM307Freq : REAL := 3.000000e+01; + _CIP2StepTN301Lvl : REAL; // Local CIP - 2 Step loading TN301 Level + _CIP2StepTM301Lvl : REAL; // Local CIP - 2 Step loading TM301 Level + _CIP2StepTP301Lvl : REAL; // Local CIP - 2 Step loading TP301 Level + _PumpNominalFreq : REAL := 5.000000e+01; // 50.0 Hz or 60.0 Hz + END_STRUCT; + _SwitchOff_DensityOK : BOOL; + END_STRUCT; +BEGIN + Processor_Options.Blender_OPT._ModelNum := 6; + Processor_Options.Blender_OPT._CO2_Offset := 4.500000e-01; + Processor_Options.Blender_OPT._MaxSyrDeltaBrix := 8.000000e-01; + Processor_Options.Blender_OPT._BrixMeter := TRUE; + Processor_Options.Blender_OPT.Spare101 := FALSE; + Processor_Options.Blender_OPT._TrackH2OEnable := FALSE; + Processor_Options.Blender_OPT._PAmPDSType := FALSE; + Processor_Options.Blender_OPT._HistoricalTrends := TRUE; + Processor_Options.Blender_OPT._PowerMeter := FALSE; + Processor_Options.Blender_OPT._Report := TRUE; + Processor_Options.Blender_OPT._Balaiage := FALSE; + Processor_Options.Blender_OPT._Valves_FullFeedback := TRUE; + Processor_Options.Blender_OPT._Valves_SingleFeedback := FALSE; + Processor_Options.Blender_OPT._PumpsSafetySwitches := FALSE; + Processor_Options.Blender_OPT._SurgeProtectionAct := FALSE; + Processor_Options.Blender_OPT._DBC_Type := FALSE; + Processor_Options.Blender_OPT._CO2InletMeter := TRUE; + Processor_Options.Blender_OPT._ProductO2Meter := FALSE; + Processor_Options.Blender_OPT._CopressedAirInletMeter := FALSE; + Processor_Options.Blender_OPT._MeterType := 6; + Processor_Options.Blender_OPT._MeterReceiveOnly := FALSE; + Processor_Options.Blender_OPT._SyrBrixMeter := FALSE; + Processor_Options.Blender_OPT._Flooding_Start_Up := FALSE; + Processor_Options.Blender_OPT._FastChangeOverEnabled := TRUE; + Processor_Options.Blender_OPT._WaterInletMeter := FALSE; + Processor_Options.Blender_OPT._BlendFillSystem := TRUE; + Processor_Options.Blender_OPT._TrackFillerSpeed := TRUE; + Processor_Options.Blender_OPT._SignalExchange := 1; + Processor_Options.Blender_OPT._CoolerPresent := TRUE; + Processor_Options.Blender_OPT._CoolerControl := 4; + Processor_Options.Blender_OPT._CoolerType := 0; + Processor_Options.Blender_OPT._LocalCIP := FALSE; + Processor_Options.Blender_OPT._ICS_CustomerHotWater := FALSE; + Processor_Options.Blender_OPT._ICS_CustomerChemRecov := FALSE; + Processor_Options.Blender_OPT._CIPSignalExchange := FALSE; + Processor_Options.Blender_OPT._ICS_CustomerChemicals := FALSE; + Processor_Options.Blender_OPT._CarboPresent := TRUE; + Processor_Options.Blender_OPT._InverterSyrupPumpPPP302 := FALSE; + Processor_Options.Blender_OPT._InverterWaterPumpPPN301 := FALSE; + Processor_Options.Blender_OPT._DoubleDeair := TRUE; + Processor_Options.Blender_OPT._DeairPreMixed := FALSE; + Processor_Options.Blender_OPT._Deaireation := TRUE; + Processor_Options.Blender_OPT._StillWaterByPass := FALSE; + Processor_Options.Blender_OPT._ManifoldSetting := TRUE; + Processor_Options.Blender_OPT._InverterProdPumpPPM303 := FALSE; + Processor_Options.Blender_OPT._SidelCip := FALSE; + Processor_Options.Blender_OPT._EthernetCom_CpuPN_CP := TRUE; + Processor_Options.Blender_OPT._2ndOutlet := 0; + Processor_Options.Blender_OPT._Promass := 2; + Processor_Options.Blender_OPT._WaterPromass := TRUE; + Processor_Options.Blender_OPT._ProductConductimeter := FALSE; + Processor_Options.Blender_OPT._ICS_CustomerH2ORecov := FALSE; + Processor_Options.Blender_OPT.Spare303 := FALSE; + Processor_Options.Blender_OPT._CO2_GAS2_Injection := FALSE; + Processor_Options.Blender_OPT._InverterVacuuPumpPPN304 := FALSE; + Processor_Options.Blender_OPT._InverterBoostPumpPPM307 := FALSE; + Processor_Options.Blender_OPT._RunOut_Water := TRUE; + Processor_Options.Blender_OPT._FlowMeterType := TRUE; + Processor_Options.Blender_OPT._SidelFiller := FALSE; + Processor_Options.Blender_OPT._Simulation := FALSE; + Processor_Options.Blender_OPT._ProductCoolingCTRL := FALSE; + Processor_Options.Blender_OPT._ChillerCTRL := FALSE; + Processor_Options.Blender_OPT._CO2_SterileFilter := TRUE; + Processor_Options.Blender_OPT._InverterRecirPumpPPM306 := FALSE; + Processor_Options.Blender_OPT._ProdPressReleaseRVM304 := FALSE; + Processor_Options.Blender_OPT._VacuumPump := 1; + Processor_Options.Blender_OPT._GAS2InjectionType := 0; + Processor_Options.Blender_OPT._InjectionPress_Ctrl := 1; + Processor_Options.Blender_OPT._ProdPressureType := 0; + Processor_Options.Blender_OPT._CIPHeatType := 0; + Processor_Options.Blender_OPT._EHS_NrRes := 6; + _RVM301_DeadBand := 5.000000e-02; + _RVM301_Kp := 9.000000e+01; + Actual_Recipe_Parameters._Name := ''; + Actual_Recipe_Parameters._EnProdTemp := TRUE; + Actual_Recipe_Parameters._SyrFlushing := FALSE; + Actual_Recipe_Parameters._GAS2_Injection := FALSE; + Actual_Recipe_Parameters._Eq_Pression_Selected := FALSE; + Actual_Recipe_Parameters._DeoxStripEn := FALSE; + Actual_Recipe_Parameters._DeoxVacuumEn := TRUE; + Actual_Recipe_Parameters._DeoxPreMixed := FALSE; + Actual_Recipe_Parameters._EnBlowOffProdPipeCO2Fil := FALSE; + Actual_Recipe_Parameters._WaterSelection := B#16#0; + Actual_Recipe_Parameters._FillerNextRecipeNum := B#16#0; + Actual_Recipe_Parameters._BottleShape := B#16#0; + Actual_Recipe_Parameters._Type := 2; + Actual_Recipe_Parameters._ProdMeterRecipeNum := 1; + Actual_Recipe_Parameters._SyrupBrix := 4.625000e+01; + Actual_Recipe_Parameters._SyrupDensity := 1.206908e+00; + Actual_Recipe_Parameters._SyrupFactor := 1.000000e+00; + Actual_Recipe_Parameters._ProductBrix := 1.000000e+01; + Actual_Recipe_Parameters._ProductionRate := 3.800000e+02; + Actual_Recipe_Parameters._Ratio := 4.238896e+00; + Actual_Recipe_Parameters._ProdBrixOffset := 2.500000e-01; + Actual_Recipe_Parameters._CO2Vols := 2.550000e+00; + Actual_Recipe_Parameters._CO2Fact := 9.400000e-01; + Actual_Recipe_Parameters._ProdTankPress := 4.400000e+00; + Actual_Recipe_Parameters._SP_ProdTemp := 1.700000e+01; + Actual_Recipe_Parameters._PrdTankMinLevel := 3.500000e+01; + Actual_Recipe_Parameters._WaterValveSave := 0.000000e+00; + Actual_Recipe_Parameters._SyrupValveSave := 0.000000e+00; + Actual_Recipe_Parameters._CarboCO2ValveSave := 0.000000e+00; + Actual_Recipe_Parameters._ProdMeterHighBrix := 1.030000e+01; + Actual_Recipe_Parameters._ProdMeterLowBrix := 9.830000e+00; + Actual_Recipe_Parameters._ProdMeterHighCO2 := 2.900000e+00; + Actual_Recipe_Parameters._ProdMeterLowCO2 := 2.300000e+00; + Actual_Recipe_Parameters._ProdMeter_ZeroCO2 := 0.000000e+00; + Actual_Recipe_Parameters._ProdMeter_ZeroBrix := 0.000000e+00; + Actual_Recipe_Parameters._ProdHighCond := 0.000000e+00; + Actual_Recipe_Parameters._ProdLowCond := 0.000000e+00; + Actual_Recipe_Parameters._BottleSize := 0.000000e+00; + Actual_Recipe_Parameters._FillingValveHead_SP := 0.000000e+00; + Actual_Recipe_Parameters._SyrMeter_ZeroBrix := 0.000000e+00; + Actual_Recipe_Parameters._FirstProdExtraCO2Fact := 1.020000e+00; + Actual_Recipe_Parameters._Gas2Vols := 0.000000e+00; + Actual_Recipe_Parameters._Gas2Fact := 0.000000e+00; + Actual_Recipe_Parameters._SyrupPumpPressure := 0.000000e+00; + Actual_Recipe_Parameters._WaterPumpPressure := 0.000000e+00; + Actual_Recipe_Parameters._CO2_Air_N2_PressSelect := 0; + Actual_Recipe_Parameters._KFactRVM304BlowOff := 0.000000e+00; + Actual_Recipe_Parameters._ProdRecircPumpFreq := 0.000000e+00; + Actual_Recipe_Parameters._ProdBoosterPumpPress := 0.000000e+00; + Actual_Recipe_Parameters._ProdSendPumpFreq := 0.000000e+00; + Next_Recipe_Name := 'cambio 1$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00'; + Next_Recipe_Number := 0; + ProcessSetup.Spare000 := 0.000000e+00; + ProcessSetup.Spare040 := 0.000000e+00; + ProcessSetup._KWaterLoss := 1.000000e-03; + ProcessSetup._KSyrupLoss := 7.800000e-03; + ProcessSetup._KProdLoss := 1.390000e-02; + ProcessSetup._KPPM303 := 5.700000e+00; + ProcessSetup._BaialageRVM301OVMin := 2.000000e+00; + ProcessSetup._SyrupLinePressure := 2.200000e+00; + ProcessSetup._CIPRMM301OV := 1.000000e+01; + ProcessSetup._CIPRMP302OV := 1.500000e+01; + ProcessSetup._CIPTM301MinLevel := 3.500000e+01; + ProcessSetup._CIPTM301MaxLevel := 5.500000e+01; + ProcessSetup._CIPPPM303Freq := 5.000000e+01; + ProcessSetup._CIPTP301MinLevel := 2.500000e+01; + ProcessSetup._CIPTP301MaxLevel := 4.500000e+01; + ProcessSetup._RinseRMM301OV := 1.000000e+01; + ProcessSetup._RinseRMP302OV := 1.400000e+01; + ProcessSetup._RinseTM301Press := 3.000000e-01; + ProcessSetup._RinsePPM303Freq := 5.000000e+01; + ProcessSetup._DrainTM301Press := 1.000000e+00; + ProcessSetup._KRecBlendError := 2.000000e+00; + ProcessSetup._KRecCarboCO2Error := 2.000000e+00; + ProcessSetup._MaxBlendError := 1.000000e+02; + ProcessSetup._MaxCarboCO2Error := 5.000000e+02; + ProcessSetup._StartUpBrixExtraWater := 4.700000e+01; + ProcessSetup._StartUpCO2ExtraWater := 8.000000e+00; + ProcessSetup._StartUpPPM303Freq := 2.000000e+01; + ProcessSetup._SyrupRoomTank := 1; + ProcessSetup._SyrupRunOutLiters := 2.900000e+02; + ProcessSetup._InjCO2Press_Offset := 5.000000e-01; + ProcessSetup._InjCO2Press_MinFlow := 4.500000e+02; + ProcessSetup._InjCO2Press_MaxFlow := 2.500000e+03; + ProcessSetup._CarboCO2Pressure := 1.250000e+01; + ProcessSetup._N2MinPressure := 1.000000e+00; + ProcessSetup._DiffSensor_Height := 3.950000e+02; + ProcessSetup._DiffSensor_DeltaHeight := -2.500000e+01; + ProcessSetup._DiffSensor_Offset := 3.618000e+01; + ProcessSetup._FillingValveHeight := 1.400000e+03; + ProcessSetup._FillerDiameter := 2.520000e+03; + ProcessSetup._FillingValveNum := 91; + ProcessSetup._FillerProdPipeDN := 1.000000e+02; + ProcessSetup._FillerProdPipeMass := 1.600000e+02; + ProcessSetup._FillingTime := 3.200000e+00; + ProcessSetup._TM301Height_0 := 1.050000e+03; + ProcessSetup._TM301LevelPerc_2 := 4.600000e+01; + ProcessSetup._TM301Height_2 := 1.625000e+03; + ProcessSetup._RVN304Factor := 1.000000e+00; + ProcessSetup._DrainTM301Flushing := 1.300000e+00; + ProcessSetup._FirstProdExtraBrix := 5.000000e-02; + ProcessSetup._FirstProdDietExtraSyr := 1.400000e-03; + ProcessSetup._EndProdLastSyrlt := 0.000000e+00; + ProcessSetup._TM301DrainSt0Time := W#16#A; + ProcessSetup._TM301DrainSt1Time := W#16#50; + ProcessSetup._ProdPipeRunOutSt0Time := W#16#1; + ProcessSetup._RMM301ProdPipeRunOu := 3.000000e+01; + ProcessSetup._RMP302ProdPipeRunOu := 4.000000e+01; + ProcessSetup._ProdPipeRunOutAmount := 3.000000e+01; + ProcessSetup._TM301RunOutChiller := 5.000000e+00; + ProcessSetup._MinSpeedNominalProd := 4.000000e-01; + ProcessSetup._MinSpeedSlowProd := 3.000000e-01; + ProcessSetup._FastChgOvrTM301DrnPrss := 9.000000e-01; + ProcessSetup._CIPTN301MinLevel := 3.500000e+01; + ProcessSetup._CIPTN301MaxLevel := 6.000000e+01; + ProcessSetup._ProdPPN304Freq := 5.000000e+01; + ProcessSetup._GAS2InjectionPress := 4.000000e+00; + ProcessSetup._BaialageRVM301OVMax := 2.000000e+01; + ProcessSetup._RinsePPN301Freq := 5.000000e+00; + ProcessSetup._CIPPPN301Freq := 5.000000e+00; + ProcessSetup._RinsePPP302Freq := 5.000000e+00; + ProcessSetup._CIPPPP302Freq := 5.000000e+00; + ProcessSetup._PercSyrupBrixSyrStarUp := 2.500000e+01; + ProcessSetup._RefTempCoolingCTRL := 0.000000e+00; + ProcessSetup._H2OSerpPrimingVolume := 1.500000e+02; + ProcessSetup._AVN301_Nozzle_Kv := 1.650000e+02; + ProcessSetup._AVN302_Nozzle_Kv := 2.600000e+02; + ProcessSetup._AVN303_Nozzle_Kv := 1.650000e+02; + ProcessSetup._DeoxSpryball_Kv := 6.700000e+01; + ProcessSetup._PremixedLineDrainTime := 300; + ProcessSetup._PPN301_H_MaxFlow := 9.000000e+01; + ProcessSetup._PPN301_H_MinFlow := 8.700000e+01; + ProcessSetup._PPN301_MaxFlow := 5.070000e+02; + ProcessSetup._PPN301_MinFlow := 2.110000e+02; + ProcessSetup._PPP302_H_MaxFlow := 8.600000e+01; + ProcessSetup._PPP302_H_MinFlow := 8.500000e+01; + ProcessSetup._PPP302_MaxFlow := 1.150000e+02; + ProcessSetup._PPP302_MinFlow := 3.200000e+01; + ProcessSetup._RinsePPM306Freq := 5.000000e+00; + ProcessSetup._CIPPPM306Freq := 5.000000e+00; + ProcessSetup._PPM307_H_MaxFlow := 0.000000e+00; + ProcessSetup._PPM307_H_MinFlow := 0.000000e+00; + ProcessSetup._PPM307_MaxFlow := 0.000000e+00; + ProcessSetup._PPM307_MinFlow := 0.000000e+00; + ProcessSetup._Temp0_VacuumCtrl := 1.800000e+01; + ProcessSetup._Temp1_VacuumCtrl := 2.000000e+00; + ProcessSetup._Temp2_VacuumCtrl := 2.000000e+00; + ProcessSetup._Temp3_VacuumCtrl := 5.000000e+01; + ProcessSetup._Temp4_VacuumCtrl := 5.000000e+01; + ProcessSetup._T1_VacuumCtrl := L#1500; + ProcessSetup._T2_VacuumCtrl := L#1500; + ProcessSetup._T3_VacuumCtrl := L#1000; + ProcessSetup._T4_VacuumCtrl := L#1000; + ProcessSetup._ICS_VolDosWorkTimePAA := 30; + ProcessSetup._ICS_VolPauseTimePAA := 30; + ProcessSetup._ICS_PAAPulseWeight := 10; + ProcessSetup._ICS_CausticPulseWeight := 10; + ProcessSetup._ICS_AcidPulseWeight := 10; + ProcessSetup._ICS_VolumeRestOfLine := 3.500000e+02; + ProcessSetup._ICS_VolDosWorkTimeCaus := 30; + ProcessSetup._ICS_VolDosPauseTimeCaus := 30; + ProcessSetup._ICS_VolDosWorkTimeAcid := 30; + ProcessSetup._ICS_VolDosPauseTimeAcid := 30; + ProcessSetup._ICS_ConcDosWorkTimeCaus := 30; + ProcessSetup._ICS_ConcDosPausTimeCaus := 30; + ProcessSetup._ICS_ConcDosWorkTimeAcid := 30; + ProcessSetup._ICS_ConcDosPausTimeAcid := 30; + ProcessSetup._RinsePPM307Freq := 3.000000e+01; + ProcessSetup._CIPPPM307Freq := 3.000000e+01; + ProcessSetup._CIP2StepTN301Lvl := 0.000000e+00; + ProcessSetup._CIP2StepTM301Lvl := 0.000000e+00; + ProcessSetup._CIP2StepTP301Lvl := 0.000000e+00; + ProcessSetup._PumpNominalFreq := 5.000000e+01; + _SwitchOff_DensityOK := FALSE; +END_DATA_BLOCK; + diff --git a/backend/script_groups/S7_DB_Utils/script_config.json b/backend/script_groups/S7_DB_Utils/script_config.json new file mode 100644 index 0000000..b0bedb8 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/script_config.json @@ -0,0 +1,9 @@ +{ + "level1": { + "api_key": "your-api-key-here", + "model": "gpt-3.5-turbo" + }, + "level2": {}, + "level3": {}, + "working_directory": "C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\\Reporte\\DB1001" +} \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/scripts_description.json b/backend/script_groups/S7_DB_Utils/scripts_description.json new file mode 100644 index 0000000..c234c9d --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/scripts_description.json @@ -0,0 +1,26 @@ +{ + "x1.py": { + "display_name": "01: Copiar Valores Actuales y de Inizio", + "short_description": "Copia los valores desde una DB exportada como .DB a otra", + "long_description": "Copia los valores desde una DB exportada como .DB a otra usando la posición de cada variable. Primero controla que el tipo de datos sea correcto para continuar con la asignacion.", + "hidden": false + }, + "x2.py": { + "display_name": "02: Generar comparativa", + "short_description": "Genera archivo Excel con la comparación de los 3 archivos.", + "long_description": "", + "hidden": false + }, + "DB_Parser.py": { + "display_name": "DB_Parser", + "short_description": "Sin descripción corta.", + "long_description": "", + "hidden": true + }, + "x3.py": { + "display_name": "x3", + "short_description": "Sin descripción corta.", + "long_description": "", + "hidden": false + } +} \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/work_dir.json b/backend/script_groups/S7_DB_Utils/work_dir.json new file mode 100644 index 0000000..aed892c --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/work_dir.json @@ -0,0 +1,6 @@ +{ + "path": "C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\\Reporte\\DB1001", + "history": [ + "C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\\Reporte\\DB1001" + ] +} \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/x1.py b/backend/script_groups/S7_DB_Utils/x1.py new file mode 100644 index 0000000..dd2857c --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/x1.py @@ -0,0 +1,497 @@ +import re +import os +import sys +import json +import glob + +script_root = os.path.dirname( + os.path.dirname(os.path.dirname(os.path.dirname(__file__))) +) +sys.path.append(script_root) +from backend.script_utils import load_configuration + +def find_working_directory(): + configs = load_configuration() + working_directory = configs.get("working_directory") + if not working_directory: + print("No working directory specified in the configuration file.") + sys.exit(1) + return working_directory + +def find_data_files(working_dir, source_pattern_suffix="_data.", target_pattern_suffix="_format."): + """Find source and target files based on glob patterns and suffixes.""" + all_db_files = glob.glob(os.path.join(working_dir, "*.db")) + all_awl_files = glob.glob(os.path.join(working_dir, "*.awl")) + all_txt_files = glob.glob(os.path.join(working_dir, "*.txt")) # For .db.txt style + + potential_files = all_db_files + all_awl_files + all_txt_files + + source_files_found = [] + target_files_found = [] + + for f_path in potential_files: + f_name = os.path.basename(f_path) + # Check for source pattern (e.g., ends with _data.db or _data.db.txt) + # We check if `source_pattern_suffix` is part of the name before the final extension + name_part, ext_part = os.path.splitext(f_name) + if name_part.endswith(source_pattern_suffix.rstrip('.')): # Handles cases like _data.db or _data.db (if suffix includes .) + source_files_found.append(f_path) + elif source_pattern_suffix.rstrip('.') in name_part and f_name.endswith(".txt") and ".db" in name_part : # for like _data.db.txt + if name_part.split(".db")[0].endswith(source_pattern_suffix.rstrip('.')): + source_files_found.append(f_path) + + + # Check for target pattern + name_part_target, ext_part_target = os.path.splitext(f_name) + if name_part_target.endswith(target_pattern_suffix.rstrip('.')): + target_files_found.append(f_path) + elif target_pattern_suffix.rstrip('.') in name_part_target and f_name.endswith(".txt") and ".db" in name_part_target: # for like _format.db.txt + if name_part_target.split(".db")[0].endswith(target_pattern_suffix.rstrip('.')): + target_files_found.append(f_path) + + + if not source_files_found: + print(f"Warning: No source files found matching pattern ending with '{source_pattern_suffix}*' in '{working_dir}'.") + # Try a broader search for any file containing '_data' if the strict one fails + source_files_found = [f for f in potential_files if "_data" in os.path.basename(f)] + if source_files_found: + print(f"Found potential source files with less strict '_data' search: {source_files_found}") + + + if not target_files_found: + print(f"Warning: No target files found matching pattern ending with '{target_pattern_suffix}*' in '{working_dir}'.") + # Try a broader search for any file containing '_format' + target_files_found = [f for f in potential_files if "_format" in os.path.basename(f)] + if target_files_found: + print(f"Found potential target files with less strict '_format' search: {target_files_found}") + + + # Logic to select the best match if multiple are found (e.g. prefer .db over .txt, or based on modification time) + # For now, just take the first one found. + source_file = source_files_found[0] if source_files_found else None + target_file = target_files_found[0] if target_files_found else None + + if source_file: print(f"Selected source file: {os.path.basename(source_file)}") + if target_file: print(f"Selected target file: {os.path.basename(target_file)}") + + return source_file, target_file + + +def extract_sections(content): + content = content.replace('\r\n', '\n') # Normalize line endings + + udt_definitions_content = "" + udt_matches = list(re.finditer(r'(?s)(TYPE\s+.*?\s+END_TYPE\s*\n?)', content, re.IGNORECASE)) + + content_after_udts = content + if udt_matches: + udt_definitions_content = "".join(match.group(0) for match in udt_matches) + last_udt_end = udt_matches[-1].end() + content_after_udts = content[last_udt_end:] + + header_match = re.search(r'(?s)^(.*?(?:DATA_BLOCK.*?VERSION.*?\n))(.*?STRUCT)', content_after_udts, re.IGNORECASE) + if header_match: + header = header_match.group(1) + # The rest_of_content should start from "STRUCT" + rest_of_content = content_after_udts[header_match.start(2):] + else: # Fallback if the specific DATA_BLOCK header is not found + header_fallback_match = re.search(r'(?s)(.*?)(STRUCT)', content_after_udts, re.IGNORECASE) + if header_fallback_match: + header = header_fallback_match.group(1) + # Ensure rest_of_content starts with "STRUCT" + rest_of_content = content_after_udts[header_fallback_match.start(2) - len("STRUCT") if header_fallback_match.start(2) >= len("STRUCT") else 0:] + if not rest_of_content.lstrip().upper().startswith("STRUCT"): # Verification + # This might happen if STRUCT was at the very beginning. + rest_of_content = "STRUCT" + rest_of_content # Prepend if missing + else: # No STRUCT found at all after UDTs + print("Critical Warning: No 'STRUCT' keyword found for DATA_BLOCK content.") + return udt_definitions_content, content_after_udts, "", "", "" + + decl_match = re.search(r'(?s)STRUCT\s+(.*?)BEGIN', rest_of_content, re.IGNORECASE) + decl_section = decl_match.group(1) if decl_match else "" + + init_match = re.search(r'(?s)BEGIN\s+(.*?)END_DATA_BLOCK', rest_of_content, re.IGNORECASE) + init_section = init_match.group(1) if init_match else "" + + footer_match = re.search(r'(?s)END_DATA_BLOCK(.*?)$', rest_of_content, re.IGNORECASE) + footer = footer_match.group(1) if footer_match else "" + + return udt_definitions_content, header, decl_section, init_section, footer + + +def analyze_source_file(decl_section, init_section): + source_decl_values = [] + source_init_values = [] + + decl_idx = 0 + for line_content in decl_section.split('\n'): + line = line_content.strip() + if not line or line.startswith('//') or \ + (line.upper().startswith('STRUCT') and ';' not in line) or \ + (line.upper().startswith('END_STRUCT') and ';' not in line) : + continue + + if ';' in line: + type_match = re.search(r':\s*([^:=;]+)', line) + var_type = type_match.group(1).strip() if type_match else "" + value = None + comment = '' + + assignment_match = re.search(r':=\s*([^;]+)', line) + if assignment_match: + value = assignment_match.group(1).strip() + comment_match = re.search(r';(.*)', line[assignment_match.end():]) + if comment_match: comment = comment_match.group(1).strip() + else: + comment_match = re.search(r';(.*)', line) + if comment_match: comment = comment_match.group(1).strip() + + source_decl_values.append({ + "index": decl_idx, "type": var_type, "value": value, + "comment": comment, "original_line_for_debug": line + }) + decl_idx += 1 + + init_idx = 0 + for line_content in init_section.split('\n'): + line = line_content.strip() + if not line or line.startswith('//'): continue + + assignment_match = re.search(r':=\s*([^;]+)', line) + if assignment_match and ';' in line: + value = assignment_match.group(1).strip() + comment_match = re.search(r';(.*)', line[assignment_match.end():]) + comment = comment_match.group(1).strip() if comment_match else "" + + source_init_values.append({ + "index": init_idx, "value": value, "comment": comment, + "original_line_for_debug": line + }) + init_idx += 1 + + return source_decl_values, source_init_values + + +def analyze_target_declarations(decl_section): + target_decl_info_list = [] + current_var_idx = 0 + decl_lines_split = decl_section.split('\n') + + for line_num, line_content in enumerate(decl_lines_split): + original_line = line_content + line = line_content.strip() + is_udt_ref = False + udt_name = None + var_type_str = None + + entry = { + "line_index_in_section": line_num, "var_idx": -1, + "is_udt_instance": False, "udt_name_if_any": None, + "original_line": original_line, "type": None + } + + if not line or line.startswith('//') or \ + (line.upper().startswith('STRUCT') and ';' not in line and ':' not in line) or \ + (line.upper().startswith('END_STRUCT') and ';' not in line and ':' not in line): + target_decl_info_list.append(entry) + continue + + if ';' in line: + var_type_match = re.search(r':\s*([^:=;]+)', line) + var_type_str = var_type_match.group(1).strip() if var_type_match else "" + + udt_match = re.search(r':\s*"(.*?)"', line) + if udt_match: + is_udt_ref = True + udt_name = udt_match.group(1) + + entry.update({ + "var_idx": current_var_idx, + "is_udt_instance": is_udt_ref, + "udt_name_if_any": udt_name, + "type": var_type_str + }) + current_var_idx += 1 + + target_decl_info_list.append(entry) + + return target_decl_info_list + +def analyze_target_assignments(init_section): + target_init_info_list = [] + current_assign_idx = 0 + init_lines_split = init_section.split('\n') + + for line_num, line_content in enumerate(init_lines_split): + original_line = line_content + line = line_content.strip() + + entry = {"line_index_in_section": line_num, "assign_idx": -1, "original_line": original_line} + + if not line or line.startswith('//'): + target_init_info_list.append(entry) + continue + + if ':=' in line and ';' in line: + entry["assign_idx"] = current_assign_idx + current_assign_idx += 1 + + target_init_info_list.append(entry) + + return target_init_info_list + +def is_compatible_type(source_value_str, target_type_str): + if source_value_str is None: return True + if not target_type_str: return True + + s_val = source_value_str.upper() + t_type = target_type_str.upper() + + if "STRING" in t_type: return s_val.startswith("'") and s_val.endswith("'") + if "BOOL" == t_type: return s_val in ["TRUE", "FALSE", "1", "0"] + if "BYTE" == t_type: return s_val.startswith(("B#16#", "16#")) or (s_val.isdigit() and 0 <= int(s_val) <= 255) + if "WORD" == t_type or "DWORD" == t_type : return s_val.startswith(("W#16#", "DW#16#", "16#")) + if "INT" == t_type: + try: int(s_val); return True + except ValueError: return False + if "DINT" == t_type: + try: + int(s_val[2:]) if s_val.startswith("L#") else int(s_val) + return True + except ValueError: return False + if "REAL" == t_type: + try: float(s_val.replace('E', 'e')); return True + except ValueError: return False + if t_type.startswith("ARRAY"): return True + return True + + +def transfer_values_by_position(source_file_path, target_file_path, output_file_path): + try: + with open(source_file_path, 'r', encoding='utf-8-sig') as f: + source_content = f.read() + with open(target_file_path, 'r', encoding='utf-8-sig') as f: + target_content = f.read() + + source_udt_defs_ignored, source_header_ignored, source_decl_sec, source_init_sec, source_footer_ignored = extract_sections(source_content) + target_udt_defs, target_header, target_decl_sec, target_init_sec, target_footer = extract_sections(target_content) + + source_decl_values, source_init_values = analyze_source_file(source_decl_sec, source_init_sec) + + s_decl_ptr = 0 + decl_values_transferred_count = 0 + init_values_transferred_count = 0 + + processed_target_udt_lines = [] + if target_udt_defs: + udt_section_lines = target_udt_defs.split('\n') + in_udt_struct_definition = False + + for udt_line_content in udt_section_lines: + line_ws = udt_line_content + stripped_line = udt_line_content.strip() + modified_udt_line = line_ws + + if stripped_line.upper().startswith("TYPE"): in_udt_struct_definition = False + if stripped_line.upper().startswith("STRUCT") and not stripped_line.upper().startswith("END_STRUCT"): + prev_lines = [l.strip().upper() for l in processed_target_udt_lines if l.strip()] + if prev_lines and prev_lines[-1].startswith("TYPE"): in_udt_struct_definition = True + + if stripped_line.upper().startswith("END_STRUCT"): in_udt_struct_definition = False + + if in_udt_struct_definition and ';' in stripped_line and \ + not stripped_line.upper().startswith(("STRUCT", "END_STRUCT", "//")): + if s_decl_ptr < len(source_decl_values): + src_data = source_decl_values[s_decl_ptr] + src_val_str = src_data["value"] + src_comment = src_data["comment"] + + type_m = re.search(r':\s*([^:=;]+)', stripped_line) + target_member_type = type_m.group(1).strip() if type_m else "" + + if src_val_str is not None: + if is_compatible_type(src_val_str, target_member_type): + parts = line_ws.split(';',1) + decl_part = parts[0] + comment_part = f";{parts[1]}" if len(parts) > 1 else ";" + + if ':=' in decl_part: mod_decl = re.sub(r':=\s*[^;]+', f':= {src_val_str}', decl_part.rstrip()) + else: mod_decl = decl_part.rstrip() + f' := {src_val_str}' + + final_comment = comment_part + if comment_part == ";" and src_comment: final_comment = f"; {src_comment}" + modified_udt_line = mod_decl + final_comment + decl_values_transferred_count +=1 + else: + parts = line_ws.split(';',1) + decl_part = parts[0] + comment_part = f";{parts[1]}" if len(parts) > 1 else ";" + if ':=' in decl_part: + mod_decl = re.sub(r'\s*:=\s*[^;]+', '', decl_part.rstrip()) + modified_udt_line = mod_decl + comment_part + s_decl_ptr += 1 + processed_target_udt_lines.append(modified_udt_line) + target_udt_defs_updated = '\n'.join(processed_target_udt_lines) + else: + target_udt_defs_updated = target_udt_defs + + target_decl_block_info = analyze_target_declarations(target_decl_sec) + output_decl_block_lines = target_decl_sec.split('\n') + + for target_info in target_decl_block_info: + line_idx_in_sec = target_info["line_index_in_section"] + if target_info["var_idx"] == -1 or target_info["is_udt_instance"]: continue + + if s_decl_ptr < len(source_decl_values): + src_data = source_decl_values[s_decl_ptr] + src_val_str = src_data["value"] + src_comment = src_data["comment"] + target_type = target_info["type"] + original_target_line_ws = target_info["original_line"] + + if src_val_str is not None: + if is_compatible_type(src_val_str, target_type): + parts = original_target_line_ws.split(';',1) + decl_part = parts[0] + comment_part = f";{parts[1]}" if len(parts) > 1 else ";" + + if ':=' in decl_part: mod_decl = re.sub(r':=\s*[^;]+', f':= {src_val_str}', decl_part.rstrip()) + else: mod_decl = decl_part.rstrip() + f' := {src_val_str}' + + final_comment = comment_part + if comment_part == ";" and src_comment: final_comment = f"; {src_comment}" + output_decl_block_lines[line_idx_in_sec] = mod_decl + final_comment + decl_values_transferred_count +=1 + else: + parts = original_target_line_ws.split(';',1) + decl_part = parts[0] + comment_part = f";{parts[1]}" if len(parts) > 1 else ";" + if ':=' in decl_part: + mod_decl = re.sub(r'\s*:=\s*[^;]+', '', decl_part.rstrip()) + output_decl_block_lines[line_idx_in_sec] = mod_decl + comment_part + s_decl_ptr += 1 + else: pass + + target_init_block_info = analyze_target_assignments(target_init_sec) + output_init_block_lines = target_init_sec.split('\n') + + for target_info in target_init_block_info: + line_idx_in_sec = target_info["line_index_in_section"] + if target_info["assign_idx"] == -1: continue + + current_target_assign_idx = target_info["assign_idx"] + original_target_line_ws = target_info["original_line"] + + if current_target_assign_idx < len(source_init_values): + src_data = source_init_values[current_target_assign_idx] + src_val_str = src_data["value"] + src_comment = src_data["comment"] + + if src_val_str is not None: + parts = original_target_line_ws.split(';',1) + assign_part_target = parts[0] + comment_part_target = f";{parts[1]}" if len(parts) > 1 else ";" + + mod_assign = re.sub(r':=\s*.*$', f':= {src_val_str}', assign_part_target.rstrip()) + + final_comment = comment_part_target + if comment_part_target == ";" and src_comment: final_comment = f"; {src_comment}" + output_init_block_lines[line_idx_in_sec] = mod_assign + final_comment + init_values_transferred_count += 1 + + final_parts = [] + if target_udt_defs_updated.strip(): final_parts.append(target_udt_defs_updated.rstrip('\n') + '\n\n') # Ensure space after UDTs + elif target_udt_defs: final_parts.append(target_udt_defs) + + + if target_header.strip() : final_parts.append(target_header) # Header already includes its spacing + elif target_header and not target_udt_defs_updated.strip(): # if header has only newlines but no UDTs before it + final_parts.append(target_header) + + + if target_decl_sec.strip(): + final_parts.append("STRUCT\n") + final_parts.append('\n'.join(output_decl_block_lines)) + final_parts.append("\n") + elif target_decl_sec: + final_parts.append(target_decl_sec) + + final_parts.append("BEGIN\n") + final_parts.append('\n'.join(output_init_block_lines)) + # Ensure END_DATA_BLOCK is on its own line or correctly spaced + final_parts.append("\nEND_DATA_BLOCK") + if target_footer: final_parts.append(target_footer.rstrip('\n') + '\n' if target_footer.strip() else target_footer) + + + final_content = "".join(final_parts) + # Ensure there's a newline at the end of the file + if not final_content.endswith('\n'): final_content += '\n' + # Remove potential multiple blank lines at the end, keep one + final_content = re.sub(r'\n\s*\n$', '\n', final_content) + + + with open(output_file_path, 'w', encoding='utf-8') as f: + f.write(final_content) + + print(f"\nSuccessfully transferred {decl_values_transferred_count} initial values and {init_values_transferred_count} current values.") + print(f"Output file created: {output_file_path}") + return True + + except FileNotFoundError: + print(f"Error: File not found. Source: '{source_file_path}', Target: '{target_file_path}'") + return False + except Exception as e: + print(f"An error occurred during transfer: {e}") + import traceback + print(traceback.format_exc()) + return False + +def main(): + print("PLC Data Block Adapter - Advanced UDT Handling (Restored Auto File Find)") + print("========================================================================") + + working_dir = find_working_directory() + print(f"Using working directory: {working_dir}") + + # Using automatic file finding based on patterns + # "_data." will match _data.db, _data.awl, _data.db.txt (if .txt is handled in find_data_files) + source_f, target_f = find_data_files(working_dir, + source_pattern_suffix="_data", + target_pattern_suffix="_format") + + if not source_f or not target_f: + print("Error: Could not automatically find required source or target files using patterns.") + print("Please ensure files ending with e.g., '_data.db' (source) and '_format.db' (target) exist.") + return False + + # Construct output name + target_basename = os.path.basename(target_f) + name_part, first_ext = os.path.splitext(target_basename) + if first_ext.lower() == ".txt" and ".db" in name_part.lower(): # Handles .db.txt + name_part, second_ext = os.path.splitext(name_part) # name_part is now "xxx_format" + output_basename = name_part + "_updated" + second_ext + first_ext # e.g. xxx_format_updated.db.txt + elif first_ext.lower() in ['.db', '.awl']: + output_basename = name_part + "_updated" + first_ext + else: # Fallback for other extensions or no extension + output_basename = target_basename.rsplit('.',1)[0] if '.' in target_basename else target_basename + output_basename += "_updated" + ('.' + target_basename.rsplit('.',1)[1] if '.' in target_basename else ".db") + + + output_f = os.path.join(working_dir, output_basename) + + print(f"\nProcessing:") + print(f" Source: {os.path.basename(source_f)}") + print(f" Target: {os.path.basename(target_f)}") + print(f" Output: {os.path.basename(output_f)}") + + success = transfer_values_by_position(source_f, target_f, output_f) + + if success: + print(f"\nSUCCESS: Script finished. Output: '{os.path.basename(output_f)}'") + else: + print(f"\nERROR: Script failed. Please check messages above.") + + return success + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/x2.py b/backend/script_groups/S7_DB_Utils/x2.py new file mode 100644 index 0000000..ee48848 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/x2.py @@ -0,0 +1,335 @@ +import re +import os +import sys # Not strictly needed by this version but often kept from original +import glob +import pandas as pd # For Excel writing + +# --- Functions for script operation --- + +def find_working_directory_from_x1(): + """ + Finds the working directory. + Defaults to current directory. Adapt if specific configuration is needed. + """ + print("Info: `find_working_directory_from_x1` is using the current directory.") + return os.getcwd() + +def extract_sections(content): + """ + Extracts UDT definitions, main declaration section, and initialization section from S7 AWL/DB content. + Uses re.IGNORECASE and re.DOTALL (via ?is) for matching keywords across different casings and newlines. + """ + content = content.replace('\r\n', '\n') # Normalize line endings + + udt_definitions_content = "" + # Regex to find TYPE...END_TYPE blocks (UDT definitions) + udt_matches = list(re.finditer(r'(?is)(TYPE\s+.*?\s+END_TYPE\s*\n?)', content)) + + content_after_udts = content + if udt_matches: + udt_definitions_content = "".join(match.group(0) for match in udt_matches) + # Get content after the last UDT definition + last_udt_end = udt_matches[-1].end() + content_after_udts = content[last_udt_end:] + + header_text = "" # Placeholder, not actively used in this script's comparison logic + rest_of_content_for_struct = content_after_udts + + # Try to find the main DATA_BLOCK header and the start of its STRUCT + header_match = re.search(r'(?is)^(.*?(?:DATA_BLOCK.*?VERSION.*?\n))(.*?STRUCT)', content_after_udts) + if header_match: + # Content for further parsing starts at "STRUCT" + rest_of_content_for_struct = content_after_udts[header_match.start(2):] + else: + # Fallback: find the first "STRUCT" if the specific header pattern isn't met + header_fallback_match = re.search(r'(?is)(.*?)(STRUCT)', content_after_udts) + if header_fallback_match: + rest_of_content_for_struct = content_after_udts[header_fallback_match.start(2):] + else: + # If no STRUCT is found, declaration section will be empty + print(f"Warning: No 'STRUCT' keyword found for main DB declarations in a content block.") + + # Declaration section: from the found STRUCT up to BEGIN + decl_match = re.search(r'(?is)STRUCT\s*(.*?)BEGIN', rest_of_content_for_struct) + decl_section = decl_match.group(1).strip() if decl_match else "" + + # Initialization section: from BEGIN up to END_DATA_BLOCK + init_match = re.search(r'(?is)BEGIN\s*(.*?)END_DATA_BLOCK', rest_of_content_for_struct) + init_section = init_match.group(1).strip() if init_match else "" + + # Footer after END_DATA_BLOCK isn't used + return udt_definitions_content, header_text, decl_section, init_section, "" + + +def find_comparison_files_detailed(working_dir, data_suffix="_data", format_suffix="_format", updated_suffix_part="_updated"): + """Finds data, format, and _updated files based on naming conventions.""" + all_files_in_dir = [] + for ext_pattern in ["*.db", "*.awl", "*.txt"]: # Common S7 export extensions + all_files_in_dir.extend(glob.glob(os.path.join(working_dir, ext_pattern))) + # Normalize paths for consistent comparisons and ensure uniqueness + all_files_in_dir = sorted(list(set(os.path.normpath(f) for f in all_files_in_dir))) + + found_paths = {'data': None, 'format': None, 'updated': None} + + def select_best_file(file_list): + if not file_list: return None + # Prioritize: .db, then .awl, then .txt + file_list.sort(key=lambda x: ('.db' not in x.lower(), '.awl' not in x.lower(), '.txt' not in x.lower())) + return file_list[0] + + # Find _data file: contains data_suffix, does not contain updated_suffix_part + data_candidates = [f for f in all_files_in_dir if data_suffix in os.path.basename(f).lower() and updated_suffix_part not in os.path.basename(f).lower()] + found_paths['data'] = select_best_file(data_candidates) + + # Find _format file: contains format_suffix, does not contain updated_suffix_part + format_candidates = [f for f in all_files_in_dir if format_suffix in os.path.basename(f).lower() and updated_suffix_part not in os.path.basename(f).lower()] + if found_paths['data'] and format_candidates: # Ensure it's not the same as _data file + format_candidates = [f for f in format_candidates if f != found_paths['data']] + found_paths['format'] = select_best_file(format_candidates) + + # Find _updated file: + # Strategy 1: Based on format_file name (most reliable if format_file found) + if found_paths['format']: + format_basename = os.path.basename(found_paths['format']) + name_part, first_ext = os.path.splitext(format_basename) + updated_basename_candidate = "" + # Handle double extensions like ".db.txt" or ".awl.txt" + if first_ext.lower() == ".txt" and ('.db' in name_part.lower() or '.awl' in name_part.lower()): + base_name_for_main_ext, second_ext = os.path.splitext(name_part) + updated_basename_candidate = base_name_for_main_ext + updated_suffix_part + second_ext + first_ext + else: # Single extension + updated_basename_candidate = name_part + updated_suffix_part + first_ext + + potential_updated_path = os.path.join(working_dir, updated_basename_candidate) + if os.path.exists(potential_updated_path) and potential_updated_path in all_files_in_dir: + found_paths['updated'] = potential_updated_path + + # Strategy 2: If not found by deriving from format_file, search more broadly + if not found_paths['updated']: + updated_candidates = [f for f in all_files_in_dir if updated_suffix_part in os.path.basename(f).lower()] + if found_paths['format'] and updated_candidates: # Prefer updated file related to format file's base name + format_base = os.path.basename(found_paths['format']).split(format_suffix)[0] + updated_candidates = [f for f in updated_candidates if format_base in os.path.basename(f)] + + # Exclude already identified data and format files + if found_paths['data'] and updated_candidates: updated_candidates = [f for f in updated_candidates if f != found_paths['data']] + if found_paths['format'] and updated_candidates: updated_candidates = [f for f in updated_candidates if f != found_paths['format']] + found_paths['updated'] = select_best_file(updated_candidates) + + print("Identified files for comparison:") + for key, val in found_paths.items(): + print(f" {key.capitalize()} file: {os.path.basename(val) if val else 'Not found'}") + return found_paths['data'], found_paths['format'], found_paths['updated'] + + +def get_variables_from_section_content(section_str, section_type="declaration"): + """ Parses a declaration or initialization section string and returns a list of variable dicts. """ + variables = [] + idx = 0 + lines = section_str.replace('\r\n', '\n').split('\n') + + for line_content in lines: + line = line_content.strip() + if not line or line.startswith('//'): continue # Skip empty or comment lines + + line_upper = line.upper() + # Skip lines that are purely structural (STRUCT, TYPE, END_STRUCT) + # unless they also contain a full declaration/assignment on the same line. + if (line_upper == 'STRUCT' or line_upper.startswith('TYPE ') or line_upper == 'END_STRUCT' or line_upper == 'BEGIN' or line_upper == 'END_DATA_BLOCK'): + if not (':' in line and ';' in line or ':=' in line and ';' in line ): # if not also a var line + continue + + var_name, var_type, value = None, None, None + + if section_type == "declaration": # Expect: VarName : VarType [:= InitialValue] ; + if ':' in line and ';' in line: + # Name: part before ':' (handles simple and "quoted" names) + name_match = re.match(r'^\s*(\"(?:\\\"|[^\"])*\"|[a-zA-Z_][\w]*)', line, re.IGNORECASE) + var_name = name_match.group(1).strip().replace('"', "") if name_match else None + + # Type: part between ':' and potential ':=' or ';' (handles "UDT", simple, ARRAY) + type_match = re.search(r':\s*(\"[^\"]+\"|[^:=;]+)', line, re.IGNORECASE) + var_type = type_match.group(1).strip().replace('"', "") if type_match else None + + # Value: part between ':=' and ';' + assign_match = re.search(r':=\s*([^;]+)', line, re.IGNORECASE) + if assign_match: value = assign_match.group(1).strip() + + if not var_name or not var_type: continue # Must have name and type for a declaration + else: continue # Not a declaration line by this rule + + elif section_type == "initialization": # Expect: VarNameOrPath := Value ; + if ':=' in line and ';' in line: + # Name/Path: part before ':=' (handles "Quoted.Path", Simple.Path, Array[1].Path) + name_match = re.match(r'^\s*(\"(?:\\\"|[^\"])*\"|[a-zA-Z_][\w"\[\],\.]*(?:\[.*?\]|\.[a-zA-Z_][\w"\[\],\.]*)*)\s*:=', line, re.IGNORECASE) + var_name = name_match.group(1).strip().replace('"', "") if name_match else None + + # Value: part between ':=' and ';' + value_match = re.search(r':=\s*([^;]+)', line, re.IGNORECASE) + value = value_match.group(1).strip() if value_match else None + + if not var_name or value is None : continue # Must have name and value for assignment + else: continue # Not an assignment line + + if var_name is not None: # If a name was captured (and other conditions met), record it + variables.append({ + "index": idx, "name": var_name, "type": var_type, "value": value, + "original_line": line_content + }) + idx += 1 + return variables + +def process_file_for_vars(file_path): + """ + Reads a file, extracts main STRUCT declarations and BEGIN block initializations. + UDT definitions themselves are not included in the returned `main_struct_decl_vars`. + """ + if not file_path or not os.path.exists(file_path): + return [], [] # Return empty lists if file not found + + try: + with open(file_path, 'r', encoding='utf-8-sig') as f: # utf-8-sig handles BOM + content = f.read() + except Exception as e: + print(f"Error reading file {file_path}: {e}") + return [], [] + + # udt_definitions_content is extracted but not directly used for the comparison lists below + _udt_definitions_content, _header, decl_content_main, init_content, _footer = extract_sections(content) + + # "main_struct_decl_vars" are from the main DATA_BLOCK's STRUCT section (initial values). + main_struct_decl_vars = get_variables_from_section_content(decl_content_main, "declaration") + + # "begin_block_init_vars" are from the BEGIN...END_DATA_BLOCK section (current values). + begin_block_init_vars = get_variables_from_section_content(init_content, "initialization") + + return main_struct_decl_vars, begin_block_init_vars + + +def generate_excel_comparison(data_file, format_file, updated_file, output_excel_path): + """Generates an Excel file with two sheets comparing variables from three source files.""" + + print(f"\nProcessing _data file: {os.path.basename(data_file) if data_file else 'N/A'}") + data_decl_vars, data_init_vars = process_file_for_vars(data_file) + print(f" Found {len(data_decl_vars)} declaration vars, {len(data_init_vars)} initialization vars in _data file.") + + print(f"Processing _format file: {os.path.basename(format_file) if format_file else 'N/A'}") + format_decl_vars, format_init_vars = process_file_for_vars(format_file) + print(f" Found {len(format_decl_vars)} declaration vars, {len(format_init_vars)} initialization vars in _format file.") + + print(f"Processing _updated file: {os.path.basename(updated_file) if updated_file else 'N/A'}") + updated_decl_vars, updated_init_vars = process_file_for_vars(updated_file) + print(f" Found {len(updated_decl_vars)} declaration vars, {len(updated_init_vars)} initialization vars in _updated file.") + + + placeholder_var = {"name": "", "type": "", "value": "", "original_line": ""} + # Define column order once, will be used for both sheets + column_order = ["Variable Name (_data / _format)", "Data Type", "Value (_data)", "Value (_format)", "Value (_updated)"] + + # --- Prepare data for "Declarations (Initial Values)" sheet --- + decl_excel_rows = [] + # Determine max length for declaration rows based on non-empty lists + decl_lengths = [len(lst) for lst in [data_decl_vars, format_decl_vars, updated_decl_vars] if lst is not None] + max_decl_len = max(decl_lengths) if decl_lengths else 0 + + print(f"\nComparing {max_decl_len} positional declaration entries (STRUCT section)...") + for i in range(max_decl_len): + var_d = data_decl_vars[i] if data_decl_vars and i < len(data_decl_vars) else placeholder_var + var_f = format_decl_vars[i] if format_decl_vars and i < len(format_decl_vars) else placeholder_var + var_u = updated_decl_vars[i] if updated_decl_vars and i < len(updated_decl_vars) else placeholder_var + + # Construct combined name + name_d_str = var_d['name'] if var_d['name'] else "" + name_f_str = var_f['name'] if var_f['name'] else "" + combined_name = f"{name_d_str} / {name_f_str}".strip(" /") + if not combined_name: combined_name = var_u['name'] or name_d_str or name_f_str # Fallback + + # Determine Data Type: Priority: format, then updated, then data + type_to_use = var_f['type'] or var_u['type'] or var_d['type'] or "N/A" + + decl_excel_rows.append({ + "Variable Name (_data / _format)": combined_name, + "Data Type": type_to_use, + "Value (_data)": str(var_d['value']) if var_d['value'] is not None else "", + "Value (_format)": str(var_f['value']) if var_f['value'] is not None else "", + "Value (_updated)": str(var_u['value']) if var_u['value'] is not None else "" + }) + df_declarations = pd.DataFrame(decl_excel_rows) + if not df_declarations.empty: # Apply column order if DataFrame is not empty + for col in column_order: + if col not in df_declarations.columns: df_declarations[col] = "" # Ensure all columns exist + df_declarations = df_declarations[column_order] + + + # --- Prepare data for "Initializations (Current Values)" sheet --- + init_excel_rows = [] + init_lengths = [len(lst) for lst in [data_init_vars, format_init_vars, updated_init_vars] if lst is not None] + max_init_len = max(init_lengths) if init_lengths else 0 + + print(f"Comparing {max_init_len} positional initialization entries (BEGIN block)...") + for i in range(max_init_len): + var_d = data_init_vars[i] if data_init_vars and i < len(data_init_vars) else placeholder_var + var_f = format_init_vars[i] if format_init_vars and i < len(format_init_vars) else placeholder_var + var_u = updated_init_vars[i] if updated_init_vars and i < len(updated_init_vars) else placeholder_var + + name_d_str = var_d['name'] if var_d['name'] else "" + name_f_str = var_f['name'] if var_f['name'] else "" + combined_name = f"{name_d_str} / {name_f_str}".strip(" /") + if not combined_name: combined_name = var_u['name'] or name_d_str or name_f_str + + init_excel_rows.append({ + "Variable Name (_data / _format)": combined_name, + "Data Type": "N/A", # Type is not usually re-declared in initialization lines + "Value (_data)": str(var_d['value']) if var_d['value'] is not None else "", + "Value (_format)": str(var_f['value']) if var_f['value'] is not None else "", + "Value (_updated)": str(var_u['value']) if var_u['value'] is not None else "" + }) + df_initializations = pd.DataFrame(init_excel_rows) + if not df_initializations.empty: # Apply column order + for col in column_order: + if col not in df_initializations.columns: df_initializations[col] = "" + df_initializations = df_initializations[column_order] + + # --- Write to Excel with two sheets --- + try: + with pd.ExcelWriter(output_excel_path, engine='openpyxl') as writer: + if not df_declarations.empty: + df_declarations.to_excel(writer, sheet_name='Declarations (Initial Values)', index=False) + print(f"Written 'Declarations (Initial Values)' sheet with {len(df_declarations)} rows.") + else: + print("No data for 'Declarations (Initial Values)' sheet.") + + if not df_initializations.empty: + df_initializations.to_excel(writer, sheet_name='Initializations (Current Values)', index=False) + print(f"Written 'Initializations (Current Values)' sheet with {len(df_initializations)} rows.") + else: + print("No data for 'Initializations (Current Values)' sheet.") + + if df_declarations.empty and df_initializations.empty: + print("No data written to Excel as both datasets are empty.") + else: + print(f"\nSuccessfully generated Excel comparison: {output_excel_path}") + + except Exception as e: + print(f"Error writing Excel file {output_excel_path}: {e}") + + +def main_comparator(): + print("S7 Data Block Comparator to Excel (Multi-Sheet)") + print("==============================================") + working_dir = find_working_directory_from_x1() + print(f"Using working directory: {working_dir}") + + data_f, format_f, updated_f = find_comparison_files_detailed(working_dir) + + if not any([data_f, format_f, updated_f]): # Check if at least one relevant file was found + print("\nError: Could not find a sufficient set of input files (_data, _format, _updated). Exiting.") + return + + output_filename = "S7_DB_Comparison_MultiSheet.xlsx" + output_excel_file = os.path.join(working_dir, output_filename) + + generate_excel_comparison(data_f, format_f, updated_f, output_excel_file) + +if __name__ == "__main__": + main_comparator() \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/x3.py b/backend/script_groups/S7_DB_Utils/x3.py new file mode 100644 index 0000000..6f2c219 --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/x3.py @@ -0,0 +1,533 @@ +import re +import json +from dataclasses import dataclass, field +from typing import List, Dict, Optional, Union, Tuple, Any +import copy + +@dataclass +class ArrayDimension: + lower_bound: int + upper_bound: int + + @property + def count(self) -> int: + return self.upper_bound - self.lower_bound + 1 + +@dataclass +class VariableInfo: + name: str + data_type: str + byte_offset: float + size_in_bytes: int # For BOOL arrays, this is the number of bytes spanned. For single BOOL, 0. + bit_size: int = 0 # For BOOL, this is 1. For others, usually 0 unless it's a bitfield type. + udt_source_name: Optional[str] = None + string_length: Optional[int] = None + array_dimensions: List[ArrayDimension] = field(default_factory=list) + initial_value: Optional[str] = None + current_value: Optional[str] = None + comment: Optional[str] = None + children: List['VariableInfo'] = field(default_factory=list) + is_udt_expanded_member: bool = False + +@dataclass +class UdtInfo: + name: str + family: Optional[str] = None + version: Optional[str] = None + members: List[VariableInfo] = field(default_factory=list) + total_size_in_bytes: int = 0 + +@dataclass +class DbInfo: + name: str + title: Optional[str] = None + family: Optional[str] = None + version: Optional[str] = None + members: List[VariableInfo] = field(default_factory=list) + total_size_in_bytes: int = 0 + _initial_values_from_begin_block: Dict[str, str] = field(default_factory=dict) + +@dataclass +class ParsedData: + udts: List[UdtInfo] = field(default_factory=list) + dbs: List[DbInfo] = field(default_factory=list) + +@dataclass +class OffsetContext: + byte_offset: int = 0 + bit_offset: int = 0 # 0-7 + + def get_combined_offset(self) -> float: + if self.bit_offset == 0: + return float(self.byte_offset) + return float(self.byte_offset * 10 + self.bit_offset) / 10.0 + + def advance_bits(self, num_bits: int): + self.bit_offset += num_bits + self.byte_offset += self.bit_offset // 8 + self.bit_offset %= 8 + + def align_to_byte(self): + if self.bit_offset > 0: + self.byte_offset += 1 + self.bit_offset = 0 + + def align_to_word(self): + self.align_to_byte() + if self.byte_offset % 2 != 0: + self.byte_offset += 1 + +S7_PRIMITIVE_SIZES = { + # type_name: (size_in_bytes, alignment_in_bytes_for_start, is_bool_type) + "BOOL": (0, 1, True), "BYTE": (1, 1, False), "CHAR": (1, 1, False), + "SINT": (1, 1, False), "USINT": (1, 1, False), "WORD": (2, 2, False), + "INT": (2, 2, False), "UINT": (2, 2, False), "S5TIME": (2, 2, False), + "DATE": (2, 2, False), "DWORD": (4, 2, False), "DINT": (4, 2, False), + "UDINT": (4, 2, False), "REAL": (4, 2, False), "TIME": (4, 2, False), + "TIME_OF_DAY": (4, 2, False), "TOD": (4, 2, False), # TOD is alias for TIME_OF_DAY + "LREAL": (8, 2, False), "LINT": (8, 2, False), "ULINT": (8, 2, False), + "LWORD": (8, 2, False), "DATE_AND_TIME": (8, 2, False), "DT": (8, 2, False), # DT is alias for DATE_AND_TIME + # STRING is handled specially due to its length component +} + +class S7Parser: + def __init__(self): + self.parsed_data = ParsedData() + self.known_udts: Dict[str, UdtInfo] = {} + self.type_start_regex = re.compile(r'^\s*TYPE\s+"([^"]+)"', re.IGNORECASE) + self.db_start_regex = re.compile(r'^\s*DATA_BLOCK\s+"([^"]+)"', re.IGNORECASE) + self.property_regex = re.compile(r'^\s*([A-Z_]+)\s*:\s*(.+?)(?:\s*;)?\s*(?://.*)?$', re.IGNORECASE) + self.struct_start_regex = re.compile(r'^\s*STRUCT\b', re.IGNORECASE) + self.end_struct_regex = re.compile(r'^\s*END_STRUCT\b', re.IGNORECASE) + self.end_type_regex = re.compile(r'^\s*END_TYPE\b', re.IGNORECASE) + self.end_db_regex = re.compile(r'^\s*END_DATA_BLOCK\b', re.IGNORECASE) + self.begin_regex = re.compile(r'^\s*BEGIN\b', re.IGNORECASE) + + self.var_regex_simplified = re.compile( + r'^\s*(?P[a-zA-Z_][a-zA-Z0-9_]*)\s*:\s*' + r'(?P' + r'(?:ARRAY\s*\[(?P[^\]]+?)\]\s*OF\s*)?' + r'(?P(?:"[^"]+"|[a-zA-Z_][a-zA-Z0-9_]*))' # UDTs in quotes, primitives without + r'(?:\s*\[\s*(?P\d+)\s*\])?' # Optional string length + r')' + r'(?:\s*:=\s*(?P[^;]*?))??\s*' # Initial value: non-greedy, does not cross a semicolon + r';?\s*$', # Optional semicolon at the end of the declaration + re.IGNORECASE + ) + self.array_dim_regex = re.compile(r'(\d+)\s*\.\.\s*(\d+)') + + + def _get_type_details(self, type_name_raw: str) -> Tuple[int, int, bool, str]: + type_name_cleaned = type_name_raw.strip('"').upper() + udt_original_case_name = type_name_raw.strip('"') + + if type_name_cleaned in S7_PRIMITIVE_SIZES: + size, align, is_bool = S7_PRIMITIVE_SIZES[type_name_cleaned] + return size, align, is_bool, type_name_cleaned + elif udt_original_case_name in self.known_udts: + udt = self.known_udts[udt_original_case_name] + return udt.total_size_in_bytes, 2, False, udt_original_case_name # UDTs align like structs (word) + elif type_name_cleaned == "STRUCT": # For explicit STRUCT members + return 0, 2, False, "STRUCT" # Size determined by members, aligns to word + raise ValueError(f"Unknown data type or UDT not defined: '{type_name_raw}' (Cleaned: '{type_name_cleaned}', Original UDT: '{udt_original_case_name}')") + + @staticmethod + def _adjust_children_offsets(children: List[VariableInfo], base_offset_add: float): + for child in children: + child.byte_offset += base_offset_add + if child.byte_offset == float(int(child.byte_offset)): + child.byte_offset = float(int(child.byte_offset)) + if child.children: + S7Parser._adjust_children_offsets(child.children, base_offset_add) # Pass the original base_offset_add + + def _parse_struct_members(self, lines: List[str], current_line_idx: int, + parent_members_list: List[VariableInfo], + active_context: OffsetContext, + is_top_level_struct_in_block: bool = False) -> int: + idx_to_process = current_line_idx + + while idx_to_process < len(lines): + original_line_text_with_leading_space = lines[idx_to_process] + original_line_text = original_line_text_with_leading_space.strip() + + line_to_parse = original_line_text + line_comment = None + comment_marker_idx = original_line_text.find("//") + if comment_marker_idx != -1: + line_to_parse = original_line_text[:comment_marker_idx].strip() + line_comment = original_line_text[comment_marker_idx + 2:].strip() + + line_index_for_return = idx_to_process # Save index before incrementing + idx_to_process += 1 # Pre-increment for next loop or return + + if not line_to_parse: # If line is empty after stripping comments, or was originally empty + continue + + # Handle block endings (STRUCT, TYPE, DB, BEGIN) based on line_to_parse + if self.end_struct_regex.match(line_to_parse): + if not is_top_level_struct_in_block: # End of a nested STRUCT member + active_context.align_to_byte() # Ensure current byte is finished + if active_context.byte_offset % 2 != 0: # Struct total size must be even + active_context.byte_offset += 1 + return idx_to_process # Return line number AFTER END_STRUCT + # If is_top_level_struct_in_block, END_STRUCT is for the main block, handled by END_TYPE/DB + + if is_top_level_struct_in_block and \ + (self.end_type_regex.match(line_to_parse) or \ + self.end_db_regex.match(line_to_parse) or \ + self.begin_regex.match(line_to_parse)): + active_context.align_to_byte() # Finish current byte for the whole UDT/DB declaration part + if active_context.byte_offset % 2 != 0: # Total size must be even + active_context.byte_offset += 1 + return line_index_for_return # Return index OF the BEGIN/END_TYPE/END_DB line + + # Check for STRUCT start for a member + if self.struct_start_regex.match(line_to_parse): # This is a nested STRUCT member declaration + # This line should be matched by var_regex as a variable of type STRUCT + # If we are here, it means var_regex didn't match it, or it's an anonymous struct. + # For simplicity, we assume named structs are parsed by var_regex. + # This path might need review if anonymous structs are common. + # For now, we assume explicit STRUCT members are named and caught by var_regex + pass # Let var_regex handle it if it's a named struct + + var_match = self.var_regex_simplified.match(line_to_parse) + if var_match: + var_data = var_match.groupdict() + var_info = VariableInfo(name=var_data['name'], data_type="", byte_offset=0, size_in_bytes=0) + + initial_val_str = var_data.get('initval') + if initial_val_str: + var_info.initial_value = initial_val_str.strip() + if line_comment: + var_info.comment = line_comment + + raw_base_type = var_data['basetype'].strip() + var_info.data_type = raw_base_type.strip('"') # Store clean type for logic + if raw_base_type.startswith('"') and raw_base_type.endswith('"'): + var_info.udt_source_name = raw_base_type # Store with quotes if UDT + + num_array_elements = 1 + if var_data['arraydims']: + for dim_match in self.array_dim_regex.finditer(var_data['arraydims']): + var_info.array_dimensions.append(ArrayDimension(int(dim_match.group(1)), int(dim_match.group(2)))) + if var_info.array_dimensions: + for dim in var_info.array_dimensions: + num_array_elements *= dim.count + + # --- Offset and Size Calculation --- + if var_info.data_type.upper() == "STRUCT": # Member is explicitly 'STRUCT' + active_context.align_to_word() + var_info.byte_offset = active_context.get_combined_offset() + + nested_struct_context = OffsetContext() # Children offsets are relative to this new context + # We need to find the line "STRUCT" and parse from the line AFTER it + # The current idx_to_process is already advanced. + # The _parse_struct_members call will continue from where the var_match line was, + # which is not right for a struct definition that spans multiple lines. + # This means "STRUCT" members need to be handled by the parser finding "STRUCT" keyword, + # not just by var_regex matching "Variable : STRUCT". + # For now, assume if var_regex matched, it's a named struct. + # The call to _parse_struct_members for children should start from the *next line* in the input lines list. + + idx_after_nested_struct = self._parse_struct_members( + lines, + idx_to_process, # Start parsing members of this struct from the next available line + var_info.children, + nested_struct_context, + is_top_level_struct_in_block=False # This is a nested struct + ) + var_info.size_in_bytes = nested_struct_context.byte_offset # This is the calculated size of the nested struct + + # Adjust children offsets to be absolute + # The children's byte_offset are currently relative to the start of the nested_struct_context (0.0) + # They need to be relative to the DB/UDT. + # var_info.byte_offset is the absolute start of this STRUCT member. + for child in var_info.children: + child.byte_offset += var_info.byte_offset + if child.byte_offset == float(int(child.byte_offset)): + child.byte_offset = float(int(child.byte_offset)) + if child.children: # If UDTs within struct had their own structs + S7Parser._adjust_children_offsets(child.children, var_info.byte_offset) + + + active_context.byte_offset += var_info.size_in_bytes # Advance parent context + idx_to_process = idx_after_nested_struct # Update main loop's line index + + elif var_info.data_type.upper() == "STRING" and var_data['stringlength']: + var_info.string_length = int(var_data['stringlength']) + unit_size = var_info.string_length + 2 + active_context.align_to_word() # STRINGs are word-aligned + var_info.byte_offset = active_context.get_combined_offset() + var_info.size_in_bytes = unit_size * num_array_elements + active_context.byte_offset += var_info.size_in_bytes + + else: # Primitive or UDT instance + # Use var_info.data_type (cleaned name) for _get_type_details + unit_size_bytes, unit_alignment_req, is_bool, type_name_for_udt_lookup = self._get_type_details(var_info.data_type) + + if is_bool: + var_info.bit_size = 1 # A single BOOL is 1 bit + # For an array of BOOLs, record offset of the first bit + var_info.byte_offset = active_context.get_combined_offset() + active_context.advance_bits(num_array_elements) # Advance context by total bits + + # Calculate effective byte span for the BOOL or BOOL array + start_byte_abs = int(var_info.byte_offset) + start_bit_in_byte = int(round((var_info.byte_offset - start_byte_abs) * 10)) + + if num_array_elements == 1: + var_info.size_in_bytes = 0 # Convention for single bit + else: # Array of BOOLs + bits_remaining = num_array_elements + bytes_spanned = 0 + if start_bit_in_byte > 0: # Starts mid-byte + bits_in_first_byte = 8 - start_bit_in_byte + if bits_remaining <= bits_in_first_byte: + bytes_spanned = 1 + else: + bytes_spanned = 1 + bits_remaining -= bits_in_first_byte + bytes_spanned += (bits_remaining + 7) // 8 # Ceiling division for remaining full bytes + else: # Starts on a byte boundary + bytes_spanned = (bits_remaining + 7) // 8 + var_info.size_in_bytes = bytes_spanned + + else: # Non-BOOL primitive or UDT + active_context.align_to_byte() # Finish any pending bits + if unit_alignment_req == 2: # WORD, DWORD, REAL, UDT, etc. + active_context.align_to_word() + + var_info.byte_offset = active_context.get_combined_offset() + var_info.size_in_bytes = unit_size_bytes * num_array_elements + active_context.byte_offset += var_info.size_in_bytes + + # If it's a UDT instance, expand its members + if type_name_for_udt_lookup in self.known_udts and not is_bool: + udt_def = self.known_udts[type_name_for_udt_lookup] + udt_instance_absolute_start_offset = var_info.byte_offset + + for udt_member_template in udt_def.members: + expanded_member = copy.deepcopy(udt_member_template) + expanded_member.is_udt_expanded_member = True + # udt_member_template.byte_offset is relative to UDT start (0.0) + expanded_member.byte_offset += udt_instance_absolute_start_offset + if expanded_member.byte_offset == float(int(expanded_member.byte_offset)): + expanded_member.byte_offset = float(int(expanded_member.byte_offset)) + + # If the UDT member itself has children (e.g., a struct within the UDT) + # their offsets also need to be made absolute relative to the DB. + # The base_offset_add for _adjust_children_offsets should be the + # absolute start of the current UDT instance. + if expanded_member.children: + S7Parser._adjust_children_offsets(expanded_member.children, udt_instance_absolute_start_offset) + + var_info.children.append(expanded_member) + parent_members_list.append(var_info) + else: # Line not matched by var_regex + # Check if it's a STRUCT definition line that var_regex MISSED + # This is a fallback / debug for when 'STRUCT' starts a definition block for a member + struct_keyword_match = self.struct_start_regex.match(line_to_parse) + if struct_keyword_match and not var_match : # An unnamed struct or parsing issue + print(f"DEBUG: Found 'STRUCT' keyword on line but not parsed by var_regex: '{original_line_text}' | Processed='{line_to_parse}'") + # This case might need more robust handling if anonymous structs are used or if var_regex is too strict for named structs + elif line_to_parse and \ + not self.end_struct_regex.match(line_to_parse) and \ + not (is_top_level_struct_in_block and \ + (self.end_type_regex.match(line_to_parse) or \ + self.end_db_regex.match(line_to_parse) or \ + self.begin_regex.match(line_to_parse))): + print(f"DEBUG: Line not parsed as variable or known keyword: Original='{original_line_text}' | Processed='{line_to_parse}'") + + # This final padding should ideally be handled when END_STRUCT or END_TYPE/DB is detected + # For is_top_level_struct_in_block, it's handled by BEGIN/END_TYPE/DB detection. + # For nested structs, it's handled by END_STRUCT detection. + return idx_to_process + + + def _parse_begin_block(self, lines: List[str], start_idx: int, db_info: DbInfo) -> int: + idx = start_idx + # Regex for assignment: path := value ; + # Path can contain dots, array indices. Value can be complex. + assignment_regex = re.compile(r'^\s*(?P[a-zA-Z0-9_."\[\],\s]+?)\s*:=\s*(?P.+?)\s*;?\s*$', re.IGNORECASE) + while idx < len(lines): + original_line = lines[idx].strip() + + line_to_parse = original_line + comment_marker_idx = original_line.find("//") + if comment_marker_idx != -1: + line_to_parse = original_line[:comment_marker_idx].strip() + # comment = original_line[comment_marker_idx+2:].strip() # Comment in BEGIN usually not stored + + if self.end_db_regex.match(line_to_parse): # END_DATA_BLOCK terminates BEGIN section + return idx # Return index of END_DATA_BLOCK + + idx += 1 # Advance to next line + + if not line_to_parse: continue # Skip empty lines + + match = assignment_regex.match(line_to_parse) + if match: + path = match.group("path").strip() + value = match.group("value").strip().rstrip(';').strip() + db_info._initial_values_from_begin_block[path] = value + # else: # Optional: print lines in BEGIN that don't match assignment + # print(f"DEBUG: Line in BEGIN not matched as assignment: '{original_line}'") + + raise SyntaxError("Expected END_DATA_BLOCK after BEGIN section, but not found.") + + + def _apply_current_values(self, members: List[VariableInfo], begin_values: Dict[str, str], current_path_prefix: str = ""): + for var_info in members: + # Construct full path, handling array indices if necessary (simplification: not handling array element assignment here) + # For UDTs, the path in BEGIN block directly names the UDT member, e.g., "MyUdtVar._Name" + full_member_path = f"{current_path_prefix}{var_info.name}" + + if var_info.is_udt_expanded_member: # Path comes from the UDT parent + # This requires careful reconstruction if the assignment path is more complex + # For now, assume direct member access for expanded UDTs. + # Example: If parent is "Actual_Recipe", and child is "_Name", path is "Actual_Recipe._Name" + # current_path_prefix should be the name of the UDT variable instance. + pass # The full_member_path is already constructed above with current_path_prefix + + if full_member_path in begin_values: + var_info.current_value = begin_values[full_member_path] + elif var_info.initial_value is not None: # Fallback to declaration initial value + var_info.current_value = var_info.initial_value + + # If this member itself has children (it's a parsed STRUCT or an expanded UDT that contained STRUCTs), + # recurse into them. + if var_info.children and not var_info.is_udt_expanded_member: # Recurse for normal structs + self._apply_current_values(var_info.children, begin_values, f"{full_member_path}.") + # For expanded UDT members (is_udt_expanded_member = True), their values are set directly, + # and if THEY had children (structs within the UDT def), those are part of the UDT expansion. + # The BEGIN block paths would typically be like "MyUdtInstance.StructInUdt.Member". + # This simplified _apply_current_values might need enhancement for complex paths into UDTs. + + + def parse_file(self, filepath: str) -> ParsedData: + try: + with open(filepath, 'r', encoding='utf-8-sig') as f: + lines = f.readlines() + except Exception as e: + print(f"Error reading file {filepath}: {e}") + return self.parsed_data + + current_block_handler: Optional[Union[UdtInfo, DbInfo]] = None + active_block_context = OffsetContext() + + idx = 0 + while idx < len(lines): + original_line = lines[idx].strip() + line_to_parse = original_line + comment_marker_idx = original_line.find("//") + if comment_marker_idx != -1: + line_to_parse = original_line[:comment_marker_idx].strip() + # Top-level comments usually not stored with block definition + + type_match = self.type_start_regex.match(line_to_parse) + db_match = self.db_start_regex.match(line_to_parse) + + if type_match: + if current_block_handler: print(f"Warning: Starting new TYPE block for '{type_match.group(1)}' before previous block '{current_block_handler.name}' ended.") + udt_name = type_match.group(1) + current_block_handler = UdtInfo(name=udt_name) + self.parsed_data.udts.append(current_block_handler) + active_block_context = OffsetContext() + idx += 1; continue + elif db_match: + if current_block_handler: print(f"Warning: Starting new DATA_BLOCK for '{db_match.group(1)}' before previous block '{current_block_handler.name}' ended.") + db_name = db_match.group(1) + current_block_handler = DbInfo(name=db_name) + self.parsed_data.dbs.append(current_block_handler) + active_block_context = OffsetContext() + idx += 1; continue + + if not current_block_handler: + idx += 1; continue + + # Inside a UDT or DB block definition part (before BEGIN for DBs) + prop_match = self.property_regex.match(original_line) # Properties can have comments + struct_keyword_on_line = self.struct_start_regex.match(line_to_parse) # Check for "STRUCT" keyword line + + if prop_match: + key, value = prop_match.group(1).upper(), prop_match.group(2).strip() + attr_name = key.lower() + if hasattr(current_block_handler, attr_name): + setattr(current_block_handler, attr_name, value) + + elif struct_keyword_on_line and not current_block_handler.members: # Start of main STRUCT for UDT/DB + # The line 'STRUCT' itself is consumed. Parsing of members starts from the next line. + idx = self._parse_struct_members( + lines, idx + 1, # Start from line AFTER "STRUCT" + current_block_handler.members, + active_block_context, + is_top_level_struct_in_block=True + ) + # idx is now the line number of BEGIN, END_TYPE, or END_DB + continue # Let the main loop handle this new line index + + elif self.begin_regex.match(line_to_parse) and isinstance(current_block_handler, DbInfo): + # Finalize size from declaration part + current_block_handler.total_size_in_bytes = active_block_context.byte_offset + idx = self._parse_begin_block(lines, idx + 1, current_block_handler) # idx + 1 to start after BEGIN + # idx is now the line of END_DATA_BLOCK + continue + + elif self.end_type_regex.match(line_to_parse) and isinstance(current_block_handler, UdtInfo): + if not hasattr(current_block_handler, 'total_size_in_bytes') or current_block_handler.total_size_in_bytes == 0: + current_block_handler.total_size_in_bytes = active_block_context.byte_offset # Size from declarations + self.known_udts[current_block_handler.name] = current_block_handler + print(f"Parsed UDT: {current_block_handler.name}, Size: {current_block_handler.total_size_in_bytes} bytes. Members: {len(current_block_handler.members)}") + current_block_handler = None + + elif self.end_db_regex.match(line_to_parse) and isinstance(current_block_handler, DbInfo): + if not hasattr(current_block_handler, 'total_size_in_bytes') or current_block_handler.total_size_in_bytes == 0: # If no BEGIN block, size is from declarations + current_block_handler.total_size_in_bytes = active_block_context.byte_offset + self._apply_current_values(current_block_handler.members, current_block_handler._initial_values_from_begin_block) + print(f"Parsed DB: {current_block_handler.name}, Decl. Size: {current_block_handler.total_size_in_bytes} bytes. Members: {len(current_block_handler.members)}") + current_block_handler = None + + idx += 1 + + return self.parsed_data + +def custom_json_serializer(obj: Any) -> Any: + if isinstance(obj, OffsetContext): return None # Don't serialize OffsetContext + if hasattr(obj, '__dict__'): + # Filter out None values, empty lists, and specific private fields + d = {k: v for k, v in obj.__dict__.items() + if v is not None and \ + not (isinstance(v, list) and not v) and \ + k != '_initial_values_from_begin_block'} + + # Ensure 'is_udt_expanded_member' is present even if False (unless explicitly None) + if isinstance(obj, VariableInfo): + if 'is_udt_expanded_member' not in d and obj.is_udt_expanded_member is False: + d['is_udt_expanded_member'] = False + # If it was True, it would already be in d or caught by the general v is not None + elif obj.is_udt_expanded_member is True: + d['is_udt_expanded_member'] = True + + return d + raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable") + +if __name__ == "__main__": + parser = S7Parser() + # IMPORTANT: Ensure this filepath points to your actual source file. + # The filename was changed to .txt for upload, adjust if your local file is .db + filepath = "db1001_format.db.txt" # Or "db1001_format.db" if that's the actual name + + print(f"Attempting to parse: {filepath}") + parsed_result = parser.parse_file(filepath) + + json_output_filename = "parsed_s7_data_expanded.json" # New output filename + print(f"\nParsing complete. Attempting to serialize to JSON.") + + try: + json_output = json.dumps(parsed_result, default=custom_json_serializer, indent=2) + # print(json_output) # Optional: print to console for quick check + with open(json_output_filename, "w", encoding='utf-8') as f: + f.write(json_output) + print(f"Result saved to {json_output_filename}") + except Exception as e: + print(f"Error during JSON serialization or file writing: {e}") \ No newline at end of file diff --git a/backend/script_groups/S7_DB_Utils/x4.py b/backend/script_groups/S7_DB_Utils/x4.py new file mode 100644 index 0000000..8e27a2e --- /dev/null +++ b/backend/script_groups/S7_DB_Utils/x4.py @@ -0,0 +1,303 @@ +import json +from typing import List, Dict, Any, Union + +# Se asume que las dataclasses (VariableInfo, UdtInfo, etc.) del script x3.py +# estarían disponibles si este script fuera parte de un paquete más grande. +# Para este script independiente, trabajaremos directamente con los diccionarios del JSON. + +def format_data_type_for_source(var_info: Dict[str, Any]) -> str: + """Formatea la declaración de tipo completa para la variable en S7 source.""" + base_type = var_info.get("udt_source_name") if var_info.get("udt_source_name") else var_info["data_type"] + + type_str = "" + if var_info.get("array_dimensions"): + dims_str = ",".join([f"{d['lower_bound']}..{d['upper_bound']}" for d in var_info["array_dimensions"]]) + type_str += f"ARRAY [{dims_str}] OF " + + type_str += base_type + + if var_info["data_type"].upper() == "STRING" and var_info.get("string_length") is not None: + type_str += f"[{var_info['string_length']}]" + + return type_str + +def generate_variable_declaration_for_source(var_info: Dict[str, Any], indent_level: int) -> str: + """Genera una línea de declaración de variable S7.""" + indent_str = " " * indent_level + type_declaration_str = format_data_type_for_source(var_info) + + line = f'{indent_str}{var_info["name"]} : {type_declaration_str}' + + if var_info.get("initial_value") is not None: + # Asegurarse de que los booleanos se escriban como TRUE/FALSE + initial_val = var_info["initial_value"] + if isinstance(initial_val, bool): + initial_val_str = "TRUE" if initial_val else "FALSE" + else: + initial_val_str = str(initial_val) + line += f' := {initial_val_str}' + + line += ';' + + if var_info.get("comment"): + line += f'\t// {var_info["comment"]}' + + return line + +def generate_struct_members_for_source(members: List[Dict[str, Any]], indent_level: int) -> List[str]: + """Genera recursivamente las declaraciones de miembros para STRUCTs/UDTs.""" + lines = [] + for var_info in members: + # No expandir UDTs anidados dentro de la sección de declaración de otro UDT o DB. + # Solo declarar la variable del tipo UDT. + # La expansión de miembros de UDT solo ocurre en el JSON para análisis, no para la reconstrucción de la fuente. + if var_info.get("is_udt_expanded_member"): # Estos no se declaran individualmente en el padre. + continue + + if var_info["data_type"].upper() == "STRUCT" and not var_info.get("udt_source_name"): # Es una definición de STRUCT anidada + current_indent_str = " " * indent_level + lines.append(f'{current_indent_str}{var_info["name"]} : STRUCT;') + if var_info.get("children"): + lines.extend(generate_struct_members_for_source(var_info["children"], indent_level + 1)) + lines.append(f'{current_indent_str}END_STRUCT;') + else: # Variable primitiva, String, Array, o instancia de UDT + lines.append(generate_variable_declaration_for_source(var_info, indent_level)) + return lines + +def _generate_assignments_recursive(members: List[Dict[str, Any]], path_prefix: str, indent_str: str) -> List[str]: + """Ayudante recursivo para generar asignaciones del bloque BEGIN.""" + assignment_lines = [] + for var_info in members: + # Construir la ruta actual para esta variable + current_member_name = var_info['name'] + current_full_path = f"{path_prefix}{current_member_name}" + + # Si es una instancia de UDT, sus 'children' en el JSON son los miembros expandidos. + # Necesitamos iterar sobre estos 'children' para obtener sus 'current_value'. + if var_info.get("udt_source_name") and var_info.get("children"): + # Para la instancia de UDT, recursivamente generar asignaciones para sus miembros. + # El prefijo de ruta para los miembros del UDT será el nombre de la instancia UDT seguido de un punto. + assignment_lines.extend( + _generate_assignments_recursive(var_info["children"], f"{current_full_path}.", indent_str) + ) + # Si es un STRUCT definido inline (no una instancia de UDT) + elif var_info["data_type"].upper() == "STRUCT" and not var_info.get("udt_source_name") and var_info.get("children"): + assignment_lines.extend( + _generate_assignments_recursive(var_info["children"], f"{current_full_path}.", indent_str) + ) + # Si es un miembro primitivo (o array/string que tiene un current_value directo) + # y tiene un 'current_value'. Los miembros expandidos de UDT (is_udt_expanded_member=True) + # tendrán su current_value y su current_full_path ya incluirá el nombre de la instancia UDT. + elif var_info.get("current_value") is not None: + val_str = var_info["current_value"] + if isinstance(val_str, bool): # Convertir booleanos de JSON a TRUE/FALSE de S7 + val_str = "TRUE" if val_str else "FALSE" + + assignment_lines.append(f"{indent_str}{current_full_path} := {val_str};") + + return assignment_lines + +# En x4.py +def generate_begin_block_assignments(db_info: Dict[str, Any], indent_level: int, parsed_json_udts: Dict[str, Dict[str, Any]]) -> List[str]: + indent_str = " " * indent_level + lines = [] + + # Utilizar directamente _initial_values_from_begin_block del JSON + # ¡ASEGÚRATE DE QUE x3.py INCLUYA ESTE CAMPO EN EL JSON! + begin_values_map = db_info.get("_initial_values_from_begin_block") + + if begin_values_map and isinstance(begin_values_map, dict): + # Intentar un ordenamiento simple por clave para una salida más consistente, + # aunque el orden original del bloque BEGIN no se garantiza. + for path, value_str in sorted(begin_values_map.items()): + # Aquí, value_str ya es una cadena. Si necesitáramos convertir booleanos + # necesitaríamos información del tipo del 'path', lo cual es complejo aquí. + # Asumimos que x3.py guardó los valores en el formato correcto (ej. TRUE/FALSE para bools). + # Si x3.py guardó Python bools (true/false), necesitamos convertir. + # Para ser seguro, si el valor es "true" o "false" (strings), convertir. + + # Esta conversión es una heurística. Sería mejor si x3.py ya los formateara. + final_value_str = str(value_str) # Asegurar que es string + if final_value_str.lower() == "true": + final_value_str = "TRUE" + elif final_value_str.lower() == "false": + final_value_str = "FALSE" + + lines.append(f"{indent_str}{path} := {final_value_str};") + else: + # Fallback si _initial_values_from_begin_block no está o está mal formado. + # Este fallback ahora necesita ser más inteligente o se eliminará si el principal funciona. + # print(f"Advertencia: _initial_values_from_begin_block no encontrado o vacío para DB {db_info['name']}. Reconstrucción de BEGIN puede ser incompleta.") + # La función _generate_assignments_recursive anterior podría ser un fallback, + # pero depende de que los `current_value` de los elementos de array estén bien poblados. + # Si se implementa el `current_element_values` en `VariableInfo` en x3.py: + def generate_recursive_fallback(members, prefix, current_indent): + fallback_lines = [] + for v_info in members: + m_name = v_info['name'] + m_path = f"{prefix}{m_name}" + if v_info.get("current_element_values") and isinstance(v_info["current_element_values"], dict): + for index_str, val_str_el in sorted(v_info["current_element_values"].items()): + # index_str puede ser "1" o "1,2" etc. + el_path = f"{m_path}[{index_str}]" + + f_val_str_el = str(val_str_el) + if f_val_str_el.lower() == "true": f_val_str_el = "TRUE" + elif f_val_str_el.lower() == "false": f_val_str_el = "FALSE" + fallback_lines.append(f"{current_indent}{el_path} := {f_val_str_el};") + + elif v_info.get("udt_source_name") and v_info.get("children"): + fallback_lines.extend(generate_recursive_fallback(v_info["children"], f"{m_path}.", current_indent)) + elif v_info.get("data_type", "").upper() == "STRUCT" and not v_info.get("udt_source_name") and v_info.get("children"): + fallback_lines.extend(generate_recursive_fallback(v_info["children"], f"{m_path}.", current_indent)) + elif v_info.get("current_value") is not None: + val_str_cv = v_info["current_value"] + f_val_str_cv = str(val_str_cv) + if f_val_str_cv.lower() == "true": f_val_str_cv = "TRUE" + elif f_val_str_cv.lower() == "false": f_val_str_cv = "FALSE" + fallback_lines.append(f"{current_indent}{m_path} := {f_val_str_cv};") + return fallback_lines + + lines.extend(generate_recursive_fallback(db_info.get("members", []), "", indent_str)) + + return lines + +def generate_s7_source_code_lines(data: Dict[str, Any]) -> List[str]: + """Genera el código fuente S7 completo (UDTs y DBs) a partir de los datos JSON.""" + lines = [] + + # Generar UDTs + for udt in data.get("udts", []): + lines.append(f'TYPE "{udt["name"]}"') + if udt.get("family"): lines.append(f' FAMILY : {udt["family"]};') + if udt.get("version"): lines.append(f' VERSION : {udt["version"]};') + lines.append("") # Línea en blanco + lines.append(" STRUCT") + # Los miembros del UDT están directamente bajo 'members' + lines.extend(generate_struct_members_for_source(udt["members"], 2)) # Indentación 2 para miembros + lines.append(" END_STRUCT;") + lines.append(f'END_TYPE;') + lines.append("") # Línea en blanco después de cada UDT + + # Generar DBs + for db in data.get("dbs", []): + lines.append(f'DATA_BLOCK "{db["name"]}"') + if db.get("title"): lines.append(f' TITLE = {db["title"]};') # Asumir que el título ya tiene el formato correcto + if db.get("family"): lines.append(f' FAMILY : {db["family"]};') + if db.get("version"): lines.append(f' VERSION : {db["version"]};') + lines.append("") # Línea en blanco + lines.append(" STRUCT") + lines.extend(generate_struct_members_for_source(db["members"], 2)) # Indentación 2 para miembros + lines.append(" END_STRUCT;") + + # Generar bloque BEGIN si hay valores actuales (implicando que hubo un bloque BEGIN) + # La forma más fiable es chequear si hay current_values en los miembros. + # O, si el parser x3.py guardara una bandera explícita "has_begin_block". + # Por ahora, generaremos BEGIN si hay miembros, ya que las asignaciones se basan en current_value. + if db.get("members"): # Asumimos que si hay miembros, puede haber un bloque BEGIN. + lines.append("BEGIN") + lines.extend(generate_begin_block_assignments(db, 1)) # Indentación 1 para asignaciones + + lines.append(f'END_DATA_BLOCK;') + lines.append("") # Línea en blanco después de cada DB + + return lines + +def generate_markdown_table(db_info: Dict[str, Any]) -> List[str]: + """Genera una tabla Markdown para la documentación de un DB.""" + lines = [] + lines.append(f"# Documentación para DB: {db_info['name']}") + lines.append("") + lines.append("| Address | Name | Type | Initial Value | Actual Value | Comment |") + lines.append("|---|---|---|---|---|---|") + + def flatten_members_for_markdown(members: List[Dict[str, Any]], prefix: str = "", base_offset: float = 0.0): + md_lines = [] + for var in members: + if var.get("is_udt_expanded_member"): # No listar miembros expandidos como filas separadas de alto nivel aquí + continue + + name = f"{prefix}{var['name']}" + + # El offset en el JSON ya debería ser absoluto para los miembros del DB. + # Para miembros dentro de STRUCTs anidados, el JSON también debería tener offsets absolutos. + address = f"{var['byte_offset']:.1f}" if isinstance(var['byte_offset'], float) else str(var['byte_offset']) + if var.get("bit_size", 0) > 0 and isinstance(var['byte_offset'], float) and var['byte_offset'] != int(var['byte_offset']): + pass # El formato X.Y ya está bien para bools + elif var.get("bit_size", 0) > 0 : # bool en X.0 + address = f"{int(var['byte_offset'])}.0" + + + data_type_str = format_data_type_for_source(var) # Usar la misma función de formato + initial_value = str(var.get("initial_value", "")) + actual_value = str(var.get("current_value", "")) + comment = str(var.get("comment", "")) + + # Reemplazar pipes en los valores para no romper la tabla Markdown + initial_value = initial_value.replace("|", "\\|") + actual_value = actual_value.replace("|", "\\|") + comment = comment.replace("|", "\\|").replace("\n", " ") + + + md_lines.append(f"| {address} | {name} | {data_type_str} | {initial_value} | {actual_value} | {comment} |") + + # Si es un STRUCT (no UDT) o un UDT, listar sus miembros constitutivos recursivamente para la documentación + if var.get("children"): + # Si es una instancia de UDT, los hijos son los miembros expandidos. + # Si es un STRUCT, los hijos son los miembros directos del STRUCT. + # El prefijo para los hijos debe ser el nombre completo del padre (STRUCT/UDT). + md_lines.extend(flatten_members_for_markdown(var["children"], f"{name}.", var['byte_offset'])) + return md_lines + + lines.extend(flatten_members_for_markdown(db_info.get("members", []))) + return lines + +def main(): + json_input_filename = "parsed_s7_data_expanded.json" + s7_output_filename = "reconstructed_s7_source_v2.txt" # Nuevo nombre para la salida S7 + + try: + with open(json_input_filename, 'r', encoding='utf-8') as f: + data_from_json = json.load(f) + except FileNotFoundError: + print(f"Error: No se encontró el archivo JSON de entrada: {json_input_filename}") + return + except json.JSONDecodeError: + print(f"Error: El archivo JSON de entrada no es válido: {json_input_filename}") + return + except Exception as e: + print(f"Error al leer el archivo JSON {json_input_filename}: {e}") + return + + print(f"Archivo JSON '{json_input_filename}' cargado correctamente.") + + # 1. Generar el archivo S7 reconstruido + s7_code_lines = generate_s7_source_code_lines(data_from_json) + try: + with open(s7_output_filename, 'w', encoding='utf-8') as f: + for line in s7_code_lines: + f.write(line + "\n") + print(f"Archivo S7 reconstruido generado: {s7_output_filename}") + except Exception as e: + print(f"Error al escribir el archivo S7 {s7_output_filename}: {e}") + + # 2. Generar la documentación Markdown (para cada DB encontrado) + if data_from_json.get("dbs"): + for db_to_document in data_from_json["dbs"]: + db_name_safe = db_to_document['name'].replace('"', '').replace(' ', '_') + md_filename_specific = f"documentation_db_{db_name_safe}.md" + + print(f"\nGenerando documentación Markdown para DB: {db_to_document['name']}...") + markdown_lines = generate_markdown_table(db_to_document) + try: + with open(md_filename_specific, 'w', encoding='utf-8') as f: + for line in markdown_lines: + f.write(line + "\n") + print(f"Archivo Markdown de documentación generado: {md_filename_specific}") + except Exception as e: + print(f"Error al escribir el archivo Markdown {md_filename_specific}: {e}") + else: + print("No se encontraron DBs en el archivo JSON para generar documentación.") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/data/log.txt b/data/log.txt index 4fb7b47..d011dcf 100644 --- a/data/log.txt +++ b/data/log.txt @@ -1,10 +1,42 @@ -[14:05:02] Iniciando ejecución de x4_prompt_generator.py en C:\Trabajo\SIDEL\06 - E5.007363 - Modifica O&U - SAE196 (cip integrato)\Reporte\TAGsIO\v2... -[14:05:03] Generador de prompt para adaptación de IO -[14:05:03] ========================================= -[14:05:03] Usando directorio de trabajo: C:\Trabajo\SIDEL\06 - E5.007363 - Modifica O&U - SAE196 (cip integrato)\Reporte\TAGsIO\v2 -[14:05:03] Usando ruta de Obsidian desde configuración: C:\Users\migue\OneDrive\Miguel\Obsidean\Trabajo\VM\04-SIDEL\00 - MASTER\MIXER\IO -[14:05:03] Usando carpeta de equivalencias en Obsidian: C:\Users\migue\OneDrive\Miguel\Obsidean\Trabajo\VM\04-SIDEL\00 - MASTER\MIXER\IO -[14:05:03] ¡Prompt generado y copiado al portapapeles con éxito! -[14:05:03] Prompt guardado en: C:\Trabajo\SIDEL\06 - E5.007363 - Modifica O&U - SAE196 (cip integrato)\Reporte\TAGsIO\v2\IO_Adaptation_Prompt.txt -[14:05:04] Ejecución de x4_prompt_generator.py finalizada (success). Duración: 0:00:01.643930. -[14:05:04] Log completo guardado en: d:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\IO_adaptation\log_x4_prompt_generator.txt +[20:15:59] Iniciando ejecución de x3.py en C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001... +[20:16:00] --- ERRORES --- +[20:16:00] 2025-05-16 20:16:00,228 - db_mapper - INFO - Iniciando mapeo de DBs por dirección absoluta +[20:16:00] 2025-05-16 20:16:00,309 - db_mapper - INFO - Directorio de trabajo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 +[20:16:00] 2025-05-16 20:16:00,310 - db_mapper - INFO - Encontrados 3 archivos para procesar +[20:16:00] 2025-05-16 20:16:00,310 - db_mapper - INFO - Procesando: db1001_data.db +[20:16:00] 2025-05-16 20:16:00,310 - db_mapper - INFO - Procesando archivo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_data.db +[20:16:00] 2025-05-16 20:16:00,310 - db_mapper - ERROR - Error procesando archivo C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_data.db: module 'DB_Parser' has no attribute 'parse_db_definition' +[20:16:00] Traceback (most recent call last): +[20:16:00] File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 76, in process_db_file +[20:16:00] db_node, db_number, db_name, family, version = DB_Parser.parse_db_definition(db_content, udt_definitions) +[20:16:00] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[20:16:00] AttributeError: module 'DB_Parser' has no attribute 'parse_db_definition' +[20:16:00] 2025-05-16 20:16:00,312 - db_mapper - INFO - Procesando: db1001_format.db +[20:16:00] 2025-05-16 20:16:00,312 - db_mapper - INFO - Procesando archivo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_format.db +[20:16:00] 2025-05-16 20:16:00,313 - db_mapper - ERROR - Error procesando archivo C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_format.db: module 'DB_Parser' has no attribute 'parse_udt_definition' +[20:16:00] Traceback (most recent call last): +[20:16:00] File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 64, in process_db_file +[20:16:00] udt_name, udt_node = DB_Parser.parse_udt_definition(udt_content) +[20:16:00] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[20:16:00] AttributeError: module 'DB_Parser' has no attribute 'parse_udt_definition' +[20:16:00] 2025-05-16 20:16:00,316 - db_mapper - INFO - Procesando: db1001_format_updated.db +[20:16:00] 2025-05-16 20:16:00,316 - db_mapper - INFO - Procesando archivo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_format_updated.db +[20:16:00] 2025-05-16 20:16:00,316 - db_mapper - ERROR - Error procesando archivo C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_format_updated.db: module 'DB_Parser' has no attribute 'parse_udt_definition' +[20:16:00] Traceback (most recent call last): +[20:16:00] File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 64, in process_db_file +[20:16:00] udt_name, udt_node = DB_Parser.parse_udt_definition(udt_content) +[20:16:00] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[20:16:00] AttributeError: module 'DB_Parser' has no attribute 'parse_udt_definition' +[20:16:00] Traceback (most recent call last): +[20:16:00] File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 444, in +[20:16:00] main() +[20:16:00] File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 430, in main +[20:16:00] processed_files, mapped_pairs = process_all_files_in_directory() +[20:16:00] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[20:16:00] File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\x3.py", line 372, in process_all_files_in_directory +[20:16:00] "timestamp": import_datetime().now().isoformat() +[20:16:00] ^^^^^^^^^^^^^^^^^^^^^ +[20:16:00] AttributeError: module 'datetime' has no attribute 'now' +[20:16:00] --- FIN ERRORES --- +[20:16:00] Ejecución de x3.py finalizada (error). Duración: 0:00:00.897567. Se detectaron errores (ver log). +[20:16:00] Log completo guardado en: D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\log_x3.txt