一、环境配置与基础依赖
-
开发环境要求
-
.NET Framework 4.6.1+ 或 .NET Core 3.1+
-
Visual Studio 2019+
-
OPC Foundation库(通过NuGet安装)
csharpInstall-Package OpcFoundation.OpcDa
-
-
关键依赖项
csharpusing Opc.Da; // OPC DA核心接口 using Opc.Com; // COM互操作支持 using System; using System.Collections.Generic;
二、核心功能实现
1. OPC服务器连接管理
csharp
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. 数据项订阅与读取
csharp
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;
}
}
三、完整使用示例
csharp
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. 异步数据读取
csharp
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. 批量写入操作
csharp
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());
}
五、异常处理与最佳实践
-
连接异常处理
csharptry { client.Connect("opc.da://invalid-server"); } catch (OpcCom.Da.ServerNotFoundException) { Console.WriteLine("服务器未找到"); } catch (OpcCom.Da.UnauthorizedAccessException) { Console.WriteLine("认证失败"); } -
资源释放
csharppublic void Dispose() { _group?.Dispose(); _server?.Dispose(); _connection?.Dispose(); } -
多线程安全
csharpprivate 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; } }
六、依赖项配置说明
-
NuGet包管理
csharp<!-- .csproj文件 --> <ItemGroup> <PackageReference Include="OpcFoundation.OpcDa" Version="3.0.0" /> </ItemGroup> -
COM组件注册
-
若使用OPCDAAuto.dll:
csharpregsvr32 OPCDAAuto.dll -
在代码中引用:
csharpusing OPC.Automation;
-
参考代码 OPC DA(客户端)源码 www.youwenfan.com/contentcsq/46008.html
七、调试与测试
-
日志记录
csharppublic void Log(string message) { File.AppendAllText("opc_log.txt", $"{DateTime.Now}: {message}{Environment.NewLine}"); } -
模拟服务器测试
使用Matrikon OPC Server Simulation进行单元测试:
csharp[Test] public void TestConnect() { var client = new OpcDaClient(); Assert.IsTrue(client.Connect("opc.da://localhost/Matrikon.Server.1")); }