147 lines
5.5 KiB
Python
147 lines
5.5 KiB
Python
import pandas as pd
|
|
import re
|
|
|
|
def _is_hub_tagname_pattern(tagname: str) -> bool:
|
|
"""Check if TAGNAME matches hub patterns like FIO1H, FIO2H3, FIOH1, etc."""
|
|
# Match patterns like FIO1H, FIO2H3, FIOH1, etc.
|
|
hub_pattern = re.compile(r'FIO(\d+)?H\d*', re.IGNORECASE)
|
|
return bool(hub_pattern.search(tagname))
|
|
|
|
def _is_master_tagname_pattern(tagname: str) -> bool:
|
|
"""Check if TAGNAME matches master patterns like FIO2M1, FIO3M, etc."""
|
|
# Match patterns like FIO2M1, FIO3M, etc.
|
|
master_pattern = re.compile(r'FIO\d+M\d*', re.IGNORECASE)
|
|
return bool(master_pattern.search(tagname))
|
|
|
|
def _is_hub_desca_pattern(desca: str) -> bool:
|
|
"""Check if DESCA matches hub patterns like FIO1H, PDP12_FIO1H, FIO2H3, etc."""
|
|
# Match patterns like FIO1H, PDP12_FIO1H, FIO2H3, etc. in DESCA
|
|
# Allow optional prefix, FIO + digits + H + optional digits
|
|
hub_pattern = re.compile(r'FIO\d+H\d*', re.IGNORECASE)
|
|
return bool(hub_pattern.search(desca))
|
|
|
|
def classify_signal(desca, tagname, descb=None, excel_filename=None):
|
|
"""
|
|
Classify signal based on DESCA content, TAGNAME, DESCB, and Excel filename
|
|
Priority order matters: PB_LT before PB, FIOH before FIO, SOL+DIVERT before SOL
|
|
|
|
Special rules:
|
|
- If Excel filename contains MCM05, SOL signals are classified as 'O' instead of 'IOLink'
|
|
"""
|
|
if pd.isna(desca):
|
|
return 'UNKNOWN'
|
|
|
|
desca_str = str(desca).upper()
|
|
tagname_str = str(tagname).upper()
|
|
descb_str = str(descb).upper() if pd.notna(descb) else ''
|
|
|
|
# Check if Excel filename contains MCM05 (special rule for solenoids)
|
|
is_mcm05 = False
|
|
if excel_filename:
|
|
is_mcm05 = 'MCM05' in str(excel_filename).upper()
|
|
|
|
# Check for SPARE first
|
|
if re.search(r'SPARE', desca_str):
|
|
return 'SPARE'
|
|
|
|
# Signal O patterns (check higher priority first)
|
|
if re.search(r'BCN\d+_[AGBR]', desca_str): # e.g., BCN3_B, BCN1_A
|
|
return 'O'
|
|
elif re.search(r'PB_LT', desca_str):
|
|
return 'O'
|
|
elif re.search(r'_PE5', desca_str): # PB patterns (already had this but moved up)
|
|
return 'O'
|
|
|
|
# Check for PR sensors (user rule: PR is I) - moved after specific patterns
|
|
elif re.search(r'_PR\d+|PR\d+', desca_str): # Match PR followed by digits (proximity sensors)
|
|
return 'I'
|
|
elif re.search(r'STO', desca_str):
|
|
return 'O'
|
|
elif re.search(r'BCN', desca_str) and 'FIOH' in tagname_str:
|
|
return 'O'
|
|
elif re.search(r'_H', desca_str):
|
|
return 'O'
|
|
|
|
# IOLink patterns (check these first before general I patterns to avoid conflicts)
|
|
elif re.search(r'SOL', desca_str) and re.search(r'DIVERT', descb_str):
|
|
# MCM05 rule: SOL signals should be 'O', not 'IOLink'
|
|
if is_mcm05:
|
|
return 'O'
|
|
return 'IOLink'
|
|
elif re.search(r'LPE', desca_str): # LPE must be checked before PE patterns
|
|
return 'IOLink'
|
|
|
|
# Signal I patterns (check these after IOLink patterns to avoid conflicts)
|
|
elif re.search(r'TS\d*|BDS\d*', desca_str): # TS and BDS patterns
|
|
return 'I'
|
|
elif re.search(r'LRPE', desca_str): # LRPE patterns
|
|
return 'I'
|
|
elif re.search(r'PWM', desca_str):
|
|
return 'I'
|
|
elif re.search(r'CB', desca_str):
|
|
return 'I'
|
|
elif re.search(r'FPE', desca_str):
|
|
return 'I'
|
|
elif re.search(r'EN', desca_str):
|
|
return 'I'
|
|
elif re.search(r'PS', desca_str):
|
|
return 'I'
|
|
elif re.search(r'EPC', desca_str):
|
|
return 'I'
|
|
elif re.search(r'PX', desca_str):
|
|
return 'I'
|
|
elif re.search(r'PE\d*', desca_str): # PE patterns (moved after LPE check)
|
|
return 'I'
|
|
elif re.search(r'PB', desca_str): # PB patterns (already had this but moved up)
|
|
return 'I'
|
|
elif re.search(r'MDR', desca_str): # PB patterns (already had this but moved up)
|
|
return 'O'
|
|
|
|
# Check SOL patterns first (before general FIOH patterns)
|
|
elif re.search(r'SOL', desca_str):
|
|
# SOL signals are always 'O' (including MCM05 rule)
|
|
return 'O'
|
|
|
|
# Remaining IOLink patterns
|
|
elif re.search(r'FIOH', desca_str):
|
|
return 'IOLink'
|
|
elif _is_hub_desca_pattern(desca_str): # Check for FIO1H1, FIO2H3 etc patterns in DESCA
|
|
return 'IOLink'
|
|
elif _is_hub_tagname_pattern(tagname_str): # Check for FIO1H, FIO2H3 etc patterns (lower priority)
|
|
return 'IOLink'
|
|
elif re.search(r'BCN', desca_str) and 'FIO' in tagname_str:
|
|
return 'IOLink'
|
|
elif re.search(r'DISC', desca_str):
|
|
return 'I'
|
|
elif re.search(r'ESTOP', desca_str):
|
|
return 'I'
|
|
elif 'IB16' in tagname_str or 'IB16S' in tagname_str:
|
|
return 'I'
|
|
elif 'OB16E' in tagname_str:
|
|
return 'O'
|
|
|
|
return 'UNKNOWN'
|
|
|
|
def get_device_type(tagname):
|
|
"""Determine device type from TAGNAME"""
|
|
tagname_str = str(tagname).upper()
|
|
|
|
if 'VFD' in tagname_str:
|
|
return 'APF'
|
|
elif 'FIOH' in tagname_str:
|
|
return 'Hub'
|
|
elif _is_hub_tagname_pattern(tagname_str): # Check for FIO1H, FIO2H3 etc patterns
|
|
return 'Hub'
|
|
elif _is_master_tagname_pattern(tagname_str): # Check for FIO2M1, FIO3M etc patterns
|
|
return 'M12DR'
|
|
elif 'FIO' in tagname_str:
|
|
return 'M12DR'
|
|
elif 'SIO' in tagname_str:
|
|
return 'SIO'
|
|
elif 'OB16E' in tagname_str:
|
|
return 'OB16E'
|
|
elif 'IB16S' in tagname_str:
|
|
return 'IB16S'
|
|
elif 'IB16' in tagname_str:
|
|
return 'IB16'
|
|
return 'UNKNOWN' |