268 lines
7.1 KiB
Python
268 lines
7.1 KiB
Python
# -*- mode: python ; coding: utf-8 -*-
|
|
import os
|
|
import sys
|
|
|
|
block_cipher = None
|
|
|
|
# Analysis for main application (backend)
|
|
a_main = Analysis(
|
|
['main.py'],
|
|
pathex=[],
|
|
binaries=[
|
|
# Include snap7.dll - now confirmed to be in project root
|
|
('snap7.dll', '.'),
|
|
],
|
|
datas=[
|
|
# Include the entire frontend build
|
|
('frontend/dist', 'frontend/dist'),
|
|
|
|
# Include configuration directories and schemas
|
|
('config', 'config'),
|
|
|
|
# Include core modules
|
|
('core', 'core'),
|
|
|
|
# Include utils
|
|
('utils', 'utils'),
|
|
|
|
# Include translation files
|
|
('translation.json', '.'),
|
|
('i18n.js', '.'),
|
|
|
|
],
|
|
hiddenimports=[
|
|
# Flask and web dependencies
|
|
'jinja2.ext',
|
|
'flask',
|
|
'flask_cors',
|
|
'flask_socketio',
|
|
'socketio',
|
|
'werkzeug',
|
|
|
|
# JSON Schema validation
|
|
'jsonschema',
|
|
'jsonschema.validators',
|
|
'jsonschema._format',
|
|
'jsonschema._types',
|
|
|
|
# PLC and system dependencies
|
|
'snap7',
|
|
'psutil._pswindows',
|
|
'psutil._psutil_windows',
|
|
|
|
# Data processing
|
|
'pandas',
|
|
'numpy',
|
|
|
|
# Threading and networking
|
|
'threading',
|
|
'socket',
|
|
'json',
|
|
'csv',
|
|
'datetime',
|
|
'pathlib',
|
|
|
|
# Core modules (explicit imports)
|
|
'core.config_manager',
|
|
'core.plc_client',
|
|
'core.plc_data_streamer',
|
|
'core.event_logger',
|
|
'core.instance_manager',
|
|
'core.schema_manager',
|
|
'core.streamer',
|
|
'core.plot_manager',
|
|
'core.historical_cache',
|
|
'core.performance_monitor',
|
|
'core.priority_manager',
|
|
'core.rotating_logger',
|
|
|
|
# Utils modules
|
|
'utils.csv_validator',
|
|
'utils.json_manager',
|
|
'utils.symbol_loader',
|
|
'utils.symbol_processor',
|
|
'utils.instance_manager',
|
|
],
|
|
hookspath=[],
|
|
hooksconfig={},
|
|
runtime_hooks=[],
|
|
excludes=[
|
|
# Exclude unnecessary packages to reduce size
|
|
'matplotlib',
|
|
'scipy',
|
|
'IPython',
|
|
'notebook',
|
|
'jupyter',
|
|
'tests',
|
|
'unittest',
|
|
'pydoc',
|
|
'doctest',
|
|
],
|
|
win_no_prefer_redirects=False,
|
|
win_private_assemblies=False,
|
|
cipher=block_cipher,
|
|
noarchive=False,
|
|
)
|
|
|
|
# Analysis for backend manager (watchdog)
|
|
a_manager = Analysis(
|
|
['backmanager.py'],
|
|
pathex=[],
|
|
binaries=[],
|
|
datas=[
|
|
# Include utils for instance management
|
|
('utils', 'utils'),
|
|
],
|
|
hiddenimports=[
|
|
# System and monitoring dependencies
|
|
'psutil',
|
|
'psutil._pswindows',
|
|
'psutil._psutil_windows',
|
|
'requests',
|
|
'subprocess',
|
|
'logging',
|
|
'json',
|
|
|
|
# Utils modules needed by manager
|
|
'utils.instance_manager',
|
|
],
|
|
hookspath=[],
|
|
hooksconfig={},
|
|
runtime_hooks=[],
|
|
excludes=[
|
|
# Exclude heavy packages not needed by manager
|
|
'matplotlib',
|
|
'scipy',
|
|
'IPython',
|
|
'notebook',
|
|
'jupyter',
|
|
'flask',
|
|
'snap7',
|
|
'pandas',
|
|
'numpy',
|
|
],
|
|
win_no_prefer_redirects=False,
|
|
win_private_assemblies=False,
|
|
cipher=block_cipher,
|
|
noarchive=False,
|
|
)
|
|
|
|
# Build PYZ files
|
|
pyz_main = PYZ(a_main.pure, a_main.zipped_data, cipher=block_cipher)
|
|
pyz_manager = PYZ(a_manager.pure, a_manager.zipped_data, cipher=block_cipher)
|
|
|
|
# Build main backend executable
|
|
exe_main = EXE(
|
|
pyz_main,
|
|
a_main.scripts,
|
|
[],
|
|
exclude_binaries=True,
|
|
name='S7_Streamer_Logger',
|
|
debug=False,
|
|
bootloader_ignore_signals=False,
|
|
strip=False,
|
|
upx=True,
|
|
console=True, # True para ver los logs del servidor en una consola.
|
|
disable_windowed_traceback=False,
|
|
argv_emulation=False,
|
|
target_arch=None,
|
|
codesign_identity=None,
|
|
entitlements_file=None,
|
|
)
|
|
|
|
# Build backend manager executable
|
|
exe_manager = EXE(
|
|
pyz_manager,
|
|
a_manager.scripts,
|
|
[],
|
|
exclude_binaries=True,
|
|
name='Backend_Manager',
|
|
debug=False,
|
|
bootloader_ignore_signals=False,
|
|
strip=False,
|
|
upx=True,
|
|
console=True,
|
|
disable_windowed_traceback=False,
|
|
argv_emulation=False,
|
|
target_arch=None,
|
|
codesign_identity=None,
|
|
entitlements_file=None,
|
|
)
|
|
|
|
# Collect all files together - Only include executables and shared dependencies
|
|
coll = COLLECT(
|
|
exe_main,
|
|
exe_manager,
|
|
a_main.binaries,
|
|
a_main.zipfiles,
|
|
a_main.datas,
|
|
# Don't duplicate manager dependencies since they're minimal
|
|
strip=False,
|
|
upx=True,
|
|
upx_exclude=[],
|
|
name='main'
|
|
)
|
|
|
|
# Post-build: Copy config directory to the same level as the executable
|
|
import shutil
|
|
import os
|
|
|
|
def copy_config_external():
|
|
"""Copy config directory to external location for runtime access"""
|
|
try:
|
|
# Get absolute paths
|
|
current_dir = os.path.abspath('.')
|
|
source_config = os.path.join(current_dir, 'config')
|
|
dist_main_dir = os.path.join(current_dir, 'dist', 'main')
|
|
dest_config = os.path.join(dist_main_dir, 'config')
|
|
|
|
print(f"Current directory: {current_dir}")
|
|
print(f"Source config: {source_config}")
|
|
print(f"Destination config: {dest_config}")
|
|
|
|
# Ensure dist/main directory exists
|
|
os.makedirs(dist_main_dir, exist_ok=True)
|
|
|
|
# Remove existing config if present
|
|
if os.path.exists(dest_config):
|
|
shutil.rmtree(dest_config)
|
|
print(f"Removed existing config at: {dest_config}")
|
|
|
|
# Copy config directory to dist/main/config
|
|
if os.path.exists(source_config):
|
|
shutil.copytree(source_config, dest_config)
|
|
print(f"✓ Config directory copied to: {dest_config}")
|
|
return True
|
|
else:
|
|
print(f"✗ Source config directory not found: {source_config}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"✗ Error copying config directory: {e}")
|
|
return False
|
|
|
|
# Execute the copy operation
|
|
copy_config_external()
|
|
|
|
def config_path(relative_path):
|
|
"""Get path to config file, checking external location first when running as executable"""
|
|
if getattr(sys, 'frozen', False):
|
|
# Running as executable - config should be at same level as executable
|
|
executable_dir = os.path.dirname(sys.executable)
|
|
external_config = os.path.join(executable_dir, 'config', relative_path)
|
|
|
|
if os.path.exists(external_config):
|
|
return external_config
|
|
|
|
# Fallback to internal config within _internal
|
|
internal_config = os.path.join(executable_dir, '_internal', 'config', relative_path)
|
|
if os.path.exists(internal_config):
|
|
return internal_config
|
|
|
|
raise FileNotFoundError(f"Configuration file not found: {relative_path}")
|
|
else:
|
|
# Running as script - use standard path
|
|
base_dir = os.path.dirname(os.path.abspath(__file__))
|
|
project_root = os.path.dirname(base_dir)
|
|
return os.path.join(project_root, 'config', relative_path)
|