Modificada directorio base del proyecto

This commit is contained in:
Miguel 2025-09-01 17:20:34 +02:00
parent 581aa551c4
commit c8ceb8fddd
38 changed files with 849 additions and 2197 deletions

View File

@ -1,72 +0,0 @@
# AutoBackups Project
## Overview
AutoBackups is a Python application designed to automate the backup of Simatic S7 projects and other user-defined directories. The application leverages the Everything API to efficiently locate files and manage backups based on user-defined configurations.
## Features
- Monitors specified directories for Simatic S7 files (*.s7p) and other user-defined directories.
- Automatically compresses and backs up projects on a configurable schedule (daily, hourly, 3-hour, 7-hour intervals, startup, or manual).
- Supports manual backup triggers.
- Skips projects with files in use and retries after one hour.
- Maintains a two-stage hash system: first checking *.s7p files, then all files to avoid unnecessary backups.
- User-friendly web interface built with Flask for configuration and status monitoring.
- Comprehensive logging system with timestamped log files.
## Project Structure
```
autobackups
├── .logs/ # Application logs with startup timestamps
├── src
│ ├── app.py # Main entry point of the Flask application
│ ├── models
│ │ └── __init__.py # Data models for configuration and directories
│ ├── routes
│ │ └── __init__.py # API routes for backup operations
│ ├── services
│ │ └── __init__.py # Business logic for backups
│ └── utils
│ └── __init__.py # Utility functions for hashing and file access
├── static
│ ├── css # CSS files for styling
│ └── js # JavaScript files for client-side functionality
├── templates
│ └── index.html # Main HTML template for the web interface
├── config.json # Global configuration settings for the application
├── projects.json # Per-project configuration, schedules, and hash storage
├── requirements.txt # Python dependencies
└── README.md # Project documentation
```
## Installation
1. Clone the repository:
```
git clone <repository-url>
cd autobackups
```
2. Create a Miniconda environment:
```
conda create --name autobackups python=3.12
conda activate autobackups
```
3. Install the required packages:
```
pip install -r requirements.txt
```
4. Configure the application by editing `config.json` to specify directories to monitor and backup settings.
## Usage
- Start the Flask application:
```
python src/app.py
```
- Access the web interface at `http://localhost:5000` to configure settings and monitor backup statuses.
## Contributing
Contributions are welcome! Please submit a pull request or open an issue for any enhancements or bug fixes.
## License
This project is licensed under the MIT License. See the LICENSE file for details.

View File

@ -1,258 +0,0 @@
# AutoBackups - Especificación Técnica Detallada
## Resumen Ejecutivo
AutoBackups es una aplicación Python que automatiza el backup de proyectos Simatic S7 y directorios definidos por el usuario, utilizando la API de Everything para búsqueda eficiente de archivos y un sistema de hash inteligente para evitar backups innecesarios.
## Arquitectura del Sistema
### 1. Componentes Principales
#### 1.1 Motor de Búsqueda (Everything API)
- **Librería**: PyEverything wrapper
- **DLL Local**: `Everything-SDK\dll\Everything64.dll`
- **Función**: Localizar archivos *.s7p en directorios de observación
- **Optimización**: Evitar último nivel del árbol para archivos .s7p
- **Ventaja**: Aprovecha el índice existente de Everything para búsquedas instantáneas
#### 1.2 Sistema de Hash en Dos Etapas
**Etapa 1**: Hash rápido de archivos *.s7p
- Solo verifica MD5 de (timestamp + tamaño) de archivos .s7p
- Si no hay cambios → no se procede con backup
- Si hay cambios → procede a Etapa 2
**Etapa 2**: Hash completo del proyecto
- Calcula MD5 de (timestamp + tamaño) de todos los archivos del directorio
- Compara con último hash almacenado
- Solo hace backup si hay diferencias
#### 1.3 Scheduler de Background
- **daily**: Una vez al día a hora configurada
- **hourly**: Cada hora
- **3-hour**: Cada 3 horas
- **7-hour**: Cada 7 horas
- **startup**: Al iniciar la aplicación
- **manual**: Solo bajo demanda del usuario
- **Escaneos**: Automáticos cada 1 hora
- **Backups**: Mínimo cada 10 minutos
- **Prioridad**: Baja prioridad de sistema
### 2. Estructura de Datos
#### 2.1 config.json (Configuración Global)
```json
{
"observation_directories": [
{
"path": "C:\\Projects\\Siemens",
"type": "siemens_s7",
"enabled": true
},
{
"path": "D:\\Engineering\\Projects",
"type": "siemens_s7",
"enabled": true
},
{
"path": "C:\\Important\\Docs",
"type": "manual",
"enabled": true
}
],
"backup_destination": "D:\\Backups\\AutoBackups",
"default_schedule": "daily",
"default_schedule_time": "02:00",
"retry_delay_hours": 1,
"web_interface": {
"host": "127.0.0.1",
"port": 5000
},
"logging": {
"level": "INFO",
"max_log_files": 30
}
}
```
#### 2.2 projects.json (Estado de Proyectos)
```json
{
"projects": [
{
"id": "project_001",
"name": "PLC_MainLine",
"path": "C:\\Projects\\Siemens\\PLC_MainLine",
"type": "siemens_s7",
"s7p_file": "C:\\Projects\\Siemens\\PLC_MainLine\\PLC_MainLine.s7p",
"schedule": "daily",
"schedule_time": "02:00",
"enabled": true,
"last_backup": "2025-09-01T02:15:30",
"last_s7p_hash": "abc123def456",
"last_full_hash": "def789ghi012",
"last_s7p_timestamp": "2025-08-31T14:30:00",
"status": "ready",
"retry_count": 0,
"next_retry": null,
"error_message": null
}
]
}
```
### 3. Flujo de Operación
#### 3.1 Inicio de Aplicación
1. Cargar configuración desde `config.json`
2. Cargar estado de proyectos desde `projects.json`
3. Inicializar logger con timestamp de inicio
4. Escanear directorios de observación usando Everything API
5. Actualizar lista de proyectos detectados
6. Iniciar scheduler
7. Iniciar interfaz web Flask
#### 4.2 Proceso de Backup
1. **Verificación de Espacio**: Verificar mínimo 100MB libres
2. **Verificación de Acceso .s7p**: Intentar comprimir solo archivo .s7p
3. **Hash Etapa 1**: Verificar MD5 de (timestamp + tamaño) del archivo .s7p
4. **Hash Etapa 2**: Si Etapa 1 detecta cambios, verificar hash completo
5. **Compresión**: Crear archivo ZIP con estructura específica preservada
6. **Almacenamiento**: Guardar en `backup_destination/ProjectPath/YYYY-MM-DD/HH-MM-SS_projects.zip`
7. **Actualización**: Actualizar hashes y timestamps en `projects.json`
#### 3.3 Gestión de Errores
- **Archivos en uso**: Marcar proyecto para reintento en 1 hora
- **Errores de permisos**: Log de error y notificación en interfaz
- **Errores de espacio**: Verificar espacio disponible antes de backup
### 4. Interfaz Web
#### 4.1 Dashboard Principal
- **Lista de Proyectos**: Tabla con estado, último backup, próximo backup
- **Controles Globales**: Backup manual global, pausar/reanudar scheduler
- **Estadísticas**: Total de proyectos, backups exitosos, errores
#### 4.2 Configuración de Proyectos
- **Habilitación/Deshabilitación**: Toggle por proyecto
- **Configuración de Schedule**: Dropdown con opciones de frecuencia
- **Backup Manual**: Botón de backup inmediato por proyecto
#### 4.3 Logs y Monitoreo
- **Log Viewer**: Mostrar logs recientes con filtros por nivel
- **Estado del Sistema**: Información de Everything API, espacio en disco
### 5. Estructura de Backup
#### 5.1 Nomenclatura de Archivos (Estructura Específica)
```
backup_destination/
├── LineA/
│ └── Project1/
│ ├── 2025-09-01/
│ │ ├── 02-15-30_projects.zip
│ │ └── 14-30-15_projects.zip
│ └── 2025-09-02/
│ └── 02-15-45_projects.zip
└── LineB/
└── Project2/
└── 2025-09-01/
└── 08-20-10_projects.zip
```
#### 5.2 Contenido del ZIP
```
02-15-30_projects.zip
└── LineA/
└── Project1/
├── project.s7p
├── subfolder1/
└── subfolder2/
```
### 6. Tecnologías y Librerías
#### 6.1 Python Core
- **Python**: 3.12
- **Framework Web**: Flask
- **Scheduler**: APScheduler
- **Compresión**: zipfile (biblioteca estándar)
#### 6.2 Librerías Específicas
- **Everything API**: PyEverything wrapper con DLL local
- **Hashing**: hashlib MD5 para (timestamp + tamaño)
- **Config**: json (biblioteca estándar)
- **Logging**: logging (biblioteca estándar)
- **File Access Check**: Intento de compresión + verificación .s7p
- **Process Priority**: pywin32 para baja prioridad
- **Disk Space**: psutil para monitoreo de espacio libre
#### 6.3 Frontend
- **HTML/CSS/JavaScript**: Vanilla (sin React por simplicidad)
- **AJAX**: Para comunicación con Flask API
- **Bootstrap**: Para estilizado responsivo
### 7. Consideraciones de Seguridad
#### 7.1 Acceso a Archivos
- Verificación de permisos antes de backup
- Manejo seguro de rutas para evitar path traversal
- Logs de todos los accesos a archivos
#### 7.2 Interfaz Web
- Solo acceso local (127.0.0.1)
- No autenticación requerida (uso local únicamente)
- Validación de inputs en formularios
### 8. Logging y Monitoreo
#### 8.1 Estructura de Logs
```
.logs/
├── autobackups_2025-09-01_08-30-15.log
├── autobackups_2025-09-02_08-30-22.log
└── ...
```
#### 8.2 Niveles de Log
- **INFO**: Inicio/fin de backups, descubrimiento de proyectos
- **WARNING**: Archivos en uso, reintentos
- **ERROR**: Fallos de backup, errores de configuración
- **DEBUG**: Detalles de hashes, operaciones de archivos
### 9. Instalación y Despliegue
#### 9.1 Entorno Miniconda
```bash
conda create --name autobackups python=3.12
conda activate autobackups
pip install -r requirements.txt
```
#### 9.2 Ejecución
- **Desarrollo**: `python src/app.py`
- **Producción**: `pythonw.exe src/app.py` (sin consola)
- **Como servicio**: Futuro enhancement con `python-windows-service`
### 10. Roadmap de Desarrollo
#### Fase 1: Core Backend
- [ ] Integración con Everything API
- [ ] Sistema de hash en dos etapas
- [ ] Motor de backup básico
- [ ] Scheduler con APScheduler
#### Fase 2: Interfaz Web
- [ ] Dashboard básico con Flask
- [ ] API REST para operaciones CRUD
- [ ] Frontend con HTML/JS/Bootstrap
#### Fase 3: Características Avanzadas
- [ ] Logs web viewer
- [ ] Configuración avanzada de directorios
- [ ] Estadísticas y reportes
#### Fase 4: Optimizaciones
- [ ] Ejecución como servicio Windows
- [ ] Notificaciones por email
- [ ] Backup incremental
Este documento será la base para el desarrollo del proyecto AutoBackups.

View File

