现场总线(Fieldbus)的配置映射FieldbusMappings 类

public class FieldbusMappings
    {
        internal const string FieldbusConfigurationSectionName = "FieldbusMap";

        private readonly XmlElement fieldbusElement;

        private readonly XmlNamespaceManager nsManager;

        private readonly HilscherConnectionCollection hilscherConnMappings = new HilscherConnectionCollection();

        private readonly FieldbusConnectionCollection<PCModbusMasterConnectionMappings, ModbusMasterConnectionInformation, PCModbusMasterMapping> pcModbusMasterMappings = new FieldbusConnectionCollection<PCModbusMasterConnectionMappings, ModbusMasterConnectionInformation, PCModbusMasterMapping>();

        private PCModbusSlaveConnectionMappings pcModbusSlaveMappings;

        private readonly DriveModbusMasterConnectionCollection driveModbusMasterMappings = new DriveModbusMasterConnectionCollection();

        public INamedCollection<HilscherConnectionMappings, HilscherConnectionInformation> Hilscher => hilscherConnMappings;

        public INamedCollection<PCModbusMasterConnectionMappings, ModbusMasterConnectionInformation> PCModbusMaster => pcModbusMasterMappings;

        public PCModbusSlaveConnectionMappings PCModbusSlave
        {
            get
            {
                return pcModbusSlaveMappings;
            }
            set
            {
                if (pcModbusSlaveMappings == null && value == null)
                {
                    return;
                }

                PCModbusSlaveConnectionMappings pCModbusSlaveConnectionMappings = pcModbusSlaveMappings;
                try
                {
                    pcModbusSlaveMappings = null;
                    if (value != null)
                    {
                        foreach (PCModbusSlaveMapping item in value)
                        {
                            nameValidatingHandler(this, new FieldbusMappingNameValidatingEventArgs(item.Name));
                        }
                    }
                }
                catch (InvalidOperationException ex)
                {
                    pcModbusSlaveMappings = pCModbusSlaveConnectionMappings;
                    throw ex;
                }

                pcModbusSlaveMappings = value;
                if (pCModbusSlaveConnectionMappings != null)
                {
                    pCModbusSlaveConnectionMappings.ConfigurationChanged -= configurationChangedHandler;
                    pCModbusSlaveConnectionMappings.NameValidating -= nameValidatingHandler;
                }

                if (value != null)
                {
                    pcModbusSlaveMappings.ConfigurationChanged += configurationChangedHandler;
                    pcModbusSlaveMappings.NameValidating += nameValidatingHandler;
                }

                configurationChangedHandler(this, new FieldbusMappingChangedEventArgs());
            }
        }

        public INamedCollection<DriveModbusMasterConnectionMappings, DriveModbusMasterConnectionInformation> DriveModbusMaster => driveModbusMasterMappings;

        internal static VariableType[] FieldbusVariableTypes => new VariableType[21]
        {
        VariableType.Bit,
        VariableType.Bool,
        VariableType.Byte,
        VariableType.DInt,
        VariableType.Double,
        VariableType.DWord,
        VariableType.Int,
        VariableType.Int16,
        VariableType.Int32,
        VariableType.Int8,
        VariableType.LReal,
        VariableType.Real,
        VariableType.Single,
        VariableType.SInt,
        VariableType.UDInt,
        VariableType.UInt,
        VariableType.UInt16,
        VariableType.UInt32,
        VariableType.UInt8,
        VariableType.USInt,
        VariableType.Word
        };

        internal FieldbusMappings(ParameterFile paramFile, XmlDocument paramFileXmlDoc, XmlNamespaceManager nsManager)
        {
            this.nsManager = nsManager;
            XmlElement xmlElement = paramFile.UserDataSections["FieldbusMap"];
            if (xmlElement == null)
            {
                xmlElement = paramFileXmlDoc.CreateElement("FieldbusMap", "http://www.aerotech.com/xsd/Controller/Parameters/2009/");
                paramFile.UserDataSections["FieldbusMap"] = xmlElement;
            }

            fieldbusElement = xmlElement;
            initHilscher();
            initDriveModbusMaster();
            initPcModbusMaster();
            initPcModbusSlave();
        }

        private void initHilscher()
        {
            hilscherConnMappings.NameValidating += nameValidatingHandler;
            foreach (XmlElement item in fieldbusElement.SelectNodes("p:HilscherCard", nsManager))
            {
                HilscherConnectionInformation hilscherConnectionInformation = new HilscherConnectionInformation();
                ((IParameterFileStorable)hilscherConnectionInformation).FromXml(item);
                HilscherConnectionMappings hilscherConnectionMappings = new HilscherConnectionMappings(hilscherConnectionInformation);
                foreach (XmlNode childNode in item.ChildNodes)
                {
                    if (childNode.NodeType == XmlNodeType.Element)
                    {
                        HilscherMapping hilscherMapping = new HilscherMapping();
                        ((IParameterFileStorable)hilscherMapping).FromXml((XmlElement)childNode);
                        hilscherConnectionMappings.Add(hilscherMapping);
                    }
                }

                hilscherConnMappings.Add(hilscherConnectionMappings);
            }

            hilscherConnMappings.ConfigurationChanged += configurationChangedHandler;
        }

        private void initPcModbusMaster()
        {
            pcModbusMasterMappings.NameValidating += nameValidatingHandler;
            foreach (XmlElement item in fieldbusElement.SelectNodes("p:PcModbusMaster", nsManager))
            {
                ModbusMasterConnectionInformation modbusMasterConnectionInformation = new ModbusMasterConnectionInformation();
                ((IParameterFileStorable)modbusMasterConnectionInformation).FromXml(item);
                PCModbusMasterConnectionMappings pCModbusMasterConnectionMappings = new PCModbusMasterConnectionMappings(modbusMasterConnectionInformation);
                foreach (XmlNode childNode in item.ChildNodes)
                {
                    if (childNode.NodeType == XmlNodeType.Element)
                    {
                        PCModbusMasterMapping pCModbusMasterMapping = new PCModbusMasterMapping();
                        ((IParameterFileStorable)pCModbusMasterMapping).FromXml((XmlElement)childNode);
                        pCModbusMasterConnectionMappings.Add(pCModbusMasterMapping);
                    }
                }

                pcModbusMasterMappings.Add(pCModbusMasterConnectionMappings);
            }

            pcModbusMasterMappings.ConfigurationChanged += configurationChangedHandler;
        }

        private void initPcModbusSlave()
        {
            XmlElement xmlElement = (XmlElement)fieldbusElement.SelectSingleNode("p:PcModbusSlave", nsManager);
            if (xmlElement == null)
            {
                return;
            }

            ModbusSlaveConnectionInformation modbusSlaveConnectionInformation = new ModbusSlaveConnectionInformation();
            ((IParameterFileStorable)modbusSlaveConnectionInformation).FromXml(xmlElement);
            PCModbusSlaveConnectionMappings pCModbusSlaveConnectionMappings = new PCModbusSlaveConnectionMappings(modbusSlaveConnectionInformation);
            foreach (XmlNode childNode in xmlElement.ChildNodes)
            {
                if (childNode.NodeType == XmlNodeType.Element)
                {
                    PCModbusSlaveMapping pCModbusSlaveMapping = new PCModbusSlaveMapping();
                    ((IParameterFileStorable)pCModbusSlaveMapping).FromXml((XmlElement)childNode);
                    pCModbusSlaveConnectionMappings.Add(pCModbusSlaveMapping);
                }
            }

            pcModbusSlaveMappings = pCModbusSlaveConnectionMappings;
            pcModbusSlaveMappings.ConfigurationChanged += configurationChangedHandler;
            pcModbusSlaveMappings.NameValidating += nameValidatingHandler;
        }

        private void initDriveModbusMaster()
        {
            driveModbusMasterMappings.NameValidating += nameValidatingHandler;
            foreach (XmlElement item in fieldbusElement.SelectNodes("p:DriveModbusMaster", nsManager))
            {
                DriveModbusMasterConnectionInformation driveModbusMasterConnectionInformation = new DriveModbusMasterConnectionInformation();
                ((IParameterFileStorable)driveModbusMasterConnectionInformation).FromXml(item);
                DriveModbusMasterConnectionMappings driveModbusMasterConnectionMappings = new DriveModbusMasterConnectionMappings(driveModbusMasterConnectionInformation);
                foreach (XmlNode childNode in item.ChildNodes)
                {
                    if (childNode.NodeType == XmlNodeType.Element)
                    {
                        DriveModbusMasterMapping driveModbusMasterMapping = new DriveModbusMasterMapping();
                        ((IParameterFileStorable)driveModbusMasterMapping).FromXml((XmlElement)childNode);
                        driveModbusMasterConnectionMappings.Add(driveModbusMasterMapping);
                    }
                }

                driveModbusMasterMappings.Add(driveModbusMasterConnectionMappings);
            }

            driveModbusMasterMappings.ConfigurationChanged += configurationChangedHandler;
        }

        private void configurationChangedHandler(object sender, FieldbusMappingChangedEventArgs e)
        {
            fieldbusElement.RemoveAll();
            foreach (HilscherConnectionMappings hilscherConnMapping in hilscherConnMappings)
            {
                fieldbusElement.AppendChild(((IParameterFileStorable)hilscherConnMapping).ToXml(fieldbusElement.OwnerDocument));
            }

            foreach (PCModbusMasterConnectionMappings pcModbusMasterMapping in pcModbusMasterMappings)
            {
                fieldbusElement.AppendChild(((IParameterFileStorable)pcModbusMasterMapping).ToXml(fieldbusElement.OwnerDocument));
            }

            foreach (DriveModbusMasterConnectionMappings driveModbusMasterMapping in driveModbusMasterMappings)
            {
                fieldbusElement.AppendChild(((IParameterFileStorable)driveModbusMasterMapping).ToXml(fieldbusElement.OwnerDocument));
            }

            if (pcModbusSlaveMappings != null)
            {
                fieldbusElement.AppendChild(((IParameterFileStorable)pcModbusSlaveMappings).ToXml(fieldbusElement.OwnerDocument));
            }
        }

        private void nameValidatingHandler(object sender, FieldbusMappingNameValidatingEventArgs e)
        {
            if (CheckNameExists(e.Name))
            {
                throw new InvalidOperationException(string.Format(Resources.FieldbusMappingNameInvalid, e.Name));
            }
        }

        internal bool CheckNameExists(string name)
        {
            IntPtr phCompiler_ = IntPtr.Zero;
            ExceptionResolver.ResolveThrow(Wrapper.AerCompilerOpen(ref phCompiler_));
            string pszVarName_ = "$" + name;
            _PTR_DATA pVariableInfo_ = default(_PTR_DATA);
            using (CompilerHandle compilerHandle = new CompilerHandle(phCompiler_))
            {
                ExceptionResolver.ResolveThrow(Wrapper.AerCompilerParseVariableInfo(compilerHandle.Value, pszVarName_, ref pVariableInfo_));
            }

            PtrType ptrType = (PtrType)pVariableInfo_.ptrType;
            if (!isFieldbusPtrType(ptrType) && ptrType != PtrType.DBL_PROGRAM_VAR)
            {
                return true;
            }

            foreach (HilscherConnectionMappings item in Hilscher)
            {
                if (item[name] != null)
                {
                    return true;
                }
            }

            foreach (DriveModbusMasterConnectionMappings item2 in DriveModbusMaster)
            {
                if (item2[name] != null)
                {
                    return true;
                }
            }

            foreach (PCModbusMasterConnectionMappings item3 in PCModbusMaster)
            {
                if (item3[name] != null)
                {
                    return true;
                }
            }

            if (PCModbusSlave != null && PCModbusSlave[name] != null)
            {
                return true;
            }

            return false;
        }

        private static bool isFieldbusPtrType(PtrType type)
        {
#if CSHARP8_OR_ABOVE
    return type switch
    {
        PtrType.FieldbusInput => true,
        PtrType.FieldbusOutput => true,
        PtrType.ModbusMasterInputBits => true,
        PtrType.ModbusMasterInputWords => true,
        PtrType.ModbusMasterOutputBits => true,
        PtrType.ModbusMasterOutputBitsStatus => true,
        PtrType.ModbusMasterOutputWords => true,
        PtrType.ModbusMasterOutputWordsStatus => true,
        PtrType.ModbusSlaveInputBits => true,
        PtrType.ModbusSlaveInputWords => true,
        PtrType.ModbusSlaveOutputBits => true,
        PtrType.ModbusSlaveOutputWords => true,
        PtrType.DriveModbusMasterInputBits => true,
        PtrType.DriveModbusMasterInputWords => true,
        PtrType.DriveModbusMasterOutputBits => true,
        PtrType.DriveModbusMasterOutputBitsStatus => true,
        PtrType.DriveModbusMasterOutputWords => true,
        PtrType.DriveModbusMasterOutputWordsStatus => true,
        _ => false,
    };
#else
            switch (type)
            {
                case PtrType.FieldbusInput:
                case PtrType.FieldbusOutput:
                case PtrType.ModbusMasterInputBits:
                case PtrType.ModbusMasterInputWords:
                case PtrType.ModbusMasterOutputBits:
                case PtrType.ModbusMasterOutputBitsStatus:
                case PtrType.ModbusMasterOutputWords:
                case PtrType.ModbusMasterOutputWordsStatus:
                case PtrType.ModbusSlaveInputBits:
                case PtrType.ModbusSlaveInputWords:
                case PtrType.ModbusSlaveOutputBits:
                case PtrType.ModbusSlaveOutputWords:
                case PtrType.DriveModbusMasterInputBits:
                case PtrType.DriveModbusMasterInputWords:
                case PtrType.DriveModbusMasterOutputBits:
                case PtrType.DriveModbusMasterOutputBitsStatus:
                case PtrType.DriveModbusMasterOutputWords:
                case PtrType.DriveModbusMasterOutputWordsStatus:
                    return true;
                default:
                    return false;
            }
#endif
        }
    }

