2025-08-05 14:38:54 +04:00

133 lines
4.8 KiB
Python

import pandas as pd
import os
import sys
import re
from utils import normalize_io_term
def load_io_path_mappings():
"""Load IO path mappings from IO-To-Path.xlsx"""
io_path_file = "IO-To-Path.xlsx"
if not os.path.exists(io_path_file):
print(f"CRITICAL: IO path file not found: {io_path_file}")
sys.exit(1)
try:
# Read all sheets from IO-To-Path.xlsx
apf_df = pd.read_excel(io_path_file, sheet_name='APF')
m12dr_df = pd.read_excel(io_path_file, sheet_name='M12DR')
hub_df = pd.read_excel(io_path_file, sheet_name='Hub')
sorter_hub_df = pd.read_excel(io_path_file, sheet_name='SorterHub')
sio_df = pd.read_excel(io_path_file, sheet_name='SIO')
ib16_df = pd.read_excel(io_path_file, sheet_name='IB16')
ob16e_df = pd.read_excel(io_path_file, sheet_name='OB16E')
ib16s_df = pd.read_excel(io_path_file, sheet_name='IB16S')
print(f"Loaded IO path mappings:")
print(f" APF: {len(apf_df)} rows")
print(f" M12DR: {len(m12dr_df)} rows")
print(f" Hub: {len(hub_df)} rows")
print(f" SorterHub: {len(sorter_hub_df)} rows")
print(f" SIO: {len(sio_df)} rows")
print(f" IB16: {len(ib16_df)} rows")
print(f" OB16E: {len(ob16e_df)} rows")
print(f" IB16S: {len(ib16s_df)} rows")
return apf_df, m12dr_df, hub_df, sorter_hub_df, sio_df, ib16_df, ob16e_df, ib16s_df
except Exception as e:
print(f"CRITICAL: Error loading IO path mappings: {e}")
sys.exit(1)
def get_io_path(tagname, term, signal_type, device_type, apf_df, m12dr_df, hub_df, sorter_hub_df, sio_df, ib16_df, ob16e_df, ib16s_df):
"""Get IO path for a given tagname, term, and signal type"""
if device_type == 'UNKNOWN' or pd.isna(term):
return None
# Select appropriate dataframe
if device_type == 'APF':
df = apf_df
elif device_type == 'M12DR':
df = m12dr_df
elif device_type == 'Hub':
# Check if the hub has S0 in its name to determine which sheet to use
if 'S0' in str(tagname).upper():
df = sorter_hub_df
else:
df = hub_df
elif device_type == 'SIO':
df = sio_df
elif device_type == 'IB16':
df = ib16_df
elif device_type == 'OB16E':
df = ob16e_df
elif device_type == 'IB16S':
df = ib16s_df
else:
return None
if df is None:
return None
# Get term variations to handle IO1 vs IO01 inconsistencies
term_variations = normalize_io_term(term)
# Try to find matching row
matching_row = None
for term_var in term_variations:
mask = df['IO'] == term_var
if mask.any():
matching_row = df[mask].iloc[0]
break
if matching_row is None:
return None
# Select appropriate path column based on term type first, then signal type
path_value = None
term_upper = str(term).upper()
# Check term prefix first (SI/SO have dedicated columns)
if term_upper.startswith('SI') and (device_type == 'APF' or device_type == 'SIO'):
path_value = matching_row.get('SIPath')
elif term_upper.startswith('SO') and (device_type == 'APF' or device_type == 'SIO'):
path_value = matching_row.get('SOPath')
elif signal_type == 'IOLink' and (device_type == 'M12DR' or device_type == 'SIO'):
path_value = matching_row.get('IOLinkPath')
# Then check signal type for regular I/O
elif signal_type == 'I':
path_value = matching_row.get('IPath')
elif signal_type == 'O':
path_value = matching_row.get('OPath')
elif signal_type == 'SPARE': # SPARE entries default to IPath, fallback to OPath
path_value = matching_row.get('IPath')
# If IPath is empty, try OPath as fallback
if pd.isna(path_value) or path_value == '':
path_value = matching_row.get('OPath')
if pd.isna(path_value) or path_value == '':
return None
path_str = str(path_value)
# Replace device prefix with actual tagname for non-local devices
if device_type in ['APF', 'M12DR', 'Hub', 'SIO']:
if device_type == 'APF':
path_str = path_str.replace('APF', str(tagname))
elif device_type == 'M12DR':
path_str = path_str.replace('M12DR', str(tagname))
elif device_type == 'Hub':
path_str = path_str.replace('Hub', str(tagname))
elif device_type == 'SIO':
path_str = path_str.replace('SIO', str(tagname))
else:
# For local slot devices (IB16, OB16E, IB16S)
slot_match = re.search(r'SLOT(\d+)', str(tagname).upper())
if slot_match:
slot = slot_match.group(1)
path_str = f"Local:{slot}:{path_str}"
else:
return None
return path_str