""" STATION_SS_PB routine generator. Generates AOI_STATION_SS_PB calls for station SS (Start/Stop) push buttons with format: AOI_STATION_SS_PB(tag.AOI, tag.HMI, tag.CTRL, VFD.CTRL, FIO_ConnectionFault, Start_Input, Stop_Input, Light_Output); Matches entries with DESCA patterns like: - UL3_1_SS1_SPB (start pushbutton) - UL3_1_SS1_SPB_LT (start pushbutton light) - UL3_1_SS1_STPB (stop pushbutton) And finds the corresponding VFD and FIO based on the base name. """ import xml.etree.ElementTree as ET from typing import Dict, Any import pandas as pd import re from ..utils.common import format_xml_to_match_original, natural_sort_key from ..plugin_system import RoutinePlugin, register_plugin def generate_station_ss_pb_routine(data_loader) -> ET.Element: """Generate the STATION_SS_PB routine XML element.""" station_ss_pb_data = data_loader.station_ss_pb_data # Config-driven routine name try: from ..config import get_config routine_name = get_config().routines.name_map.get('station_ss_pb', 'R096_STATION_SS_PB') except Exception: routine_name = 'R096_STATION_SS_PB' routine = ET.Element('Routine', Name=routine_name, Type='RLL') desc = ET.SubElement(routine, 'Description') desc.text = 'Station SS (Start/Stop) Push Button Control Routine' # Create RLLContent rll_content = ET.SubElement(routine, 'RLLContent') # Generate rungs for each STATION_SS_PB configuration rung_number = 0 for ss_pb_name, config in sorted(station_ss_pb_data.items(), key=lambda x: natural_sort_key(x[0])): # Build AOI call aoi_params = [ f"{ss_pb_name}_STATION.AOI", f"{ss_pb_name}_STATION.HMI", f"{ss_pb_name}_STATION.CTRL", config['vfd_ctrl'], # VFD controller config['fio_connection_fault'], # FIO connection fault config['start_input_path'], # SS1_SPB start input path config['stop_input_path'], # SS1_STPB stop input path config['light_output_path'], # SS1_SPB_LT light output path config['jr_station_ctrl'] # Closest JR station controller ] # Create rung rung = ET.SubElement(rll_content, 'Rung', Number=str(rung_number), Type='N') comment = ET.SubElement(rung, 'Comment') comment.text = f"Station SS Push Button Control for {ss_pb_name}" text = ET.SubElement(rung, 'Text') text.text = f"AOI_STATION_SS_PB({','.join(aoi_params)});" rung_number += 1 # Convert to string and format xml_str = ET.tostring(routine, encoding='unicode') formatted_xml = format_xml_to_match_original(xml_str) return ET.fromstring(formatted_xml) class StationSsPbRoutinePlugin(RoutinePlugin): name = "station_ss_pb" description = "Generates the STATION_SS_PB routine" category = "device" def can_generate(self) -> bool: return bool(self.context.data_loader.station_ss_pb_data) def generate(self) -> bool: elem = generate_station_ss_pb_routine(self.context.data_loader) if elem is None: return False self.context.routines_element.append(elem) return True register_plugin(StationSsPbRoutinePlugin)