1. 类概述

FieldbusMappings 类用于管理现场总线(Fieldbus)的配置映射,包括:

  • Hilscher 卡通信配置

  • PC Modbus 主站/从站配置

  • 驱动器 Modbus 主站配置
    通过 XML 文件存储和加载配置,支持动态验证和事件通知。


2. 核心成员

(1) 字段与属性
  • 配置节名称
    FieldbusConfigurationSectionName 定义 XML 中存储配置的节点名(FieldbusMap)。

  • XML 相关

    • fieldbusElement:根 XML 节点

    • nsManager:XML 命名空间管理器

  • 连接映射集合

    • hilscherConnMappings:Hilscher 卡连接配置

    • pcModbusMasterMappings:PC Modbus 主站配置

    • pcModbusSlaveMappings:PC Modbus 从站配置(可空)

    • driveModbusMasterMappings:驱动器 Modbus 主站配置

  • 公开属性
    通过 INamedCollection 接口暴露集合,如 HilscherPCModbusMaster 等。

(2) 事件与委托
  • ConfigurationChanged
    当配置变更时触发,重新序列化所有配置到 XML。

  • NameValidating
    验证名称是否重复或非法(通过 CheckNameExists 方法)。


3. 关键方法解析

(1) 初始化方法
  • 构造函数
    从 ParameterFile 加载或创建 FieldbusMap XML 节点,并调用各子初始化方法:

