Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import xml.etree.ElementTree as ET | |
| import io | |
| def get_total_capacity_from_xml(xml_file_path, substation_names_str, profile, flexibility_level): | |
| """ | |
| Calculates the total capacity for specified substations, profile, and flexibility level | |
| from an uploaded XML file's content. | |
| Args: | |
| xml_file_path (str): The file path (string) of the temporary uploaded XML file. | |
| substation_names_str (str): A comma-separated string of substation names. | |
| profile (str): The profile type (e.g., "pv", "load", "battery"). | |
| flexibility_level (str): The flexibility level (e.g., "0%_flex", "5%_flex"). | |
| Returns: | |
| str: A message indicating the total combined capacity or an error. | |
| """ | |
| if xml_file_path is None: | |
| return "Error: No XML file uploaded." | |
| try: | |
| # Read the content from the temporary file path provided by Gradio | |
| with open(xml_file_path, 'r', encoding='utf-8') as f: | |
| xml_file_content = f.read() | |
| except Exception as e: | |
| return f"Error reading XML file: {e}" | |
| if not xml_file_content: | |
| return "Error: Uploaded XML file is empty or could not be read." | |
| substation_names = [s.strip() for s in substation_names_str.split(',') if s.strip()] | |
| if not substation_names: | |
| return "Error: Please enter at least one substation name." | |
| total_capacity = 0.0 | |
| # Define namespaces used in the XML | |
| namespaces = { | |
| 'default': 'http://schemas.datacontract.org/2004/07/Elia.EliaBeControls.WebApi.Interface.Dto.Hcm', | |
| 'd5p1': 'http://schemas.microsoft.com/2003/10/Serialization/Arrays' | |
| } | |
| try: | |
| # Parse the XML content from the string | |
| root = ET.parse(io.StringIO(xml_file_content)).getroot() | |
| except ET.ParseError as e: | |
| return f"Error parsing XML: The file might be malformed or not valid XML. Details: {e}" | |
| except Exception as e: | |
| return f"An unexpected error occurred during XML parsing: {e}" | |
| found_any_matching_data = False | |
| # Iterate through each SiteDetailDto element | |
| for site_detail_dto in root.findall('default:SiteDetailDto', namespaces): | |
| site_name_element = site_detail_dto.find('default:Site', namespaces) | |
| # Check if the site name element exists and its text is in our list of substations | |
| if site_name_element is not None and site_name_element.text in substation_names: | |
| # Iterate through each SubstationDetailDto within the site | |
| for substation_detail_dto in site_detail_dto.findall('.//default:SubstationDetailDto', namespaces): | |
| # Iterate through profiles | |
| for profile_kv in substation_detail_dto.findall('default:Profiles/d5p1:KeyValueOfstringArrayOfProfileInfoDtoOJezfHCJ', namespaces): | |
| key_element = profile_kv.find('d5p1:Key', namespaces) | |
| # Check if the profile key matches the requested profile | |
| if key_element is not None and key_element.text == profile: | |
| # Iterate through flexibility levels within the profile | |
| for profile_info_dto in profile_kv.findall('d5p1:Value/default:ProfileInfoDto', namespaces): | |
| flexibility_level_element = profile_info_dto.find('default:FlexibilityLevel', namespaces) | |
| # Check if the flexibility level matches the requested level | |
| if flexibility_level_element is not None and flexibility_level_element.text == flexibility_level: | |
| capacity_element = profile_info_dto.find('default:FlexibilityDetail/default:Capacity', namespaces) | |
| # Check if the capacity element exists and has text | |
| if capacity_element is not None and capacity_element.text: | |
| try: | |
| total_capacity += float(capacity_element.text) | |
| found_any_matching_data = True | |
| except ValueError: | |
| # Log or handle cases where capacity might not be a valid float | |
| print(f"Warning: Could not convert capacity '{capacity_element.text}' to float for {site_name_element.text}, Profile: {profile}, Flex: {flexibility_level}") | |
| pass # Continue processing other elements | |
| if not found_any_matching_data and total_capacity == 0.0: | |
| return f"No matching data found for substations: {substation_names_str}, profile: '{profile}', and flexibility: '{flexibility_level}'. Check your inputs and the XML structure." | |
| return f"The total capacity for the selected criteria is: {total_capacity}" | |
| # Gradio Interface setup | |
| # Input components | |
| # Changed type="filepath" to ensure a string path is passed to the function | |
| xml_upload = gr.File(label="Upload XML File", file_types=[".xml"], type="filepath") | |
| substation_input = gr.Textbox(label="Enter Substation(s) (comma-separated, e.g., AALST,AALTR)", placeholder="AALST, AALTR") | |
| profile_dropdown = gr.Dropdown(choices=["pv", "load", "battery"], label="Select Profile", value="pv") | |
| flexibility_dropdown = gr.Dropdown(choices=["0%_flex", "5%_flex", "10%_flex", "20%_flex"], label="Select Flexibility Level", value="5%_flex") | |
| # Define the Gradio interface | |
| iface = gr.Interface( | |
| fn=get_total_capacity_from_xml, | |
| inputs=[xml_upload, substation_input, profile_dropdown, flexibility_dropdown], | |
| outputs="text", | |
| title="Substation Capacity Calculator from XML", | |
| description="Upload an XML file, then select substations, profile, and flexibility level to get the total capacity. This tool performs basic structural checks on the XML." | |
| ) | |
| # Launch the Gradio app | |
| iface.launch(share=True) |