Corregido error de acentos para los script del LAD a SCL
This commit is contained in:
parent
eacce5d8bd
commit
6d021b8211
110
app.py
110
app.py
|
@ -1,9 +1,18 @@
|
|||
from flask import Flask, render_template, request, jsonify, url_for
|
||||
from flask_sock import Sock
|
||||
from config_manager import ConfigurationManager
|
||||
from datetime import datetime
|
||||
import os
|
||||
import json # Added import
|
||||
from datetime import datetime
|
||||
import time # Added for shutdown delay
|
||||
|
||||
# --- Imports for System Tray Icon ---
|
||||
import threading
|
||||
import webbrowser
|
||||
import sys
|
||||
import requests # To send shutdown request
|
||||
from PIL import Image
|
||||
import pystray
|
||||
|
||||
app = Flask(
|
||||
__name__, static_url_path="", static_folder="static", template_folder="templates"
|
||||
|
@ -14,6 +23,9 @@ config_manager = ConfigurationManager()
|
|||
# Lista global para mantener las conexiones WebSocket activas
|
||||
websocket_connections = set()
|
||||
|
||||
# --- Globals for Tray Icon ---
|
||||
tray_icon = None
|
||||
|
||||
|
||||
@sock.route("/ws")
|
||||
def handle_websocket(ws):
|
||||
|
@ -227,5 +239,99 @@ def get_directory_history(group):
|
|||
return jsonify(history)
|
||||
|
||||
|
||||
# --- System Tray Icon Functions ---
|
||||
|
||||
def run_flask():
|
||||
"""Runs the Flask app."""
|
||||
print("Starting Flask server on http://127.0.0.1:5000/")
|
||||
try:
|
||||
# use_reloader=False is important when running in a thread
|
||||
# For production, consider using waitress or gunicorn instead of app.run
|
||||
app.run(host='127.0.0.1', port=5000, debug=True, use_reloader=False)
|
||||
except Exception as e:
|
||||
print(f"Error running Flask app: {e}")
|
||||
# Optionally try to stop the tray icon if Flask fails critically
|
||||
if tray_icon:
|
||||
print("Attempting to stop tray icon due to Flask error.")
|
||||
tray_icon.stop()
|
||||
|
||||
def open_app_browser(icon, item):
|
||||
"""Callback function to open the browser."""
|
||||
print("Opening application in browser...")
|
||||
webbrowser.open("http://127.0.0.1:5000/")
|
||||
|
||||
def shutdown_flask_server():
|
||||
"""Attempts to gracefully shut down the Werkzeug server."""
|
||||
try:
|
||||
# This requires the development server (werkzeug)
|
||||
# Send a request to a special shutdown route
|
||||
requests.post("http://127.0.0.1:5000/_shutdown", timeout=1)
|
||||
except Exception as e:
|
||||
print(f"Could not send shutdown request to Flask server: {e}")
|
||||
print("Flask server might need to be closed manually.")
|
||||
|
||||
def stop_icon_thread():
|
||||
"""Helper function to stop the icon after a delay, allowing HTTP response."""
|
||||
time.sleep(0.1) # Small delay to allow the HTTP response to be sent
|
||||
if tray_icon:
|
||||
print("Stopping tray icon from shutdown route...")
|
||||
tray_icon.stop()
|
||||
else:
|
||||
print("Tray icon not available to stop.")
|
||||
# As a last resort if the icon isn't running for some reason
|
||||
# print("Attempting os._exit(0) as fallback.")
|
||||
# os._exit(0) # Force exit - use with caution
|
||||
|
||||
@app.route('/_shutdown', methods=['POST'])
|
||||
def shutdown_route():
|
||||
"""Internal route to shut down the application via the tray icon."""
|
||||
print("Shutdown endpoint called.")
|
||||
# Stop the main application thread by stopping the tray icon.
|
||||
# Do this in a separate thread to allow the HTTP response to return first.
|
||||
stopper = threading.Thread(target=stop_icon_thread, daemon=True)
|
||||
stopper.start()
|
||||
print("Shutdown signal sent to tray icon thread.")
|
||||
return jsonify(status="success", message="Application shutdown initiated..."), 200
|
||||
|
||||
def exit_application(icon, item):
|
||||
"""Callback function to exit the application."""
|
||||
print("Exit requested via tray menu.")
|
||||
# Just stop the icon. This will end the main thread, and the daemon Flask thread will exit.
|
||||
print("Stopping tray icon...")
|
||||
if icon: # pystray passes the icon object
|
||||
icon.stop()
|
||||
elif tray_icon: # Fallback just in case
|
||||
tray_icon.stop()
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
||||
# --- Start Flask in a background thread ---
|
||||
flask_thread = threading.Thread(target=run_flask, daemon=True)
|
||||
flask_thread.start()
|
||||
|
||||
# --- Setup and run the system tray icon ---
|
||||
icon_path = r"d:\Proyectos\Scripts\ParamManagerScripts\icon.png" # Use absolute path
|
||||
try:
|
||||
image = Image.open(icon_path)
|
||||
menu = pystray.Menu(
|
||||
pystray.MenuItem("Abrir ParamManager", open_app_browser, default=True),
|
||||
pystray.MenuItem("Salir", exit_application)
|
||||
)
|
||||
tray_icon = pystray.Icon("ParamManager", image, "ParamManager", menu)
|
||||
print("Starting system tray icon...")
|
||||
tray_icon.run() # This blocks the main thread until icon.stop() is called
|
||||
except FileNotFoundError:
|
||||
print(f"Error: Icono no encontrado en '{icon_path}'. El icono de notificación no se iniciará.", file=sys.stderr)
|
||||
print("La aplicación Flask seguirá ejecutándose en segundo plano. Presiona Ctrl+C para detenerla si es necesario.")
|
||||
# Keep the main thread alive so the Flask thread doesn't exit immediately
|
||||
# This allows Flask to continue running even without the tray icon.
|
||||
try:
|
||||
while flask_thread.is_alive():
|
||||
flask_thread.join(timeout=1.0) # Wait indefinitely
|
||||
except KeyboardInterrupt:
|
||||
print("\nCtrl+C detectado. Intentando detener Flask...")
|
||||
shutdown_flask_server() # Try to shutdown Flask on Ctrl+C too
|
||||
print("Saliendo.")
|
||||
except Exception as e:
|
||||
print(f"Error al iniciar el icono de notificación: {e}", file=sys.stderr)
|
||||
|
||||
print("Aplicación finalizada.")
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,15 +23,8 @@ script_root = os.path.dirname(
|
|||
sys.path.append(script_root)
|
||||
from backend.script_utils import load_configuration
|
||||
|
||||
# --- Funciones (get_console_encoding - sin cambios) ---
|
||||
def get_console_encoding():
|
||||
try:
|
||||
return locale.getpreferredencoding(False)
|
||||
except Exception:
|
||||
return "cp1252"
|
||||
|
||||
|
||||
CONSOLE_ENCODING = get_console_encoding()
|
||||
CONSOLE_ENCODING = "utf-8"
|
||||
|
||||
# <-- NUEVO: Importar format_variable_name (necesario para predecir nombre de salida) -->
|
||||
try:
|
||||
|
|
4580
data/log.txt
4580
data/log.txt
File diff suppressed because it is too large
Load Diff
|
@ -1,15 +1,16 @@
|
|||
flask
|
||||
flask-sock
|
||||
lxml
|
||||
pandas
|
||||
google-cloud-translate
|
||||
openai
|
||||
ollama
|
||||
langid
|
||||
openpyxl
|
||||
beautifulsoup4
|
||||
requests
|
||||
mammoth
|
||||
html2text
|
||||
pypandoc
|
||||
# siemens-tia-scripting # Requiere instalación especial de TIA Portal Openness
|
||||
beautifulsoup4==4.13.4
|
||||
Flask==3.1.0
|
||||
flask_sock==0.7.0
|
||||
html2text==2025.4.15
|
||||
langid==1.1.6
|
||||
lxml==5.4.0
|
||||
mammoth==1.9.0
|
||||
ollama==0.4.8
|
||||
openai==1.77.0
|
||||
openpyxl==3.1.5
|
||||
pandas==2.2.3
|
||||
protobuf==6.30.2
|
||||
pypandoc==1.15
|
||||
Requests==2.32.3
|
||||
siemens_tia_scripting==1.0.7
|
||||
sympy==1.13.3
|
||||
|
|
|
@ -960,6 +960,81 @@ function collectFormData(level) {
|
|||
return data;
|
||||
}
|
||||
|
||||
// Añade esta función al final de tu archivo static/js/script.js
|
||||
|
||||
function shutdownServer() {
|
||||
if (confirm("¿Estás seguro de que quieres detener el servidor? La aplicación se cerrará.")) {
|
||||
fetch('/_shutdown', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
alert("El servidor se está deteniendo. Puede que necesites cerrar esta pestaña manualmente.");
|
||||
// Opcionalmente, puedes intentar cerrar la ventana/pestaña
|
||||
// window.close(); // Esto puede no funcionar en todos los navegadores por seguridad
|
||||
document.body.innerHTML = '<div class="alert alert-info">El servidor se ha detenido. Cierra esta ventana.</div>';
|
||||
} else {
|
||||
alert("Error al intentar detener el servidor: " + data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// Es normal recibir un error de red aquí porque el servidor se está apagando
|
||||
console.warn("Error esperado al detener el servidor (puede que ya se haya detenido):", error);
|
||||
alert("Solicitud de detención enviada. El servidor debería detenerse. Cierra esta ventana.");
|
||||
document.body.innerHTML = '<div class="alert alert-info">El servidor se está deteniendo. Cierra esta ventana.</div>';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Asegúrate de que las funciones fetchLogs y clearLogs también estén definidas en este archivo si las usas.
|
||||
// Ejemplo de fetchLogs y clearLogs (si no las tienes ya):
|
||||
|
||||
function fetchLogs() {
|
||||
fetch('/api/logs')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const logOutput = document.getElementById('log-output');
|
||||
logOutput.textContent = data.logs || 'No hay logs.';
|
||||
logOutput.scrollTop = logOutput.scrollHeight; // Scroll to bottom
|
||||
})
|
||||
.catch(error => console.error('Error fetching logs:', error));
|
||||
}
|
||||
|
||||
function clearLogs() {
|
||||
if (confirm("¿Estás seguro de que quieres borrar los logs?")) {
|
||||
fetch('/api/logs', { method: 'DELETE' })
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
fetchLogs(); // Refresh logs after clearing
|
||||
showToast('Logs borrados correctamente.');
|
||||
} else {
|
||||
showToast('Error al borrar los logs.', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error clearing logs:', error);
|
||||
showToast('Error de red al borrar los logs.', 'error');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Necesitarás una función showToast o similar si la usas
|
||||
function showToast(message, type = 'success') {
|
||||
// Implementa tu lógica de Toast aquí
|
||||
console.log(`Toast (${type}): ${message}`);
|
||||
alert(`Toast (${type}): ${message}`); // Simple alert como placeholder
|
||||
}
|
||||
|
||||
// Llama a fetchLogs al cargar la página si es necesario
|
||||
// document.addEventListener('DOMContentLoaded', fetchLogs);
|
||||
|
||||
|
||||
|
||||
// Agregar función para guardar configuración
|
||||
async function saveConfig(level) {
|
||||
const saveButton = document.getElementById(`save-config-${level}`);
|
||||
|
|
|
@ -68,6 +68,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Botón para detener el servidor -->
|
||||
<div class="mt-8 pt-4 border-t border-gray-300">
|
||||
<button class="w-full bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded shadow" onclick="shutdownServer()">
|
||||
Detener Servidor
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue