#!/usr/bin/env python3 """ Generate MainProgram with DPM routines from DESC_IP data. This script creates a complete MainProgram.L5X file with: - R000_SAFETY_TAG_MAP routine - R020_DPM routine (with AOI_DPM calls) - R100_ESTOP_CHECK routine - Complete controller tags Usage: python generate_main_with_dpm.py --desc-ip-mode python generate_main_with_dpm.py --desc-ip-mode --project-name MTN6_MCM05_CHUTE_LOAD """ from __future__ import annotations import argparse import sys from pathlib import Path # If repo root is current dir, add nested "src" folder to sys.path pkg_dir = Path(__file__).resolve().parent / "src" if pkg_dir.is_dir(): sys.path.insert(0, str(pkg_dir)) from src.generators import FullMainProgramGenerator, LimitedSafetyProgramGenerator def parse_args(): """Parse command line arguments.""" parser = argparse.ArgumentParser( description="Generate MainProgram L5X with DPM routines from DESC_IP data" ) parser.add_argument( '--desc-ip-mode', action='store_true', help='Use DESC_IP extraction mode (default: true for this script)' ) parser.add_argument( '--project-name', type=str, help='Project name for output files (e.g., MTN6_MCM05_CHUTE_LOAD)' ) parser.add_argument( '--ignore-estop1ok', action='store_true', help='Ignore ESTOP1_OK validation errors' ) return parser.parse_args() def main(): """Generate MainProgram and SafetyProgram L5X files with DPM routines.""" args = parse_args() print("=== MainProgram Generator with DPM Routines ===") print("Using DESC_IP extraction mode for device data") # Use DESC_IP_MERGED.xlsx from current directory excel_file = Path("DESC_IP_MERGED.xlsx") if not excel_file.exists(): print(f"ERROR: {excel_file} not found in current directory") print("Please ensure DESC_IP_MERGED.xlsx is available") sys.exit(1) print(f"Using Excel file: {excel_file}") # Load zones configuration based on project type zones_dict = None try: # Add parent directory to sys.path to find zones_config.py sys.path.insert(0, str(Path(__file__).parent.parent)) from zones_config import ZONES_CONFIGS, DEFAULT_ZONES # Detect project type from project name argument import re if args.project_name: mcm_match = re.search(r"(MCM\d+)", args.project_name, re.IGNORECASE) if mcm_match: mcm_type = mcm_match.group(1).upper() zones_dict = ZONES_CONFIGS.get(mcm_type, DEFAULT_ZONES) print(f"Detected {mcm_type} project from '{args.project_name}', loaded {len(zones_dict)} zones from zones_config.py") else: zones_dict = DEFAULT_ZONES print(f"No MCM type detected in '{args.project_name}', loaded {len(zones_dict)} default zones from zones_config.py") else: zones_dict = DEFAULT_ZONES print(f"No project name provided, loaded {len(zones_dict)} default zones from zones_config.py") except ImportError as e: print(f"Warning: Could not load zones_config.py: {e}") print("Proceeding without zones configuration...") try: # Generate MainProgram with DPM routines print("\n--- Generating MainProgram L5X ---") main_generator = FullMainProgramGenerator(excel_path=excel_file, zones_dict=zones_dict) # Determine output filename if args.project_name: main_output = f"MainProgram_{args.project_name}.L5X" safety_output = f"SafetyProgram_{args.project_name}.L5X" else: main_output = "MainProgram_Generated.L5X" safety_output = "SafetyProgram_Generated.L5X" main_generator.write(main_output) print(f"SUCCESS: MainProgram written to {main_output}") # Generate SafetyProgram print("\n--- Generating SafetyProgram L5X ---") safety_generator = LimitedSafetyProgramGenerator(excel_path=excel_file, zones_dict=zones_dict, ignore_estop1ok=args.ignore_estop1ok) safety_generator.write(safety_output) print(f"SUCCESS: SafetyProgram written to {safety_output}") print("\n=== Generation Complete ===") print(f"Generated files:") print(f" • {main_output}") print(f" • {safety_output}") # Summary of generated content print(f"\nMainProgram includes:") print(f" • R000_SAFETY_TAG_MAP routine") print(f" • R020_DPM routine with AOI_DPM calls") print(f" • R100_ESTOP_CHECK routine") print(f" • Complete controller tags") except Exception as e: print(f"ERROR: Generation failed: {e}") import traceback traceback.print_exc() sys.exit(1) if __name__ == "__main__": main()