@ -1,124 +0,0 @@
# AutoBackups - Preguntas Técnicas Pendientes
## Preguntas Críticas para el Desarrollo
### 1. Everything API - Integración
**Pregunta**: ¿Everything está instalado y funcionando en el sistema objetivo?
**Impacto**: Si no está disponible, necesitaremos un método alternativo de búsqueda de archivos.
**Opciones**:
- Usar `python-everything` si Everything está disponible
- Implementar búsqueda recursiva con `os.walk()` como fallback
- Usar `pathlib` con `glob` patterns
**Decisión necesaria**: ¿Podemos asumir que Everything estará disponible o necesitamos fallback?
### 2. Estructura de Backup - Clarificación de Rutas
**Pregunta**: Si tenemos un archivo en `C:\Projects\Siemens\LineA\Project1\project.s7p`, ¿el backup debe ser?
**Opción A**:
```
backup_destination/2025-09-01_14-30-15/Projects_Siemens_LineA_Project1.zip
└── Projects/Siemens/LineA/Project1/...
```
**Opción B**:
```
backup_destination/2025-09-01_14-30-15/LineA_Project1.zip
└── LineA/Project1/...
```
**Decisión necesaria**: ¿Qué estructura prefieres?
### 3. Configuración de Schedules - Granularidad
**Pregunta**: ¿Los schedules deben ser configurables a nivel de:
- Por directorio de observación (todos los proyectos de un directorio)
- Por proyecto individual
- Ambos (global con override por proyecto)
**Decisión necesaria**: ¿Qué nivel de granularidad necesitas?
### 4. Hash de Archivos - Algoritmo y Almacenamiento
**Pregunta**: Para el sistema de hash en dos etapas:
- ¿Usamos MD5 (rápido) o SHA256 (más seguro) para los hashes?
- ¿El hash incluye solo timestamp o también tamaño de archivo?
- ¿Cómo manejamos archivos que se mueven dentro del proyecto?
**Decisión necesaria**: ¿Qué balance entre velocidad y precisión prefieres?
### 5. Detección de Archivos en Uso - Método
**Pregunta**: Para detectar archivos bloqueados, ¿prefieres:
**Opción A**: Intentar abrir cada archivo en modo escritura exclusiva
**Opción B**: Usar `lsof` (Linux) / `handle.exe` (Windows) para listar archivos abiertos
**Opción C**: Solo verificar el archivo .s7p principal
**Decisión necesaria**: ¿Qué método consideras más apropiado?
### 6. Manejo de Proyectos Grandes - Performance
**Pregunta**: ¿Hay límites que debamos considerar?
- Tamaño máximo de proyecto para backup
- Tiempo máximo de backup
- Número máximo de archivos por proyecto
**Decisión necesaria**: ¿Necesitamos algún tipo de throttling o límites?
### 7. Configuración de Directorios - Recursividad
**Pregunta**: Cuando especificamos un directorio de observación como `C:\Projects`, ¿debemos:
- Buscar solo en subdirectorios inmediatos
- Buscar recursivamente en toda la jerarquía
- Permitir configurar la profundidad de búsqueda
**Decisión necesaria**: ¿Qué comportamiento prefieres por defecto?
### 8. Backup Incremental vs Completo
**Pregunta**: ¿Todos los backups deben ser completos o consideras backup incremental?
- Backup completo: Todo el proyecto cada vez
- Backup incremental: Solo archivos modificados
**Decisión necesaria**: ¿Preferencia por simplicidad o eficiencia de espacio?
### 9. Web Interface - Características Específicas
**Pregunta**: ¿Qué funcionalidades son prioritarias en la interfaz web?
**Must-have**:
- Lista de proyectos con estado
- Trigger manual de backup
- Ver logs básicos
**Nice-to-have**:
- Configurar schedules por proyecto
- Ver progreso de backup en tiempo real
- Estadísticas históricas
- Configurar nuevos directorios
**Decisión necesaria**: ¿Cuáles son must-have vs nice-to-have?
### 10. Error Handling - Estrategias de Recuperación
**Pregunta**: ¿Cómo manejar errores específicos?
- Espacio insuficiente en destino de backup
- Pérdida de conexión con Everything
- Corrupción de archivos de configuración
- Falla durante compresión
**Decisión necesaria**: ¿Qué nivel de robustez necesitas?
### 11. Startup Behavior - Inicialización
**Pregunta**: Al iniciar la aplicación:
- ¿Debe hacer un escaneo completo inmediatamente?
- ¿Debe esperar al primer schedule programado?
- ¿Debe permitir configurar el comportamiento de startup?
**Decisión necesaria**: ¿Qué comportamiento prefieres al iniciar?
### 12. Multi-threading - Concurrencia
**Pregunta**: ¿Los backups deben ejecutarse:
- Secuencialmente (uno por vez)
- En paralelo (múltiples simultáneos)
- Con límite configurable de concurrencia
**Decisión necesaria**: ¿Qué balance entre velocidad y recursos del sistema?
## Próximos Pasos
Una vez que tengas respuestas a estas preguntas, podremos:
1. Finalizar el diseño técnico
2. Crear el `requirements.txt` definitivo
3. Comenzar con la implementación por fases
4. Definir el plan de testing
¿Podrías revisar estas preguntas y darme tus preferencias para cada una?

View File

@ -1,60 +0,0 @@
{
"observation_directories": [
{
"path": "C:\\Projects\\Siemens",
"type": "siemens_s7",
"enabled": true,
"description": "Directorio principal de proyectos Siemens"
},
{
"path": "D:\\Engineering\\Projects",
"type": "siemens_s7",
"enabled": true,
"description": "Proyectos de ingeniería adicionales"
},
{
"path": "C:\\Important\\Documentation",
"type": "manual",
"enabled": true,
"description": "Documentación importante para backup manual"
}
],
"backup_destination": "D:\\Backups\\AutoBackups",
"global_settings": {
"default_schedule": "daily",
"default_schedule_time": "02:00",
"retry_delay_hours": 1,
"backup_timeout_minutes": 0,
"min_free_space_mb": 100,
"scan_interval_minutes": 60,
"min_backup_interval_minutes": 10
},
"everything_api": {
"dll_path": "Everything-SDK\\dll\\Everything64.dll",
"enabled": true,
"search_depth": -1,
"skip_last_level_for_s7p": true
},
"web_interface": {
"host": "127.0.0.1",
"port": 5000,
"debug": false
},
"logging": {
"level": "INFO",
"max_log_files": 30,
"log_rotation_days": 30
},
"backup_options": {
"compression_level": 6,
"include_subdirectories": true,
"preserve_directory_structure": true,
"hash_algorithm": "md5",
"hash_includes": ["timestamp", "size"],
"backup_type": "complete",
"process_priority": "low",
"sequential_execution": true,
"filename_format": "HH-MM-SS_projects.zip",
"date_format": "YYYY-MM-DD"
}
}

View File

@ -1,62 +0,0 @@
{
"metadata": {
"version": "1.0",
"last_updated": "2025-09-01T08:30:15Z",
"total_projects": 0
},
"projects": [
{
"id": "example_project_001",
"name": "PLC_MainLine_Example",
"path": "C:\\Projects\\Siemens\\LineA\\Project1",
"type": "siemens_s7",
"s7p_file": "C:\\Projects\\Siemens\\LineA\\Project1\\project.s7p",
"observation_directory": "C:\\Projects\\Siemens",
"relative_path": "LineA\\Project1",
"backup_path": "LineA\\Project1",
"schedule_config": {
"schedule": "daily",
"schedule_time": "02:00",
"enabled": true,
"next_scheduled_backup": "2025-09-02T02:00:00Z"
},
"backup_history": {
"last_backup_date": "2025-09-01T02:15:30Z",
"last_backup_file": "D:\\Backups\\AutoBackups\\LineA\\Project1\\2025-09-01\\02-15-30_projects.zip",
"backup_count": 5,
"last_successful_backup": "2025-09-01T02:15:30Z"
},
"hash_info": {
"last_s7p_hash": "abc123def456789",
"last_full_hash": "def789ghi012345",
"last_s7p_timestamp": "2025-08-31T14:30:00Z",
"last_s7p_size": 2048576,
"last_scan_timestamp": "2025-09-01T02:10:00Z",
"file_count": 1247,
"total_size_bytes": 125847296
},
"status": {
"current_status": "ready",
"last_error": null,
"retry_count": 0,
"next_retry": null,
"files_in_use": false,
"exclusivity_check_passed": true,
"last_status_update": "2025-09-01T02:15:35Z"
},
"discovery_info": {
"discovered_date": "2025-09-01T08:30:15Z",
"discovery_method": "everything_api",
"auto_discovered": true
}
}
],
"statistics": {
"total_backups_created": 15,
"total_backup_size_mb": 2450.5,
"average_backup_time_seconds": 45.2,
"last_global_scan": "2025-09-01T08:30:15Z",
"projects_with_errors": 0,
"projects_pending_retry": 0
}
}

View File

@ -1,32 +0,0 @@
# Core Framework
Flask==2.3.3
Werkzeug==2.3.7
# Scheduling
APScheduler==3.10.4
# Everything API Integration
PyEverything==1.0.1 # Wrapper para Everything SDK
# File Operations and Utilities
pathlib2==2.3.7.post1 # Enhanced pathlib for Python 3.12
psutil==5.9.5 # System utilities (disk space monitoring)
filelock==3.12.4 # File locking for concurrent access
# Web Interface
Jinja2==3.1.2 # Template engine for Flask
# Configuration and Data
jsonschema==4.19.1 # JSON schema validation
# Logging
colorlog==6.7.0 # Colored logging output
# Windows-specific dependencies
pywin32==306; sys_platform == "win32" # Windows API access for low priority
# Development and Testing (opcional, remove for production)
pytest==7.4.2
pytest-flask==1.2.0
black==23.9.1 # Code formatting
flake8==6.1.0 # Code linting

525
README.md Normal file
View File

