diff --git a/backend/script_groups/S7_DB_Utils/log_x4.txt b/backend/script_groups/S7_DB_Utils/log_x4.txt index a1dbbba..6202d9b 100644 --- a/backend/script_groups/S7_DB_Utils/log_x4.txt +++ b/backend/script_groups/S7_DB_Utils/log_x4.txt @@ -1,15 +1,15 @@ --- Log de Ejecución: x4.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-18 02:13:16 -Fin: 2025-05-18 02:13:16 -Duración: 0:00:00.162328 +Inicio: 2025-05-18 13:15:28 +Fin: 2025-05-18 13:15:28 +Duración: 0:00:00.188819 Estado: SUCCESS (Código de Salida: 0) --- SALIDA ESTÁNDAR (STDOUT) --- Using working directory: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 Los archivos de documentación generados se guardarán en: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation -Archivos JSON encontrados para procesar: 2 +Archivos JSON encontrados para procesar: 3 --- Procesando archivo JSON: db1001_data.json --- Archivo JSON 'db1001_data.json' cargado correctamente. @@ -21,6 +21,11 @@ Archivo JSON 'db1001_format.json' cargado correctamente. Archivo S7 reconstruido generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_format.txt Archivo Markdown de documentación generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_format.md +--- Procesando archivo JSON: db1001_updated.json --- +Archivo JSON 'db1001_updated.json' cargado correctamente. +Archivo S7 reconstruido generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.txt +Archivo Markdown de documentación generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.md + --- Proceso de generación de documentación completado --- --- ERRORES (STDERR) --- diff --git a/backend/script_groups/S7_DB_Utils/log_x6.txt b/backend/script_groups/S7_DB_Utils/log_x6.txt index 6977baa..21a0fa9 100644 --- a/backend/script_groups/S7_DB_Utils/log_x6.txt +++ b/backend/script_groups/S7_DB_Utils/log_x6.txt @@ -1,25 +1,30 @@ --- Log de Ejecución: x6.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-18 02:20:21 -Fin: 2025-05-18 02:20:22 -Duración: 0:00:01.130771 +Inicio: 2025-05-18 12:06:45 +Fin: 2025-05-18 12:06:46 +Duración: 0:00:00.564906 Estado: SUCCESS (Código de Salida: 0) --- SALIDA ESTÁNDAR (STDOUT) --- Using working directory: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 Los archivos Excel de documentación se guardarán en: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation -Archivos JSON encontrados para procesar: 2 +Archivos JSON encontrados para procesar: 3 --- Procesando archivo JSON para Excel: db1001_data.json --- Archivo JSON 'db1001_data.json' cargado correctamente. -Generando documentación Excel para DB: 'HMI_Blender_Parameters' (desde db1001_data.json) -> C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_data.json_HMI_Blender_Parameters.xlsx -Excel documentation generated: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_data.json_HMI_Blender_Parameters.xlsx +Generando documentación Excel para DB: 'HMI_Blender_Parameters' (desde db1001_data.json) -> C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_data.json.xlsx +Excel documentation generated: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_data.json.xlsx --- Procesando archivo JSON para Excel: db1001_format.json --- Archivo JSON 'db1001_format.json' cargado correctamente. -Generando documentación Excel para DB: 'HMI_Blender_Parameters' (desde db1001_format.json) -> C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_format.json_HMI_Blender_Parameters.xlsx -Excel documentation generated: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_format.json_HMI_Blender_Parameters.xlsx +Generando documentación Excel para DB: 'HMI_Blender_Parameters' (desde db1001_format.json) -> C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_format.json.xlsx +Excel documentation generated: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_format.json.xlsx + +--- Procesando archivo JSON para Excel: db1001_updated.json --- +Archivo JSON 'db1001_updated.json' cargado correctamente. +Generando documentación Excel para DB: 'HMI_Blender_Parameters' (desde db1001_updated.json) -> C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.json.xlsx +Excel documentation generated: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.json.xlsx --- Proceso de generación de documentación Excel completado --- diff --git a/backend/script_groups/S7_DB_Utils/log_x7_value_updater.txt b/backend/script_groups/S7_DB_Utils/log_x7_value_updater.txt index 1941584..d31b775 100644 --- a/backend/script_groups/S7_DB_Utils/log_x7_value_updater.txt +++ b/backend/script_groups/S7_DB_Utils/log_x7_value_updater.txt @@ -1,9 +1,9 @@ --- Log de Ejecución: x7_value_updater.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-18 02:56:24 -Fin: 2025-05-18 02:56:25 -Duración: 0:00:00.761362 +Inicio: 2025-05-18 13:21:37 +Fin: 2025-05-18 13:21:38 +Duración: 0:00:01.043746 Estado: SUCCESS (Código de Salida: 0) --- SALIDA ESTÁNDAR (STDOUT) --- @@ -22,7 +22,7 @@ Comparando estructuras para DB 'HMI_Blender_Parameters': 284 variables en _data, Los archivos son compatibles. Creando el archivo _updated... Archivo _updated generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\json\db1001_updated.json -Archivo de comparación Excel generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_comparison.xlsx +Comparison Excel file generated: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_comparison.xlsx Archivo Markdown generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.md Archivo S7 generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.txt Archivo S7 copiado a: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_updated.db diff --git a/backend/script_groups/S7_DB_Utils/scripts_description.json b/backend/script_groups/S7_DB_Utils/scripts_description.json index 2040fda..04e9b7d 100644 --- a/backend/script_groups/S7_DB_Utils/scripts_description.json +++ b/backend/script_groups/S7_DB_Utils/scripts_description.json @@ -30,19 +30,19 @@ "hidden": false }, "x5.py": { - "display_name": "05: Generar Descripción MD del JSON", + "display_name": "05: Generar Descripción MD", "short_description": "Genera documentación descriptiva de archivos JSON en Markdown.", "long_description": "Crea un archivo Markdown que documenta la estructura interna de los archivos JSON (generados por x3.py). Detalla UDTs y DBs, incluyendo sus miembros, offsets, tipos de datos, y valores iniciales/actuales, facilitando la comprensión del contenido del JSON.", "hidden": false }, "x6.py": { - "display_name": "06: Generar Excel desde JSON", + "display_name": "06: Generar Excel", "short_description": "Genera documentación de DBs en formato Excel (.xlsx) desde JSON.", "long_description": "Procesa archivos JSON (generados por x3.py) y exporta la información de cada Bloque de Datos (DB) a un archivo Excel (.xlsx). La hoja de cálculo incluye detalles como direcciones, nombres de variables, tipos de datos, valores iniciales, valores actuales y comentarios.", "hidden": false }, "x7_value_updater.py": { - "display_name": "07: Actualizar Valores de DB (JSON)", + "display_name": "07: Actualizar Valores data+format->updated", "short_description": "Busca archivos .db o .awl con la terminacion _data y _format. Si los encuentra y son compatibles usa los datos de _data para generar un _updated con los nombres de las variables de _format", "long_description": "Procesa pares de archivos a JSON (_data.json y _format.json, generados por x3.py). Compara sus estructuras por offset para asegurar compatibilidad. Si son compatibles, crea un nuevo archivo _updated.json que combina la estructura del _format.json con los valores actuales del _data.json.", "hidden": false diff --git a/backend/script_groups/S7_DB_Utils/x3.py b/backend/script_groups/S7_DB_Utils/x3.py index 63eaf00..e5fe109 100644 --- a/backend/script_groups/S7_DB_Utils/x3.py +++ b/backend/script_groups/S7_DB_Utils/x3.py @@ -47,7 +47,8 @@ class VariableInfo: comment: Optional[str] = None children: List['VariableInfo'] = field(default_factory=list) is_udt_expanded_member: bool = False - current_element_values: Optional[Dict[str, str]] = None + current_element_values: Optional[Dict[str, str]] = None + element_type: str = "SIMPLE_VAR" # New field with default value @dataclass class UdtInfo: @@ -147,9 +148,9 @@ class S7Parser: S7Parser._adjust_children_offsets(child.children, 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: + 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 = lines[idx_to_process].strip() @@ -166,9 +167,9 @@ class S7Parser: is_nested_end_struct = self.end_struct_regex.match(line_to_parse) and not is_top_level_struct_in_block is_main_block_end_struct = self.end_struct_regex.match(line_to_parse) and is_top_level_struct_in_block is_block_terminator = 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)) + (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)) if is_nested_end_struct: active_context.align_to_byte() @@ -191,6 +192,17 @@ class S7Parser: data_type=clean_data_type, byte_offset=0, size_in_bytes=0, udt_source_name=udt_source_name_val) + + # Set element_type based on what we know about the variable + if var_data['arraydims']: + var_info.element_type = "ARRAY" + elif clean_data_type.upper() == "STRUCT": + var_info.element_type = "STRUCT" + elif udt_source_name_val: + var_info.element_type = "UDT_INSTANCE" + else: + var_info.element_type = "SIMPLE_VAR" + if var_data.get('initval'): var_info.initial_value = var_data['initval'].strip() if line_comment: var_info.comment = line_comment num_array_elements = 1 @@ -245,10 +257,10 @@ class S7Parser: var_info.children.append(expanded_member) parent_members_list.append(var_info) elif line_to_parse and \ - not self.struct_start_regex.match(line_to_parse) and \ - not is_main_block_end_struct and \ - not is_nested_end_struct and \ - not is_block_terminator : + not self.struct_start_regex.match(line_to_parse) and \ + not is_main_block_end_struct and \ + not is_nested_end_struct and \ + not is_block_terminator : print(f"DEBUG (_parse_struct_members): Line not parsed: Original='{original_line_text}' | Processed='{line_to_parse}'") return idx_to_process @@ -635,71 +647,84 @@ def calculate_array_element_offset(var: VariableInfo, indices_str: str) -> float def flatten_db_structure(db_info: Dict[str, Any]) -> List[Dict[str, Any]]: """ - Función genérica que aplana completamente una estructura de DB/UDT, - expandiendo todas las variables anidadas, UDTs y elementos de array. - Garantiza ordenamiento estricto por offset (byte.bit). + Function that completely flattens a DB/UDT structure, + expanding all nested variables, UDTs, and array elements. + Ensures strict ordering by offset (byte.bit). Returns: - List[Dict]: Lista de variables aplanadas con todos sus atributos - y un path completo, ordenada por offset estricto. + List[Dict]: Flattened list of variables with all attributes + and a complete path, strictly ordered by offset. """ flat_variables = [] - processed_ids = set() # Para evitar duplicados + processed_ids = set() # To avoid duplicates def process_variable(var: Dict[str, Any], path_prefix: str = "", is_expansion: bool = False): - # Identificador único para esta variable en este contexto + # Unique identifier for this variable in this context var_id = f"{path_prefix}{var['name']}_{var['byte_offset']}" - # Evitar procesar duplicados (como miembros expandidos de UDTs) + # Avoid processing duplicates (like expanded UDT members) if is_expansion and var_id in processed_ids: return if is_expansion: processed_ids.add(var_id) - # Crear copia de la variable con path completo + # Create copy of the variable with complete path flat_var = var.copy() flat_var["full_path"] = f"{path_prefix}{var['name']}" - flat_var["is_array_element"] = False # Por defecto no es elemento de array + flat_var["is_array_element"] = False # Default is not an array element - # Determinar si es array con valores específicos + # Preserve or infer element_type + if "element_type" not in flat_var: + # Infer type for backward compatibility + if var.get("array_dimensions"): + flat_var["element_type"] = "ARRAY" + elif var.get("children") and var["data_type"].upper() == "STRUCT": + flat_var["element_type"] = "STRUCT" + elif var.get("udt_source_name"): + flat_var["element_type"] = "UDT_INSTANCE" + else: + flat_var["element_type"] = "SIMPLE_VAR" + + # Determine if it's an array with specific values is_array = bool(var.get("array_dimensions")) has_array_values = is_array and var.get("current_element_values") - # Si no es un array con valores específicos, agregar la variable base + # If not an array with specific values, add the base variable if not has_array_values: - # Asegurarse de que el offset esté en el formato correcto + # Ensure the offset is in the correct format flat_var["address_display"] = format_address_for_display(var["byte_offset"], var.get("bit_size", 0)) flat_variables.append(flat_var) - # Si es array con valores específicos, expandir cada elemento como variable individual + # If it's an array with specific values, expand each element as individual variable if has_array_values: for idx, element_data in var.get("current_element_values", {}).items(): - # Extraer valor y offset del elemento + # Extract value and offset of the element if isinstance(element_data, dict) and "value" in element_data and "offset" in element_data: - # Nuevo formato con offset calculado + # New format with calculated offset value = element_data["value"] element_offset = element_data["offset"] else: - # Compatibilidad con formato antiguo + # Compatibility with old format value = element_data - element_offset = var["byte_offset"] # Offset base + element_offset = var["byte_offset"] # Base offset - # Crear una entrada por cada elemento del array + # Create an entry for each array element array_element = var.copy() array_element["full_path"] = f"{path_prefix}{var['name']}[{idx}]" array_element["is_array_element"] = True array_element["array_index"] = idx array_element["current_value"] = value - array_element["byte_offset"] = element_offset # Usar offset calculado + array_element["byte_offset"] = element_offset # Use calculated offset array_element["address_display"] = format_address_for_display(element_offset, var.get("bit_size", 0)) + array_element["element_type"] = "ARRAY_ELEMENT" - # Eliminar current_element_values para evitar redundancia + # Remove current_element_values to avoid redundancy if "current_element_values" in array_element: del array_element["current_element_values"] flat_variables.append(array_element) - # Procesar recursivamente todos los hijos + # Process all children recursively if var.get("children"): for child in var.get("children", []): process_variable( @@ -708,11 +733,11 @@ def flatten_db_structure(db_info: Dict[str, Any]) -> List[Dict[str, Any]]: is_expansion=bool(var.get("udt_source_name")) ) - # Procesar todos los miembros desde el nivel superior + # Process all members from the top level for member in db_info.get("members", []): process_variable(member) - # Ordenar estrictamente por offset byte.bit + # Sort strictly by offset byte.bit flat_variables.sort(key=lambda x: ( int(x["byte_offset"]), int(round((x["byte_offset"] - int(x["byte_offset"])) * 10)) diff --git a/backend/script_groups/S7_DB_Utils/x6.py b/backend/script_groups/S7_DB_Utils/x6.py index 8e6cccd..ac5f43f 100644 --- a/backend/script_groups/S7_DB_Utils/x6.py +++ b/backend/script_groups/S7_DB_Utils/x6.py @@ -147,8 +147,9 @@ def main(): if data_from_json.get("dbs"): for db_to_document in data_from_json["dbs"]: - excel_output_filename = os.path.join(documentation_dir, f"{current_json_filename}_{db_to_document['name'].replace('"', '')}.xlsx") - + ## excel_output_filename = os.path.join(documentation_dir, f"{current_json_filename}_{db_to_document['name'].replace('"', '')}.xlsx") + excel_output_filename = os.path.join(documentation_dir, f"{current_json_filename}.xlsx") + print(f"Generando documentación Excel para DB: '{db_to_document['name']}' (desde {current_json_filename}) -> {excel_output_filename}") try: generate_excel_table(db_to_document, excel_output_filename) diff --git a/backend/script_groups/S7_DB_Utils/x7_value_updater.py b/backend/script_groups/S7_DB_Utils/x7_value_updater.py index 1b7c465..42d8767 100644 --- a/backend/script_groups/S7_DB_Utils/x7_value_updater.py +++ b/backend/script_groups/S7_DB_Utils/x7_value_updater.py @@ -132,174 +132,6 @@ def compare_structures_by_offset(data_vars: List[Dict], format_vars: List[Dict]) return len(issues) == 0, issues -def create_updated_json(data_json: Dict, format_json: Dict) -> Dict: - """ - Crea JSON actualizado basado en la estructura de _format con valores de _data. - Utiliza offset como clave principal para encontrar variables correspondientes. - Reporta errores si no se encuentra un offset correspondiente. - """ - # Copia profunda de format_json para no modificar el original - updated_json = copy.deepcopy(format_json) - - # Procesar cada DB - for db_idx, format_db in enumerate(format_json.get("dbs", [])): - # Buscar el DB correspondiente en data_json - data_db = next((db for db in data_json.get("dbs", []) if db["name"] == format_db["name"]), None) - if not data_db: - print(f"Error: No se encontró DB '{format_db['name']}' en data_json") - continue # No hay DB correspondiente en data_json - - # Aplanar variables de ambos DBs - flat_data_vars = flatten_db_structure(data_db) - flat_format_vars = flatten_db_structure(format_db) - - # Crear mapa de offset a variable para data - data_by_offset = {var["byte_offset"]: var for var in flat_data_vars} - - # Para cada variable en format, buscar su correspondiente en data por offset - for format_var in flat_format_vars: - offset = format_var["byte_offset"] - path = format_var["full_path"] - - # Buscar la variable correspondiente en data_json por offset - if offset in data_by_offset: - data_var = data_by_offset[offset] - - # Encontrar la variable original en la estructura jerárquica - path_parts = format_var["full_path"].split('.') - current_node = updated_json["dbs"][db_idx] - - # Variable para rastrear si se encontró la ruta - path_found = True - - # Navegar la jerarquía hasta encontrar el nodo padre - for i in range(len(path_parts) - 1): - if "members" in current_node: - # Buscar el miembro correspondiente - member_name = path_parts[i] - matching_members = [m for m in current_node["members"] if m["name"] == member_name] - if matching_members: - current_node = matching_members[0] - else: - print(f"Error: No se encontró el miembro '{member_name}' en la ruta '{path}'") - path_found = False - break # No se encontró la ruta - elif "children" in current_node: - # Buscar el hijo correspondiente - child_name = path_parts[i] - matching_children = [c for c in current_node["children"] if c["name"] == child_name] - if matching_children: - current_node = matching_children[0] - else: - print(f"Error: No se encontró el hijo '{child_name}' en la ruta '{path}'") - path_found = False - break # No se encontró la ruta - else: - print(f"Error: No se puede navegar más en la ruta '{path}', nodo actual no tiene members ni children") - path_found = False - break # No se puede navegar más - - # Si encontramos el nodo padre, actualizar el hijo - if path_found and ("members" in current_node or "children" in current_node): - target_list = current_node.get("members", current_node.get("children", [])) - target_name = path_parts[-1] - - # Si es un elemento de array, extraer el nombre base y el índice - if '[' in target_name and ']' in target_name: - base_name = target_name.split('[')[0] - index_str = target_name[target_name.find('[')+1:target_name.find(']')] - - # Buscar el array base - array_var = next((var for var in target_list if var["name"] == base_name), None) - if array_var: - # Asegurarse que existe current_element_values - if "current_element_values" not in array_var: - array_var["current_element_values"] = {} - - # Copiar el valor del elemento del array - if "current_value" in data_var: - array_var["current_element_values"][index_str] = { - "value": data_var["current_value"], - "offset": data_var["byte_offset"] - } - else: - # Buscar la variable a actualizar - target_var_found = False - for target_var in target_list: - if target_var["name"] == target_name: - target_var_found = True - - # Limpiar y copiar initial_value si existe - if "initial_value" in target_var: - del target_var["initial_value"] - if "initial_value" in data_var and data_var["initial_value"] is not None: - target_var["initial_value"] = data_var["initial_value"] - - # Limpiar y copiar current_value si existe - if "current_value" in target_var: - del target_var["current_value"] - if "current_value" in data_var and data_var["current_value"] is not None: - target_var["current_value"] = data_var["current_value"] - - # Limpiar y copiar current_element_values si existe - if "current_element_values" in target_var: - del target_var["current_element_values"] - if "current_element_values" in data_var and data_var["current_element_values"]: - target_var["current_element_values"] = copy.deepcopy(data_var["current_element_values"]) - - break - - if not target_var_found and not ('[' in target_name and ']' in target_name): - print(f"Error: No se encontró la variable '{target_name}' en la ruta '{path}'") - else: - # El offset no existe en data_json, reportar error - print(f"Error: Offset {offset} (para '{path}') no encontrado en los datos source (_data)") - - # Eliminar valores si es una variable que no es elemento de array - if '[' not in path or ']' not in path: - # Encontrar la variable original en la estructura jerárquica - path_parts = path.split('.') - current_node = updated_json["dbs"][db_idx] - - # Navegar hasta el nodo padre para limpiar valores - path_found = True - for i in range(len(path_parts) - 1): - if "members" in current_node: - member_name = path_parts[i] - matching_members = [m for m in current_node["members"] if m["name"] == member_name] - if matching_members: - current_node = matching_members[0] - else: - path_found = False - break - elif "children" in current_node: - child_name = path_parts[i] - matching_children = [c for c in current_node["children"] if c["name"] == child_name] - if matching_children: - current_node = matching_children[0] - else: - path_found = False - break - else: - path_found = False - break - - if path_found and ("members" in current_node or "children" in current_node): - target_list = current_node.get("members", current_node.get("children", [])) - target_name = path_parts[-1] - - for target_var in target_list: - if target_var["name"] == target_name: - # Eliminar valores iniciales y actuales - if "initial_value" in target_var: - del target_var["initial_value"] - if "current_value" in target_var: - del target_var["current_value"] - if "current_element_values" in target_var: - del target_var["current_element_values"] - break - - return updated_json def process_updated_json(updated_json: Dict, updated_json_path: str, working_dir: str, documentation_dir: str, original_format_file: str): """ @@ -347,230 +179,451 @@ def process_updated_json(updated_json: Dict, updated_json_path: str, working_dir except Exception as e: print(f"Error al generar archivo S7 para {base_name}: {e}") + +def create_updated_json(data_json: Dict, format_json: Dict) -> Dict: + """ + Creates an updated JSON based on the structure of _format with values from _data. + Uses offset as the primary key for finding corresponding variables. + Reports errors if a corresponding offset is not found. + """ + # Deep copy of format_json to avoid modifying the original + updated_json = copy.deepcopy(format_json) + + # Process each DB + for db_idx, format_db in enumerate(format_json.get("dbs", [])): + # Find corresponding DB in data_json + data_db = next((db for db in data_json.get("dbs", []) if db["name"] == format_db["name"]), None) + if not data_db: + print(f"Error: DB '{format_db['name']}' not found in data_json") + continue # No corresponding DB in data_json + + # Flatten variables from both DBs + flat_data_vars = flatten_db_structure(data_db) + flat_format_vars = flatten_db_structure(format_db) + + # Create offset to variable map for data - ONLY include usable variables (SIMPLE_VAR and ARRAY_ELEMENT) + # This is the key fix: filter by element_type to avoid matching STRUCT and other non-value types + data_by_offset = { + var["byte_offset"]: var for var in flat_data_vars + if var.get("element_type") in ["SIMPLE_VAR", "ARRAY_ELEMENT"] + } + + # For each variable in format, find its corresponding in data by offset + for format_var in flat_format_vars: + # Only process variables and array elements, not structures or UDT instances + if format_var.get("element_type") not in ["SIMPLE_VAR", "ARRAY_ELEMENT"]: + continue + + offset = format_var["byte_offset"] + path = format_var["full_path"] + + # Find the corresponding variable in data_json by offset + if offset in data_by_offset: + data_var = data_by_offset[offset] + + # Even though we've filtered the data variables, double-check element types + format_element_type = format_var.get("element_type") + data_element_type = data_var.get("element_type") + + # Only copy values if element types are compatible + if format_element_type == data_element_type or ( + format_element_type in ["SIMPLE_VAR", "ARRAY_ELEMENT"] and + data_element_type in ["SIMPLE_VAR", "ARRAY_ELEMENT"] + ): + # Find the original variable in the hierarchical structure + path_parts = format_var["full_path"].split('.') + current_node = updated_json["dbs"][db_idx] + + # Variable to track if the path was found + path_found = True + + # Navigate the hierarchy to find the parent node + for i in range(len(path_parts) - 1): + if "members" in current_node: + # Find the corresponding member + member_name = path_parts[i] + matching_members = [m for m in current_node["members"] if m["name"] == member_name] + if matching_members: + current_node = matching_members[0] + else: + print(f"Error: Member '{member_name}' not found in path '{path}'") + path_found = False + break # Path not found + elif "children" in current_node: + # Find the corresponding child + child_name = path_parts[i] + matching_children = [c for c in current_node["children"] if c["name"] == child_name] + if matching_children: + current_node = matching_children[0] + else: + print(f"Error: Child '{child_name}' not found in path '{path}'") + path_found = False + break # Path not found + else: + print(f"Error: Cannot navigate further in path '{path}', current node has no members or children") + path_found = False + break # Cannot navigate further + + # If parent node found, update the child + if path_found and ("members" in current_node or "children" in current_node): + target_list = current_node.get("members", current_node.get("children", [])) + target_name = path_parts[-1] + + # If it's an array element, extract the base name and index + if '[' in target_name and ']' in target_name: + base_name = target_name.split('[')[0] + index_str = target_name[target_name.find('[')+1:target_name.find(']')] + + # Find the base array + array_var = next((var for var in target_list if var["name"] == base_name), None) + if array_var: + # Ensure current_element_values exists + if "current_element_values" not in array_var: + array_var["current_element_values"] = {} + + # Copy the array element value + if "current_value" in data_var: + array_var["current_element_values"][index_str] = { + "value": data_var["current_value"], + "offset": data_var["byte_offset"] + } + else: + # Find the variable to update + target_var_found = False + for target_var in target_list: + if target_var["name"] == target_name: + target_var_found = True + + # Clean and copy initial_value if exists + if "initial_value" in target_var: + del target_var["initial_value"] + if "initial_value" in data_var and data_var["initial_value"] is not None: + target_var["initial_value"] = data_var["initial_value"] + + # Clean and copy current_value if exists + if "current_value" in target_var: + del target_var["current_value"] + if "current_value" in data_var and data_var["current_value"] is not None: + target_var["current_value"] = data_var["current_value"] + + # Clean and copy current_element_values if exists + if "current_element_values" in target_var: + del target_var["current_element_values"] + if "current_element_values" in data_var and data_var["current_element_values"]: + target_var["current_element_values"] = copy.deepcopy(data_var["current_element_values"]) + + break + + if not target_var_found and not ('[' in target_name and ']' in target_name): + print(f"Error: Variable '{target_name}' not found in path '{path}'") + else: + print(f"Warning: Element types don't match at offset {offset} for '{path}': {format_element_type} vs {data_element_type}") + else: + # Offset not found in data_json, report error + print(f"Error: Offset {offset} (for '{path}') not found in source data (_data)") + + # Clear values if it's not an array element + if '[' not in path or ']' not in path: + # Find the original variable in the hierarchical structure + path_parts = path.split('.') + current_node = updated_json["dbs"][db_idx] + + # Navigate to the parent node to clean values + path_found = True + for i in range(len(path_parts) - 1): + if "members" in current_node: + member_name = path_parts[i] + matching_members = [m for m in current_node["members"] if m["name"] == member_name] + if matching_members: + current_node = matching_members[0] + else: + path_found = False + break + elif "children" in current_node: + child_name = path_parts[i] + matching_children = [c for c in current_node["children"] if c["name"] == child_name] + if matching_children: + current_node = matching_children[0] + else: + path_found = False + break + else: + path_found = False + break + + if path_found and ("members" in current_node or "children" in current_node): + target_list = current_node.get("members", current_node.get("children", [])) + target_name = path_parts[-1] + + for target_var in target_list: + if target_var["name"] == target_name: + # Remove initial and current values + if "initial_value" in target_var: + del target_var["initial_value"] + if "current_value" in target_var: + del target_var["current_value"] + if "current_element_values" in target_var: + del target_var["current_element_values"] + break + + return updated_json + def generate_comparison_excel(format_json: Dict, data_json: Dict, updated_json: Dict, excel_filename: str): """ - Genera un archivo Excel con dos hojas que comparan los valores iniciales y actuales - entre los archivos format_json, data_json y updated_json. - Filtra STRUCTs y solo compara variables con valores reales. + Generates a comprehensive Excel file comparing values between format, data and updated JSONs. + Uses flatten_db_structure and matches by offset, leveraging element_type for better filtering. Args: - format_json: JSON con la estructura y nombres de formato - data_json: JSON con los datos source - updated_json: JSON con los datos actualizados - excel_filename: Ruta del archivo Excel a generar + format_json: JSON with the structure and names from format + data_json: JSON with the source data + updated_json: JSON with the updated data + excel_filename: Path to the Excel file to generate """ import openpyxl from openpyxl.utils import get_column_letter - from openpyxl.styles import PatternFill, Font + from openpyxl.styles import PatternFill, Font, Alignment, Border, Side - # Crear un nuevo libro de Excel + # Create a new Excel workbook workbook = openpyxl.Workbook() + sheet = workbook.active + sheet.title = "Value_Comparison" - # Definir estilos para resaltar diferencias - diff_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") # Amarillo + # Define styles + diff_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") + type_mismatch_fill = PatternFill(start_color="FF9999", end_color="FF9999", fill_type="solid") # Light red header_font = Font(bold=True) + header_fill = PatternFill(start_color="DDDDDD", end_color="DDDDDD", fill_type="solid") + thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), + top=Side(style='thin'), bottom=Side(style='thin')) - # Procesar cada DB + # Set up headers + headers = ["Address", "Name", "Type", "Element Type", + "Format Initial", "Data Initial", "Updated Initial", + "Format Current", "Data Current", "Updated Current", + "Type Match", "Value Differences"] + + for col_num, header in enumerate(headers, 1): + cell = sheet.cell(row=1, column=col_num, value=header) + cell.font = header_font + cell.fill = header_fill + cell.border = thin_border + cell.alignment = Alignment(horizontal='center') + + # Freeze top row + sheet.freeze_panes = "A2" + + current_row = 2 + + # Process each DB for db_idx, format_db in enumerate(format_json.get("dbs", [])): - # Buscar los DBs correspondientes db_name = format_db["name"] data_db = next((db for db in data_json.get("dbs", []) if db["name"] == db_name), None) updated_db = next((db for db in updated_json.get("dbs", []) if db["name"] == db_name), None) if not data_db or not updated_db: - print(f"Error: No se encontró el DB '{db_name}' en alguno de los archivos JSON") + print(f"Error: DB '{db_name}' not found in one of the JSON files") continue - # Crear hojas para valores iniciales y actuales para este DB - initial_sheet = workbook.active if db_idx == 0 else workbook.create_sheet() - initial_sheet.title = f"{db_name}_Initial"[:31] # Limitar longitud del nombre de hoja + # Add DB name as section header with merged cells + sheet.merge_cells(f'A{current_row}:L{current_row}') + header_cell = sheet.cell(row=current_row, column=1, value=f"DB: {db_name}") + header_cell.font = Font(bold=True, size=12) + header_cell.fill = PatternFill(start_color="CCCCFF", end_color="CCCCFF", fill_type="solid") # Light blue + header_cell.alignment = Alignment(horizontal='center') + current_row += 1 - current_sheet = workbook.create_sheet() - current_sheet.title = f"{db_name}_Current"[:31] - - # Aplanar variables de los tres DBs + # Get flattened variables from all sources flat_format_vars = flatten_db_structure(format_db) flat_data_vars = flatten_db_structure(data_db) flat_updated_vars = flatten_db_structure(updated_db) - # Filtrar STRUCTs - solo trabajamos con variables que tienen valores reales - flat_format_vars = [var for var in flat_format_vars - if var["data_type"].upper() != "STRUCT" and not var.get("children")] - - # Crear mapas de offset a variable para búsqueda rápida - data_by_offset = {var["byte_offset"]: var for var in flat_data_vars - if var["data_type"].upper() != "STRUCT" and not var.get("children")} - updated_by_offset = {var["byte_offset"]: var for var in flat_updated_vars - if var["data_type"].upper() != "STRUCT" and not var.get("children")} - - # Configurar encabezados para la hoja de valores iniciales - headers_initial = ["Address", "Name", "Type", "Format Initial", "Data Initial", "Updated Initial", "Difference"] - for col_num, header in enumerate(headers_initial, 1): - cell = initial_sheet.cell(row=1, column=col_num, value=header) - cell.font = header_font - - # Configurar encabezados para la hoja de valores actuales - headers_current = ["Address", "Name", "Type", "Format Current", "Data Current", "Updated Current", "Difference"] - for col_num, header in enumerate(headers_current, 1): - cell = current_sheet.cell(row=1, column=col_num, value=header) - cell.font = header_font - - # Llenar las hojas con datos - initial_row = 2 - current_row = 2 + # Create maps by offset for quick lookup + data_by_offset = {var["byte_offset"]: var for var in flat_data_vars} + updated_by_offset = {var["byte_offset"]: var for var in flat_updated_vars} + # Process each variable from format_json for format_var in flat_format_vars: + # Skip certain types based on element_type + element_type = format_var.get("element_type", "UNKNOWN") + + # Skip STRUCT types with no values, but include ARRAY and UDT_INSTANCE types + if element_type == "STRUCT" and not format_var.get("children"): + continue + offset = format_var["byte_offset"] path = format_var["full_path"] data_type = format_data_type_for_source(format_var) address = format_var.get("address_display", format_address_for_display(offset, format_var.get("bit_size", 0))) - # Obtener variables correspondientes por offset + # Find corresponding variables by offset data_var = data_by_offset.get(offset) updated_var = updated_by_offset.get(offset) - # Procesar valores iniciales (solo si la variable puede tener initial_value) - format_initial = format_var.get("initial_value", "") - data_initial = data_var.get("initial_value", "") if data_var else "" - updated_initial = updated_var.get("initial_value", "") if updated_var else "" + # Compare element types + data_element_type = data_var.get("element_type", "MISSING") if data_var else "MISSING" + updated_element_type = updated_var.get("element_type", "MISSING") if updated_var else "MISSING" - # Solo incluir en la hoja de valores iniciales si al menos uno tiene valor inicial - if format_initial or data_initial or updated_initial: - # Determinar si hay diferencias en valores iniciales - has_initial_diff = (format_initial != data_initial or - format_initial != updated_initial or - data_initial != updated_initial) - - # Escribir datos de valores iniciales - initial_sheet.cell(row=initial_row, column=1, value=address) - initial_sheet.cell(row=initial_row, column=2, value=path) - initial_sheet.cell(row=initial_row, column=3, value=data_type) - initial_sheet.cell(row=initial_row, column=4, value=str(format_initial)) - initial_sheet.cell(row=initial_row, column=5, value=str(data_initial)) - initial_sheet.cell(row=initial_row, column=6, value=str(updated_initial)) - - # Resaltar diferencias en valores iniciales - if has_initial_diff: - initial_sheet.cell(row=initial_row, column=7, value="Sí") - for col in range(4, 7): - initial_sheet.cell(row=initial_row, column=col).fill = diff_fill + # Determine type compatibility + type_match = "Yes" + if data_var and element_type != data_element_type: + # Check for compatible types + if (element_type in ["SIMPLE_VAR", "ARRAY_ELEMENT"] and + data_element_type in ["SIMPLE_VAR", "ARRAY_ELEMENT"]): + type_match = "Compatible" else: - initial_sheet.cell(row=initial_row, column=7, value="No") - - initial_row += 1 + type_match = "No" + elif not data_var: + type_match = "Missing" - # Procesar valores actuales - format_current = format_var.get("current_value", "") - data_current = data_var.get("current_value", "") if data_var else "" - updated_current = updated_var.get("current_value", "") if updated_var else "" + # Get values (with empty string defaults) + format_initial = str(format_var.get("initial_value", "")) + data_initial = str(data_var.get("initial_value", "")) if data_var else "" + updated_initial = str(updated_var.get("initial_value", "")) if updated_var else "" - # Solo incluir en la hoja de valores actuales si al menos uno tiene valor actual - if format_current or data_current or updated_current: - # Determinar si hay diferencias en valores actuales - has_current_diff = (format_current != data_current or - format_current != updated_current or - data_current != updated_current) - - # Escribir datos de valores actuales - current_sheet.cell(row=current_row, column=1, value=address) - current_sheet.cell(row=current_row, column=2, value=path) - current_sheet.cell(row=current_row, column=3, value=data_type) - current_sheet.cell(row=current_row, column=4, value=str(format_current)) - current_sheet.cell(row=current_row, column=5, value=str(data_current)) - current_sheet.cell(row=current_row, column=6, value=str(updated_current)) - - # Resaltar diferencias en valores actuales - if has_current_diff: - current_sheet.cell(row=current_row, column=7, value="Sí") - for col in range(4, 7): - current_sheet.cell(row=current_row, column=col).fill = diff_fill - else: - current_sheet.cell(row=current_row, column=7, value="No") - - current_row += 1 + format_current = str(format_var.get("current_value", "")) + data_current = str(data_var.get("current_value", "")) if data_var else "" + updated_current = str(updated_var.get("current_value", "")) if updated_var else "" - # Si es un array, procesamos también sus elementos - if format_var.get("current_element_values") or (data_var and data_var.get("current_element_values")) or (updated_var and updated_var.get("current_element_values")): - format_elements = format_var.get("current_element_values", {}) - data_elements = data_var.get("current_element_values", {}) if data_var else {} - updated_elements = updated_var.get("current_element_values", {}) if updated_var else {} - - # Unir todos los índices disponibles - all_indices = set(list(format_elements.keys()) + - list(data_elements.keys()) + - list(updated_elements.keys())) - - # Ordenar índices numéricamente - sorted_indices = sorted(all_indices, key=lambda x: [int(i) for i in x.split(',')]) if all_indices else [] - - for idx in sorted_indices: - elem_path = f"{path}[{idx}]" - - # Valores actuales para elementos de array - format_elem_val = "" - if idx in format_elements: - if isinstance(format_elements[idx], dict) and "value" in format_elements[idx]: - format_elem_val = format_elements[idx]["value"] - else: - format_elem_val = format_elements[idx] - - data_elem_val = "" - if idx in data_elements: - if isinstance(data_elements[idx], dict) and "value" in data_elements[idx]: - data_elem_val = data_elements[idx]["value"] - else: - data_elem_val = data_elements[idx] - - updated_elem_val = "" - if idx in updated_elements: - if isinstance(updated_elements[idx], dict) and "value" in updated_elements[idx]: - updated_elem_val = updated_elements[idx]["value"] - else: - updated_elem_val = updated_elements[idx] - - # Determinar si hay diferencias - has_elem_diff = (str(format_elem_val) != str(data_elem_val) or - str(format_elem_val) != str(updated_elem_val) or - str(data_elem_val) != str(updated_elem_val)) - - # Escribir datos de elementos de array (solo en hoja de valores actuales) - current_sheet.cell(row=current_row, column=1, value=address) - current_sheet.cell(row=current_row, column=2, value=elem_path) - current_sheet.cell(row=current_row, column=3, value=data_type.replace("ARRAY", "").strip()) - current_sheet.cell(row=current_row, column=4, value=str(format_elem_val)) - current_sheet.cell(row=current_row, column=5, value=str(data_elem_val)) - current_sheet.cell(row=current_row, column=6, value=str(updated_elem_val)) - - # Resaltar diferencias - if has_elem_diff: - current_sheet.cell(row=current_row, column=7, value="Sí") - for col in range(4, 7): - current_sheet.cell(row=current_row, column=col).fill = diff_fill - else: - current_sheet.cell(row=current_row, column=7, value="No") - - current_row += 1 - - # Auto-ajustar anchos de columna - for sheet in [initial_sheet, current_sheet]: - for col_idx, column_cells in enumerate(sheet.columns, 1): - max_length = 0 - column = get_column_letter(col_idx) - for cell in column_cells: - try: - if len(str(cell.value)) > max_length: - max_length = len(str(cell.value)) - except: - pass - adjusted_width = min(max_length + 2, 100) # Limitar ancho máximo - sheet.column_dimensions[column].width = adjusted_width + # Check for differences + has_initial_diff = (format_initial != data_initial or + format_initial != updated_initial or + data_initial != updated_initial) + + has_current_diff = (format_current != data_current or + format_current != updated_current or + data_current != updated_current) + + # Create detailed difference description + diff_desc = [] + if has_initial_diff: + diff_desc.append("Initial values differ") + if has_current_diff: + diff_desc.append("Current values differ") + if not diff_desc: + diff_desc.append("None") + + # Write data + sheet.cell(row=current_row, column=1, value=address) + sheet.cell(row=current_row, column=2, value=path) + sheet.cell(row=current_row, column=3, value=data_type) + sheet.cell(row=current_row, column=4, value=element_type) + sheet.cell(row=current_row, column=5, value=format_initial) + sheet.cell(row=current_row, column=6, value=data_initial) + sheet.cell(row=current_row, column=7, value=updated_initial) + sheet.cell(row=current_row, column=8, value=format_current) + sheet.cell(row=current_row, column=9, value=data_current) + sheet.cell(row=current_row, column=10, value=updated_current) + sheet.cell(row=current_row, column=11, value=type_match) + sheet.cell(row=current_row, column=12, value=", ".join(diff_desc)) + + # Add borders to all cells + for col in range(1, 13): + sheet.cell(row=current_row, column=col).border = thin_border + + # Highlight differences + if has_initial_diff: + for col in range(5, 8): + sheet.cell(row=current_row, column=col).fill = diff_fill + + if has_current_diff: + for col in range(8, 11): + sheet.cell(row=current_row, column=col).fill = diff_fill + + # Highlight type mismatches + if type_match == "No" or type_match == "Missing": + sheet.cell(row=current_row, column=11).fill = type_mismatch_fill + + current_row += 1 + + # Add filter to headers + sheet.auto_filter.ref = f"A1:L{current_row-1}" + + # Auto-adjust column widths + for col_idx, column_cells in enumerate(sheet.columns, 1): + max_length = 0 + column = get_column_letter(col_idx) + for cell in column_cells: + try: + if len(str(cell.value)) > max_length: + max_length = len(str(cell.value)) + except: + pass + adjusted_width = min(max_length + 2, 100) # Limit maximum width + sheet.column_dimensions[column].width = adjusted_width + + # Add a summary sheet + summary_sheet = workbook.create_sheet(title="Summary") + summary_sheet.column_dimensions['A'].width = 30 + summary_sheet.column_dimensions['B'].width = 15 + summary_sheet.column_dimensions['C'].width = 50 + + # Add header to summary + summary_headers = ["Database", "Item Count", "Notes"] + for col_num, header in enumerate(summary_headers, 1): + cell = summary_sheet.cell(row=1, column=col_num, value=header) + cell.font = header_font + cell.fill = header_fill + + # Add summary data + summary_row = 2 + for db_idx, format_db in enumerate(format_json.get("dbs", [])): + db_name = format_db["name"] + data_db = next((db for db in data_json.get("dbs", []) if db["name"] == db_name), None) + updated_db = next((db for db in updated_json.get("dbs", []) if db["name"] == db_name), None) + + if not data_db or not updated_db: + continue + + flat_format_vars = flatten_db_structure(format_db) + flat_data_vars = flatten_db_structure(data_db) + + # Count by element type + format_type_counts = {} + for var in flat_format_vars: + element_type = var.get("element_type", "UNKNOWN") + format_type_counts[element_type] = format_type_counts.get(element_type, 0) + 1 + + # Count value differences + data_by_offset = {var["byte_offset"]: var for var in flat_data_vars} + diff_count = 0 + type_mismatch_count = 0 + + for format_var in flat_format_vars: + offset = format_var["byte_offset"] + data_var = data_by_offset.get(offset) + + if data_var: + # Check for type mismatch + if format_var.get("element_type") != data_var.get("element_type"): + type_mismatch_count += 1 + + # Check for value differences + format_initial = str(format_var.get("initial_value", "")) + data_initial = str(data_var.get("initial_value", "")) + format_current = str(format_var.get("current_value", "")) + data_current = str(data_var.get("current_value", "")) + + if format_initial != data_initial or format_current != data_current: + diff_count += 1 + + # Write to summary + summary_sheet.cell(row=summary_row, column=1, value=db_name) + summary_sheet.cell(row=summary_row, column=2, value=len(flat_format_vars)) + + notes = [] + for element_type, count in format_type_counts.items(): + notes.append(f"{element_type}: {count}") + notes.append(f"Value differences: {diff_count}") + notes.append(f"Type mismatches: {type_mismatch_count}") + + summary_sheet.cell(row=summary_row, column=3, value=", ".join(notes)) + summary_row += 1 - # Guardar el archivo Excel try: workbook.save(excel_filename) - print(f"Archivo de comparación Excel generado: {excel_filename}") + print(f"Comparison Excel file generated: {excel_filename}") except Exception as e: - print(f"Error al escribir el archivo Excel {excel_filename}: {e}") + print(f"Error writing Excel file {excel_filename}: {e}") def main(): working_dir = find_working_directory() diff --git a/data/log.txt b/data/log.txt index af5532f..b17e88f 100644 --- a/data/log.txt +++ b/data/log.txt @@ -1,21 +1,21 @@ -[02:56:24] Iniciando ejecución de x7_value_updater.py en C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001... -[02:56:24] Using working directory: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 -[02:56:24] Los archivos JSON se guardarán en: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\json -[02:56:24] Los archivos de documentación se guardarán en: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation -[02:56:24] Se encontraron 1 pares de archivos para procesar. -[02:56:24] --- Procesando par de archivos --- -[02:56:24] Data file: db1001_data.db -[02:56:24] Format file: db1001_format.db -[02:56:24] Parseando archivo data: db1001_data.db -[02:56:24] Parseando archivo format: db1001_format.db -[02:56:24] Archivos JSON generados: db1001_data.json y db1001_format.json -[02:56:24] Comparando estructuras para DB 'HMI_Blender_Parameters': 284 variables en _data, 284 variables en _format -[02:56:24] Los archivos son compatibles. Creando el archivo _updated... -[02:56:24] Archivo _updated generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\json\db1001_updated.json -[02:56:25] Archivo de comparación Excel generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_comparison.xlsx -[02:56:25] Archivo Markdown generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.md -[02:56:25] Archivo S7 generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.txt -[02:56:25] Archivo S7 copiado a: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_updated.db -[02:56:25] --- Proceso completado --- -[02:56:25] Ejecución de x7_value_updater.py finalizada (success). Duración: 0:00:00.761362. -[02:56:25] Log completo guardado en: D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\log_x7_value_updater.txt +[13:21:37] Iniciando ejecución de x7_value_updater.py en C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001... +[13:21:37] Using working directory: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001 +[13:21:37] Los archivos JSON se guardarán en: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\json +[13:21:37] Los archivos de documentación se guardarán en: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation +[13:21:37] Se encontraron 1 pares de archivos para procesar. +[13:21:37] --- Procesando par de archivos --- +[13:21:37] Data file: db1001_data.db +[13:21:37] Format file: db1001_format.db +[13:21:37] Parseando archivo data: db1001_data.db +[13:21:37] Parseando archivo format: db1001_format.db +[13:21:37] Archivos JSON generados: db1001_data.json y db1001_format.json +[13:21:37] Comparando estructuras para DB 'HMI_Blender_Parameters': 284 variables en _data, 284 variables en _format +[13:21:37] Los archivos son compatibles. Creando el archivo _updated... +[13:21:37] Archivo _updated generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\json\db1001_updated.json +[13:21:38] Comparison Excel file generated: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_comparison.xlsx +[13:21:38] Archivo Markdown generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.md +[13:21:38] Archivo S7 generado: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\documentation\db1001_updated.txt +[13:21:38] Archivo S7 copiado a: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\DB1001\db1001_updated.db +[13:21:38] --- Proceso completado --- +[13:21:38] Ejecución de x7_value_updater.py finalizada (success). Duración: 0:00:01.043746. +[13:21:38] Log completo guardado en: D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\S7_DB_Utils\log_x7_value_updater.txt