2025-09-04 22:37:52 +04:00

100 lines
3.2 KiB
Python

"""
JPE routine generator (R0100_JPE).
Generates AOI_JPE calls for:
- Entries containing "JPE" in DESCA
- Entries containing "_2_PE" pattern in DESCA
"""
from __future__ import annotations
import xml.etree.ElementTree as ET
from typing import TYPE_CHECKING
import pandas as pd
from ..utils.common import format_xml_to_match_original, natural_sort_key
from ..plugin_system import RoutinePlugin, register_plugin
if TYPE_CHECKING:
from ..data_loader import DataLoader
def generate_jpe_routine(loader: DataLoader) -> ET.Element | None:
"""Generate R0100_JPE routine from DESC_IP data."""
print("\n [R0100_JPE] Starting JPE routine generation...")
# Extract JPE data
jpe_data = loader.jpe_data
if not jpe_data:
print(" [WARNING] No JPE configurations found")
return None
print(f" Found {len(jpe_data)} JPE configurations")
# Create routine element (config-driven name)
try:
from ..config import get_config
routine_name = get_config().routines.name_map.get('jpe', 'R100_JPE')
except Exception:
routine_name = 'R100_JPE'
routine = ET.Element('Routine', Name=routine_name, Type='RLL')
desc = ET.SubElement(routine, 'Description')
desc.text = 'Jam Photo Eye Control Routine'
rll_content = ET.SubElement(routine, 'RLLContent')
# Generate rungs for each JPE configuration
rung_number = 0
for jpe_name, config in sorted(jpe_data.items(), key=lambda x: natural_sort_key(x[0])):
# Build AOI call
aoi_params = [
f"{jpe_name}.AOI",
f"{jpe_name}.HMI",
f"{jpe_name}.CTRL",
config['conveyor_ctrl'], # Conveyor/VFD controller
config['station_ctrl'], # Station controller (JR)
config['parent_comm_fault'], # Parent communication fault
config['input_path'], # Input path
"YES", # Run up PE - always YES
config['beacon_output'] # Beacon output path
]
# Create rung
rung = ET.SubElement(rll_content, 'Rung', Number=str(rung_number), Type='N')
comment = ET.SubElement(rung, 'Comment')
comment.text = f"Jam Photo Eye Control for {jpe_name}"
text = ET.SubElement(rung, 'Text')
text.text = f"AOI_JPE({','.join(aoi_params)});"
rung_number += 1
print(f" Generated {rung_number} JPE rungs")
# Convert to string and format XML to match Rockwell standards
xml_str = ET.tostring(routine, encoding='unicode')
formatted_xml = format_xml_to_match_original(xml_str)
# Parse back to Element
return ET.fromstring(formatted_xml)
class JpeRoutinePlugin(RoutinePlugin):
name = "jpe"
description = "Generates the JPE routine"
category = "device"
def can_generate(self) -> bool:
return bool(self.context.data_loader.jpe_data)
def generate(self) -> bool:
elem = generate_jpe_routine(self.context.data_loader)
if elem is None:
return False
self.context.routines_element.append(elem)
return True
register_plugin(JpeRoutinePlugin)