c#连接opc协议,基础配置搞定后,即可进行编码开发
推荐开发前可以使用可视化工具进行测试下,确定下OPC Client端是否和服务器网络是否通常
可以使用 OPCExplorer.exe工具来进行测试,免费的工具
而且网上资料也挺多的
调用OPC,解决方案需要添加如下的dll,我的c# 开发环境是.net FrameWork4.5.2
这两个dll的获取方式,推荐大家安装免费的MatrikonOPC Server for Simulation
安装完成后,在这个程序的目录包中即可找到这两个dll,而且这个软件还会为你注册这几个dll和对应的服务,大大省事!!!
下来就是贴代码了,
Helper帮助类
using System;
using System.Collections.Generic;
using OPCAutomation;//需要手动添加
using System.Security.Cryptography;
using System.Linq;
using Newtonsoft.Json;
namespace OPCAPI
{
class OPC_client
{
public OPCServer Server;//服务器对象
public OPCGroups Groups;//组列表
public OPCGroup Group;//组对象
public OPCItems Items;//节点列表
//public OPCItem Item;//节点对象
public bool ConnectedState { get; private set; }
public delegate string ServerShutDown(string Reason);
/// <summary>
/// 服务器断开连接事件
/// </summary>
public event ServerShutDown OnServerShutDown;
/// <summary>
/// 连接
/// </summary>
/// <param name="ServerName"></param>
/// <param name="ServerIP"></param>
/// <returns></returns>
public bool Connect(string ServerName, string ServerIP, out string Message)
{
try
{
if (Server == null) Server = new OPCServer();
Server.Connect(ServerName, ServerIP);
if (Server.ServerState == (int)OPCServerState.OPCRunning)
{
Server.ServerShutDown += Server_ServerShutDown;
Message = "连接成功";
ConnectedState = true;
IniServer();
return true;
}
else
{
Message = "连接失败。状态码:" + Server.ServerState.ToString();
ConnectedState = false;
return false;
}
}
catch (Exception ex)
{
Message = ex.Message;
return false;
}
}
/// <summary>
/// 服务器异常断开连接
/// </summary>
/// <param name="Reason"></param>
private void Server_ServerShutDown(string Reason)
{
ConnectedState = false;
OnServerShutDown?.Invoke(Reason);
}
/// <summary>
/// 断开连接
/// </summary>
public void DisConnect()
{
Server?.Disconnect();
}
/// <summary>
/// 添加一个测试组,之后读取都在这个测试组中添加或者删除item
/// </summary>
private void IniServer()
{
Groups = Server.OPCGroups;
Group = Server.OPCGroups.Add("AncnRobot");
Items = Group.OPCItems;
}
/// <summary>
/// 获取OPCDA服务器中所有的节点<br/>
/// 有一些节点服务器自带有Write的,不能读取。
/// </summary>
/// <returns></returns>
public List<string> GetBrowser()
{
try
{
List<string> result = new List<string>();
OPCBrowser browser = Server.CreateBrowser();
browser.ShowBranches();
browser.ShowLeafs(true);
foreach (var item in browser)
{
result.Add(item.ToString());
}
return result;
}
catch (Exception)
{
return null;
}
}
/// <summary>
/// 读取一条数据
/// </summary>
/// <param name="tagAddress"></param>
/// <returns></returns>
public OPCResponse ReadOne(string tagAddress)
{
try
{
var model = Items.AddItem(tagAddress, 1);
model.Read(1,
out object ItemValues,
out object Qualities,
out object TimeStamps);
var read_ = new OPCResponse()
{
Tag = tagAddress,
Value = ItemValues.ToString(),
Quanlity = Qualities.ToString(),
Time = TimeStamps.ToString()
};
return read_;
}
catch (Exception ex)
{
Logger.Info($"读取指定数据异常,读取的数据内容是:{tagAddress}错误原因是:{JsonConvert.SerializeObject(ex)}");
}
return null;
}
/// <summary>
/// 读取节点数据
/// </summary>
/// <param name="tagAddress">需要读取的节点</param>
/// <returns></returns>
public List<OPCResponse> Read(List<string> tagAddress)
{
List<OPCResponse> results = new List<OPCResponse>();
try
{
OPCItem[] items = new OPCItem[tagAddress.Count];
int[] temp = new int[items.Length + 1];
temp[0] = 0;//这个第一个数据一定不能为空,索引是从1开始的
for (int i = 0; i < items.Length; i++)
{
items[i] = Items.AddItem(tagAddress[i], i);
OPCResponse read_;
try
{
items[i].Read(1,
out object ItemValues,
out object Qualities,
out object TimeStamps);
read_ = new OPCResponse()
{
Tag = tagAddress[i],
Value = ItemValues.ToString(),
Quanlity = Qualities.ToString(),
Time = TimeStamps.ToString()
};
}
catch (Exception)
{
read_ = new OPCResponse()
{
Tag = tagAddress[i],
Value = "--",
Quanlity = "--",
Time = "--"
};
results.Add(read_);
continue;
}
results.Add(read_);
temp[i + 1] = items[i].ServerHandle;
}
try
{
Array serverHandles = (Array)temp;
Array errors;
Items.Remove(1, serverHandles, out errors);
}
catch (Exception) { }
return results;
}
catch (Exception ee)
{
return null;
}
}
/// <summary>
/// 数据变化之后推送事件
/// </summary>
/// <param name="TransactionID"></param>
/// <param name="NumItems"></param>
/// <param name="ClientHandles"></param>
/// <param name="ItemValues"></param>
/// <param name="Qualities"></param>
/// <param name="TimeStamps"></param>
private void Group_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
{
Console.ForegroundColor = ConsoleColor.Green;
for (int i = 1; i <= NumItems; i++)
{
int tmpClientHandle = Convert.ToInt32(ClientHandles.GetValue(i));
string tmpValue = ItemValues.GetValue(i).ToString();
string tmpTime = ((DateTime)(TimeStamps.GetValue(i))).ToString();
Console.WriteLine("Time:" + tmpTime);
Console.WriteLine("ClientHandle : " + tmpClientHandle.ToString());
Console.WriteLine("tag value " + tmpValue);
}
}
}
}
返回参数数据(我这个是业务上要求写的,大家参考就行)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OPCAPI.Models
{
public class OPCRequest
{
public string TagId { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OPCAPI
{
public class OPCResponse
{
/// <summary>
/// OPCIterm变量名称
/// </summary>
public string Tag { get; set; }
/// <summary>
/// OPCIterm数值
/// </summary>
public string Value { get; set; }
/// <summary>
/// OPCIterm质量
/// </summary>
public string Quanlity { get; set; }
/// <summary>
/// OPCIterm时间戳
/// </summary>
public string Time { get; set; }
}
}
调用去读取一条数据
static bool OPCInit()
{
try
{
if (_client == null || !_client.ConnectedState)
{
if (_client != null)
{
Logger.Info($"当前连接状态是:{_client.ConnectedState},准备重新初始化!");
}
_client = new OPC_client();
var config = AppConfig.GetInstance();
if (config != null)
{
//这里需要修改 去填 组id,opc服务器ip
bool con = _client.Connect(config.ProgId, config.OPCIp, out string msg);
Logger.Info($"连接结果是:{con},连接返回内容是:{msg}");
return con;
}
}
else
{
Logger.Info($"当前连接状态是:{_client.ConnectedState},初始化成功!");
return _client.ConnectedState;
}
}
catch (Exception ex)
{
Logger.Info("初始化OPC服务异常:" + JsonConvert.SerializeObject(ex));
}
return false;
}
public static OPCResponse Read(OPCRequest request)
{
OPCResponse response = null;
try
{
if (OPCInit())
{//opc初始化
var config = AppConfig.GetInstance();
//这里需要修改 key改为dcs系统中的唯一主键,我这里是我自己业务逻辑的拼接
string key = config.TagPrefix + request.TagId + config.TagValueAttribute;
var result = _client.ReadOne(key);
if (result != null)
{
return result;
}
}
}
catch (Exception ex)
{
Logger.Info("opc服务读取异常:" + JsonConvert.SerializeObject(ex));
response = null;
}
return response;
}