Se actualizaron los archivos de configuración JSON para reflejar nuevos parámetros de directorios de exportación, incluyendo "aml_exp_directory" y "resultados_exp_directory". Además, se realizaron mejoras en el script `x1_export_CAx.py`, optimizando la gestión de directorios de salida y la detección de archivos de proyecto TIA. Se ajustaron los mensajes de depuración y se mejoró la estructura del código para mayor claridad.
This commit is contained in:
parent
2297e217c7
commit
c8141deb63
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
alwaysApply: true
|
||||
---
|
||||
Puedes usar .doc\MemoriaDeEvolucion.md para obtener un contexto de las ultimas modificaciones y conceptos sobre este proyecto. Quisiera que con los conocimientos importantes y desiciones importantes adquiridas en cada modificacion los agregues a MemoriaDeEvolucion.md manteniendo el estilo que ya tenemos de texto simple sin demasiado codigo y una semantica resumida.
|
|
@ -0,0 +1,69 @@
|
|||
Definiciones de Frontend en .doc\backend_setup.md
|
||||
|
||||
|
||||
### Flujo de trabajo:
|
||||
|
||||
Se usa [x1] para exportar los datos de configuración desde el proyecto de Tia Portal, incluidos los IO configurados en el hardware. Esto genera un archivo AML.
|
||||
Con [x2] se procesa el archivo AML y se convierte en markdown. Si hay un solo PLC se genera el archivo [Hardware.md]. **Además genera un archivo Excel con los IOs por nodos del PLC.**
|
||||
3. Se deben procesar los IO **desde el esquema eléctrico y agregarlos** a [Hardware.md].
|
||||
Se debe exportar todos los tags como un archivo excel desde el Tia Portal.
|
||||
Con [x3] se convierte y se filtran los tags según los path definidos en [io_paths_config] y se genera un archivo "Master IO Tags.md".
|
||||
[x4] Genera el prompt a usar con Claude usando MCP para que pueda acceder a los archivos originales y evitar tener que hacer uploads.
|
||||
Una vez que se genera el archivo procesado por el LLM se puede usar
|
||||
[x5] que convierte las adaptaciones a un archivo que luego se puede importar en Tia Portal
|
||||
8. Importar en Tia Portal el archivo [PLCTags_Updated.xlsx]
|
||||
|
||||
**Nuevo flujo alternativo con Excel:**
|
||||
|
||||
Después del paso 2, se puede usar :
|
||||
[x7] para: Modificar manualmente el archivo Excel de IOs generado- Aplicar los cambios de vuelta al archivo AML original Generar un AML actualizado con las modificaciones
|
||||
|
||||
### Cambios recientes:
|
||||
|
||||
**Automatización de selección de proyecto TIA Portal (x1_export_CAx.py):**
|
||||
- Eliminada la interfaz gráfica tkinter para selección manual de archivos
|
||||
- El script ahora lee automáticamente la ruta del proyecto desde la configuración `siemens_tia_project` en work_dir.json
|
||||
- Nueva función `find_project_file_in_dir()` que busca automáticamente archivos .ap18/.ap19/.ap20 en el directorio configurado
|
||||
- Validación automática que verifica que exista exactamente un archivo de proyecto en el directorio especificado
|
||||
- Mejora en la experiencia de usuario al eliminar pasos manuales de selección de archivos
|
||||
|
||||
**Directorio de exportación CAx configurable (x1_export_CAx.py):**
|
||||
- La ruta de exportación de archivos CAx ahora es configurable.
|
||||
- El script utiliza el valor `aml_exp_directory` de la configuración `level2` en `work_dir.json`.
|
||||
- La nueva ruta de salida se construye como `working_directory` / `aml_exp_directory`.
|
||||
- Todos los archivos generados (AML, Markdown y log) se guardan en este directorio, manteniendo los artefactos de exportación organizados.
|
||||
|
||||
**Directorio de E/S configurable para el procesamiento CAx (x2_process_CAx.py):**
|
||||
- El script ahora utiliza el directorio `aml_exp_directory` de `work_dir.json` para la entrada y salida de archivos.
|
||||
- Se ha unificado el comportamiento con `x1_export_CAx.py`, esperando el archivo AML de entrada en `working_directory` / `aml_exp_directory`.
|
||||
- Todos los archivos generados (JSON, Markdown, Excel) se guardan en este mismo directorio, manteniendo la consistencia del flujo de trabajo.
|
||||
- Se mantiene el fallback al directorio `.debug` para la ejecución independiente del script.
|
||||
|
||||
**Selección automática de archivo AML (x2_process_CAx.py):**
|
||||
- El script ahora busca automáticamente un único archivo `.aml` en el directorio `aml_exp_directory`.
|
||||
- Si se encuentra un solo archivo, se utiliza directamente, eliminando la necesidad del diálogo de selección manual.
|
||||
- Si se encuentran cero o múltiples archivos `.aml`, el script recurre al diálogo de selección manual para que el usuario resuelva la ambigüedad.
|
||||
- Esta mejora agiliza el flujo de trabajo al automatizar la selección de archivos en el caso más común.
|
||||
|
||||
**Directorio de resultados configurable (x1 y x2):**
|
||||
- Se ha agregado el parámetro `resultados_exp_directory` a la configuración `level2` en `work_dir.json`.
|
||||
- `x1_export_CAx.py` ahora guarda la tabla de resumen (`*CAx_Summary.md`) en el subdirectorio `working_directory` / `resultados_exp_directory`.
|
||||
- `x2_process_CAx.py` guarda todos los archivos de resultados finales (tablas Markdown y reportes Excel) en `working_directory` / `resultados_exp_directory`, anidados en carpetas por PLC.
|
||||
- Los archivos intermedios (JSON, logs, debug files) permanecen en `aml_exp_directory`, separando los artefactos de compilación de los resultados finales.
|
||||
|
||||
**Corrección de errores de exportación en TIA Portal (x1_export_CAx.py):**
|
||||
- Se ha solucionado un error que ocurría cuando el archivo AML a exportar ya existía. El script ahora elimina los archivos `.aml` y `.log` existentes antes de la exportación para permitir la sobrescritura.
|
||||
- Se ha corregido el manejo de excepciones al eliminar un bloque `except` que intentaba capturar una excepción inexistente (`TiaException`), lo que causaba un error secundario y ocultaba el problema original.
|
||||
|
||||
**Flujo de trabajo de E/S con Excel mejorado (x3_excel_to_md.py):**
|
||||
- **Directorios configurables**: El script ahora utiliza `tags_exp_directory` (de `level3`) para buscar archivos Excel y `resultados_exp_directory` (de `level2`) para guardar el archivo Markdown resultante. Ambos se leen desde `work_dir.json`.
|
||||
- **Selección automática de archivo**: Si solo existe un archivo `.xlsx` en `tags_exp_directory`, el script lo utiliza automáticamente, eliminando la necesidad de selección manual.
|
||||
- **Fallback a diálogo manual**: Si se encuentran cero o múltiples archivos Excel, el script muestra un diálogo para que el usuario seleccione el archivo correcto, manteniendo la flexibilidad.
|
||||
- **Consistencia del proyecto**: Esta actualización alinea el comportamiento de `x3_excel_to_md.py` con los scripts `x1` y `x2`, creando un flujo de trabajo más coherente y automatizado.
|
||||
|
||||
**Configuración dinámica de rutas en el generador de prompts (x4_prompt_generator.py):**
|
||||
- Las rutas de los archivos de entrada (`Master IO Tags.md` y `Hardware.md`) ahora se construyen dinámicamente utilizando `resultados_exp_directory` de la configuración `level2`, alineándose con el resto de los scripts.
|
||||
- La configuración de las rutas base de Obsidian (`ObsideanDir`, `ObsideanProjectsBase`) se ha movido al `level3` para una mejor organización de la configuración.
|
||||
- El prompt generado refleja automáticamente estas rutas configurables, asegurando que las herramientas de IA siempre utilicen las ubicaciones correctas de los archivos.
|
||||
|
||||
|
|
@ -0,0 +1,410 @@
|
|||
# Guía de Configuración para Scripts Backend
|
||||
|
||||
## Introducción
|
||||
|
||||
Esta guía explica cómo usar la función `load_configuration()` para cargar parámetros desde un archivo `script_config.json` en los scripts del backend.
|
||||
|
||||
## 1. Configuración del Script
|
||||
|
||||
Para que tus scripts puedan encontrar los módulos del proyecto, necesitas añadir el directorio raíz al path de Python.
|
||||
|
||||
### Path Setup e Importación
|
||||
|
||||
Coloca este código al inicio de tu script:
|
||||
|
||||
```python
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Añadir el directorio raíz al sys.path
|
||||
# El número de `os.path.dirname()` depende de la profundidad del script.
|
||||
# Para /backend/script_groups/grupo/script.py, son 4.
|
||||
script_root = os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
)
|
||||
sys.path.append(script_root)
|
||||
|
||||
# Importar la función
|
||||
from backend.script_utils import load_configuration
|
||||
```
|
||||
|
||||
## 2. Cargar la Configuración
|
||||
|
||||
La función `load_configuration()` busca y carga un archivo llamado `script_config.json` que debe estar en el **mismo directorio** que el script que la ejecuta. Devuelve un diccionario con todo el contenido del JSON.
|
||||
|
||||
### Ejemplo de Uso
|
||||
|
||||
```python
|
||||
def main():
|
||||
# Cargar configuraciones del archivo script_config.json
|
||||
configs = load_configuration()
|
||||
|
||||
# Es buena práctica verificar si la configuración se cargó
|
||||
if not configs:
|
||||
print("Error: No se pudo cargar la configuración. Saliendo.")
|
||||
return
|
||||
|
||||
# Acceder a los parámetros usando .get() para evitar errores
|
||||
working_directory = configs.get("working_directory", "")
|
||||
level1_config = configs.get("level1", {})
|
||||
level2_config = configs.get("level2", {})
|
||||
level3_config = configs.get("level3", {})
|
||||
|
||||
# Ejemplo de uso de un parámetro específico con valor por defecto
|
||||
scl_output_dir = level2_config.get("scl_output_dir", "scl_output")
|
||||
xref_output_dir = level2_config.get("xref_output_dir", "xref_output")
|
||||
|
||||
print(f"Directorio de trabajo: {working_directory}")
|
||||
print(f"Directorio de salida SCL: {scl_output_dir}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
## 3. Archivo `script_config.json`
|
||||
|
||||
Este archivo contiene los parámetros de tu script. La estructura interna del JSON, como el uso de `"level1"`, `"level2"`, etc., es una convención para organizar los parámetros. `load_configuration()` simplemente lee el archivo y devuelve su contenido.
|
||||
|
||||
**Ejemplo de `script_config.json`:**
|
||||
```json
|
||||
{
|
||||
"working_directory": "/ruta/al/directorio/de/trabajo",
|
||||
"level1": {
|
||||
"parametro_global_1": "valor1"
|
||||
},
|
||||
"level2": {
|
||||
"scl_output_dir": "scl_output",
|
||||
"xref_output_dir": "xref_output"
|
||||
},
|
||||
"level3": {
|
||||
"parametro_especifico_1": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Manejo de Errores
|
||||
|
||||
`load_configuration()` está diseñada para ser robusta:
|
||||
- Si `script_config.json` no se encuentra, retorna un diccionario vacío `{}`.
|
||||
- Si el JSON es inválido, imprime un error y también retorna `{}`.
|
||||
|
||||
**Siempre** comprueba si el diccionario devuelto está vacío para manejar estos casos de forma segura en tu script.
|
||||
|
||||
## 5. Jerarquía de Archivos de Configuración
|
||||
|
||||
El sistema utiliza un modelo de configuración en cascada para gestionar los parámetros de los scripts. Esta jerarquía permite establecer configuraciones a nivel global, de grupo y de trabajo. Antes de la ejecución, el launcher lee estos archivos, los combina y genera un único `script_config.json` en la carpeta del script. La función `load_configuration()` es la que finalmente lee este archivo consolidado.
|
||||
|
||||
A continuación se describe la finalidad y ubicación de cada archivo clave.
|
||||
|
||||
### Archivos de Valores (Parámetros)
|
||||
|
||||
Contienen los datos y variables que utilizará el script. La configuración se superpone en el siguiente orden: `Nivel 1 < Nivel 2 < Nivel 3`.
|
||||
|
||||
- **`data.json` (Nivel 1 - Global)**
|
||||
- **Ubicación:** `data/data.json`
|
||||
- **Utilidad:** Almacena variables globales disponibles para todos los scripts. Ideal para parámetros generales.
|
||||
- **Acceso:** Sus datos se cargan en la clave `"level1"` del diccionario `configs`.
|
||||
|
||||
- **`script_config.json` (Nivel 2 - Grupo)**
|
||||
- **Ubicación:** En la raíz de cada directorio de grupo (ej: `backend/script_groups/MiGrupo/script_config.json`).
|
||||
- **Utilidad:** Define parámetros compartidos por todos los scripts de un grupo.
|
||||
- **Acceso:** Sus datos se cargan en la clave `"level2"`.
|
||||
|
||||
- **`work_dir.json` (Nivel 3 - Directorio de Trabajo)**
|
||||
- **Ubicación:** Dentro del directorio de trabajo que el script va a procesar.
|
||||
- **Utilidad:** Contiene parámetros para una ejecución específica. Es el nivel más específico y sobrescribe los anteriores.
|
||||
- **Acceso:** Sus datos se cargan en la clave `"level3"`.
|
||||
|
||||
### Archivos de Esquema (Definiciones de Estructura)
|
||||
|
||||
No contienen valores, sino que describen la estructura y tipos de datos que los archivos de valores deben tener. Son usados por el launcher para validación y para generar interfaces de configuración.
|
||||
|
||||
- **`esquema_group.json`**
|
||||
- **Ubicación:** Raíz del directorio del grupo.
|
||||
- **Utilidad:** Define la estructura del `script_config.json` del grupo.
|
||||
|
||||
- **`esquema_work.json`**
|
||||
- **Ubicación:** Raíz del directorio del grupo.
|
||||
- **Utilidad:** Define la estructura del `work_dir.json`.
|
||||
|
||||
## 6. Documentación de Scripts para el Launcher
|
||||
|
||||
El sistema de launcher utiliza archivos JSON para mostrar información sobre los grupos de scripts y scripts individuales en la interfaz web.
|
||||
|
||||
### Archivo description.json (Descripción del Grupo)
|
||||
|
||||
Ubicación: En el directorio raíz del grupo de scripts.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Nombre del Grupo",
|
||||
"description": "Descripción del propósito y funcionalidad del grupo",
|
||||
"version": "1.0",
|
||||
"author": "Nombre del Autor"
|
||||
}
|
||||
```
|
||||
|
||||
### Archivo scripts_description.json (Descripción de Scripts)
|
||||
|
||||
Ubicación: En el directorio raíz del grupo de scripts.
|
||||
|
||||
```json
|
||||
{
|
||||
"nombre_script.py": {
|
||||
"display_name": "Nombre para mostrar en la UI",
|
||||
"short_description": "Descripción breve del script",
|
||||
"long_description": "Descripción detallada con explicación completa de funcionalidad, pasos que ejecuta, y contexto de uso",
|
||||
"hidden": false
|
||||
},
|
||||
"script_interno.py": {
|
||||
"display_name": "Script Interno",
|
||||
"short_description": "Script de uso interno",
|
||||
"long_description": "",
|
||||
"hidden": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Propiedades Importantes
|
||||
|
||||
- **hidden**: `true` oculta el script del launcher (útil para scripts auxiliares)
|
||||
- **display_name**: Nombre amigable que aparece en la interfaz
|
||||
- **short_description**: Se muestra en la lista de scripts
|
||||
- **long_description**: Se muestra al expandir detalles del script
|
||||
|
||||
### Ejemplo Práctico
|
||||
|
||||
Para un grupo "XML Parser to SCL":
|
||||
|
||||
**description.json:**
|
||||
```json
|
||||
{
|
||||
"name": "Siemens-Tia : 03 : Procesador de XML LAD-SCL-AWL",
|
||||
"description": "Scripts que procesan archivos XML exportados de TIA, convirtiendo LAD a SCL",
|
||||
"version": "1.0",
|
||||
"author": "Miguel"
|
||||
}
|
||||
```
|
||||
|
||||
**scripts_description.json:**
|
||||
```json
|
||||
{
|
||||
"x0_main.py": {
|
||||
"display_name": "1: Procesar Exportación XML completa",
|
||||
"short_description": "Conversor principal de LAD/FUP XML a SCL",
|
||||
"long_description": "Script orquestador que procesa todos los archivos XML...",
|
||||
"hidden": false
|
||||
},
|
||||
"x1_to_json.py": {
|
||||
"display_name": "x1_to_json",
|
||||
"short_description": "Converter XML interno",
|
||||
"long_description": "",
|
||||
"hidden": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7. Requisitos de Codificación de Salida (stdout)
|
||||
|
||||
Toda la salida estándar (`stdout`) generada por los scripts (por ejemplo, mediante la función `print()`) es capturada en tiempo real y mostrada en el panel de logs del frontend.
|
||||
|
||||
Para garantizar que el texto se muestre correctamente y evitar caracteres corruptos (mojibake), **la salida de los scripts debe tener codificación UTF-8**.
|
||||
|
||||
### Configuración Automática
|
||||
|
||||
El sistema está diseñado para facilitar esto. Al ejecutar un script, el entorno se configura automáticamente para que la salida de Python sea UTF-8. Específicamente, se establece la variable de entorno `PYTHONIOENCODING=utf-8`.
|
||||
|
||||
Gracias a esto, en la mayoría de los casos, **no necesitas hacer nada especial**. Simplemente usa `print()` y la codificación será la correcta.
|
||||
|
||||
### Casos Especiales y Solución de Problemas
|
||||
|
||||
Pueden surgir problemas si tu script lee datos de fuentes externas (como archivos) que tienen una codificación diferente. Si imprimes contenido directamente sin decodificarlo primero, podrías enviar bytes no válidos a la salida.
|
||||
|
||||
La regla es: **decodifica los datos de entrada a un string de Python lo antes posible, y deja que `print()` se encargue de la codificación de salida.**
|
||||
|
||||
**Ejemplo de cómo manejar un archivo con codificación `latin-1`:**
|
||||
|
||||
```python
|
||||
# INCORRECTO: Si el archivo no es UTF-8, esto puede enviar bytes inválidos.
|
||||
# El launcher intentará decodificarlos como UTF-8 y podría fallar o mostrar basura.
|
||||
try:
|
||||
with open('mi_archivo_legacy.txt', 'rb') as f:
|
||||
print(f.read())
|
||||
except Exception as e:
|
||||
print(f"Esto probablemente falle o muestre texto corrupto: {e}")
|
||||
|
||||
|
||||
# CORRECTO: Leer el archivo especificando su codificación para decodificarlo a un string.
|
||||
# Una vez que es un string de Python, `print` lo manejará correctamente.
|
||||
try:
|
||||
with open('mi_archivo_legacy.txt', 'r', encoding='latin-1') as f:
|
||||
contenido = f.read()
|
||||
# Ahora `contenido` es un string de Python.
|
||||
# print() lo codificará a UTF-8 automáticamente gracias a la configuración del entorno.
|
||||
print(contenido)
|
||||
except FileNotFoundError:
|
||||
print("El archivo 'mi_archivo_legacy.txt' no fue encontrado para el ejemplo.")
|
||||
except Exception as e:
|
||||
print(f"Error al procesar el archivo: {e}")
|
||||
```
|
||||
|
||||
## 8. Uso de Servicios Compartidos
|
||||
|
||||
El proyecto ofrece una serie de servicios reutilizables en el directorio `services/` para tareas comunes como la manipulación de archivos Excel, detección de idioma o traducción.
|
||||
|
||||
Para utilizar estos servicios en tu script, asegúrate de que el directorio raíz del proyecto esté en el `sys.path`, como se explica en la sección 1 de esta guía.
|
||||
|
||||
### 8.1 Servicio de Excel (`ExcelService`)
|
||||
|
||||
El `ExcelService` (`services/excel/excel_service.py`) facilita la lectura y escritura de archivos Excel, con manejo de reintentos (por si el archivo está abierto) y opciones de formato.
|
||||
|
||||
**Ejemplo de importación y uso:**
|
||||
|
||||
```python
|
||||
# Asegúrate de tener el path raíz configurado
|
||||
# ... (código de configuración de sys.path)
|
||||
|
||||
from services.excel.excel_service import ExcelService
|
||||
|
||||
def main():
|
||||
excel_service = ExcelService()
|
||||
|
||||
# Leer un archivo Excel
|
||||
try:
|
||||
df = excel_service.read_excel("mi_archivo_de_entrada.xlsx")
|
||||
print("Datos cargados exitosamente.")
|
||||
|
||||
# ... procesar el DataFrame ...
|
||||
|
||||
# Guardar el DataFrame con formato personalizado
|
||||
format_options = {
|
||||
'freeze_row': 2,
|
||||
'header_color': 'E6E6E6'
|
||||
}
|
||||
|
||||
excel_service.save_excel(
|
||||
df,
|
||||
"mi_archivo_de_salida.xlsx",
|
||||
sheet_name="Resultados",
|
||||
format_options=format_options
|
||||
)
|
||||
print("Archivo guardado con éxito.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Ocurrió un error al manejar el archivo Excel: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
### 8.2 Servicios de Lenguaje
|
||||
|
||||
Los servicios de lenguaje (`services/language/`) permiten detectar el idioma de un texto.
|
||||
|
||||
**Ejemplo de importación y uso:**
|
||||
|
||||
```python
|
||||
# Asegúrate de tener el path raíz configurado
|
||||
# ... (código de configuración de sys.path)
|
||||
|
||||
from services.language.language_factory import LanguageFactory
|
||||
from services.language.language_utils import LanguageUtils
|
||||
|
||||
def main():
|
||||
# Crear el servicio de detección de idioma
|
||||
allowed_languages = LanguageUtils.get_available_languages()
|
||||
detector = LanguageFactory.create_service("langid", allowed_languages=allowed_languages)
|
||||
|
||||
# Detectar idioma de un texto
|
||||
text = "Este es un texto de ejemplo en español."
|
||||
lang, confidence = detector.detect_language(text)
|
||||
|
||||
print(f"Texto: '{text}'")
|
||||
print(f"Idioma detectado: {LanguageUtils.get_language_name(lang)} (código: {lang})")
|
||||
print(f"Confianza: {confidence:.2f}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
### 8.3 Servicios de LLM (Modelos de Lenguaje Grandes)
|
||||
|
||||
El proyecto integra una fábrica de servicios (`LLMFactory`) para interactuar con diferentes Modelos de Lenguaje Grandes (LLMs). Esto permite a los scripts aprovechar la IA generativa para tareas como el análisis de código, la generación de descripciones semánticas, etc.
|
||||
|
||||
#### 8.3.1 Configuración de API Keys
|
||||
|
||||
La mayoría de los servicios de LLM requieren una clave de API para funcionar. El sistema gestiona esto de forma centralizada a través de variables de entorno.
|
||||
|
||||
1. **Crear el archivo `.env`**: En el **directorio raíz del proyecto**, crea un archivo llamado `.env` (si aún no existe).
|
||||
|
||||
2. **Añadir las API Keys**: Abre el archivo `.env` y añade las claves para los servicios que planeas utilizar. El sistema cargará estas variables automáticamente al inicio.
|
||||
|
||||
```env
|
||||
# Ejemplo de contenido para el archivo .env
|
||||
# (Solo necesitas añadir las claves de los servicios que vayas a usar)
|
||||
|
||||
OPENAI_API_KEY="sk-..."
|
||||
GROQ_API_KEY="gsk_..."
|
||||
CLAUDE_API_KEY="sk-ant-..."
|
||||
GEMINI_API_KEY="AIzaSy..."
|
||||
GROK_API_KEY="TU_API_KEY_DE_GROK"
|
||||
```
|
||||
|
||||
**Nota**: El servicio `ollama` se ejecuta localmente y no requiere una clave de API.
|
||||
|
||||
#### 8.3.2 Ejemplo de importación y uso
|
||||
|
||||
El siguiente ejemplo muestra cómo un script puede cargar su configuración, inicializar un servicio de LLM y usarlo para generar texto. Este patrón es similar al utilizado en `x3_generate_semantic_descriptions.py`.
|
||||
|
||||
```python
|
||||
# Asegúrate de tener el path raíz configurado
|
||||
# ... (código de configuración de sys.path)
|
||||
|
||||
from services.llm.llm_factory import LLMFactory
|
||||
from backend.script_utils import load_configuration
|
||||
|
||||
def main():
|
||||
# Cargar la configuración del script, que puede incluir qué LLM usar
|
||||
configs = load_configuration()
|
||||
llm_configs = configs.get("llm", {})
|
||||
|
||||
# Obtener el tipo de servicio y otros parámetros del config
|
||||
# Por defecto, usamos 'groq' si no se especifica
|
||||
service_type = llm_configs.get("service", "groq")
|
||||
|
||||
print(f"🤖 Inicializando servicio LLM: {service_type}")
|
||||
|
||||
# Crear una instancia del servicio usando la fábrica
|
||||
# La fábrica se encarga de pasar las API keys desde las variables de entorno
|
||||
llm_service = LLMFactory.create_service(service_type, **llm_configs)
|
||||
|
||||
if not llm_service:
|
||||
print(f"❌ Error: No se pudo crear el servicio LLM '{service_type}'. Abortando.")
|
||||
return
|
||||
|
||||
# Usar el servicio para generar texto
|
||||
try:
|
||||
prompt = "Explica la computación cuántica en una sola frase."
|
||||
print(f"Enviando prompt: '{prompt}'")
|
||||
|
||||
description = llm_service.generate_text(prompt)
|
||||
|
||||
print("\nRespuesta del LLM:")
|
||||
print(description)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Ocurrió un error al contactar al servicio LLM: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
#### 8.3.3 Servicios Disponibles
|
||||
|
||||
La `LLMFactory` soporta los siguientes tipos de servicio (`service_type`):
|
||||
- `openai`
|
||||
- `groq`
|
||||
- `claude`
|
||||
- `gemini`
|
||||
- `grok`
|
||||
- `ollama` (para ejecución local)
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"ObsideanDir": "C:\\Users\\migue\\OneDrive\\Miguel\\Obsidean\\Trabajo\\VM",
|
||||
"ObsideanProjectsBase": "\\04-SIDEL"
|
||||
"aml_exp_directory": "aml",
|
||||
"resultados_exp_directory": "Resultados"
|
||||
}
|
|
@ -1,18 +1,17 @@
|
|||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ObsideanDir": {
|
||||
"aml_exp_directory": {
|
||||
"type": "string",
|
||||
"title": "Directorio de Vault de Obsidean",
|
||||
"description": "Directorio de Vault de Obsidean",
|
||||
"format": "directory",
|
||||
"default": "C:\\Users\\migue\\OneDrive\\Miguel\\Obsidean\\Trabajo\\VM"
|
||||
"title": "Directorio de exportación AML",
|
||||
"description": "",
|
||||
"default": "aml"
|
||||
},
|
||||
"ObsideanProjectsBase": {
|
||||
"resultados_exp_directory": {
|
||||
"type": "string",
|
||||
"title": "Subdirectorio",
|
||||
"description": "Subdirectorio de los proyectos actuales en el Vault de Obsidean",
|
||||
"default": "\\04-SIDEL"
|
||||
"title": "Subdirectorio donde se colocan las tablas",
|
||||
"description": "Subdirectorio donde se colocan las tablas",
|
||||
"default": "Resultados"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,17 +7,30 @@
|
|||
"description": "",
|
||||
"format": "directory"
|
||||
},
|
||||
"siemens_tia_project": {
|
||||
"type": "string",
|
||||
"title": "Proyecto Tia Portal",
|
||||
"description": "Donde esta el archivo *.ap18 - *.ap19 - *.ap20",
|
||||
"format": "directory"
|
||||
},
|
||||
"tags_exp_directory": {
|
||||
"type": "string",
|
||||
"title": "Directorio con el archivo Excel de Tags exportado de Tia",
|
||||
"description": "",
|
||||
"format": "directory"
|
||||
},
|
||||
"siemens_tia_project": {
|
||||
"ObsideanDir": {
|
||||
"type": "string",
|
||||
"title": "Proyecto Tia Portal",
|
||||
"description": "Donde esta el archivo *.ap18 - *.ap19 - *.ap20",
|
||||
"format": "directory"
|
||||
"title": "Directorio de Vault de Obsidean",
|
||||
"description": "Directorio de Vault de Obsidean",
|
||||
"format": "directory",
|
||||
"default": "C:\\Users\\migue\\OneDrive\\Miguel\\Obsidean\\Trabajo\\VM"
|
||||
},
|
||||
"ObsideanProjectsBase": {
|
||||
"type": "string",
|
||||
"title": "Subdirectorio",
|
||||
"description": "Subdirectorio de los proyectos actuales en el Vault de Obsidean",
|
||||
"default": "\\04-SIDEL"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,9 +4,15 @@
|
|||
"model": "gpt-3.5-turbo"
|
||||
},
|
||||
"level2": {
|
||||
"ObsideanDir": "C:\\Users\\migue\\OneDrive\\Miguel\\Obsidean\\Trabajo\\VM",
|
||||
"ObsideanProjectsBase": "\\04-SIDEL"
|
||||
"aml_exp_directory": "aml",
|
||||
"resultados_exp_directory": "Resultados"
|
||||
},
|
||||
"level3": {},
|
||||
"working_directory": "C:\\Trabajo\\SIDEL\\13 - E5.007560 - Modifica O&U - SAE235\\Reporte\\IOTags"
|
||||
"level3": {
|
||||
"ObsideanDir": "C:\\Users\\migue\\OneDrive\\Miguel\\Obsidean\\Trabajo\\VM",
|
||||
"ObsideanProjectsBase": "\\04-SIDEL",
|
||||
"siemens_exp_directory": "C:\\Trabajo\\SIDEL\\13 - E5.007560 - Modifica O&U - SAE235\\Reporte\\ExportTia",
|
||||
"siemens_tia_project": "C:/Trabajo/SIDEL/13 - E5.007560 - Modifica O&U - SAE235/InLavoro/PLC/SSAE0235/_NEW/SAE235_v0.4",
|
||||
"tags_exp_directory": "C:\\Trabajo\\SIDEL\\13 - E5.007560 - Modifica O&U - SAE235\\Reporte\\IOTags"
|
||||
},
|
||||
"working_directory": "C:\\Trabajo\\SIDEL\\13 - E5.007560 - Modifica O&U - SAE235\\Reporte\\Analisis\\Siemens"
|
||||
}
|
|
@ -2,8 +2,6 @@
|
|||
export_CAx_from_tia : Script que exporta los datos CAx de un proyecto de TIA Portal y genera un resumen en Markdown.
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
@ -18,11 +16,7 @@ from backend.script_utils import load_configuration
|
|||
|
||||
# --- Configuration ---
|
||||
# Supported TIA Portal versions mapping (extension -> version)
|
||||
SUPPORTED_TIA_VERSIONS = {
|
||||
".ap18": "18.0",
|
||||
".ap19": "19.0",
|
||||
".ap20": "20.0"
|
||||
}
|
||||
SUPPORTED_TIA_VERSIONS = {".ap18": "18.0", ".ap19": "19.0", ".ap20": "20.0"}
|
||||
|
||||
# --- TIA Scripting Import Handling ---
|
||||
# (Same import handling as the previous script)
|
||||
|
@ -45,18 +39,25 @@ except Exception as e:
|
|||
# --- Functions ---
|
||||
|
||||
|
||||
def get_supported_filetypes():
|
||||
"""Returns the supported file types for TIA Portal projects."""
|
||||
filetypes = []
|
||||
for ext, version in SUPPORTED_TIA_VERSIONS.items():
|
||||
version_major = version.split('.')[0]
|
||||
filetypes.append((f"TIA Portal V{version_major} Projects", f"*{ext}"))
|
||||
def find_project_file_in_dir(directory):
|
||||
"""Finds a TIA project file in the given directory."""
|
||||
project_files = []
|
||||
supported_extensions = SUPPORTED_TIA_VERSIONS.keys()
|
||||
for ext in supported_extensions:
|
||||
project_files.extend(list(Path(directory).glob(f"*{ext}")))
|
||||
|
||||
# Add option to show all supported files
|
||||
all_extensions = " ".join([f"*{ext}" for ext in SUPPORTED_TIA_VERSIONS.keys()])
|
||||
filetypes.insert(0, ("All TIA Portal Projects", all_extensions))
|
||||
|
||||
return filetypes
|
||||
if len(project_files) == 1:
|
||||
return project_files[0]
|
||||
elif len(project_files) == 0:
|
||||
print(f"ERROR: No TIA Portal project file found in {directory}.")
|
||||
print(f"Supported extensions: {list(supported_extensions)}")
|
||||
return None
|
||||
else:
|
||||
print(f"ERROR: Multiple TIA Portal project files found in {directory}:")
|
||||
for f in project_files:
|
||||
print(f" - {f}")
|
||||
print("Please ensure only one project file exists in the directory.")
|
||||
return None
|
||||
|
||||
|
||||
def detect_tia_version(project_file_path):
|
||||
|
@ -66,44 +67,19 @@ def detect_tia_version(project_file_path):
|
|||
|
||||
if file_extension in SUPPORTED_TIA_VERSIONS:
|
||||
detected_version = SUPPORTED_TIA_VERSIONS[file_extension]
|
||||
print(f"Detected TIA Portal version: {detected_version} (from extension {file_extension})")
|
||||
print(
|
||||
f"Detected TIA Portal version: {detected_version} (from extension {file_extension})"
|
||||
)
|
||||
return detected_version
|
||||
else:
|
||||
print(f"WARNING: Unrecognized file extension '{file_extension}'. Supported extensions: {list(SUPPORTED_TIA_VERSIONS.keys())}")
|
||||
print(
|
||||
f"WARNING: Unrecognized file extension '{file_extension}'. Supported extensions: {list(SUPPORTED_TIA_VERSIONS.keys())}"
|
||||
)
|
||||
# Default to version 18.0 for backward compatibility
|
||||
print("Defaulting to TIA Portal V18.0")
|
||||
return "18.0"
|
||||
|
||||
|
||||
def select_project_file():
|
||||
"""Opens a dialog to select a TIA Portal project file."""
|
||||
root = tk.Tk()
|
||||
root.withdraw()
|
||||
file_path = filedialog.askopenfilename(
|
||||
title="Select TIA Portal Project File",
|
||||
filetypes=get_supported_filetypes(),
|
||||
)
|
||||
root.destroy()
|
||||
if not file_path:
|
||||
print("No project file selected. Exiting.")
|
||||
sys.exit(0)
|
||||
return file_path
|
||||
|
||||
|
||||
def select_output_directory():
|
||||
"""Opens a dialog to select the output directory."""
|
||||
root = tk.Tk()
|
||||
root.withdraw()
|
||||
dir_path = filedialog.askdirectory(
|
||||
title="Select Output Directory for AML and MD files"
|
||||
)
|
||||
root.destroy()
|
||||
if not dir_path:
|
||||
print("No output directory selected. Exiting.")
|
||||
sys.exit(0)
|
||||
return dir_path
|
||||
|
||||
|
||||
def find_elements(element, path):
|
||||
"""Helper to find elements using namespaces commonly found in AML."""
|
||||
# AutomationML namespaces often vary slightly or might be default
|
||||
|
@ -253,7 +229,14 @@ def parse_aml_to_markdown(aml_file_path, md_file_path):
|
|||
|
||||
if __name__ == "__main__":
|
||||
configs = load_configuration()
|
||||
|
||||
# Get parameters from configuration file
|
||||
level3_configs = configs.get("level3", {})
|
||||
level2_configs = configs.get("level2", {})
|
||||
siemens_tia_project_dir = level3_configs.get("siemens_tia_project")
|
||||
working_directory = configs.get("working_directory")
|
||||
aml_exp_directory = level2_configs.get("aml_exp_directory")
|
||||
resultados_exp_directory = level2_configs.get("resultados_exp_directory")
|
||||
|
||||
print("--- TIA Portal Project CAx Exporter and Analyzer ---")
|
||||
|
||||
|
@ -263,14 +246,33 @@ if __name__ == "__main__":
|
|||
print("Please configure the working directory using the main application.")
|
||||
sys.exit(1)
|
||||
|
||||
# 1. Select Project File, Output Directory comes from config
|
||||
project_file = select_project_file()
|
||||
output_dir = Path(
|
||||
working_directory
|
||||
) # Use working directory from config, ensure it's a Path object
|
||||
if not aml_exp_directory:
|
||||
print("ERROR: aml_exp_directory not set in level2 configuration.")
|
||||
sys.exit(1)
|
||||
|
||||
if not resultados_exp_directory:
|
||||
print("ERROR: resultados_exp_directory not set in level2 configuration.")
|
||||
sys.exit(1)
|
||||
|
||||
# Validate TIA project directory from config
|
||||
if not siemens_tia_project_dir or not os.path.isdir(siemens_tia_project_dir):
|
||||
print("ERROR: TIA project directory is not configured or invalid.")
|
||||
print(
|
||||
'Please set the "siemens_tia_project" path in your configuration (work_dir.json).'
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
# 1. Find Project File in the configured directory
|
||||
project_file = find_project_file_in_dir(siemens_tia_project_dir)
|
||||
if not project_file:
|
||||
sys.exit(1) # Error message is printed inside the function
|
||||
|
||||
aml_output_dir = Path(working_directory) / aml_exp_directory
|
||||
md_output_dir = Path(working_directory) / resultados_exp_directory
|
||||
|
||||
print(f"\nSelected Project: {project_file}")
|
||||
print(f"Using Output Directory (Working Directory): {output_dir}")
|
||||
print(f"Using AML Output Directory: {aml_output_dir}")
|
||||
print(f"Using Results Output Directory: {md_output_dir}")
|
||||
|
||||
# 2. Detect TIA Portal version from project file
|
||||
tia_version = detect_tia_version(project_file)
|
||||
|
@ -278,10 +280,10 @@ if __name__ == "__main__":
|
|||
# Define output file names using Path object
|
||||
project_path = Path(project_file)
|
||||
project_base_name = project_path.stem # Get filename without extension
|
||||
aml_file = output_dir / f"{project_base_name}_CAx_Export.aml"
|
||||
md_file = output_dir / f"{project_base_name}_CAx_Summary.md"
|
||||
aml_file = aml_output_dir / f"{project_base_name}_CAx_Export.aml"
|
||||
md_file = md_output_dir / f"{project_base_name}_CAx_Summary.md"
|
||||
log_file = (
|
||||
output_dir / f"{project_base_name}_CAx_Export.log"
|
||||
aml_output_dir / f"{project_base_name}_CAx_Export.log"
|
||||
) # Log file for the export process
|
||||
|
||||
print(f"Will export CAx data to: {aml_file}")
|
||||
|
@ -317,8 +319,17 @@ if __name__ == "__main__":
|
|||
|
||||
# 5. Export CAx Data (Project Level)
|
||||
print(f"Exporting CAx data for the project to {aml_file}...")
|
||||
# Ensure output directory exists (Path.mkdir handles this implicitly if needed later, but good practice)
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
# Ensure output directories exist
|
||||
aml_output_dir.mkdir(parents=True, exist_ok=True)
|
||||
md_output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Delete existing files to allow overwrite by TIA Portal
|
||||
if aml_file.exists():
|
||||
print(f"Deleting existing AML file to allow overwrite: {aml_file}")
|
||||
aml_file.unlink()
|
||||
if log_file.exists():
|
||||
print(f"Deleting existing log file to allow overwrite: {log_file}")
|
||||
log_file.unlink()
|
||||
|
||||
# Pass paths as strings to the TIA function
|
||||
export_result = project_object.export_cax_data(
|
||||
|
@ -337,9 +348,6 @@ if __name__ == "__main__":
|
|||
f"# Error\n\nCAx data export failed. Check log file: {log_file}"
|
||||
)
|
||||
|
||||
except ts.TiaException as tia_ex:
|
||||
print(f"\nTIA Portal Openness Error: {tia_ex}")
|
||||
traceback.print_exc()
|
||||
except FileNotFoundError:
|
||||
print(f"\nERROR: Project file not found at {project_file}")
|
||||
except Exception as e:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -67,7 +67,7 @@ def load_path_config():
|
|||
# Si el archivo existe, cargarlo
|
||||
if os.path.exists(json_config_path):
|
||||
try:
|
||||
with open(json_config_path, 'r', encoding='utf-8') as f:
|
||||
with open(json_config_path, "r", encoding="utf-8") as f:
|
||||
config = json.load(f)
|
||||
print(f"Configuración de paths cargada desde: {json_config_path}")
|
||||
return config
|
||||
|
@ -81,33 +81,33 @@ def load_path_config():
|
|||
{
|
||||
"path": "Inputs",
|
||||
"type": "Input",
|
||||
"no_used_path": "IO Not in Hardware\\InputsMaster"
|
||||
"no_used_path": "IO Not in Hardware\\InputsMaster",
|
||||
},
|
||||
{
|
||||
"path": "Outputs",
|
||||
"type": "Output",
|
||||
"no_used_path": "IO Not in Hardware\\OutputsMaster"
|
||||
"no_used_path": "IO Not in Hardware\\OutputsMaster",
|
||||
},
|
||||
{
|
||||
"path": "OutputsFesto",
|
||||
"type": "Output",
|
||||
"no_used_path": "IO Not in Hardware\\OutputsMaster"
|
||||
"no_used_path": "IO Not in Hardware\\OutputsMaster",
|
||||
},
|
||||
{
|
||||
"path": "IO Not in Hardware\\InputsMaster",
|
||||
"type": "Input",
|
||||
"no_used_path": "IO Not in Hardware\\InputsMaster"
|
||||
"no_used_path": "IO Not in Hardware\\InputsMaster",
|
||||
},
|
||||
{
|
||||
"path": "IO Not in Hardware\\OutputsMaster",
|
||||
"type": "Output",
|
||||
"no_used_path": "IO Not in Hardware\\OutputsMaster"
|
||||
}
|
||||
"no_used_path": "IO Not in Hardware\\OutputsMaster",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
try:
|
||||
with open(json_config_path, 'w', encoding='utf-8') as f:
|
||||
with open(json_config_path, "w", encoding="utf-8") as f:
|
||||
json.dump(default_config, f, indent=2)
|
||||
print(f"Archivo de configuración creado: {json_config_path}")
|
||||
return default_config
|
||||
|
@ -118,19 +118,20 @@ def load_path_config():
|
|||
|
||||
def convert_excel_to_markdown_tables():
|
||||
"""
|
||||
Busca un archivo Excel en el working_directory o solicita al usuario seleccionarlo,
|
||||
filtra las entradas según los paths configurados en JSON,
|
||||
y genera un archivo Markdown con tablas.
|
||||
Busca un archivo Excel en el directorio configurado, lo procesa y genera
|
||||
un archivo Markdown con tablas filtradas en el directorio de resultados.
|
||||
"""
|
||||
try:
|
||||
configs = load_configuration()
|
||||
working_directory = configs.get("working_directory")
|
||||
if not working_directory:
|
||||
print("Error: 'working_directory' no se encontró en la configuración.")
|
||||
return
|
||||
if not os.path.isdir(working_directory):
|
||||
level2_configs = configs.get("level2", {})
|
||||
level3_configs = configs.get("level3", {})
|
||||
tags_exp_directory = level3_configs.get("tags_exp_directory", ".")
|
||||
resultados_exp_directory = level2_configs.get("resultados_exp_directory", ".")
|
||||
|
||||
if not working_directory or not os.path.isdir(working_directory):
|
||||
print(
|
||||
f"Error: El directorio de trabajo '{working_directory}' no existe o no es un directorio."
|
||||
f"Error: El directorio de trabajo '{working_directory}' no es válido."
|
||||
)
|
||||
return
|
||||
except Exception as e:
|
||||
|
@ -140,38 +141,48 @@ def convert_excel_to_markdown_tables():
|
|||
working_directory_abs = os.path.abspath(working_directory)
|
||||
print(f"Usando directorio de trabajo: {working_directory_abs}")
|
||||
|
||||
# Cargar la configuración de paths
|
||||
path_config = load_path_config()
|
||||
if not path_config:
|
||||
print("Error: No se pudo cargar la configuración de paths.")
|
||||
return
|
||||
|
||||
# Verificar si existe el archivo PLCTags.xlsx en el directorio de trabajo
|
||||
default_excel_path = os.path.join(working_directory_abs, "PLCTags.xlsx")
|
||||
tags_exp_dir_abs = os.path.join(working_directory_abs, tags_exp_directory)
|
||||
os.makedirs(tags_exp_dir_abs, exist_ok=True)
|
||||
print(f"Buscando archivos Excel en: {tags_exp_dir_abs}")
|
||||
|
||||
if os.path.exists(default_excel_path):
|
||||
excel_file_path = default_excel_path
|
||||
print(f"Usando archivo Excel predeterminado: {excel_file_path}")
|
||||
excel_files = [
|
||||
f for f in os.listdir(tags_exp_dir_abs) if f.lower().endswith(".xlsx")
|
||||
]
|
||||
excel_file_path = ""
|
||||
|
||||
if len(excel_files) == 1:
|
||||
excel_file_path = os.path.join(tags_exp_dir_abs, excel_files[0])
|
||||
print(f"Archivo Excel encontrado automáticamente: {excel_file_path}")
|
||||
else:
|
||||
# Solicitar al usuario que seleccione el archivo Excel
|
||||
root = tk.Tk()
|
||||
root.withdraw() # Ocultar ventana principal
|
||||
if len(excel_files) == 0:
|
||||
print(f"No se encontraron archivos Excel en '{tags_exp_dir_abs}'.")
|
||||
else:
|
||||
print(
|
||||
f"Se encontraron múltiples archivos Excel en '{tags_exp_dir_abs}'. Por favor seleccione uno."
|
||||
)
|
||||
|
||||
print("Archivo PLCTags.xlsx no encontrado. Seleccione el archivo Excel exportado de TIA Portal:")
|
||||
root = tk.Tk()
|
||||
root.withdraw()
|
||||
excel_file_path = filedialog.askopenfilename(
|
||||
title="Seleccione el archivo Excel exportado de TIA Portal",
|
||||
filetypes=[("Excel files", "*.xlsx"), ("All files", "*.*")],
|
||||
initialdir=working_directory_abs
|
||||
initialdir=tags_exp_dir_abs,
|
||||
)
|
||||
|
||||
if not excel_file_path:
|
||||
print("No se seleccionó ningún archivo Excel. Saliendo...")
|
||||
return
|
||||
|
||||
print(f"Procesando archivo Excel: {excel_file_path}...")
|
||||
|
||||
output_dir_abs = os.path.join(working_directory_abs, resultados_exp_directory)
|
||||
os.makedirs(output_dir_abs, exist_ok=True)
|
||||
output_md_filename = "Master IO Tags.md"
|
||||
output_md_filepath_abs = os.path.join(working_directory_abs, output_md_filename)
|
||||
output_md_filepath_abs = os.path.join(output_dir_abs, output_md_filename)
|
||||
|
||||
markdown_content = []
|
||||
|
||||
|
@ -207,9 +218,13 @@ def convert_excel_to_markdown_tables():
|
|||
excel_col_comment,
|
||||
]
|
||||
|
||||
missing_cols = [col for col in excel_required_cols if col not in excel_data.columns]
|
||||
missing_cols = [
|
||||
col for col in excel_required_cols if col not in excel_data.columns
|
||||
]
|
||||
if missing_cols:
|
||||
print(f"Error: Columnas faltantes en el archivo Excel: {', '.join(missing_cols)}")
|
||||
print(
|
||||
f"Error: Columnas faltantes en el archivo Excel: {', '.join(missing_cols)}"
|
||||
)
|
||||
return
|
||||
|
||||
# Organizar entradas por path y crear tablas para cada tipo
|
||||
|
@ -240,8 +255,12 @@ def convert_excel_to_markdown_tables():
|
|||
tag_type_for_md = io_type
|
||||
|
||||
master_tag_cell = f"{master_tag:<{col_widths['Master Tag']}.{col_widths['Master Tag']}}"
|
||||
type_cell = f"{tag_type_for_md:<{col_widths['Type']}.{col_widths['Type']}}"
|
||||
data_type_cell = f"{data_type:<{col_widths['Data Type']}.{col_widths['Data Type']}}"
|
||||
type_cell = (
|
||||
f"{tag_type_for_md:<{col_widths['Type']}.{col_widths['Type']}}"
|
||||
)
|
||||
data_type_cell = (
|
||||
f"{data_type:<{col_widths['Data Type']}.{col_widths['Data Type']}}"
|
||||
)
|
||||
description_cell = f"{description:<{col_widths['Description']}.{col_widths['Description']}}"
|
||||
|
||||
md_row = f"| {master_tag_cell} | {type_cell} | {data_type_cell} | {description_cell} |"
|
||||
|
@ -263,9 +282,7 @@ def convert_excel_to_markdown_tables():
|
|||
try:
|
||||
with open(output_md_filepath_abs, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(markdown_content))
|
||||
print(
|
||||
f"¡Éxito! Archivo Excel convertido a Markdown en: {output_md_filepath_abs}"
|
||||
)
|
||||
print(f"¡Éxito! Archivo Markdown generado en: {output_md_filepath_abs}")
|
||||
except IOError as e:
|
||||
print(
|
||||
f"Error al escribir el archivo Markdown '{output_md_filepath_abs}': {e}"
|
||||
|
|
|
@ -71,6 +71,14 @@ def generate_prompt():
|
|||
f"Error: El directorio de trabajo '{working_directory}' no existe o no es un directorio."
|
||||
)
|
||||
return False
|
||||
|
||||
group_config = configs.get("level2", {})
|
||||
resultados_exp_directory = group_config.get("resultados_exp_directory")
|
||||
if not resultados_exp_directory:
|
||||
print(
|
||||
"Error: 'resultados_exp_directory' no se encontró en la configuración de nivel 2."
|
||||
)
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Error al cargar la configuración: {e}")
|
||||
return False
|
||||
|
@ -85,8 +93,8 @@ def generate_prompt():
|
|||
|
||||
# Intentar obtener la carpeta base de Obsidian desde la configuración
|
||||
try:
|
||||
# Obtener configuración del nivel 2
|
||||
group_config = configs.get("level2", {})
|
||||
# Obtener configuración del nivel 3
|
||||
group_config = configs.get("level3", {})
|
||||
obsidian_dir = group_config.get("ObsideanDir")
|
||||
obsidian_projects_base = group_config.get("ObsideanProjectsBase")
|
||||
|
||||
|
@ -146,8 +154,9 @@ def generate_prompt():
|
|||
print(f"Usando carpeta de equivalencias en Obsidian: {obsidian_mixer_path}")
|
||||
|
||||
# Definir las rutas a los archivos
|
||||
master_table_path = os.path.join(working_directory_abs, "Master IO Tags.md")
|
||||
hardware_table_path = os.path.join(working_directory_abs, "Hardware.md")
|
||||
data_directory = os.path.join(working_directory_abs, resultados_exp_directory)
|
||||
master_table_path = os.path.join(data_directory, "Master IO Tags.md")
|
||||
hardware_table_path = os.path.join(data_directory, "Hardware.md")
|
||||
adaptation_table_path = os.path.join(working_directory_abs, "IO Adapted.md")
|
||||
|
||||
# Rutas a los archivos de datos semánticos
|
||||
|
@ -215,8 +224,8 @@ $Working_Directory = "{working_directory_abs}"
|
|||
$Obsidean_Base_Folder = "{obsidian_mixer_path}"
|
||||
|
||||
# Archivos de entrada
|
||||
$Master_table = $Working_Directory + "/Master IO Tags.md"
|
||||
$Hardware_table = $Working_Directory + "/Hardware.md"
|
||||
$Master_table = $Working_Directory + "/{resultados_exp_directory}/Master IO Tags.md"
|
||||
$Hardware_table = $Working_Directory + "/{resultados_exp_directory}/Hardware.md"
|
||||
|
||||
# Archivo de salida
|
||||
$Adaptation_table = $Working_Directory + "/IO Adapted.md"
|
||||
|
@ -370,7 +379,7 @@ def copy_adapted_file_to_obsidian():
|
|||
return False
|
||||
|
||||
# Obtener la ruta de destino en Obsidian
|
||||
group_config = configs.get("level2", {})
|
||||
group_config = configs.get("level3", {})
|
||||
obsidian_dir = group_config.get("ObsideanDir")
|
||||
obsidian_projects_base = group_config.get("ObsideanProjectsBase")
|
||||
|
||||
|
|
|
@ -1,5 +1,18 @@
|
|||
{
|
||||
"history": [
|
||||
{
|
||||
"id": "8f721c30",
|
||||
"group_id": "2",
|
||||
"script_name": "main.py",
|
||||
"executed_date": "2025-07-14T10:11:20.750196Z",
|
||||
"arguments": [],
|
||||
"working_directory": "D:/Proyectos/Scripts/RS485/MaselliSimulatorApp",
|
||||
"python_env": "tia_scripting",
|
||||
"executable_type": "pythonw.exe",
|
||||
"status": "running",
|
||||
"pid": 22396,
|
||||
"execution_time": null
|
||||
},
|
||||
{
|
||||
"id": "b321622a",
|
||||
"group_id": "4",
|
||||
|
|
311
data/log.txt
311
data/log.txt
|
@ -1,290 +1,21 @@
|
|||
[16:38:15] Iniciando ejecución de x2_full_io_documentation.py en C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\TwinCat...
|
||||
[16:38:16] 🚀 Iniciando documentación completa de IOs de TwinCAT
|
||||
[16:38:16] ================================================================================
|
||||
[16:38:16] 📁 Directorio de trabajo: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\TwinCat
|
||||
[16:38:16] 📁 Directorio de resultados: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\TwinCat\result
|
||||
[16:38:16] 🔍 Escaneando definiciones TwinCAT activas en: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\TwinCat\scl
|
||||
[16:38:16] ✅ Encontradas 141 definiciones de IO activas.
|
||||
[16:38:16] 🔍 Buscando usos de variables definidas en: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\TwinCat\scl
|
||||
[16:38:16] 📄 Analizando uso en: ADSVARREAD.scl
|
||||
[16:38:16] 📄 Analizando uso en: ADSVARTRANSLATE.scl
|
||||
[16:38:16] 📄 Analizando uso en: ADSVARWRITE.scl
|
||||
[16:38:16] 📄 Analizando uso en: AMMONIACTRL.scl
|
||||
[16:38:16] 📄 Analizando uso en: ARRAYTOREAL.scl
|
||||
[16:38:16] 📄 Analizando uso en: BLENDERPROCEDURE_VARIABLES.scl
|
||||
[16:38:16] 📄 Analizando uso en: BLENDERRINSE.scl
|
||||
[16:38:16] 📄 Analizando uso en: BLENDER_PID_CTRL_LOOP.scl
|
||||
[16:38:17] 📄 Analizando uso en: BLENDER_PROCEDURECALL.scl
|
||||
[16:38:17] 📄 Analizando uso en: BLENDER_RUNCONTROL.scl
|
||||
[16:38:17] 📄 Analizando uso en: BLENDER_VARIABLES.scl
|
||||
[16:38:17] 📄 Analizando uso en: BLENDFILLRECSTRUCT.scl
|
||||
[16:38:17] 📄 Analizando uso en: BLENDFILLSENDSTRUCT.scl
|
||||
[16:38:17] 📄 Analizando uso en: BLENDFILLSYSTEM_STARTUP.scl
|
||||
[16:38:17] 📄 Analizando uso en: BRIXTRACKING.scl
|
||||
[16:38:17] 📄 Analizando uso en: BYTES_TO_DWORD.scl
|
||||
[16:38:17] 📄 Analizando uso en: BYTES_TO_WORD.scl
|
||||
[16:38:17] 📄 Analizando uso en: CALC_INJPRESS.scl
|
||||
[16:38:17] 📄 Analizando uso en: CARBOWATERLINE.scl
|
||||
[16:38:17] 📄 Analizando uso en: CENTRALCIP_CTRL.scl
|
||||
[16:38:17] 📄 Analizando uso en: CETRIFUGAL_HEAD.scl
|
||||
[16:38:17] 📄 Analizando uso en: CIPRECEIVESTRUCT.scl
|
||||
[16:38:17] 📄 Analizando uso en: CIPSENDSTRUCT.scl
|
||||
[16:38:17] 📄 Analizando uso en: CIP_CVQ.scl
|
||||
[16:38:17] 📄 Analizando uso en: CIP_LINK_TYPE.scl
|
||||
[16:38:17] 📄 Analizando uso en: CIP_LIST_ELEMENT.scl
|
||||
[16:38:17] 📄 Analizando uso en: CIP_MAIN.scl
|
||||
[16:38:18] 📄 Analizando uso en: CIP_PROGRAM_VARIABLES.scl
|
||||
[16:38:18] 📄 Analizando uso en: CIP_SIMPLE_TYPE.scl
|
||||
[16:38:18] 📄 Analizando uso en: CIP_STEP_TYPE.scl
|
||||
[16:38:18] 📄 Analizando uso en: CIP_WAITEVENT_TYPE.scl
|
||||
[16:38:18] 📄 Analizando uso en: CLEANBOOLARRAY.scl
|
||||
[16:38:18] 📄 Analizando uso en: CLOCK_SIGNAL.scl
|
||||
[16:38:18] 📄 Analizando uso en: CLOCK_VARIABLES.scl
|
||||
[16:38:18] 📄 Analizando uso en: CO2EQPRESS.scl
|
||||
[16:38:18] 📄 Analizando uso en: CO2INJPRESSURE.scl
|
||||
[16:38:18] 📄 Analizando uso en: CO2_SOLUBILITY.scl
|
||||
[16:38:18] 📄 Analizando uso en: CONVERTREAL.scl
|
||||
[16:38:18] 📄 Analizando uso en: CVQ_0_6_PERC.scl
|
||||
[16:38:18] 📄 Analizando uso en: CVQ_1P7_8_PERC.scl
|
||||
[16:38:18] 📄 Analizando uso en: DATA_FROM_CIP.scl
|
||||
[16:38:18] 📄 Analizando uso en: DATA_TO_CIP.scl
|
||||
[16:38:18] 📄 Analizando uso en: DEAIRCO2TEMPCOMP.scl
|
||||
[16:38:18] 📄 Analizando uso en: DEAIREATIONVALVE.scl
|
||||
[16:38:18] 📄 Analizando uso en: DEAIREATOR_STARTUP.scl
|
||||
[16:38:18] 📄 Analizando uso en: DELAY.scl
|
||||
[16:38:18] 📄 Analizando uso en: DELTAP.scl
|
||||
[16:38:18] 📄 Analizando uso en: DENSIMETER_CALIBRATION.scl
|
||||
[16:38:18] 📄 Analizando uso en: DERIVE.scl
|
||||
[16:38:18] 📄 Analizando uso en: DEVICENET_VARIABLES.scl
|
||||
[16:38:18] 📄 Analizando uso en: DWORD_TO_BYTES.scl
|
||||
[16:38:18] 📄 Analizando uso en: EXEC_SIMPLE_CIP.scl
|
||||
[16:38:18] 📄 Analizando uso en: FASTRINSE.scl
|
||||
[16:38:18] 📄 Analizando uso en: FB41_PIDCONTROLLER.scl
|
||||
[16:38:18] 📄 Analizando uso en: FC_CONTROL_WORD.scl
|
||||
[16:38:18] 📄 Analizando uso en: FC_STATUS_WORD.scl
|
||||
[16:38:18] 📄 Analizando uso en: FEEDFORWARD.scl
|
||||
[16:38:18] 📄 Analizando uso en: FILLERHEAD.scl
|
||||
[16:38:18] 📄 Analizando uso en: FILLERRECEIVESTRUCT.scl
|
||||
[16:38:18] 📄 Analizando uso en: FILLERRINSE.scl
|
||||
[16:38:18] 📄 Analizando uso en: FILLERRINSETANK_CTRL.scl
|
||||
[16:38:18] 📄 Analizando uso en: FILLERSENDSTRUCT.scl
|
||||
[16:38:18] 📄 Analizando uso en: FILLER_CONTROL.scl
|
||||
[16:38:19] 📄 Analizando uso en: FILLINGTIME.scl
|
||||
[16:38:19] 📄 Analizando uso en: FIRSTPRODUCTION.scl
|
||||
[16:38:19] 📄 Analizando uso en: FLOW_TO_PRESS_LOSS.scl
|
||||
[16:38:19] 📄 Analizando uso en: FREQ_TO_MMH2O.scl
|
||||
[16:38:19] 📄 Analizando uso en: FRICTIONLOSS.scl
|
||||
[16:38:19] 📄 Analizando uso en: GETPRODBRIXCO2_FROMANALOGINPUT.scl
|
||||
[16:38:19] 📄 Analizando uso en: GETPRODO2_FROMANALOGINPUT.scl
|
||||
[16:38:19] 📄 Analizando uso en: GLOBAL_ALARMS.scl
|
||||
[16:38:19] 📄 Analizando uso en: GLOBAL_VARIABLES_IN_OUT.scl
|
||||
[16:38:19] 📄 Analizando uso en: HMI_ALARMS.scl
|
||||
[16:38:19] 📄 Analizando uso en: HMI_BLENDER_PARAMETERS.scl
|
||||
[16:38:19] 📄 Analizando uso en: HMI_IO_SHOWING.scl
|
||||
[16:38:19] 📄 Analizando uso en: HMI_LOCAL_CIP_VARIABLES.scl
|
||||
[16:38:19] 📄 Analizando uso en: HMI_SERVICE.scl
|
||||
[16:38:19] 📄 Analizando uso en: HMI_VARIABLES_CMD.scl
|
||||
[16:38:19] 📄 Analizando uso en: HMI_VARIABLES_STATUS.scl
|
||||
[16:38:19] 📄 Analizando uso en: INPUT.scl
|
||||
[16:38:19] 📄 Analizando uso en: INPUT_CIP_SIGNALS.scl
|
||||
[16:38:20] 📄 Analizando uso en: INPUT_SIGNAL.scl
|
||||
[16:38:20] 📄 Analizando uso en: INTEGRAL.scl
|
||||
[16:38:20] 📄 Analizando uso en: LOCALCIP_CTRL.scl
|
||||
[16:38:20] 📄 Analizando uso en: LOWPASSFILTER.scl
|
||||
[16:38:20] 📄 Analizando uso en: LOWPASSFILTEROPT.scl
|
||||
[16:38:20] 📄 Analizando uso en: MASELLI.scl
|
||||
[16:38:20] 📄 Analizando uso en: MASELLIOPTO_TYPE.scl
|
||||
[16:38:20] 📄 Analizando uso en: MASELLIUC05_TYPE.scl
|
||||
[16:38:20] 📄 Analizando uso en: MASELLIUR22_TYPE.scl
|
||||
[16:38:20] 📄 Analizando uso en: MASELLI_CONTROL.scl
|
||||
[16:38:20] 📄 Analizando uso en: MAXCARBOCO2_VOL.scl
|
||||
[16:38:20] 📄 Analizando uso en: MESSAGESCROLL.scl
|
||||
[16:38:20] 📄 Analizando uso en: MESSAGE_SCROLL.scl
|
||||
[16:38:20] 📄 Analizando uso en: MFMANALOG_VALUES.scl
|
||||
[16:38:20] 📄 Analizando uso en: MFM_REAL_STRUCT.scl
|
||||
[16:38:20] 📄 Analizando uso en: MMH2O_TO_FREQ.scl
|
||||
[16:38:20] 📄 Analizando uso en: MODVALVEFAULT.scl
|
||||
[16:38:20] 📄 Analizando uso en: MOVEARRAY.scl
|
||||
[16:38:20] 📄 Analizando uso en: MPDS1000.scl
|
||||
[16:38:20] 📄 Analizando uso en: MPDS1000_CONTROL.scl
|
||||
[16:38:20] 📄 Analizando uso en: MPDS1000_TYPE.scl
|
||||
[16:38:20] 📄 Analizando uso en: MPDS2000.scl
|
||||
[16:38:20] 📄 Analizando uso en: MPDS2000_CONTROL.scl
|
||||
[16:38:20] 📄 Analizando uso en: MPDS2000_TYPE.scl
|
||||
[16:38:20] 📄 Analizando uso en: MPDS_PA_CONTROL.scl
|
||||
[16:38:20] 📄 Analizando uso en: MSE_SLOPE.scl
|
||||
[16:38:20] 📄 Analizando uso en: MYVAR.scl
|
||||
[16:38:20] 📄 Analizando uso en: OR_ARRAYBOOL.scl
|
||||
[16:38:20] 📄 Analizando uso en: OUTPUT.scl
|
||||
[16:38:20] 📄 Analizando uso en: PARAMETERNAMETYPE.scl
|
||||
[16:38:20] 📄 Analizando uso en: PA_MPDS.scl
|
||||
[16:38:20] 📄 Analizando uso en: PERIPHERIAL.scl
|
||||
[16:38:20] 📄 Analizando uso en: PID_VARIABLES.scl
|
||||
[16:38:20] 📄 Analizando uso en: PLC CONFIGURATION.scl
|
||||
[16:38:21] 📄 Analizando uso en: PNEUMATIC_VALVE_CTRL.scl
|
||||
[16:38:21] 📄 Analizando uso en: PPM_O2.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODBRIXRECOVERY.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODTANK_DRAIN.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODTANK_RUNOUT.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODUCTAVAILABLE.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODUCTION_VARIABLES.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODUCTLITERINTANK.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODUCTPIPEDRAIN.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODUCTPIPERUNOUT.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODUCTQUALITY.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODUCTTANKBRIX.scl
|
||||
[16:38:21] 📄 Analizando uso en: PRODUCTTANK_PRESSCTRL.scl
|
||||
[16:38:21] 📄 Analizando uso en: PROFIBUS_DATA.scl
|
||||
[16:38:21] 📄 Analizando uso en: PROFIBUS_NETWORK.scl
|
||||
[16:38:21] 📄 Analizando uso en: PROFIBUS_VARIABLES.scl
|
||||
[16:38:21] 📄 Analizando uso en: PULSEPRESSURE.scl
|
||||
[16:38:21] 📄 Analizando uso en: PUMPSCONTROL.scl
|
||||
[16:38:21] 📄 Analizando uso en: READANALOGIN.scl
|
||||
[16:38:21] 📄 Analizando uso en: READPERIPHERIAL.scl
|
||||
[16:38:21] 📄 Analizando uso en: SAFETIES.scl
|
||||
[16:38:22] 📄 Analizando uso en: SELCHECKBRIXSOURCE.scl
|
||||
[16:38:22] 📄 Analizando uso en: SIGNALS_INTEFACE.scl
|
||||
[16:38:22] 📄 Analizando uso en: SIGNAL_GEN.scl
|
||||
[16:38:22] 📄 Analizando uso en: SINUSOIDAL_SIGNAL.scl
|
||||
[16:38:22] 📄 Analizando uso en: SLEWLIMIT.scl
|
||||
[16:38:22] 📄 Analizando uso en: SLIM_BLOCK.scl
|
||||
[16:38:22] 📄 Analizando uso en: SLIM_VARIABLES.scl
|
||||
[16:38:22] 📄 Analizando uso en: SOFTNET_VARIABLES.scl
|
||||
[16:38:22] 📄 Analizando uso en: SPEEDADJUST.scl
|
||||
[16:38:22] 📄 Analizando uso en: SP_AND_P_VARIABLES.scl
|
||||
[16:38:22] 📄 Analizando uso en: STANDARD.LIB_5.6.98 09_39_02.scl
|
||||
[16:38:22] 📄 Analizando uso en: STATISTICALANALISYS.scl
|
||||
[16:38:22] 📄 Analizando uso en: SYRBRIX_AUTOCORRECTION.scl
|
||||
[16:38:22] 📄 Analizando uso en: SYRUPDENSITY.scl
|
||||
[16:38:22] 📄 Analizando uso en: SYRUPROOMCTRL.scl
|
||||
[16:38:22] 📄 Analizando uso en: SYRUP_LINE_MFM_PREP.scl
|
||||
[16:38:22] 📄 Analizando uso en: SYRUP_MFM_STARTUP.scl
|
||||
[16:38:22] 📄 Analizando uso en: SYRUP_RUNOUT.scl
|
||||
[16:38:22] 📄 Analizando uso en: SYSTEMRUNOUT_VARIABLES.scl
|
||||
[16:38:22] 📄 Analizando uso en: SYSTEM_DATAS.scl
|
||||
[16:38:22] 📄 Analizando uso en: SYSTEM_RUN_OUT.scl
|
||||
[16:38:22] 📄 Analizando uso en: TANKLEVEL.scl
|
||||
[16:38:22] 📄 Analizando uso en: TANKLEVELTOHEIGHT.scl
|
||||
[16:38:22] 📄 Analizando uso en: TASK CONFIGURATION.scl
|
||||
[16:38:22] 📄 Analizando uso en: TCPLCUTILITIES.LIB_11.12.01 09_39_02.scl
|
||||
[16:38:22] 📄 Analizando uso en: TCSYSTEM.LIB_16.9.02 09_39_02.scl
|
||||
[16:38:22] 📄 Analizando uso en: TESTFLOWMETERS.scl
|
||||
[16:38:22] 📄 Analizando uso en: UDP_STRUCT.scl
|
||||
[16:38:22] 📄 Analizando uso en: UV_LAMP.scl
|
||||
[16:38:22] 📄 Analizando uso en: VACUUMCTRL.scl
|
||||
[16:38:22] 📄 Analizando uso en: VALVEFAULT.scl
|
||||
[16:38:22] 📄 Analizando uso en: VALVEFLOW.scl
|
||||
[16:38:22] 📄 Analizando uso en: VARIABLE_CONFIGURATION.scl
|
||||
[16:38:22] 📄 Analizando uso en: VOID.scl
|
||||
[16:38:22] 📄 Analizando uso en: WATERDENSITY.scl
|
||||
[16:38:22] 📄 Analizando uso en: WORD_TO_BYTES.scl
|
||||
[16:38:22] 📄 Analizando uso en: WRITEPERIPHERIAL.scl
|
||||
[16:38:22] 📄 Analizando uso en: _BLENDER_CTRL_MAIN.scl
|
||||
[16:38:23] 📄 Analizando uso en: _BLENDER_PID_MAIN.scl
|
||||
[16:38:23] 📄 Analizando uso en: _BOOLARRAY_TO_DWORD.scl
|
||||
[16:38:23] 📄 Analizando uso en: _BOOLARRAY_TO_WORD.scl
|
||||
[16:38:23] 📄 Analizando uso en: _DWORD_SWAP_BYTEARRAY.scl
|
||||
[16:38:23] 📄 Analizando uso en: _DWORD_TO_BOOLARRAY.scl
|
||||
[16:38:23] 📄 Analizando uso en: _FILLING_HEAD_PID_CTRL.scl
|
||||
[16:38:23] 📄 Analizando uso en: _PUMPCONTROL.scl
|
||||
[16:38:23] 📄 Analizando uso en: _STEPMOVE.scl
|
||||
[16:38:23] 📄 Analizando uso en: _WORD_TO_BOOLARRAY.scl
|
||||
[16:38:23] ✅ Encontrados 224 usos para 83 variables distintas.
|
||||
[16:38:23] 📄 Generando tabla resumen: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\TwinCat\result\TwinCAT_Full_IO_List.md
|
||||
[16:38:23] ✅ Tabla resumen generada exitosamente.
|
||||
[16:38:23] 📄 Generando reporte de snippets: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\TwinCat\result\TwinCAT_IO_Usage_Snippets.md
|
||||
[16:38:23] Generando snippets para 83 variables con uso...
|
||||
[16:38:23] 📝 Procesando 1/83: AI_ProductTankLevel (1 usos)
|
||||
[16:38:23] 📝 Procesando 2/83: AI_ProductTankPressure (1 usos)
|
||||
[16:38:23] 📝 Procesando 3/83: AI_DeaireationValve_VEP4 (2 usos)
|
||||
[16:38:23] 📝 Procesando 4/83: AI_ProdTankPressureValve_VEP1 (1 usos)
|
||||
[16:38:23] 📝 Procesando 5/83: AI_ProductTemperature (1 usos)
|
||||
[16:38:23] 📝 Procesando 6/83: AI_SyrupTankLevel (1 usos)
|
||||
[16:38:23] 📝 Procesando 7/83: AI_DeairWaterTemperature (1 usos)
|
||||
[16:38:23] 📝 Procesando 8/83: AI_InjectionPressure (2 usos)
|
||||
[16:38:23] 📝 Procesando 9/83: gProduct_VFC_MainActualValue (1 usos)
|
||||
[16:38:23] 📝 Procesando 10/83: DI_AuxVoltage_On (1 usos)
|
||||
[16:38:23] 📝 Procesando 11/83: DI_Reset_Horn_Btn (2 usos)
|
||||
[16:38:23] 📝 Procesando 12/83: DI_Reset_Btn (79 usos)
|
||||
[16:38:23] 📝 Procesando 13/83: DI_Blender_Stop_Btn (3 usos)
|
||||
[16:38:23] 📝 Procesando 14/83: DI_Blender_Start_Btn (1 usos)
|
||||
[16:38:23] 📝 Procesando 15/83: DI_PowerSuppliesOk (3 usos)
|
||||
[16:38:23] 📝 Procesando 16/83: DI_Min_Deair_Level (1 usos)
|
||||
[16:38:23] 📝 Procesando 17/83: DI_ProdTankEmpty (1 usos)
|
||||
[16:38:23] 📝 Procesando 18/83: DI_BatteryNotReady (1 usos)
|
||||
[16:38:23] 📝 Procesando 19/83: DI_VM1_Water_Valve_Closed (1 usos)
|
||||
[16:38:23] 📝 Procesando 20/83: DI_VM2_Syrup_Valve_Closed (1 usos)
|
||||
[16:38:23] 📝 Procesando 21/83: DI_VM3_CO2_Valve_Closed (1 usos)
|
||||
[16:38:23] 📝 Procesando 22/83: DI_Water_Pump_Contactor (1 usos)
|
||||
[16:38:23] 📝 Procesando 23/83: DI_Syrup_Pump_Ovrld (1 usos)
|
||||
[16:38:23] 📝 Procesando 24/83: DI_Syrup_Pump_Contactor (1 usos)
|
||||
[16:38:23] 📝 Procesando 25/83: DI_Product_Pump_Contactor (1 usos)
|
||||
[16:38:23] 📝 Procesando 26/83: DI_SyrRoom_Pump_Ready (1 usos)
|
||||
[16:38:23] 📝 Procesando 27/83: DI_CIP_CIPMode (1 usos)
|
||||
[16:38:23] 📝 Procesando 28/83: DI_CIP_RinseMode (1 usos)
|
||||
[16:38:23] 📝 Procesando 29/83: DI_CIP_DrainRequest (1 usos)
|
||||
[16:38:23] 📝 Procesando 30/83: DI_CIP_CIPCompleted (1 usos)
|
||||
[16:38:23] 📝 Procesando 31/83: DI_Air_InletPress_OK (1 usos)
|
||||
[16:38:23] 📝 Procesando 32/83: DI_Syrup_Line_Drain_Sensor (1 usos)
|
||||
[16:38:23] 📝 Procesando 33/83: gWaterTotCtrl_Node20 (3 usos)
|
||||
[16:38:23] 📝 Procesando 34/83: gSyrControl_Node21 (7 usos)
|
||||
[16:38:23] 📝 Procesando 35/83: gCO2Control_Node22 (7 usos)
|
||||
[16:38:23] 📝 Procesando 36/83: gProductTotCtrl_Node17 (3 usos)
|
||||
[16:38:23] 📝 Procesando 37/83: AO_WaterCtrlValve_VM1 (1 usos)
|
||||
[16:38:23] 📝 Procesando 38/83: AO_SyrupCtrlValve_VM2 (1 usos)
|
||||
[16:38:23] 📝 Procesando 39/83: AO_CarboCO2CtrlValve_VM3 (1 usos)
|
||||
[16:38:23] 📝 Procesando 40/83: AO_ProdTankPressureValve_VEP1 (1 usos)
|
||||
[16:38:23] 📝 Procesando 41/83: AO_DeaireationValve_VEP4 (2 usos)
|
||||
[16:38:23] 📝 Procesando 42/83: AO_ProdTempCtrlValve (1 usos)
|
||||
[16:38:23] 📝 Procesando 43/83: AO_SyrupInletValve_VEP3 (1 usos)
|
||||
[16:38:23] 📝 Procesando 44/83: AO_InjectionPressure (1 usos)
|
||||
[16:38:23] 📝 Procesando 45/83: gProduct_VFC_MainRefValue (1 usos)
|
||||
[16:38:23] 📝 Procesando 46/83: DO_SyrupInletValve_Enable (1 usos)
|
||||
[16:38:23] 📝 Procesando 47/83: DO_HoldBrixMeter (2 usos)
|
||||
[16:38:23] 📝 Procesando 48/83: DO_SyrupRoomPump_Run (2 usos)
|
||||
[16:38:23] 📝 Procesando 49/83: DO_SyrupRoomWaterReq (2 usos)
|
||||
[16:38:23] 📝 Procesando 50/83: DO_CIP_CIPRequest (2 usos)
|
||||
[16:38:23] 📝 Procesando 51/83: DO_CIP_DrainCompleted (2 usos)
|
||||
[16:38:23] 📝 Procesando 52/83: DO_Horn (2 usos)
|
||||
[16:38:23] 📝 Procesando 53/83: DO_Blender_Run_Lamp (2 usos)
|
||||
[16:38:23] 📝 Procesando 54/83: DO_Alarm_Lamp (2 usos)
|
||||
[16:38:23] 📝 Procesando 55/83: DO_RotorAlarm_Lamp (2 usos)
|
||||
[16:38:23] 📝 Procesando 56/83: DO_Water_Pump_Run (2 usos)
|
||||
[16:38:23] 📝 Procesando 57/83: DO_Syrup_Pump_Run (2 usos)
|
||||
[16:38:23] 📝 Procesando 58/83: DO_Product_Pump_Run (3 usos)
|
||||
[16:38:23] 📝 Procesando 59/83: DO_EV11_BlowOff_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 60/83: DO_EV13_Prod_Recirc_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 61/83: DO_EV14_DeairDrain_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 62/83: DO_EV15_ProductTank_Drain_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 63/83: DO_EV16_SyrupTank_Drain_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 64/83: DO_EV17_BufferTankSprayBall_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 65/83: DO_EV18_DeairOverfill_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 66/83: DO_EV21_ProdTankOverfill_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 67/83: DO_EV22_WaterPumpPrime_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 68/83: DO_EV23_SerpentineDrain_valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 69/83: DO_EV24_SyrupRecirc_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 70/83: DO_EV26_CO2InjShutOff_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 71/83: DO_EV27_DeairSprayBall_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 72/83: DO_EV28_DeairStartCO2Inj_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 73/83: DO_EV44_SyrupLineDrain (2 usos)
|
||||
[16:38:23] 📝 Procesando 74/83: DO_EV45_ProductChillerDrain (2 usos)
|
||||
[16:38:23] 📝 Procesando 75/83: DO_EV61_SyrupTankSprayBall (2 usos)
|
||||
[16:38:23] 📝 Procesando 76/83: DO_EV62_ProductOutlet (3 usos)
|
||||
[16:38:23] 📝 Procesando 77/83: DO_EV69_Blender_ProductPipeDrain (2 usos)
|
||||
[16:38:23] 📝 Procesando 78/83: DO_EV81_Prod_Recirc_Chiller_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 79/83: DO_EV01_Deair_Lvl_Ctrl_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 80/83: DO_EV02_Deair_FillUp_Valve (2 usos)
|
||||
[16:38:23] 📝 Procesando 81/83: gPAmPDSFreeze (2 usos)
|
||||
[16:38:23] 📝 Procesando 82/83: gPAmPDSCarboStop (2 usos)
|
||||
[16:38:23] 📝 Procesando 83/83: gPAmPDSInlinePumpStop (2 usos)
|
||||
[16:38:23] Generando tabla para 58 variables no usadas...
|
||||
[16:38:23] ✅ Reporte de snippets generado exitosamente.
|
||||
[16:38:23] 📄 Generando reporte JSON: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\TwinCat\result\TwinCAT_IO_Usage_Snippets.json
|
||||
[16:38:23] ✅ Reporte JSON generado exitosamente.
|
||||
[16:38:23] 🎉 Análisis completado exitosamente!
|
||||
[16:38:23] 📁 Archivos generados en: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\TwinCat\result
|
||||
[16:38:23] 📄 TwinCAT_Full_IO_List.md
|
||||
[16:38:23] 📄 TwinCAT_IO_Usage_Snippets.md
|
||||
[16:38:23] 📄 TwinCAT_IO_Usage_Snippets.json
|
||||
[16:38:23] Ejecución de x2_full_io_documentation.py finalizada (success). Duración: 0:00:07.976669.
|
||||
[16:38:23] Log completo guardado en: D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\TwinCat\log_x2_full_io_documentation.txt
|
||||
[18:10:38] Iniciando ejecución de x4_prompt_generator.py en C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\Siemens...
|
||||
[18:10:38] Generador de prompt para adaptación de IO
|
||||
[18:10:38] =========================================
|
||||
[18:10:38] Usando directorio de trabajo: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\Siemens
|
||||
[18:10:38] Usando ruta de Obsidian desde configuración: C:\Users\migue\OneDrive\Miguel\Obsidean\Trabajo\VM\04-SIDEL\00 - MASTER\MIXER\IO
|
||||
[18:10:38] Usando carpeta de equivalencias en Obsidian: C:\Users\migue\OneDrive\Miguel\Obsidean\Trabajo\VM\04-SIDEL\00 - MASTER\MIXER\IO
|
||||
[18:10:38] ¡Prompt generado y copiado al portapapeles con éxito!
|
||||
[18:10:38] Prompt guardado en: C:\Trabajo\SIDEL\13 - E5.007560 - Modifica O&U - SAE235\Reporte\Analisis\Siemens\IO_Adaptation_Prompt.txt
|
||||
[18:11:10] Ejecución de x4_prompt_generator.py finalizada (success). Duración: 0:00:31.385093.
|
||||
[18:11:10] Log completo guardado en: D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\IO_adaptation\.log\log_x4_prompt_generator.txt
|
||||
[10:11:20] Ejecutando script GUI: main.py
|
||||
[10:11:20] Entorno Python: tia_scripting
|
||||
[10:11:20] Ejecutable: pythonw.exe (sin logging)
|
||||
[10:11:20] Comando: C:\Users\migue\miniconda3\envs\tia_scripting\pythonw.exe D:/Proyectos/Scripts/RS485/MaselliSimulatorApp\main.py
|
||||
[10:11:20] Directorio: D:/Proyectos/Scripts/RS485/MaselliSimulatorApp
|
||||
[10:11:20] Encoding: UTF-8 (PYTHONUTF8=1, PYTHONIOENCODING=utf-8)
|
||||
[10:11:20] ==================================================
|
||||
[10:11:20] Script GUI ejecutado sin logging (pythonw.exe)
|
||||
[10:11:20] PID: 22396
|
||||
[10:11:20] ==================================================
|
||||
[10:11:20] ID de ejecución: 8f721c30
|
||||
|
|
|
@ -227,7 +227,7 @@
|
|||
<!-- Level 3 Configuration -->
|
||||
<div class="mb-8 bg-white p-6 rounded-lg shadow">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-xl font-bold">Configuración del Proyecto</h2>
|
||||
<h2 class="text-xl font-bold">Datos de Ingreso</h2>
|
||||
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="toggleConfig('level3-content')">
|
||||
Ocultar Configuración
|
||||
</button>
|
||||
|
|
Loading…
Reference in New Issue