@ -0,0 +1,525 @@
# AutoBackups Project
## Overview
AutoBackups is a Python application designed to automate the backup of Simatic S7 projects and other user-defined directories. The application leverages the Everything API to efficiently locate files and manage backups based on user-defined configurations.
## Features
- Monitors specified directories for Simatic S7 files (*.s7p) and other user-defined directories.
- Automatically compresses and backs up projects on a configurable schedule (daily, hourly, 3-hour, 7-hour intervals, startup, or manual).
- Supports manual backup triggers.
- Skips projects with files in use and retries after one hour.
- Maintains a two-stage hash system: first checking *.s7p files, then all files to avoid unnecessary backups.
- User-friendly web interface built with Flask for configuration and status monitoring.
- Comprehensive logging system with timestamped log files.
## Project Structure
```
├── .logs/ # Application logs with startup timestamps
├── src
│ ├── app.py # Main entry point of the Flask application
│ ├── models
│ │ └── __init__.py # Data models for configuration and directories
│ ├── routes
│ │ └── __init__.py # API routes for backup operations
│ ├── services
│ │ └── __init__.py # Business logic for backups
│ └── utils
│ └── __init__.py # Utility functions for hashing and file access
├── static
│ ├── css # CSS files for styling
│ └── js # JavaScript files for client-side functionality
├── templates
│ └── index.html # Main HTML template for the web interface
├── config.json # Global configuration settings for the application
├── projects.json # Per-project configuration, schedules, and hash storage
├── requirements.txt # Python dependencies
└── README.md # Project documentation
```
## Installation
1. Clone the repository:
```
git clone <repository-url>
cd autobackups
```
2. Create a Miniconda environment:
```
conda create --name autobackups python=3.12
conda activate autobackups
```
3. Install the required packages:
```
pip install -r requirements.txt
```
4. Configure the application by editing `config.json` to specify directories to monitor and backup settings.
## Usage
- Start the Flask application:
```
python src/app.py
```
- Access the web interface at `http://localhost:5120` to configure settings and monitor backup statuses.
## Contributing
Contributions are welcome! Please submit a pull request or open an issue for any enhancements or bug fixes.
## License
This project is licensed under the MIT License. See the LICENSE file for details.
# AutoBackups - Especificación Técnica Detallada
## Resumen Ejecutivo
AutoBackups es una aplicación Python que automatiza el backup de proyectos Simatic S7 y directorios definidos por el usuario, utilizando la API de Everything para búsqueda eficiente de archivos y un sistema de hash inteligente para evitar backups innecesarios.
## Arquitectura del Sistema
### 1. Componentes Principales
#### 1.1 Motor de Búsqueda (Everything API)
- **Librería**: PyEverything wrapper
- **DLL Local**: `Everything-SDK\dll\Everything64.dll`
- **Función**: Localizar archivos *.s7p en directorios de observación
- **Optimización**: Evitar último nivel del árbol para archivos .s7p
- **Ventaja**: Aprovecha el índice existente de Everything para búsquedas instantáneas
#### 1.2 Sistema de Hash en Dos Etapas
**Etapa 1**: Hash rápido de archivos *.s7p
- Solo verifica MD5 de (timestamp + tamaño) de archivos .s7p
- Si no hay cambios → no se procede con backup
- Si hay cambios → procede a Etapa 2
**Etapa 2**: Hash completo del proyecto
- Calcula MD5 de (timestamp + tamaño) de todos los archivos del directorio
- Compara con último hash almacenado
- Solo hace backup si hay diferencias
#### 1.3 Scheduler de Background
- **daily**: Una vez al día a hora configurada
- **hourly**: Cada hora
- **3-hour**: Cada 3 horas
- **7-hour**: Cada 7 horas
- **startup**: Al iniciar la aplicación
- **manual**: Solo bajo demanda del usuario
- **Escaneos**: Automáticos cada 1 hora
- **Backups**: Mínimo cada 10 minutos
- **Prioridad**: Baja prioridad de sistema
### 2. Estructura de Datos
#### 2.1 config.json (Configuración Global)
```json
{
"observation_directories": [
{
"path": "C:\\Projects\\Siemens",
"type": "siemens_s7",
"enabled": true,
"description": "Directorio principal de proyectos Siemens"
},
{
"path": "D:\\Engineering\\Projects",
"type": "siemens_s7",
"enabled": true,
"description": "Proyectos de ingeniería adicionales"
},
{
"path": "C:\\Important\\Documentation",
"type": "manual",
"enabled": true,
"description": "Documentación importante para backup manual"
}
],
"backup_destination": "D:\\Backups\\AutoBackups",
"global_settings": {
"default_schedule": "daily",
"default_schedule_time": "02:00",
"retry_delay_hours": 1,
"backup_timeout_minutes": 0,
"min_free_space_mb": 100,
"scan_interval_minutes": 60,
"min_backup_interval_minutes": 10
},
"everything_api": {
"dll_path": "Everything-SDK\\dll\\Everything64.dll",
"enabled": true,
"search_depth": -1,
"skip_last_level_for_s7p": true
},
"web_interface": {
"host": "127.0.0.1",
"port": 5000,
"debug": false
},
"logging": {
"level": "INFO",
"max_log_files": 30,
"log_rotation_days": 30
},
"backup_options": {
"compression_level": 6,
"include_subdirectories": true,
"preserve_directory_structure": true,
"hash_algorithm": "md5",
"hash_includes": ["timestamp", "size"],
"backup_type": "complete",
"process_priority": "low",
"sequential_execution": true,
"filename_format": "HH-MM-SS_projects.zip",
"date_format": "YYYY-MM-DD"
}
}
```
#### 2.2 projects.json (Estado de Proyectos)
```json
{
"metadata": {
"version": "1.0",
"last_updated": "2025-09-01T08:30:15Z",
"total_projects": 0
},
"projects": [
{
"id": "example_project_001",
"name": "PLC_MainLine_Example",
"path": "C:\\Projects\\Siemens\\LineA\\Project1",
"type": "siemens_s7",
"s7p_file": "C:\\Projects\\Siemens\\LineA\\Project1\\project.s7p",
"observation_directory": "C:\\Projects\\Siemens",
"relative_path": "LineA\\Project1",
"backup_path": "LineA\\Project1",
"schedule_config": {
"schedule": "daily",
"schedule_time": "02:00",
"enabled": true,
"next_scheduled_backup": "2025-09-02T02:00:00Z"
},
"backup_history": {
"last_backup_date": "2025-09-01T02:15:30Z",
"last_backup_file": "D:\\Backups\\AutoBackups\\LineA\\Project1\\2025-09-01\\02-15-30_projects.zip",
"backup_count": 5,
"last_successful_backup": "2025-09-01T02:15:30Z"
},
"hash_info": {
"last_s7p_hash": "abc123def456789",
"last_full_hash": "def789ghi012345",
"last_s7p_timestamp": "2025-08-31T14:30:00Z",
"last_s7p_size": 2048576,
"last_scan_timestamp": "2025-09-01T02:10:00Z",
"file_count": 1247,
"total_size_bytes": 125847296
},
"status": {
"current_status": "ready",
"last_error": null,
"retry_count": 0,
"next_retry": null,
"files_in_use": false,
"exclusivity_check_passed": true,
"last_status_update": "2025-09-01T02:15:35Z"
},
"discovery_info": {
"discovered_date": "2025-09-01T08:30:15Z",
"discovery_method": "everything_api",
"auto_discovered": true
}
}
],
"statistics": {
"total_backups_created": 15,
"total_backup_size_mb": 2450.5,
"average_backup_time_seconds": 45.2,
"last_global_scan": "2025-09-01T08:30:15Z",
"projects_with_errors": 0,
"projects_pending_retry": 0
}
}
```
### 3. Flujo de Operación
#### 3.1 Inicio de Aplicación
1. Cargar configuración desde `config.json`
2. Cargar estado de proyectos desde `projects.json`
3. Inicializar logger con timestamp de inicio
4. Escanear directorios de observación usando Everything API
5. Actualizar lista de proyectos detectados
6. Iniciar scheduler
7. Iniciar interfaz web Flask
#### 4.2 Proceso de Backup
1. **Verificación de Espacio**: Verificar mínimo 100MB libres
2. **Verificación de Acceso .s7p**: Intentar comprimir solo archivo .s7p
3. **Hash Etapa 1**: Verificar MD5 de (timestamp + tamaño) del archivo .s7p
4. **Hash Etapa 2**: Si Etapa 1 detecta cambios, verificar hash completo
5. **Compresión**: Crear archivo ZIP con estructura específica preservada
6. **Almacenamiento**: Guardar en `backup_destination/ProjectPath/YYYY-MM-DD/HH-MM-SS_projects.zip`
7. **Actualización**: Actualizar hashes y timestamps en `projects.json`
#### 3.3 Gestión de Errores
- **Archivos en uso**: Marcar proyecto para reintento en 1 hora
- **Errores de permisos**: Log de error y notificación en interfaz
- **Errores de espacio**: Verificar espacio disponible antes de backup
### 4. Interfaz Web
#### 4.1 Dashboard Principal
- **Lista de Proyectos**: Tabla con estado, último backup, próximo backup
- **Controles Globales**: Backup manual global, pausar/reanudar scheduler
- **Estadísticas**: Total de proyectos, backups exitosos, errores
#### 4.2 Configuración de Proyectos
- **Habilitación/Deshabilitación**: Toggle por proyecto
- **Configuración de Schedule**: Dropdown con opciones de frecuencia
- **Backup Manual**: Botón de backup inmediato por proyecto
#### 4.3 Logs y Monitoreo
- **Log Viewer**: Mostrar logs recientes con filtros por nivel
- **Estado del Sistema**: Información de Everything API, espacio en disco
### 5. Estructura de Backup
#### 5.1 Nomenclatura de Archivos (Estructura Específica)
```
backup_destination/
├── LineA/
│ └── Project1/
│ ├── 2025-09-01/
│ │ ├── 02-15-30_projects.zip
│ │ └── 14-30-15_projects.zip
│ └── 2025-09-02/
│ └── 02-15-45_projects.zip
└── LineB/
└── Project2/
└── 2025-09-01/
└── 08-20-10_projects.zip
```
#### 5.2 Contenido del ZIP
```
02-15-30_projects.zip
└── LineA/
└── Project1/
├── project.s7p
├── subfolder1/
└── subfolder2/
```
### 6. Tecnologías y Librerías
#### 6.1 Python Core
- **Python**: 3.12
- **Framework Web**: Flask
- **Scheduler**: APScheduler
- **Compresión**: zipfile (biblioteca estándar)
#### 6.2 Librerías Específicas
- **Everything API**: PyEverything wrapper con DLL local
- **Hashing**: hashlib MD5 para (timestamp + tamaño)
- **Config**: json (biblioteca estándar)
- **Logging**: logging (biblioteca estándar)
- **File Access Check**: Intento de compresión + verificación .s7p
- **Process Priority**: pywin32 para baja prioridad
- **Disk Space**: psutil para monitoreo de espacio libre
#### 6.3 Frontend
- **HTML/CSS/JavaScript**: Vanilla (sin React por simplicidad)
- **AJAX**: Para comunicación con Flask API
- **Bootstrap**: Para estilizado responsivo
### 7. Consideraciones de Seguridad
#### 7.1 Acceso a Archivos
- Verificación de permisos antes de backup
- Manejo seguro de rutas para evitar path traversal
- Logs de todos los accesos a archivos
#### 7.2 Interfaz Web
- Solo acceso local (127.0.0.1)
- No autenticación requerida (uso local únicamente)
- Validación de inputs en formularios
### 8. Logging y Monitoreo
#### 8.1 Estructura de Logs
```
.logs/
├── autobackups_2025-09-01_08-30-15.log
├── autobackups_2025-09-02_08-30-22.log
└── ...
```
#### 8.2 Niveles de Log
- **INFO**: Inicio/fin de backups, descubrimiento de proyectos
- **WARNING**: Archivos en uso, reintentos
- **ERROR**: Fallos de backup, errores de configuración
- **DEBUG**: Detalles de hashes, operaciones de archivos
### 9. Instalación y Despliegue
#### 9.1 Entorno Miniconda
```bash
conda create --name autobackups python=3.12
conda activate autobackups
pip install -r requirements.txt
```
#### 9.2 Ejecución
- **Desarrollo**: `python src/app.py`
- **Producción**: `pythonw.exe src/app.py` (sin consola)
- **Como servicio**: Futuro enhancement con `python-windows-service`
### 10. Roadmap de Desarrollo
#### Fase 1: Core Backend
- [ ] Integración con Everything API
- [ ] Sistema de hash en dos etapas
- [ ] Motor de backup básico
- [ ] Scheduler con APScheduler
#### Fase 2: Interfaz Web
- [ ] Dashboard básico con Flask
- [ ] API REST para operaciones CRUD
- [ ] Frontend con HTML/JS/Bootstrap
#### Fase 3: Características Avanzadas
- [ ] Logs web viewer
- [ ] Configuración avanzada de directorios
- [ ] Estadísticas y reportes
#### Fase 4: Optimizaciones
- [ ] Ejecución como servicio Windows
- [ ] Notificaciones por email
- [ ] Backup incremental
Este documento será la base para el desarrollo del proyecto AutoBackups.
# AutoBackups - Preguntas Técnicas Pendientes
## Preguntas Críticas para el Desarrollo
### 1. Everything API - Integración
**Pregunta**: ¿Everything está instalado y funcionando en el sistema objetivo?
**Impacto**: Si no está disponible, necesitaremos un método alternativo de búsqueda de archivos.
**Opciones**:
- Usar `python-everything` si Everything está disponible
- Implementar búsqueda recursiva con `os.walk()` como fallback
- Usar `pathlib` con `glob` patterns
**Decisión necesaria**: ¿Podemos asumir que Everything estará disponible o necesitamos fallback?
### 2. Estructura de Backup - Clarificación de Rutas
**Pregunta**: Si tenemos un archivo en `C:\Projects\Siemens\LineA\Project1\project.s7p`, ¿el backup debe ser?
**Opción A**:
```
backup_destination/2025-09-01_14-30-15/Projects_Siemens_LineA_Project1.zip
└── Projects/Siemens/LineA/Project1/...
```
**Opción B**:
```
backup_destination/2025-09-01_14-30-15/LineA_Project1.zip
└── LineA/Project1/...
```
**Decisión necesaria**: ¿Qué estructura prefieres?
### 3. Configuración de Schedules - Granularidad
**Pregunta**: ¿Los schedules deben ser configurables a nivel de:
- Por directorio de observación (todos los proyectos de un directorio)
- Por proyecto individual
- Ambos (global con override por proyecto)
**Decisión necesaria**: ¿Qué nivel de granularidad necesitas?
### 4. Hash de Archivos - Algoritmo y Almacenamiento
**Pregunta**: Para el sistema de hash en dos etapas:
- ¿Usamos MD5 (rápido) o SHA256 (más seguro) para los hashes?
- ¿El hash incluye solo timestamp o también tamaño de archivo?
- ¿Cómo manejamos archivos que se mueven dentro del proyecto?
**Decisión necesaria**: ¿Qué balance entre velocidad y precisión prefieres?
### 5. Detección de Archivos en Uso - Método
**Pregunta**: Para detectar archivos bloqueados, ¿prefieres:
**Opción A**: Intentar abrir cada archivo en modo escritura exclusiva
**Opción B**: Usar `lsof` (Linux) / `handle.exe` (Windows) para listar archivos abiertos
**Opción C**: Solo verificar el archivo .s7p principal
**Decisión necesaria**: ¿Qué método consideras más apropiado?
### 6. Manejo de Proyectos Grandes - Performance
**Pregunta**: ¿Hay límites que debamos considerar?
- Tamaño máximo de proyecto para backup
- Tiempo máximo de backup
- Número máximo de archivos por proyecto
**Decisión necesaria**: ¿Necesitamos algún tipo de throttling o límites?
### 7. Configuración de Directorios - Recursividad
**Pregunta**: Cuando especificamos un directorio de observación como `C:\Projects`, ¿debemos:
- Buscar solo en subdirectorios inmediatos
- Buscar recursivamente en toda la jerarquía
- Permitir configurar la profundidad de búsqueda
**Decisión necesaria**: ¿Qué comportamiento prefieres por defecto?
### 8. Backup Incremental vs Completo
**Pregunta**: ¿Todos los backups deben ser completos o consideras backup incremental?
- Backup completo: Todo el proyecto cada vez
- Backup incremental: Solo archivos modificados
**Decisión necesaria**: ¿Preferencia por simplicidad o eficiencia de espacio?
### 9. Web Interface - Características Específicas
**Pregunta**: ¿Qué funcionalidades son prioritarias en la interfaz web?
**Must-have**:
- Lista de proyectos con estado
- Trigger manual de backup
- Ver logs básicos
**Nice-to-have**:
- Configurar schedules por proyecto
- Ver progreso de backup en tiempo real
- Estadísticas históricas
- Configurar nuevos directorios
**Decisión necesaria**: ¿Cuáles son must-have vs nice-to-have?
### 10. Error Handling - Estrategias de Recuperación
**Pregunta**: ¿Cómo manejar errores específicos?
- Espacio insuficiente en destino de backup
- Pérdida de conexión con Everything
- Corrupción de archivos de configuración
- Falla durante compresión
**Decisión necesaria**: ¿Qué nivel de robustez necesitas?
### 11. Startup Behavior - Inicialización
**Pregunta**: Al iniciar la aplicación:
- ¿Debe hacer un escaneo completo inmediatamente?
- ¿Debe esperar al primer schedule programado?
- ¿Debe permitir configurar el comportamiento de startup?
**Decisión necesaria**: ¿Qué comportamiento prefieres al iniciar?
### 12. Multi-threading - Concurrencia
**Pregunta**: ¿Los backups deben ejecutarse:
- Secuencialmente (uno por vez)
- En paralelo (múltiples simultáneos)
- Con límite configurable de concurrencia
**Decisión necesaria**: ¿Qué balance entre velocidad y recursos del sistema?
## Próximos Pasos
Una vez que tengas respuestas a estas preguntas, podremos:
1. Finalizar el diseño técnico
2. Crear el `requirements.txt` definitivo
3. Comenzar con la implementación por fases
4. Definir el plan de testing
¿Podrías revisar estas preguntas y darme tus preferencias para cada una?

