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.
This commit is contained in:
parent
7f5d7ff033
commit
a82ef44fb8
|
@ -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()
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -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
|
|
@ -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;
|
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "S7 DB Utilities",
|
||||||
|
"description": "Utilidades para Trabajar con DBs de Siemens S7",
|
||||||
|
"version": "1.0",
|
||||||
|
"author": "Miguel"
|
||||||
|
}
|
|
@ -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 | |
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
}
|
|
@ -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 ---
|
|
@ -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 ---
|
|
@ -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 <module>
|
||||||
|
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 ---
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||||
|
|
||||||
|
<working_directory>/
|
||||||
|
├── <Project_Name>_CAx_Export.aml
|
||||||
|
├── <PLC1_Name>/
|
||||||
|
│ ├── 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
|
||||||
|
│ └── <Project_Name>_CAx_Export_Hardware_Tree.md
|
||||||
|
|
||||||
|
├── <PLC2_Name>/
|
||||||
|
│ ├── ProgramBlocks_XML/
|
||||||
|
│ │ └── ...
|
||||||
|
│ └── ...
|
||||||
|
└── ...
|
|
@ -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;
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
|
@ -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()
|
|
@ -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()
|
|
@ -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<name>[a-zA-Z_][a-zA-Z0-9_]*)\s*:\s*'
|
||||||
|
r'(?P<typefull>'
|
||||||
|
r'(?:ARRAY\s*\[(?P<arraydims>[^\]]+?)\]\s*OF\s*)?'
|
||||||
|
r'(?P<basetype>(?:"[^"]+"|[a-zA-Z_][a-zA-Z0-9_]*))' # UDTs in quotes, primitives without
|
||||||
|
r'(?:\s*\[\s*(?P<stringlength>\d+)\s*\])?' # Optional string length
|
||||||
|
r')'
|
||||||
|
r'(?:\s*:=\s*(?P<initval>[^;]*?))??\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<path>[a-zA-Z0-9_."\[\],\s]+?)\s*:=\s*(?P<value>.+?)\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}")
|
|
@ -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()
|
52
data/log.txt
52
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...
|
[20:15:59] Iniciando ejecución de x3.py en C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001...
|
||||||
[14:05:03] Generador de prompt para adaptación de IO
|
[20:16:00] --- ERRORES ---
|
||||||
[14:05:03] =========================================
|
[20:16:00] 2025-05-16 20:16:00,228 - db_mapper - INFO - Iniciando mapeo de DBs por dirección absoluta
|
||||||
[14:05:03] Usando directorio de trabajo: C:\Trabajo\SIDEL\06 - E5.007363 - Modifica O&U - SAE196 (cip integrato)\Reporte\TAGsIO\v2
|
[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
|
||||||
[14:05:03] Usando ruta de Obsidian desde configuración: C:\Users\migue\OneDrive\Miguel\Obsidean\Trabajo\VM\04-SIDEL\00 - MASTER\MIXER\IO
|
[20:16:00] 2025-05-16 20:16:00,310 - db_mapper - INFO - Encontrados 3 archivos para procesar
|
||||||
[14:05:03] Usando carpeta de equivalencias en Obsidian: C:\Users\migue\OneDrive\Miguel\Obsidean\Trabajo\VM\04-SIDEL\00 - MASTER\MIXER\IO
|
[20:16:00] 2025-05-16 20:16:00,310 - db_mapper - INFO - Procesando: db1001_data.db
|
||||||
[14:05:03] ¡Prompt generado y copiado al portapapeles con éxito!
|
[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
|
||||||
[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
|
[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'
|
||||||
[14:05:04] Ejecución de x4_prompt_generator.py finalizada (success). Duración: 0:00:01.643930.
|
[20:16:00] Traceback (most recent call last):
|
||||||
[14:05:04] Log completo guardado en: d:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\IO_adaptation\log_x4_prompt_generator.txt
|
[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 <module>
|
||||||
|
[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
|
||||||
|
|
Loading…
Reference in New Issue