100 lines
3.2 KiB
Python
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) |