View File

@ -1,245 +0,0 @@
# AutoBackups - Especificación Técnica Detallada
## Resumen Ejecutivo
AutoBackups es una aplicación Python que automatiza el backup de proyectos Simatic S7 y directorios definidos por el usuario, utilizando la API de Everything para búsqueda eficiente de archivos y un sistema de hash inteligente para evitar backups innecesarios.
## Arquitectura del Sistema
### 1. Componentes Principales
#### 1.1 Motor de Búsqueda (Everything API)
- **Librería**: `python-everything` o integración directa con Everything SDK
- **Función**: Localizar archivos *.s7p en directorios de observación
- **Ventaja**: Aprovecha el índice existente de Everything para búsquedas instantáneas
#### 1.2 Sistema de Hash en Dos Etapas
**Etapa 1**: Hash rápido de archivos *.s7p
- Solo verifica timestamps de archivos .s7p
- Si no hay cambios → no se procede con backup
- Si hay cambios → procede a Etapa 2
**Etapa 2**: Hash completo del proyecto
- Calcula hash de todos los archivos del directorio del proyecto
- Compara con último hash almacenado
- Solo hace backup si hay diferencias
#### 1.3 Scheduler Flexible
- **daily**: Una vez al día a hora configurada
- **hourly**: Cada hora
- **3-hour**: Cada 3 horas
- **7-hour**: Cada 7 horas
- **startup**: Al iniciar la aplicación
- **manual**: Solo bajo demanda del usuario
### 2. Estructura de Datos
#### 2.1 config.json (Configuración Global)
```json
{
"observation_directories": [
{
"path": "C:\\Projects\\Siemens",
"type": "siemens_s7",
"enabled": true
},
{
"path": "D:\\Engineering\\Projects",
"type": "siemens_s7",
"enabled": true
},
{
"path": "C:\\Important\\Docs",
"type": "manual",
"enabled": true
}
],
"backup_destination": "D:\\Backups\\AutoBackups",
"default_schedule": "daily",
"default_schedule_time": "02:00",
"retry_delay_hours": 1,
"web_interface": {
"host": "127.0.0.1",
"port": 5000
},
"logging": {
"level": "INFO",
"max_log_files": 30
}
}
```
#### 2.2 projects.json (Estado de Proyectos)
```json
{
"projects": [
{
"id": "project_001",
"name": "PLC_MainLine",
"path": "C:\\Projects\\Siemens\\PLC_MainLine",
"type": "siemens_s7",
"s7p_file": "C:\\Projects\\Siemens\\PLC_MainLine\\PLC_MainLine.s7p",
"schedule": "daily",
"schedule_time": "02:00",
"enabled": true,
"last_backup": "2025-09-01T02:15:30",
"last_s7p_hash": "abc123def456",
"last_full_hash": "def789ghi012",
"last_s7p_timestamp": "2025-08-31T14:30:00",
"status": "ready",
"retry_count": 0,
"next_retry": null,
"error_message": null
}
]
}
```
### 3. Flujo de Operación
#### 3.1 Inicio de Aplicación
1. Cargar configuración desde `config.json`
2. Cargar estado de proyectos desde `projects.json`
3. Inicializar logger con timestamp de inicio
4. Escanear directorios de observación usando Everything API
5. Actualizar lista de proyectos detectados
6. Iniciar scheduler
7. Iniciar interfaz web Flask
#### 3.2 Proceso de Backup
1. **Verificación de Acceso**: Intentar abrir archivos en modo lectura
2. **Hash Etapa 1**: Verificar timestamp del archivo .s7p
3. **Hash Etapa 2**: Si Etapa 1 detecta cambios, verificar hash completo
4. **Compresión**: Crear archivo ZIP con estructura de directorios preservada
5. **Almacenamiento**: Guardar en `backup_destination/YYYY-MM-DD_HH-MM-SS/`
6. **Actualización**: Actualizar hashes y timestamps en `projects.json`
#### 3.3 Gestión de Errores
- **Archivos en uso**: Marcar proyecto para reintento en 1 hora
- **Errores de permisos**: Log de error y notificación en interfaz
- **Errores de espacio**: Verificar espacio disponible antes de backup
### 4. Interfaz Web
#### 4.1 Dashboard Principal
- **Lista de Proyectos**: Tabla con estado, último backup, próximo backup
- **Controles Globales**: Backup manual global, pausar/reanudar scheduler
- **Estadísticas**: Total de proyectos, backups exitosos, errores
#### 4.2 Configuración de Proyectos
- **Habilitación/Deshabilitación**: Toggle por proyecto
- **Configuración de Schedule**: Dropdown con opciones de frecuencia
- **Backup Manual**: Botón de backup inmediato por proyecto
#### 4.3 Logs y Monitoreo
- **Log Viewer**: Mostrar logs recientes con filtros por nivel
- **Estado del Sistema**: Información de Everything API, espacio en disco
### 5. Estructura de Backup
#### 5.1 Nomenclatura de Archivos
```
backup_destination/
├── 2025-09-01_02-15-30/
│ ├── Projects_Siemens_PLC_MainLine.zip
│ └── Important_Docs_Documentation.zip
└── 2025-09-02_02-15-45/
└── Projects_Siemens_PLC_SecondaryLine.zip
```
#### 5.2 Contenido del ZIP
```
PLC_MainLine.zip
└── Projects/
└── Siemens/
└── PLC_MainLine/
├── PLC_MainLine.s7p
├── subfolder1/
└── subfolder2/
```
### 6. Tecnologías y Librerías
#### 6.1 Python Core
- **Python**: 3.12
- **Framework Web**: Flask
- **Scheduler**: APScheduler
- **Compresión**: zipfile (biblioteca estándar)
#### 6.2 Librerías Específicas
- **Everything API**: `python-everything` o implementación custom
- **Hashing**: hashlib (biblioteca estándar)
- **Config**: json (biblioteca estándar)
- **Logging**: logging (biblioteca estándar)
- **File Access Check**: Implementación custom con try/except
#### 6.3 Frontend
- **HTML/CSS/JavaScript**: Vanilla (sin React por simplicidad)
- **AJAX**: Para comunicación con Flask API
- **Bootstrap**: Para estilizado responsivo
### 7. Consideraciones de Seguridad
#### 7.1 Acceso a Archivos
- Verificación de permisos antes de backup
- Manejo seguro de rutas para evitar path traversal
- Logs de todos los accesos a archivos
#### 7.2 Interfaz Web
- Solo acceso local (127.0.0.1)
- No autenticación requerida (uso local únicamente)
- Validación de inputs en formularios
### 8. Logging y Monitoreo
#### 8.1 Estructura de Logs
```
.logs/
├── autobackups_2025-09-01_08-30-15.log
├── autobackups_2025-09-02_08-30-22.log
└── ...
```
#### 8.2 Niveles de Log
- **INFO**: Inicio/fin de backups, descubrimiento de proyectos
- **WARNING**: Archivos en uso, reintentos
- **ERROR**: Fallos de backup, errores de configuración
- **DEBUG**: Detalles de hashes, operaciones de archivos
### 9. Instalación y Despliegue
#### 9.1 Entorno Miniconda
```bash
conda create --name autobackups python=3.12
conda activate autobackups
pip install -r requirements.txt
```
#### 9.2 Ejecución
- **Desarrollo**: `python src/app.py`
- **Producción**: `pythonw.exe src/app.py` (sin consola)
- **Como servicio**: Futuro enhancement con `python-windows-service`
### 10. Roadmap de Desarrollo
#### Fase 1: Core Backend
- [ ] Integración con Everything API
- [ ] Sistema de hash en dos etapas
- [ ] Motor de backup básico
- [ ] Scheduler con APScheduler
#### Fase 2: Interfaz Web
- [ ] Dashboard básico con Flask
- [ ] API REST para operaciones CRUD
- [ ] Frontend con HTML/JS/Bootstrap
#### Fase 3: Características Avanzadas
- [ ] Logs web viewer
- [ ] Configuración avanzada de directorios
- [ ] Estadísticas y reportes
#### Fase 4: Optimizaciones
- [ ] Ejecución como servicio Windows
- [ ] Notificaciones por email
- [ ] Backup incremental
Este documento será la base para el desarrollo del proyecto AutoBackups.

View File

