ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

基于C#的OPC DA客户端实现源码解析

基于C#的OPC DA客户端实现源码解析

一、环境配置与基础依赖

  1. 开发环境要求

    • .NET Framework 4.6.1+ 或 .NET Core 3.1+

    • Visual Studio 2019+

    • OPC Foundation库(通过NuGet安装)

      Install-Package OpcFoundation.OpcDa
      
  2. 关键依赖项

    using Opc.Da;      // OPC DA核心接口
    using Opc.Com;     // COM互操作支持
    using System;
    using System.Collections.Generic;
    

二、核心功能实现

1. OPC服务器连接管理

public class OpcDaClient : IDisposable
{private Server _server;private Connection _connection;private Group _group;public bool Connect(string serverUrl){try{_connection = new Connection();_connection.URL = serverUrl;_connection.Timeout = 5000;  // 5秒超时_server = new Server(_connection);_server.Connect();if (_server.ServerState == Opc.Da.ServerState.Connected){InitializeGroup();return true;}return false;}catch (OpcCom.Da.ServerException ex){Console.WriteLine($"连接失败: {ex.Message}");return false;}}private void InitializeGroup(){_group = _server.AddGroup("ClientGroup");_group.IsActive = true;_group.UpdateRate = 1000;  // 1秒更新周期}public void Disconnect(){_group?.Dispose();_server?.Disconnect();}
}

2. 数据项订阅与读取

public class OpcDaClient
{// ... 上文代码public void AddItems(IEnumerable<string> itemIds){var items = new List<Item>();foreach (var id in itemIds){var item = new Item(id);item.ClientHandle = Guid.NewGuid().GetHashCode();  // 唯一客户端句柄item.Active = true;items.Add(item);}_group.AddItems(items.ToArray());SubscribeDataChanges();}private void SubscribeDataChanges(){_group.DataChange += (sender, e) => {for (int i = 1; i < e.NumItems; i++){var value = e.ItemValues.GetValue(i);var quality = e.Qualities.GetValue(i);var timestamp = e.TimeStamps.GetValue(i);Console.WriteLine($"[{DateTime.Now}] {e.ItemIDs.GetValue(i)}: {value} ({quality})");}};}public object ReadItem(string itemId){var item = _group.Items.Find(i => i.ItemID == itemId);if (item != null){return item.Value;}return null;}
}

三、完整使用示例

class Program
{static void Main(string[] args){using (var client = new OpcDaClient()){if (client.Connect("opc.da://localhost/Kepware.KEPServerEX.V6")){// 添加监控项client.AddItems(new[] { "Random.Real8", "Machine.Status" });// 同步读取示例var value = client.ReadItem("Random.Real8");Console.WriteLine($"同步读取值: {value}");Console.WriteLine("按任意键退出...");Console.ReadKey();}}}
}

四、高级功能实现

1. 异步数据读取

public async Task<object> ReadItemAsync(string itemId)
{var item = _group.Items.Find(i => i.ItemID == itemId);if (item == null) return null;return await Task.Run(() => item.Value);
}

2. 批量写入操作

public void WriteItems(Dictionary<string, object> values)
{var items = new List<Item>();foreach (var kvp in values){var item = _group.Items.Find(i => i.ItemID == kvp.Key);if (item != null){item.Value = kvp.Value;items.Add(item);}}_group.WriteItems(items.ToArray());
}

五、异常处理与最佳实践

  1. 连接异常处理

    try
    {client.Connect("opc.da://invalid-server");
    }
    catch (OpcCom.Da.ServerNotFoundException)
    {Console.WriteLine("服务器未找到");
    }
    catch (OpcCom.Da.UnauthorizedAccessException)
    {Console.WriteLine("认证失败");
    }
    
  2. 资源释放

    public void Dispose()
    {_group?.Dispose();_server?.Dispose();_connection?.Dispose();
    }
    
  3. 多线程安全

    private readonly object _lock = new object();public void SafeWrite(string itemId, object value)
    {lock (_lock){var item = _group.Items.Find(i => i.ItemID == itemId);item?.Value = value;}
    }
    

六、依赖项配置说明

  1. NuGet包管理

    <!-- .csproj文件 -->
    <ItemGroup><PackageReference Include="OpcFoundation.OpcDa" Version="3.0.0" />
    </ItemGroup>
    
  2. COM组件注册

    • 若使用OPCDAAuto.dll:

      regsvr32 OPCDAAuto.dll
      
    • 在代码中引用:

      using OPC.Automation;
      

参考代码 OPC DA(客户端)源码 www.youwenfan.com/contentcnq/46008.html

七、调试与测试

  1. 日志记录

    public void Log(string message)
    {File.AppendAllText("opc_log.txt", $"{DateTime.Now}: {message}{Environment.NewLine}");
    }
    
  2. 模拟服务器测试

    使用Matrikon OPC Server Simulation进行单元测试:

    [Test]
    public void TestConnect()
    {var client = new OpcDaClient();Assert.IsTrue(client.Connect("opc.da://localhost/Matrikon.Server.1"));
    }
    
返回列表