initHilscher();       // 初始化 Hilscher 配置
initPcModbusMaster(); // 初始化 PC Modbus 主站
initPcModbusSlave();  // 初始化 PC Modbus 从站
initDriveModbusMaster(); // 初始化驱动器 Modbus 主站
  • 子初始化逻辑
    每个方法:

    1. 从 XML 读取配置(如 SelectNodes("p:HilscherCard"))。

    2. 反序列化为对象(如 hilscherConnectionInformation.FromXml)。

    3. 添加到集合并绑定事件(如 NameValidating)。

(2) 配置持久化
  • configurationChangedHandler
    当配置变更时,清空 XML 并重新写入所有映射:

fieldbusElement.RemoveAll();
foreach (var mapping in collections) {
    fieldbusElement.AppendChild(mapping.ToXml());
}
(3) 名称验证
  • CheckNameExists
    检查名称是否已存在或冲突:

    1. 通过 AerCompilerParseVariableInfo 检查变量类型是否合法(需为现场总线类型或程序变量)。

    2. 遍历所有集合(Hilscher、Modbus 等)检查重复名称。

  • isFieldbusPtrType
    判断指针类型是否属于现场总线(如 ModbusMasterInputBits),使用 C# 8.0 switch 表达式或 传统 switch 语句(通过 #if 条件编译适配不同版本)。


4. 辅助功能

  • 类型支持
    FieldbusVariableTypes 定义了支持的变量类型(如 BitBoolInt32 等)。

  • 异常处理

    • 名称重复时抛出 InvalidOperationException

    • PC Modbus 从站设置时回滚变更(try-catch 保证原子性)。


5. 设计模式与技巧

  1. 观察者模式
    通过事件(ConfigurationChangedNameValidating)通知状态变更。

  2. 泛型与接口
    使用 INamedCollection<T> 统一管理不同类型的映射集合。

  3. 条件编译
    适配不同 C# 版本的语法(如 #if CSHARP8_OR_ABOVE)。

  4. XML 序列化
    通过 IParameterFileStorable 接口实现配置的持久化。


6. 典型流程

  1. 加载配置

名称验证:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值