@ -1,111 +0,0 @@
# AutoBackups - Decisiones Técnicas Finalizadas
## Decisiones Técnicas Confirmadas
### 1. Everything API - Integración ✅
**Decisión**: Everything SDK está instalado bajo `Everything-SDK\dll\Everything64.dll`
**Implementación**: Usar PyEverything (Wrapper) sin fallback
**Ruta DLL**: `Everything-SDK\dll\Everything64.dll`
### 2. Estructura de Backup - Clarificación de Rutas ✅
**Decisión**: Estructura específica con formato de fecha personalizado
**Ejemplo**:
- Directorio base: `C:\Projects\Siemens`
- Proyecto: `C:\Projects\Siemens\LineA\Project1\project.s7p`
- Backup: `backup_destination/LineA/Project1/2025-09-01/14-30-15_projects.zip`
**Formato**: YYYY-MM-DD para fechas, HH-MM-SS formato 24 horas
### 3. Configuración de Schedules - Granularidad ✅
**Decisión**: Ambos niveles (global con override por proyecto)
**Implementación**:
- Configuración global por defecto
- Override individual por proyecto
- Interfaz web para modificar ambos niveles
### 4. Hash de Archivos - Algoritmo y Almacenamiento ✅
**Decisión**: Hash de timestamps + tamaño (NO contenido)
**Algoritmo**: MD5 para velocidad
**Incluye**: timestamp + tamaño de archivo
**Prioridad**: Velocidad sobre seguridad criptográfica
### 5. Detección de Archivos en Uso - Método ✅
**Decisión**: Detección por intento de compresión
**Método Primario**: Intentar comprimir y detectar errores de exclusividad
**Método Rápido**: Verificar archivo .s7p antes de comprimir proyecto completo
**Manejo de Errores**: Marcar como problema de exclusividad si falla
### 6. Manejo de Proyectos Grandes - Performance ✅
**Decisión**: Sin límites de tamaño, tiempo o archivos
**Implementación**: Sin throttling, procesar cualquier tamaño de proyecto
**Prioridad**: Baja prioridad de sistema para no interferir
### 7. Configuración de Directorios - Recursividad ✅
**Decisión**: Búsqueda recursiva con optimización para .s7p
**Implementación**:
- Búsqueda recursiva en toda la jerarquía
- Optimización: evitar último nivel para archivos .s7p
- Razón: archivos .s7p no pueden estar en el último nivel del árbol
### 8. Backup Incremental vs Completo ✅
**Decisión**: Siempre backup completo
**Implementación**: Todo el proyecto cada vez
**Razón**: Simplicidad y asegurar integridad completa
### 9. Web Interface - Características Específicas ✅
**Must-have**:
- Lista de proyectos con estado ✅
- Trigger manual de backup ✅
- Ver logs básicos ✅
- Configurar schedules por proyecto ✅
- **Modificar configuración general (config.json) ✅**
**Nice-to-have**:
- Ver progreso de backup en tiempo real
- Estadísticas históricas
- Configurar nuevos directorios
### 10. Error Handling - Estrategias de Recuperación ✅
**Espacio Insuficiente**:
- Área de status en página web mostrando espacio libre
- Límite mínimo: 100MB libres para ejecutar backups
- Sin backups si espacio < 100MB
**Otros Errores**:
- Marcar para reintento en 1 hora
- Log de errores para diagnóstico
### 11. Startup Behavior - Inicialización ✅
**Decisión**: Aplicación de background con timers específicos
**Comportamiento**:
- Escaneos programados: cada 1 hora
- Backups mínimo: cada 10 minutos
- Aplicación siempre en background
- Baja prioridad de sistema
### 12. Multi-threading - Concurrencia ✅
**Decisión**: Ejecución secuencial (uno por vez)
**Implementación**:
- Backups secuenciales para economizar recursos
- Baja prioridad de sistema
- Orientado a operación en background sin interferir
## Especificación Técnica Finalizada ✅
### Resumen de Decisiones Clave:
1. **Everything SDK**: PyEverything wrapper con DLL local
2. **Estructura de Backup**: `backup_destination/ProjectPath/YYYY-MM-DD/HH-MM-SS_projects.zip`
3. **Hash**: MD5 de (timestamp + tamaño) para velocidad
4. **Detección de Uso**: Por intento de compresión + verificación .s7p
5. **Performance**: Sin límites, baja prioridad, secuencial
6. **Búsqueda**: Recursiva evitando último nivel para .s7p
7. **Backups**: Siempre completos
8. **Interfaz**: Flask con configuración de config.json
9. **Espacio**: Mínimo 100MB libres, status visible
10. **Background**: Escaneos 1h, backups min 10min
11. **Concurrencia**: Secuencial, baja prioridad
### Próximos Pasos:
1. ✅ Finalizar diseño técnico basado en decisiones
2. ⏳ Actualizar `requirements.txt` con PyEverything
3. ⏳ Comenzar implementación por fases
4. ⏳ Crear estructura básica del proyecto

216
autobackups/.gitignore vendored
View File

@ -1,216 +0,0 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[codz]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py.cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
#poetry.toml
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
#pdm.lock
#pdm.toml
.pdm-python
.pdm-build/
# pixi
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
#pixi.lock
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
# in the .venv directory. It is recommended not to include this directory in version control.
.pixi
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# Redis
*.rdb
*.aof
*.pid
# RabbitMQ
mnesia/
rabbitmq/
rabbitmq-data/
# ActiveMQ
activemq-data/
# SageMath parsed files
*.sage.py
# Environments
.env
.envrc
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Abstra
# Abstra is an AI-powered process automation framework.
# Ignore directories containing user credentials, local state, and settings.
# Learn more at https://abstra.io/docs
.abstra/
# Visual Studio Code
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
# and can be added to the global gitignore or merged into this file. However, if you prefer,
# you could uncomment the following to ignore the entire vscode folder
# .vscode/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc
# Marimo
marimo/_static/
marimo/_lsp/
__marimo__/
# Streamlit
.streamlit/secrets.toml

View File

@ -1,72 +0,0 @@
# AutoBackups Project
## Overview
AutoBackups is a Python application designed to automate the backup of Simatic S7 projects and other user-defined directories. The application leverages the Everything API to efficiently locate files and manage backups based on user-defined configurations.
## Features
- Monitors specified directories for Simatic S7 files (*.s7p) and other user-defined directories.
- Automatically compresses and backs up projects on a configurable schedule (daily, hourly, 3-hour, 7-hour intervals, startup, or manual).
- Supports manual backup triggers.
- Skips projects with files in use and retries after one hour.
- Maintains a two-stage hash system: first checking *.s7p files, then all files to avoid unnecessary backups.
- User-friendly web interface built with Flask for configuration and status monitoring.
- Comprehensive logging system with timestamped log files.
## Project Structure
```
autobackups
├── .logs/ # Application logs with startup timestamps
├── src
│ ├── app.py # Main entry point of the Flask application
│ ├── models
│ │ └── __init__.py # Data models for configuration and directories
│ ├── routes
│ │ └── __init__.py # API routes for backup operations
│ ├── services
│ │ └── __init__.py # Business logic for backups
│ └── utils
│ └── __init__.py # Utility functions for hashing and file access
├── static
│ ├── css # CSS files for styling
│ └── js # JavaScript files for client-side functionality
├── templates
│ └── index.html # Main HTML template for the web interface
├── config.json # Global configuration settings for the application
├── projects.json # Per-project configuration, schedules, and hash storage
├── requirements.txt # Python dependencies
└── README.md # Project documentation
```
## Installation
1. Clone the repository:
```
git clone <repository-url>
cd autobackups
```
2. Create a Miniconda environment:
```
conda create --name autobackups python=3.12
conda activate autobackups
```
3. Install the required packages:
```
pip install -r requirements.txt
```
4. Configure the application by editing `config.json` to specify directories to monitor and backup settings.
## Usage
- Start the Flask application:
```
python src/app.py
```
- Access the web interface at `http://localhost:5000` to configure settings and monitor backup statuses.
## Contributing
Contributions are welcome! Please submit a pull request or open an issue for any enhancements or bug fixes.
## License
This project is licensed under the MIT License. See the LICENSE file for details.

View File

@ -1,258 +0,0 @@
# AutoBackups - Especificación Técnica Detallada
## Resumen Ejecutivo
AutoBackups es una aplicación Python que automatiza el backup de proyectos Simatic S7 y directorios definidos por el usuario, utilizando la API de Everything para búsqueda eficiente de archivos y un sistema de hash inteligente para evitar backups innecesarios.
## Arquitectura del Sistema
### 1. Componentes Principales
#### 1.1 Motor de Búsqueda (Everything API)
- **Librería**: PyEverything wrapper
- **DLL Local**: `Everything-SDK\dll\Everything64.dll`
- **Función**: Localizar archivos *.s7p en directorios de observación
- **Optimización**: Evitar último nivel del árbol para archivos .s7p
- **Ventaja**: Aprovecha el índice existente de Everything para búsquedas instantáneas
#### 1.2 Sistema de Hash en Dos Etapas
**Etapa 1**: Hash rápido de archivos *.s7p
- Solo verifica MD5 de (timestamp + tamaño) de archivos .s7p
- Si no hay cambios → no se procede con backup
- Si hay cambios → procede a Etapa 2
**Etapa 2**: Hash completo del proyecto
- Calcula MD5 de (timestamp + tamaño) de todos los archivos del directorio
- Compara con último hash almacenado
- Solo hace backup si hay diferencias
#### 1.3 Scheduler de Background
- **daily**: Una vez al día a hora configurada
- **hourly**: Cada hora
- **3-hour**: Cada 3 horas
- **7-hour**: Cada 7 horas
- **startup**: Al iniciar la aplicación
- **manual**: Solo bajo demanda del usuario
- **Escaneos**: Automáticos cada 1 hora
- **Backups**: Mínimo cada 10 minutos
- **Prioridad**: Baja prioridad de sistema
### 2. Estructura de Datos
#### 2.1 config.json (Configuración Global)
```json
{
"observation_directories": [
{
"path": "C:\\Projects\\Siemens",
"type": "siemens_s7",
"enabled": true
},
{
"path": "D:\\Engineering\\Projects",
"type": "siemens_s7",
"enabled": true
},
{
"path": "C:\\Important\\Docs",
"type": "manual",
"enabled": true
}
],
"backup_destination": "D:\\Backups\\AutoBackups",
"default_schedule": "daily",
"default_schedule_time": "02:00",
"retry_delay_hours": 1,
"web_interface": {
"host": "127.0.0.1",
"port": 5000
},
"logging": {
"level": "INFO",
"max_log_files": 30
}
}
```
#### 2.2 projects.json (Estado de Proyectos)
```json
{
"projects": [
{
"id": "project_001",
"name": "PLC_MainLine",
"path": "C:\\Projects\\Siemens\\PLC_MainLine",
"type": "siemens_s7",
"s7p_file": "C:\\Projects\\Siemens\\PLC_MainLine\\PLC_MainLine.s7p",
"schedule": "daily",
"schedule_time": "02:00",
"enabled": true,
"last_backup": "2025-09-01T02:15:30",
"last_s7p_hash": "abc123def456",
"last_full_hash": "def789ghi012",
"last_s7p_timestamp": "2025-08-31T14:30:00",
"status": "ready",
"retry_count": 0,
"next_retry": null,
"error_message": null
}
]
}
```
### 3. Flujo de Operación
#### 3.1 Inicio de Aplicación
1. Cargar configuración desde `config.json`
2. Cargar estado de proyectos desde `projects.json`
3. Inicializar logger con timestamp de inicio
4. Escanear directorios de observación usando Everything API
5. Actualizar lista de proyectos detectados
6. Iniciar scheduler
7. Iniciar interfaz web Flask
#### 4.2 Proceso de Backup
1. **Verificación de Espacio**: Verificar mínimo 100MB libres
2. **Verificación de Acceso .s7p**: Intentar comprimir solo archivo .s7p
3. **Hash Etapa 1**: Verificar MD5 de (timestamp + tamaño) del archivo .s7p
4. **Hash Etapa 2**: Si Etapa 1 detecta cambios, verificar hash completo
5. **Compresión**: Crear archivo ZIP con estructura específica preservada
6. **Almacenamiento**: Guardar en `backup_destination/ProjectPath/YYYY-MM-DD/HH-MM-SS_projects.zip`
7. **Actualización**: Actualizar hashes y timestamps en `projects.json`
#### 3.3 Gestión de Errores
- **Archivos en uso**: Marcar proyecto para reintento en 1 hora
- **Errores de permisos**: Log de error y notificación en interfaz
- **Errores de espacio**: Verificar espacio disponible antes de backup
### 4. Interfaz Web
#### 4.1 Dashboard Principal
- **Lista de Proyectos**: Tabla con estado, último backup, próximo backup
- **Controles Globales**: Backup manual global, pausar/reanudar scheduler
- **Estadísticas**: Total de proyectos, backups exitosos, errores
#### 4.2 Configuración de Proyectos
- **Habilitación/Deshabilitación**: Toggle por proyecto
- **Configuración de Schedule**: Dropdown con opciones de frecuencia
- **Backup Manual**: Botón de backup inmediato por proyecto
#### 4.3 Logs y Monitoreo
- **Log Viewer**: Mostrar logs recientes con filtros por nivel
- **Estado del Sistema**: Información de Everything API, espacio en disco
### 5. Estructura de Backup
#### 5.1 Nomenclatura de Archivos (Estructura Específica)
```
backup_destination/
├── LineA/
│ └── Project1/
│ ├── 2025-09-01/
│ │ ├── 02-15-30_projects.zip
│ │ └── 14-30-15_projects.zip
│ └── 2025-09-02/
│ └── 02-15-45_projects.zip
└── LineB/
└── Project2/
└── 2025-09-01/
└── 08-20-10_projects.zip
```
#### 5.2 Contenido del ZIP
```
02-15-30_projects.zip
└── LineA/
└── Project1/
├── project.s7p
├── subfolder1/
└── subfolder2/
```
### 6. Tecnologías y Librerías
#### 6.1 Python Core
- **Python**: 3.12
- **Framework Web**: Flask
- **Scheduler**: APScheduler
- **Compresión**: zipfile (biblioteca estándar)
#### 6.2 Librerías Específicas
- **Everything API**: PyEverything wrapper con DLL local
- **Hashing**: hashlib MD5 para (timestamp + tamaño)
- **Config**: json (biblioteca estándar)
- **Logging**: logging (biblioteca estándar)
- **File Access Check**: Intento de compresión + verificación .s7p
- **Process Priority**: pywin32 para baja prioridad
- **Disk Space**: psutil para monitoreo de espacio libre
#### 6.3 Frontend
- **HTML/CSS/JavaScript**: Vanilla (sin React por simplicidad)
- **AJAX**: Para comunicación con Flask API
- **Bootstrap**: Para estilizado responsivo
### 7. Consideraciones de Seguridad
#### 7.1 Acceso a Archivos
- Verificación de permisos antes de backup
- Manejo seguro de rutas para evitar path traversal
- Logs de todos los accesos a archivos
#### 7.2 Interfaz Web
- Solo acceso local (127.0.0.1)
- No autenticación requerida (uso local únicamente)
- Validación de inputs en formularios
### 8. Logging y Monitoreo
#### 8.1 Estructura de Logs
```
.logs/
├── autobackups_2025-09-01_08-30-15.log
├── autobackups_2025-09-02_08-30-22.log
└── ...
```
#### 8.2 Niveles de Log
- **INFO**: Inicio/fin de backups, descubrimiento de proyectos
- **WARNING**: Archivos en uso, reintentos
- **ERROR**: Fallos de backup, errores de configuración
- **DEBUG**: Detalles de hashes, operaciones de archivos
### 9. Instalación y Despliegue
#### 9.1 Entorno Miniconda
```bash
conda create --name autobackups python=3.12
conda activate autobackups
pip install -r requirements.txt
```
#### 9.2 Ejecución
- **Desarrollo**: `python src/app.py`
- **Producción**: `pythonw.exe src/app.py` (sin consola)
- **Como servicio**: Futuro enhancement con `python-windows-service`
### 10. Roadmap de Desarrollo
#### Fase 1: Core Backend
- [ ] Integración con Everything API
- [ ] Sistema de hash en dos etapas
- [ ] Motor de backup básico
- [ ] Scheduler con APScheduler
#### Fase 2: Interfaz Web
- [ ] Dashboard básico con Flask
- [ ] API REST para operaciones CRUD
- [ ] Frontend con HTML/JS/Bootstrap
#### Fase 3: Características Avanzadas
- [ ] Logs web viewer
- [ ] Configuración avanzada de directorios
- [ ] Estadísticas y reportes
#### Fase 4: Optimizaciones
- [ ] Ejecución como servicio Windows
- [ ] Notificaciones por email
- [ ] Backup incremental
Este documento será la base para el desarrollo del proyecto AutoBackups.

