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

178 lines
6.2 KiB
Python

#!/usr/bin/env python3
"""
Banner ZMX Module Boilerplate Model
===================================
Model for Banner ZMX modules.
Supports name, IP address, and parent module configuration.
"""
from typing import Optional, TYPE_CHECKING
import xml.etree.ElementTree as ET
from dataclasses import dataclass
from datetime import datetime
import os
if TYPE_CHECKING:
from excel_data_processor import ModuleData
@dataclass
class ZMXModuleConfig:
"""Configuration for a Banner ZMX module instance."""
name: str # Module name (e.g., "ZMX1")
ip_address: str = "192.168.1.2"
parent_module: str = "SLOT2_EN4TR"
parent_port_id: str = "2"
class ZMXModuleGenerator:
"""Generates Banner ZMX module configurations from boilerplate."""
def __init__(self, config: ZMXModuleConfig):
self.config = config
self.boilerplate_filename = "ZMX_Module.L5X"
self.boilerplate_path = os.path.join("boilerplate", self.boilerplate_filename)
self.tree = None
self.root = None
def load_boilerplate(self):
"""Load the boilerplate XML file."""
if not os.path.exists(self.boilerplate_path):
raise FileNotFoundError(f"Boilerplate file not found: {self.boilerplate_path}")
self.tree = ET.parse(self.boilerplate_path)
self.root = self.tree.getroot()
def update_module_name(self):
"""Update the module name in the XML."""
# Update module name
module = self.root.find(".//Module[@Use='Target']")
if module is not None:
module.set("Name", self.config.name)
# Update target name in root
self.root.set("TargetName", self.config.name)
def update_ip_address(self):
"""Update the IP address in the module configuration."""
# Find the Ethernet port and update IP address
port = self.root.find(".//Port[@Type='Ethernet']")
if port is not None:
port.set("Address", self.config.ip_address)
def update_parent_module(self):
"""Update the parent module configuration."""
module = self.root.find(".//Module[@Use='Target']")
if module is not None:
module.set("ParentModule", self.config.parent_module)
module.set("ParentModPortId", self.config.parent_port_id)
def update_export_date(self):
"""Update the export date to current time."""
export_date = datetime.now().strftime("%a %b %d %H:%M:%S %Y")
self.root.set("ExportDate", export_date)
def apply_updates(self):
"""Apply all configuration updates."""
self.update_module_name()
self.update_ip_address()
self.update_parent_module()
self.update_export_date()
def save(self, output_path: str):
"""Save the configured module to a file."""
if self.tree is None:
raise ValueError("No boilerplate loaded. Call load_boilerplate() first.")
# Create output directory if it doesn't exist
output_dir = os.path.dirname(output_path)
if output_dir and not os.path.exists(output_dir):
os.makedirs(output_dir)
# Write the XML to file
with open(output_path, 'wb') as f:
f.write(b'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n')
self.tree.write(f, encoding='UTF-8')
# ------------------------------------------------------------------
# Convenience helper for generator refactor
# ------------------------------------------------------------------
@classmethod
def from_excel(cls, module_data: 'ModuleData') -> 'ZMXModuleGenerator':
"""Create and return a generator configured from Excel ModuleData."""
ip_addr = module_data.ip_address or "192.168.1.2"
cfg = create_zmx_module(
name=module_data.tagname,
ip_address=ip_addr,
parent_module="SLOT2_EN4TR",
parent_port_id="2",
)
gen = cls(cfg)
gen.load_boilerplate()
gen.apply_updates()
return gen
def create_zmx_module(name: str, ip_address: str = "192.168.1.2",
parent_module: str = "SLOT2_EN4TR",
parent_port_id: str = "2") -> ZMXModuleConfig:
"""
Factory function to create a Banner ZMX module configuration.
Args:
name: Module name (e.g., "ZMX1")
ip_address: IP address for the module (default: "192.168.1.2")
parent_module: Parent module name (default: "SLOT2_EN4TR")
parent_port_id: Parent port ID (default: "2")
Returns:
ZMXModuleConfig: Configured Banner ZMX module
"""
return ZMXModuleConfig(
name=name,
ip_address=ip_address,
parent_module=parent_module,
parent_port_id=parent_port_id
)
def main():
"""Example usage of the Banner ZMX module generator."""
print("Banner ZMX Module Generator Example")
print("=" * 40)
# Create Banner ZMX module configuration
config = create_zmx_module(
name="ZMX1",
ip_address="192.168.1.10",
parent_module="SLOT2_EN4TR"
)
# Generate the module
generator = ZMXModuleGenerator(config)
generator.load_boilerplate()
generator.apply_updates()
# Save to generated folder
os.makedirs("generated", exist_ok=True)
output_file = f"generated/{config.name}.L5X"
generator.save(output_file)
print(f"Generated Banner ZMX module: {output_file}")
print(f" Name: {config.name}")
print(f" IP Address: {config.ip_address}")
print(f" Parent Module: {config.parent_module}")
print(f" Parent Port: {config.parent_port_id}")
print("\nModule Features:")
print(" - High-speed I/O data exchange")
print(" - Input data array (68 INT elements)")
print(" - Output data array (40 INT elements)")
print(" - Banner Engineering Corporation device")
print(" - Ethernet/IP communication")
if __name__ == "__main__":
main()