View File

@ -1,124 +0,0 @@
# AutoBackups - Preguntas Técnicas Pendientes
## Preguntas Críticas para el Desarrollo
### 1. Everything API - Integración
**Pregunta**: ¿Everything está instalado y funcionando en el sistema objetivo?
**Impacto**: Si no está disponible, necesitaremos un método alternativo de búsqueda de archivos.
**Opciones**:
- Usar `python-everything` si Everything está disponible
- Implementar búsqueda recursiva con `os.walk()` como fallback
- Usar `pathlib` con `glob` patterns
**Decisión necesaria**: ¿Podemos asumir que Everything estará disponible o necesitamos fallback?
### 2. Estructura de Backup - Clarificación de Rutas
**Pregunta**: Si tenemos un archivo en `C:\Projects\Siemens\LineA\Project1\project.s7p`, ¿el backup debe ser?
**Opción A**:
```
backup_destination/2025-09-01_14-30-15/Projects_Siemens_LineA_Project1.zip
└── Projects/Siemens/LineA/Project1/...
```
**Opción B**:
```
backup_destination/2025-09-01_14-30-15/LineA_Project1.zip
└── LineA/Project1/...
```
**Decisión necesaria**: ¿Qué estructura prefieres?
### 3. Configuración de Schedules - Granularidad
**Pregunta**: ¿Los schedules deben ser configurables a nivel de:
- Por directorio de observación (todos los proyectos de un directorio)
- Por proyecto individual
- Ambos (global con override por proyecto)
**Decisión necesaria**: ¿Qué nivel de granularidad necesitas?
### 4. Hash de Archivos - Algoritmo y Almacenamiento
**Pregunta**: Para el sistema de hash en dos etapas:
- ¿Usamos MD5 (rápido) o SHA256 (más seguro) para los hashes?
- ¿El hash incluye solo timestamp o también tamaño de archivo?
- ¿Cómo manejamos archivos que se mueven dentro del proyecto?
**Decisión necesaria**: ¿Qué balance entre velocidad y precisión prefieres?
### 5. Detección de Archivos en Uso - Método
**Pregunta**: Para detectar archivos bloqueados, ¿prefieres:
**Opción A**: Intentar abrir cada archivo en modo escritura exclusiva
**Opción B**: Usar `lsof` (Linux) / `handle.exe` (Windows) para listar archivos abiertos
**Opción C**: Solo verificar el archivo .s7p principal
**Decisión necesaria**: ¿Qué método consideras más apropiado?
### 6. Manejo de Proyectos Grandes - Performance
**Pregunta**: ¿Hay límites que debamos considerar?
- Tamaño máximo de proyecto para backup
- Tiempo máximo de backup
- Número máximo de archivos por proyecto
**Decisión necesaria**: ¿Necesitamos algún tipo de throttling o límites?
### 7. Configuración de Directorios - Recursividad
**Pregunta**: Cuando especificamos un directorio de observación como `C:\Projects`, ¿debemos:
- Buscar solo en subdirectorios inmediatos
- Buscar recursivamente en toda la jerarquía
- Permitir configurar la profundidad de búsqueda
**Decisión necesaria**: ¿Qué comportamiento prefieres por defecto?
### 8. Backup Incremental vs Completo
**Pregunta**: ¿Todos los backups deben ser completos o consideras backup incremental?
- Backup completo: Todo el proyecto cada vez
- Backup incremental: Solo archivos modificados
**Decisión necesaria**: ¿Preferencia por simplicidad o eficiencia de espacio?
### 9. Web Interface - Características Específicas
**Pregunta**: ¿Qué funcionalidades son prioritarias en la interfaz web?
**Must-have**:
- Lista de proyectos con estado
- Trigger manual de backup
- Ver logs básicos
**Nice-to-have**:
- Configurar schedules por proyecto
- Ver progreso de backup en tiempo real
- Estadísticas históricas
- Configurar nuevos directorios
**Decisión necesaria**: ¿Cuáles son must-have vs nice-to-have?
### 10. Error Handling - Estrategias de Recuperación
**Pregunta**: ¿Cómo manejar errores específicos?
- Espacio insuficiente en destino de backup
- Pérdida de conexión con Everything
- Corrupción de archivos de configuración
- Falla durante compresión
**Decisión necesaria**: ¿Qué nivel de robustez necesitas?
### 11. Startup Behavior - Inicialización
**Pregunta**: Al iniciar la aplicación:
- ¿Debe hacer un escaneo completo inmediatamente?
- ¿Debe esperar al primer schedule programado?
- ¿Debe permitir configurar el comportamiento de startup?
**Decisión necesaria**: ¿Qué comportamiento prefieres al iniciar?
### 12. Multi-threading - Concurrencia
**Pregunta**: ¿Los backups deben ejecutarse:
- Secuencialmente (uno por vez)
- En paralelo (múltiples simultáneos)
- Con límite configurable de concurrencia
**Decisión necesaria**: ¿Qué balance entre velocidad y recursos del sistema?
## Próximos Pasos
Una vez que tengas respuestas a estas preguntas, podremos:
1. Finalizar el diseño técnico
2. Crear el `requirements.txt` definitivo
3. Comenzar con la implementación por fases
4. Definir el plan de testing
¿Podrías revisar estas preguntas y darme tus preferencias para cada una?

View File

@ -1,60 +0,0 @@
{
"observation_directories": [
{
"path": "C:\\Projects\\Siemens",
"type": "siemens_s7",
"enabled": true,
"description": "Directorio principal de proyectos Siemens"
},
{
"path": "D:\\Engineering\\Projects",
"type": "siemens_s7",
"enabled": true,
"description": "Proyectos de ingeniería adicionales"
},
{
"path": "C:\\Important\\Documentation",
"type": "manual",
"enabled": true,
"description": "Documentación importante para backup manual"
}
],
"backup_destination": "D:\\Backups\\AutoBackups",
"global_settings": {
"default_schedule": "daily",
"default_schedule_time": "02:00",
"retry_delay_hours": 1,
"backup_timeout_minutes": 0,
"min_free_space_mb": 100,
"scan_interval_minutes": 60,
"min_backup_interval_minutes": 10
},
"everything_api": {
"dll_path": "Everything-SDK\\dll\\Everything64.dll",
"enabled": true,
"search_depth": -1,
"skip_last_level_for_s7p": true
},
"web_interface": {
"host": "127.0.0.1",
"port": 5000,
"debug": false
},
"logging": {
"level": "INFO",
"max_log_files": 30,
"log_rotation_days": 30
},
"backup_options": {
"compression_level": 6,
"include_subdirectories": true,
"preserve_directory_structure": true,
"hash_algorithm": "md5",
"hash_includes": ["timestamp", "size"],
"backup_type": "complete",
"process_priority": "low",
"sequential_execution": true,
"filename_format": "HH-MM-SS_projects.zip",
"date_format": "YYYY-MM-DD"
}
}

View File

@ -1,62 +0,0 @@
{
"metadata": {
"version": "1.0",
"last_updated": "2025-09-01T08:30:15Z",
"total_projects": 0
},
"projects": [
{
"id": "example_project_001",
"name": "PLC_MainLine_Example",
"path": "C:\\Projects\\Siemens\\LineA\\Project1",
"type": "siemens_s7",
"s7p_file": "C:\\Projects\\Siemens\\LineA\\Project1\\project.s7p",
"observation_directory": "C:\\Projects\\Siemens",
"relative_path": "LineA\\Project1",
"backup_path": "LineA\\Project1",
"schedule_config": {
"schedule": "daily",
"schedule_time": "02:00",
"enabled": true,
"next_scheduled_backup": "2025-09-02T02:00:00Z"
},
"backup_history": {
"last_backup_date": "2025-09-01T02:15:30Z",
"last_backup_file": "D:\\Backups\\AutoBackups\\LineA\\Project1\\2025-09-01\\02-15-30_projects.zip",
"backup_count": 5,
"last_successful_backup": "2025-09-01T02:15:30Z"
},
"hash_info": {
"last_s7p_hash": "abc123def456789",
"last_full_hash": "def789ghi012345",
"last_s7p_timestamp": "2025-08-31T14:30:00Z",
"last_s7p_size": 2048576,
"last_scan_timestamp": "2025-09-01T02:10:00Z",
"file_count": 1247,
"total_size_bytes": 125847296
},
"status": {
"current_status": "ready",
"last_error": null,
"retry_count": 0,
"next_retry": null,
"files_in_use": false,
"exclusivity_check_passed": true,
"last_status_update": "2025-09-01T02:15:35Z"
},
"discovery_info": {
"discovered_date": "2025-09-01T08:30:15Z",
"discovery_method": "everything_api",
"auto_discovered": true
}
}
],
"statistics": {
"total_backups_created": 15,
"total_backup_size_mb": 2450.5,
"average_backup_time_seconds": 45.2,
"last_global_scan": "2025-09-01T08:30:15Z",
"projects_with_errors": 0,
"projects_pending_retry": 0
}
}

View File

@ -1,32 +0,0 @@
# Core Framework
Flask==2.3.3
Werkzeug==2.3.7
# Scheduling
APScheduler==3.10.4
# Everything API Integration
PyEverything==1.0.1 # Wrapper para Everything SDK
# File Operations and Utilities
pathlib2==2.3.7.post1 # Enhanced pathlib for Python 3.12
psutil==5.9.5 # System utilities (disk space monitoring)
filelock==3.12.4 # File locking for concurrent access
# Web Interface
Jinja2==3.1.2 # Template engine for Flask
# Configuration and Data
jsonschema==4.19.1 # JSON schema validation
# Logging
colorlog==6.7.0 # Colored logging output
# Windows-specific dependencies
pywin32==306; sys_platform == "win32" # Windows API access for low priority
# Development and Testing (opcional, remove for production)
pytest==7.4.2
pytest-flask==1.2.0
black==23.9.1 # Code formatting
flake8==6.1.0 # Code linting

View File

@ -1,275 +0,0 @@
"""
AutoBackups - Aplicación Principal
Sistema automatizado de backup para proyectos Simatic S7
"""
import sys
import os
import logging
from pathlib import Path
from datetime import datetime
# Agregar el directorio src al path para imports
current_dir = Path(__file__).parent
src_dir = current_dir
sys.path.insert(0, str(src_dir))
# Imports de módulos propios
from models.config_model import Config
from models.project_model import ProjectManager
from utils.file_utils import DiskSpaceChecker
from services.basic_backup_service import BasicBackupService
class AutoBackupsApp:
"""Aplicación principal de AutoBackups"""
def __init__(self):
self.config = None
self.project_manager = None
self.discovery_service = None
self.disk_checker = None
self.logger = None
# Inicializar aplicación
self._setup_logging()
self._load_configuration()
self._initialize_services()
def _setup_logging(self):
"""Configurar sistema de logging"""
try:
# Crear directorio de logs si no existe
logs_dir = Path(__file__).parent / ".logs"
logs_dir.mkdir(exist_ok=True)
# Nombre del archivo de log con timestamp
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
log_filename = logs_dir / f"autobackups_{timestamp}.log"
# Configurar logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(log_filename, encoding='utf-8'),
logging.StreamHandler(sys.stdout)
]
)
self.logger = logging.getLogger(__name__)
self.logger.info(f"AutoBackups iniciado - Log: {log_filename}")
except Exception as e:
print(f"Error configurando logging: {e}")
sys.exit(1)
def _load_configuration(self):
"""Cargar configuración del sistema"""
try:
self.logger.info("Cargando configuración...")
self.config = Config()
self.logger.info("Configuración cargada exitosamente")
# Mostrar información básica de configuración
self.logger.info(f"Directorios de observación: {len(self.config.observation_directories)}")
self.logger.info(f"Destino de backups: {self.config.backup_destination}")
except Exception as e:
self.logger.error(f"Error cargando configuración: {e}")
sys.exit(1)
def _initialize_services(self):
"""Inicializar servicios principales"""
try:
self.logger.info("Inicializando servicios...")
# Project Manager
self.project_manager = ProjectManager()
self.logger.info("Project Manager inicializado")
# Disk Space Checker
self.disk_checker = DiskSpaceChecker()
self.logger.info("Disk Space Checker inicializado")
# Basic Backup Service (Fase 1)
self.backup_service = BasicBackupService(self.config)
self.logger.info("Basic Backup Service inicializado")
# Project Discovery Service (temporalmente comentado)
# self.discovery_service = ProjectDiscoveryService(self.config, self.project_manager)
# self.logger.info("Project Discovery Service inicializado")
self.logger.info("Todos los servicios inicializados correctamente")
except Exception as e:
self.logger.error(f"Error inicializando servicios: {e}")
sys.exit(1)
def check_system_requirements(self) -> bool:
"""Verificar requerimientos del sistema"""
try:
self.logger.info("Verificando requerimientos del sistema...")
# Verificar espacio en disco
backup_destination = self.config.backup_destination
min_space_mb = self.config.get_min_free_space_mb()
free_space_mb = self.disk_checker.get_free_space_mb(backup_destination)
if free_space_mb < min_space_mb:
self.logger.error(
f"Espacio insuficiente en destino de backup. "
f"Disponible: {free_space_mb:.1f}MB, "
f"Requerido: {min_space_mb}MB"
)
return False
self.logger.info(f"Espacio en disco OK: {free_space_mb:.1f}MB disponibles")
# Verificar Everything API (opcional en Fase 1)
if hasattr(self, 'backup_service'):
if self.backup_service.check_system_requirements():
self.logger.info("Requerimientos del sistema verificados")
else:
self.logger.warning("Algunos requerimientos fallaron")
else:
self.logger.warning("Backup service no disponible")
# Verificar directorios de observación
missing_dirs = []
for obs_dir in self.config.observation_directories:
if not Path(obs_dir["path"]).exists():
missing_dirs.append(obs_dir["path"])
if missing_dirs:
self.logger.warning(f"Directorios de observación no encontrados: {missing_dirs}")
self.logger.info("Verificación de requerimientos completada")
return True
except Exception as e:
self.logger.error(f"Error verificando requerimientos del sistema: {e}")
return False
def discover_projects(self) -> int:
"""Descubrir proyectos en directorios de observación"""
try:
self.logger.info("Iniciando descubrimiento de proyectos...")
# Usar el servicio básico de backup
if hasattr(self, 'backup_service'):
projects = self.backup_service.discover_projects_basic()
else:
projects = []
# Agregar proyectos al manager
for project_info in projects:
self.project_manager.add_or_update_project(project_info)
msg = f"Descubrimiento completado: {len(projects)} proyectos"
self.logger.info(msg)
return len(projects)
except Exception as e:
self.logger.error(f"Error en descubrimiento de proyectos: {e}")
return 0
def show_system_status(self):
"""Mostrar estado actual del sistema"""
try:
self.logger.info("=== ESTADO DEL SISTEMA ===")
# Información de configuración
self.logger.info(f"Directorios de observación configurados: {len(self.config.observation_directories)}")
self.logger.info(f"Destino de backups: {self.config.backup_destination}")
# Información de proyectos
all_projects = self.project_manager.get_all_projects()
enabled_projects = self.project_manager.get_enabled_projects()
self.logger.info(f"Total de proyectos: {len(all_projects)}")
self.logger.info(f"Proyectos habilitados: {len(enabled_projects)}")
# Información de espacio en disco
backup_dest = self.config.backup_destination
total_mb, used_mb, free_mb = self.disk_checker.get_disk_usage_info(backup_dest)
self.logger.info(f"Espacio en disco (destino backup):")
self.logger.info(f" Total: {total_mb:.1f}MB")
self.logger.info(f" Usado: {used_mb:.1f}MB")
self.logger.info(f" Libre: {free_mb:.1f}MB")
# Información de Everything API
if self.discovery_service.everything_searcher:
self.logger.info("Everything API: Disponible")
else:
self.logger.info("Everything API: No disponible")
self.logger.info("=== FIN ESTADO DEL SISTEMA ===")
except Exception as e:
self.logger.error(f"Error mostrando estado del sistema: {e}")
def run_initial_setup(self):
"""Ejecutar configuración inicial de la aplicación"""
try:
self.logger.info("=== CONFIGURACIÓN INICIAL DE AUTOBACKUPS ===")
# Verificar requerimientos del sistema
if not self.check_system_requirements():
self.logger.error("Los requerimientos del sistema no se cumplen")
return False
# Descubrir proyectos
projects_found = self.discover_projects()
if projects_found == 0:
self.logger.warning("No se encontraron proyectos para backup")
# Mostrar estado del sistema
self.show_system_status()
self.logger.info("=== CONFIGURACIÓN INICIAL COMPLETADA ===")
return True
except Exception as e:
self.logger.error(f"Error en configuración inicial: {e}")
return False
def main():
"""Función principal"""
try:
print("AutoBackups - Sistema de Backup Automatizado")
print("=" * 50)
# Crear y configurar aplicación
app = AutoBackupsApp()
# Ejecutar configuración inicial
if app.run_initial_setup():
app.logger.info("AutoBackups configurado correctamente")
# TODO: En las siguientes fases:
# - Iniciar scheduler de backups
# - Iniciar interfaz web Flask
# - Configurar tareas en background
print("\nConfiguración inicial completada.")
print("Revisa el archivo de log para más detalles.")
else:
print("Error en la configuración inicial. Revisa los logs.")
sys.exit(1)
except KeyboardInterrupt:
print("\nAplicación interrumpida por el usuario")
except Exception as e:
print(f"Error inesperado: {e}")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -1,9 +0,0 @@
"""
AutoBackups - Data Models
Modelos de datos para configuración y manejo de proyectos
"""
from .config_model import Config
from .project_model import Project, ProjectStatus
__all__ = ['Config', 'Project', 'ProjectStatus']

View File

@ -1,12 +0,0 @@
"""
AutoBackups - Services
Servicios principales para backup y descubrimiento de proyectos
"""
# Imports comentados temporalmente para evitar problemas de dependencias circulares
# from .project_discovery_service import ProjectDiscoveryService
# from .backup_service import BackupService
# from .scheduler_service import SchedulerService
from .basic_backup_service import BasicBackupService
__all__ = ['BasicBackupService']

View File

@ -1,10 +0,0 @@
"""
AutoBackups - Utilities
Funciones de utilidad para hashing, manejo de archivos y otras operaciones
"""
from .hash_utils import HashCalculator
from .file_utils import FileChecker, DiskSpaceChecker
from .everything_wrapper import EverythingSearcher
__all__ = ['HashCalculator', 'FileChecker', 'DiskSpaceChecker', 'EverythingSearcher']

View File

@ -24,13 +24,16 @@
"default_schedule": "daily", "default_schedule": "daily",
"default_schedule_time": "02:00", "default_schedule_time": "02:00",
"retry_delay_hours": 1, "retry_delay_hours": 1,
"max_concurrent_backups": 2, "backup_timeout_minutes": 0,
"backup_timeout_minutes": 60 "min_free_space_mb": 100,
"scan_interval_minutes": 60,
"min_backup_interval_minutes": 10
}, },
"everything_api": { "everything_api": {
"dll_path": "Everything-SDK\\dll\\Everything64.dll",
"enabled": true, "enabled": true,
"fallback_to_filesystem_search": true, "search_depth": -1,
"search_depth": -1 "skip_last_level_for_s7p": true
}, },
"web_interface": { "web_interface": {
"host": "127.0.0.1", "host": "127.0.0.1",
@ -46,6 +49,12 @@
"compression_level": 6, "compression_level": 6,
"include_subdirectories": true, "include_subdirectories": true,
"preserve_directory_structure": true, "preserve_directory_structure": true,
"hash_algorithm": "md5" "hash_algorithm": "md5",
"hash_includes": ["timestamp", "size"],
"backup_type": "complete",
"process_priority": "low",
"sequential_execution": true,
"filename_format": "HH-MM-SS_projects.zip",
"date_format": "YYYY-MM-DD"
} }
} }

View File

@ -8,11 +8,12 @@
{ {
"id": "example_project_001", "id": "example_project_001",
"name": "PLC_MainLine_Example", "name": "PLC_MainLine_Example",
"path": "C:\\Projects\\Siemens\\PLC_MainLine", "path": "C:\\Projects\\Siemens\\LineA\\Project1",
"type": "siemens_s7", "type": "siemens_s7",
"s7p_file": "C:\\Projects\\Siemens\\PLC_MainLine\\PLC_MainLine.s7p", "s7p_file": "C:\\Projects\\Siemens\\LineA\\Project1\\project.s7p",
"observation_directory": "C:\\Projects\\Siemens", "observation_directory": "C:\\Projects\\Siemens",
"relative_path": "PLC_MainLine", "relative_path": "LineA\\Project1",
"backup_path": "LineA\\Project1",
"schedule_config": { "schedule_config": {
"schedule": "daily", "schedule": "daily",
"schedule_time": "02:00", "schedule_time": "02:00",
@ -21,7 +22,7 @@
}, },
"backup_history": { "backup_history": {
"last_backup_date": "2025-09-01T02:15:30Z", "last_backup_date": "2025-09-01T02:15:30Z",
"last_backup_file": "D:\\Backups\\AutoBackups\\2025-09-01_02-15-30\\Projects_Siemens_PLC_MainLine.zip", "last_backup_file": "D:\\Backups\\AutoBackups\\LineA\\Project1\\2025-09-01\\02-15-30_projects.zip",
"backup_count": 5, "backup_count": 5,
"last_successful_backup": "2025-09-01T02:15:30Z" "last_successful_backup": "2025-09-01T02:15:30Z"
}, },
@ -29,8 +30,10 @@
"last_s7p_hash": "abc123def456789", "last_s7p_hash": "abc123def456789",
"last_full_hash": "def789ghi012345", "last_full_hash": "def789ghi012345",
"last_s7p_timestamp": "2025-08-31T14:30:00Z", "last_s7p_timestamp": "2025-08-31T14:30:00Z",
"last_s7p_size": 2048576,
"last_scan_timestamp": "2025-09-01T02:10:00Z", "last_scan_timestamp": "2025-09-01T02:10:00Z",
"file_count": 1247 "file_count": 1247,
"total_size_bytes": 125847296
}, },
"status": { "status": {
"current_status": "ready", "current_status": "ready",
@ -38,6 +41,7 @@
"retry_count": 0, "retry_count": 0,
"next_retry": null, "next_retry": null,
"files_in_use": false, "files_in_use": false,
"exclusivity_check_passed": true,
"last_status_update": "2025-09-01T02:15:35Z" "last_status_update": "2025-09-01T02:15:35Z"
}, },
"discovery_info": { "discovery_info": {

View File

@ -5,12 +5,12 @@ Werkzeug==2.3.7
# Scheduling # Scheduling
APScheduler==3.10.4 APScheduler==3.10.4
# Everything API Integration (si está disponible) # Everything API Integration
# python-everything==1.0.1 # Descomenta si existe la librería PyEverything==1.0.1 # Wrapper para Everything SDK
# File Operations and Utilities # File Operations and Utilities
pathlib2==2.3.7.post1 # Enhanced pathlib for Python 3.12 pathlib2==2.3.7.post1 # Enhanced pathlib for Python 3.12
psutil==5.9.5 # System and process utilities psutil==5.9.5 # System utilities (disk space monitoring)
filelock==3.12.4 # File locking for concurrent access filelock==3.12.4 # File locking for concurrent access
# Web Interface # Web Interface
@ -22,11 +22,11 @@ jsonschema==4.19.1 # JSON schema validation
# Logging # Logging
colorlog==6.7.0 # Colored logging output colorlog==6.7.0 # Colored logging output
# Windows-specific dependencies
pywin32==306; sys_platform == "win32" # Windows API access for low priority
# Development and Testing (opcional, remove for production) # Development and Testing (opcional, remove for production)
pytest==7.4.2 pytest==7.4.2
pytest-flask==1.2.0 pytest-flask==1.2.0
black==23.9.1 # Code formatting black==23.9.1 # Code formatting
flake8==6.1.0 # Code linting flake8==6.1.0 # Code linting
# Windows-specific dependencies
pywin32==306; sys_platform == "win32" # Windows API access

View File

@ -1,38 +1,275 @@
from flask import Flask """
from apscheduler.schedulers.background import BackgroundScheduler AutoBackups - Aplicación Principal
import json Sistema automatizado de backup para proyectos Simatic S7
"""
import sys
import os import os
import logging
from pathlib import Path
from datetime import datetime
app = Flask(__name__) # Agregar el directorio src al path para imports
current_dir = Path(__file__).parent
src_dir = current_dir
sys.path.insert(0, str(src_dir))
# Load configuration from config.json # Imports de módulos propios
with open('config.json') as config_file: from models.config_model import Config
config = json.load(config_file) from models.project_model import ProjectManager
from utils.file_utils import DiskSpaceChecker
from services.basic_backup_service import BasicBackupService
# Initialize the scheduler
scheduler = BackgroundScheduler()
def backup_projects(): class AutoBackupsApp:
# Logic to scan directories and perform backups """Aplicación principal de AutoBackups"""
pass
# Schedule the backup task def __init__(self):
scheduler.add_job(backup_projects, 'interval', hours=config.get('backup_interval_hours', 24)) self.config = None
scheduler.start() self.project_manager = None
self.discovery_service = None
self.disk_checker = None
self.logger = None
@app.route('/') # Inicializar aplicación
def index(): self._setup_logging()
return "Welcome to the Auto Backup System" self._load_configuration()
self._initialize_services()
@app.route('/backup', methods=['POST']) def _setup_logging(self):
def trigger_backup(): """Configurar sistema de logging"""
# Logic to manually trigger a backup try:
return "Backup triggered" # Crear directorio de logs si no existe
logs_dir = Path(__file__).parent / ".logs"
logs_dir.mkdir(exist_ok=True)
@app.route('/status', methods=['GET']) # Nombre del archivo de log con timestamp
def backup_status(): timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
# Logic to check the status of backups log_filename = logs_dir / f"autobackups_{timestamp}.log"
return "Backup status"
if __name__ == '__main__': # Configurar logging
app.run(host='0.0.0.0', port=5000) logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(log_filename, encoding='utf-8'),
logging.StreamHandler(sys.stdout)
]
)
self.logger = logging.getLogger(__name__)
self.logger.info(f"AutoBackups iniciado - Log: {log_filename}")
except Exception as e:
print(f"Error configurando logging: {e}")
sys.exit(1)
def _load_configuration(self):
"""Cargar configuración del sistema"""
try:
self.logger.info("Cargando configuración...")
self.config = Config()
self.logger.info("Configuración cargada exitosamente")
# Mostrar información básica de configuración
self.logger.info(f"Directorios de observación: {len(self.config.observation_directories)}")
self.logger.info(f"Destino de backups: {self.config.backup_destination}")
except Exception as e:
self.logger.error(f"Error cargando configuración: {e}")
sys.exit(1)
def _initialize_services(self):
"""Inicializar servicios principales"""
try:
self.logger.info("Inicializando servicios...")
# Project Manager
self.project_manager = ProjectManager()
self.logger.info("Project Manager inicializado")
# Disk Space Checker
self.disk_checker = DiskSpaceChecker()
self.logger.info("Disk Space Checker inicializado")
# Basic Backup Service (Fase 1)
self.backup_service = BasicBackupService(self.config)
self.logger.info("Basic Backup Service inicializado")
# Project Discovery Service (temporalmente comentado)
# self.discovery_service = ProjectDiscoveryService(self.config, self.project_manager)
# self.logger.info("Project Discovery Service inicializado")
self.logger.info("Todos los servicios inicializados correctamente")
except Exception as e:
self.logger.error(f"Error inicializando servicios: {e}")
sys.exit(1)
def check_system_requirements(self) -> bool:
"""Verificar requerimientos del sistema"""
try:
self.logger.info("Verificando requerimientos del sistema...")
# Verificar espacio en disco
backup_destination = self.config.backup_destination
min_space_mb = self.config.get_min_free_space_mb()
free_space_mb = self.disk_checker.get_free_space_mb(backup_destination)
if free_space_mb < min_space_mb:
self.logger.error(
f"Espacio insuficiente en destino de backup. "
f"Disponible: {free_space_mb:.1f}MB, "
f"Requerido: {min_space_mb}MB"
)
return False
self.logger.info(f"Espacio en disco OK: {free_space_mb:.1f}MB disponibles")
# Verificar Everything API (opcional en Fase 1)
if hasattr(self, 'backup_service'):
if self.backup_service.check_system_requirements():
self.logger.info("Requerimientos del sistema verificados")
else:
self.logger.warning("Algunos requerimientos fallaron")
else:
self.logger.warning("Backup service no disponible")
# Verificar directorios de observación
missing_dirs = []
for obs_dir in self.config.observation_directories:
if not Path(obs_dir["path"]).exists():
missing_dirs.append(obs_dir["path"])
if missing_dirs:
self.logger.warning(f"Directorios de observación no encontrados: {missing_dirs}")
self.logger.info("Verificación de requerimientos completada")
return True
except Exception as e:
self.logger.error(f"Error verificando requerimientos del sistema: {e}")
return False
def discover_projects(self) -> int:
"""Descubrir proyectos en directorios de observación"""
try:
self.logger.info("Iniciando descubrimiento de proyectos...")
# Usar el servicio básico de backup
if hasattr(self, 'backup_service'):
projects = self.backup_service.discover_projects_basic()
else:
projects = []
# Agregar proyectos al manager
for project_info in projects:
self.project_manager.add_or_update_project(project_info)
msg = f"Descubrimiento completado: {len(projects)} proyectos"
self.logger.info(msg)
return len(projects)
except Exception as e:
self.logger.error(f"Error en descubrimiento de proyectos: {e}")
return 0
def show_system_status(self):
"""Mostrar estado actual del sistema"""
try:
self.logger.info("=== ESTADO DEL SISTEMA ===")
# Información de configuración
self.logger.info(f"Directorios de observación configurados: {len(self.config.observation_directories)}")
self.logger.info(f"Destino de backups: {self.config.backup_destination}")
# Información de proyectos
all_projects = self.project_manager.get_all_projects()
enabled_projects = self.project_manager.get_enabled_projects()
self.logger.info(f"Total de proyectos: {len(all_projects)}")
self.logger.info(f"Proyectos habilitados: {len(enabled_projects)}")
# Información de espacio en disco
backup_dest = self.config.backup_destination
total_mb, used_mb, free_mb = self.disk_checker.get_disk_usage_info(backup_dest)
self.logger.info(f"Espacio en disco (destino backup):")
self.logger.info(f" Total: {total_mb:.1f}MB")
self.logger.info(f" Usado: {used_mb:.1f}MB")
self.logger.info(f" Libre: {free_mb:.1f}MB")
# Información de Everything API
if self.discovery_service.everything_searcher:
self.logger.info("Everything API: Disponible")
else:
self.logger.info("Everything API: No disponible")
self.logger.info("=== FIN ESTADO DEL SISTEMA ===")
except Exception as e:
self.logger.error(f"Error mostrando estado del sistema: {e}")
def run_initial_setup(self):
"""Ejecutar configuración inicial de la aplicación"""
try:
self.logger.info("=== CONFIGURACIÓN INICIAL DE AUTOBACKUPS ===")
# Verificar requerimientos del sistema
if not self.check_system_requirements():
self.logger.error("Los requerimientos del sistema no se cumplen")
return False
# Descubrir proyectos
projects_found = self.discover_projects()
if projects_found == 0:
self.logger.warning("No se encontraron proyectos para backup")
# Mostrar estado del sistema
self.show_system_status()
self.logger.info("=== CONFIGURACIÓN INICIAL COMPLETADA ===")
return True
except Exception as e:
self.logger.error(f"Error en configuración inicial: {e}")
return False
def main():
"""Función principal"""
try:
print("AutoBackups - Sistema de Backup Automatizado")
print("=" * 50)
# Crear y configurar aplicación
app = AutoBackupsApp()
# Ejecutar configuración inicial
if app.run_initial_setup():
app.logger.info("AutoBackups configurado correctamente")
# TODO: En las siguientes fases:
# - Iniciar scheduler de backups
# - Iniciar interfaz web Flask
# - Configurar tareas en background
print("\nConfiguración inicial completada.")
print("Revisa el archivo de log para más detalles.")
else:
print("Error en la configuración inicial. Revisa los logs.")
sys.exit(1)
except KeyboardInterrupt:
print("\nAplicación interrumpida por el usuario")
except Exception as e:
print(f"Error inesperado: {e}")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -1 +1,9 @@
# This file is intentionally left blank. """
AutoBackups - Data Models
Modelos de datos para configuración y manejo de proyectos
"""
from .config_model import Config
from .project_model import Project, ProjectStatus
__all__ = ['Config', 'Project', 'ProjectStatus']

View File

@ -1,5 +0,0 @@
from flask import Blueprint
bp = Blueprint('routes', __name__)
from . import backup_routes, status_routes, config_routes

View File

@ -1 +1,12 @@
# This file is intentionally left blank. """
AutoBackups - Services
Servicios principales para backup y descubrimiento de proyectos
"""
# Imports comentados temporalmente para evitar problemas de dependencias circulares
# from .project_discovery_service import ProjectDiscoveryService
# from .backup_service import BackupService
# from .scheduler_service import SchedulerService
from .basic_backup_service import BasicBackupService
__all__ = ['BasicBackupService']

View File

@ -1,19 +1,10 @@
def hash_timestamps(file_paths): """
# Implement hashing logic for file timestamps AutoBackups - Utilities
pass Funciones de utilidad para hashing, manejo de archivos y otras operaciones
"""
def check_file_access(file_path): from .hash_utils import HashCalculator
# Implement logic to check if a file is in use from .file_utils import FileChecker, DiskSpaceChecker
pass from .everything_wrapper import EverythingSearcher
def get_everything_results(query): __all__ = ['HashCalculator', 'FileChecker', 'DiskSpaceChecker', 'EverythingSearcher']
# Implement interaction with the Everything API
pass
def compress_files(file_paths, destination):
# Implement file compression logic
pass
def log_backup_status(project_name, status):
# Implement logging of backup status
pass

View File

@ -1 +0,0 @@
/* This file is intentionally left blank. */

View File

@ -1 +0,0 @@
// This file is intentionally left blank.

View File

@ -1,32 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Auto Backups</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<div class="container">
<h1>Auto Backups</h1>
<div id="backup-status">
<h2>Backup Status</h2>
<ul id="status-list">
<!-- Backup status items will be dynamically inserted here -->
</ul>
</div>
<div id="backup-controls">
<h2>Backup Controls</h2>
<button id="manual-backup">Force Backup Now</button>
<label for="backup-interval">Backup Interval:</label>
<select id="backup-interval">
<option value="hourly">Hourly</option>
<option value="daily" selected>Daily</option>
<option value="weekly">Weekly</option>
</select>
<button id="save-settings">Save Settings</button>
</div>
</div>
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
</body>
</html>