using OPCAutomation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class NewOPC
{
OPCServer KepServer;
public string ErrorMsg = "";
bool opc_connected = false;
//连接OPC
public bool ConnectRemoteServer(string OpcIP, string OpcVersion)
{
try
{
KepServer = new OPCServer();
KepServer.Connect(OpcVersion, OpcIP);
if (KepServer.ServerState != (int)OPCServerState.OPCRunning)
{
ErrorMsg = "KepServer状态异常:" + KepServer.ServerState.ToString();
return false;
}
opc_connected = true;
}
catch (Exception err)
{
ErrorMsg = "连接远程服务器出现错误:" + err.Message;
return false;
}
return true;
}
public void Quite()
{
if (opc_connected)
{
KepServer.Disconnect();
}
}
int itmHandleClient = 0;
List<taginfo> taglist = new List<taginfo>();
class taginfo
{
public string group = "";
public string tag = "";
public string Clientid = "";
public int Serverid = 0;
public string value = "";
public taginfo(string _group, string _tag, string _cid, int _sid, string _val)
{
group = _group;
tag = _tag;
Clientid = _cid;
Serverid = _sid;
value = _val;
}
}
OPCGroups KepGroups;
OpcGroup_Class[] KepGroupCollect;
//创建组
public bool CreateGroup(OpcGroup_Class[] KepGroupCollect)
{
if (KepGroupCollect == null)
{
ErrorMsg = "异常:传入的opc组为空!";
return false;
}
this.KepGroupCollect = KepGroupCollect;
KepGroups = KepServer.OPCGroups;
//宏观默认设定 具体执行要看具体的group
KepGroups.DefaultGroupIsActive = true;//激活组
KepGroups.DefaultGroupDeadband = 0;//死区值,设为0时,服务器端该组内任何数据变化都通知组。
KepGroups.DefaultGroupUpdateRate = 100;//默认刷新频率
foreach (OpcGroup_Class group in KepGroupCollect)
{
OPCGroup KepGroup = KepGroups.Add(group.groupName);
KepGroup.UpdateRate = group.updateRate;
KepGroup.IsActive = group.IsActive;
KepGroup.IsSubscribed = group.IsSubscribed;
KepGroup.DeadBand = group.Deadband;
group.G = KepGroup;
OPCItems KepItems = KepGroup.OPCItems;
for (int i = 0; i < group.tags.Count(); i++)
{
itmHandleClient++;
KepItems.AddItem(group.tags[i], itmHandleClient);
int itemid = KepItems.Item(group.tags[i]).ServerHandle;
taginfo tf = new taginfo(group.groupName, group.tags[i], itmHandleClient.ToString(), itemid, "");
taglist.Add(tf);
}
if (group.isDataChange)
{
group.G.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
}
if (group.isAsyncRead)
{
group.G.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(KepGroup_AsyncReadComplete);
}
if (group.isAsyncWrite)
{
group.G.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete);
}
}
return true;
}
public event EventHandler<EventData> DataChange;
void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
{
if (DataChange != null)
{
EventData ed = new EventData();
for (int i = 1; i <= NumItems; i++)
{
DataChangeObject dco = new DataChangeObject();
dco.TagHandler = ClientHandles.GetValue(i).ToString();
taginfo tf = taglist.FirstOrDefault(p => p.Clientid == dco.TagHandler);
if (tf != null)
{
dco.TagFullName = tf.tag;
dco.TagValue = ItemValues.GetValue(i).ToString();
dco.Qualitie = Qualities.GetValue(i).ToString();
dco.TimeStamp = TimeStamps.GetValue(i).ToString();
ed.ChangeValues.Add(dco);
}
}
DataChange(ClientHandles, ed);
}
}
public event EventHandler<EventData> AsyncReadComplete;
private void KepGroup_AsyncReadComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps, ref Array Errors)
{
if (AsyncReadComplete != null)
{
EventData ed = new EventData();
for (int i = 1; i <= NumItems; i++)
{
DataChangeObject dco = new DataChangeObject();
dco.FlagNum = TransactionID;
dco.TagHandler = ClientHandles.GetValue(i).ToString();
taginfo tf = taglist.FirstOrDefault(p => p.Clientid == dco.TagHandler);
if (tf != null)
{
dco.TagFullName = tf.tag;
dco.TagValue = ItemValues.GetValue(i).ToString();
dco.Qualitie = Qualities.GetValue(i).ToString();
dco.TimeStamp = TimeStamps.GetValue(i).ToString();
dco.Errors = Errors.GetValue(i).ToString();
ed.ChangeValues.Add(dco);
}
}
AsyncReadComplete(ClientHandles, ed);
}
}
public event EventHandler<EventData> AsyncWriteComplete;
void KepGroup_AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
{
if (AsyncWriteComplete != null)
{
EventData ed = new EventData();
for (int i = 1; i <= NumItems; i++)
{
DataChangeObject dco = new DataChangeObject();
dco.TagHandler = ClientHandles.GetValue(i).ToString();
taginfo tf = taglist.FirstOrDefault(p => p.Clientid == dco.TagHandler);
if (tf != null)
{
dco.TagFullName = tf.tag;
dco.TagValue = tf.value;
dco.Errors = Errors.GetValue(i).ToString();
ed.ChangeValues.Add(dco);
}
}
AsyncWriteComplete(ClientHandles, ed);
}
}
/// <summary>
/// 注意 Group 是同一组的时候才能使用!!
/// </summary>
public bool AsyncWrite(ToWrite[] toWriteitems)
{
if (opc_connected)
{
//删除空Tag
toWriteitems = toWriteitems.Where(s => !string.IsNullOrEmpty(s.Tag)).ToArray();
int TagCount = toWriteitems.Count() + 1;
if (TagCount == 1)
{
return true;
}
int[] temp = new int[TagCount];
temp[0] = 0;
object[] valueTemp = new object[TagCount];
valueTemp[0] = "";
int i = 1;
string group = "";
foreach (ToWrite item in toWriteitems)
{
taginfo tf = taglist.FirstOrDefault(p => p.tag == item.Tag);
if (tf != null)
{
temp[i] = tf.Serverid;
group = tf.group;
valueTemp[i] = item.Val;
tf.value = item.Val;
i++;
}
else
{
ErrorMsg = "异常:未找到tag标签:" + item.Tag;
return false;
}
}
Array serverHandles = (Array)temp;
Array values = (Array)valueTemp;
Array Errors;
int cancelID;
OPCGroup KepGroup = KepGroups.GetOPCGroup(group);
if (KepGroup == null)
{
ErrorMsg = "异常:未找到OPCGroup组:" + group;
return false;
}
Random r = new Random();
int idnum = r.Next(0, 999999);
KepGroup.AsyncWrite(TagCount - 1, ref serverHandles, ref values, out Errors, idnum, out cancelID);
//KepItem.Write(txtWriteTagValue.Text);//这句也可以写入,但并不触发写入事件
GC.Collect();
return true;
}
else
{
ErrorMsg = "异常:OPC未连接!";
return false;
}
}
public bool AsyncWrite(string tag, string val)
{
if (opc_connected)
{
if (tag == "")
{
return true;
}
int[] temp = new int[2];
taginfo tf = taglist.FirstOrDefault(p => p.tag == tag);
if (tf != null)
{
temp[0] = 0;
temp[1] = tf.Serverid;
tf.value = val;
}
else
{
ErrorMsg = "异常:未找到tag标签:" + tag;
return false;
}
Array serverHandles = (Array)temp;
object[] valueTemp = new object[2] { "", val };
Array values = (Array)valueTemp;
Array Errors;
int cancelID;
OPCGroup KepGroup = KepGroups.GetOPCGroup(tf.group);
if (KepGroup == null)
{
ErrorMsg = "异常:未找到OPCGroup组:" + tf.group;
return false;
}
Random r = new Random();
int idnum = r.Next(0, 999999);
KepGroup.AsyncWrite(1, ref serverHandles, ref values, out Errors, idnum, out cancelID);
//KepItem.Write(txtWriteTagValue.Text);//这句也可以写入,但并不触发写入事件
GC.Collect();
return true;
}
else
{
ErrorMsg = "异常:OPC未连接!";
return false;
}
}
public bool AsyncRead(string[] tags, int TransactionID)
{
if (opc_connected)
{
//删除空Tag
tags = tags.Where(p => !string.IsNullOrEmpty(p)).ToArray();
int TagCount = tags.Count() + 1;
int[] temp = new int[TagCount];
temp[0] = 0;
int i = 1;
string group = "";
foreach (string tag in tags)
{
taginfo tf = taglist.FirstOrDefault(p => p.tag == tag);
if (tf != null)
{
temp[i] = tf.Serverid;
group = tf.group;
i++;
}
else
{
ErrorMsg = "异常:未找到tag标签:" + tag;
return false;
}
}
Array serverHandles = (Array)temp;
Array Errors;
int cancelID;
OPCGroup KepGroup = KepGroups.GetOPCGroup(group);
if (KepGroup == null)
{
ErrorMsg = "异常:未找到OPCGroup组:" + group;
return false;
}
KepGroup.AsyncRead(TagCount - 1, ref serverHandles, out Errors, TransactionID, out cancelID);
GC.Collect();
return true;
}
else
{
return false;
}
}
public bool AsyncRead(string tag, int TransactionID)
{
if (opc_connected)
{
int[] temp = new int[2];
taginfo tf = taglist.FirstOrDefault(p => p.tag == tag);
if (tf != null)
{
temp[0] = 0;
temp[1] = tf.Serverid;
}
else
{
ErrorMsg = "异常:未找到tag标签:" + tag;
return false;
}
Array serverHandles = (Array)temp;
Array Errors;
int cancelID;
OPCGroup KepGroup = KepGroups.GetOPCGroup(tf.group);
if (KepGroup == null)
{
ErrorMsg = "异常:未找到OPCGroup组:" + tf.group;
return false;
}
KepGroup.AsyncRead(1, ref serverHandles, out Errors, TransactionID, out cancelID);
GC.Collect();
return true;
}
else
{
return false;
}
}
}
public class EventData : EventArgs
{
public EventData()
{
}
private List<DataChangeObject> _ChangeValues = new List<DataChangeObject>();
public List<DataChangeObject> ChangeValues
{
get
{
return _ChangeValues;
}
set
{
_ChangeValues = value;
}
}
}
public class DataChangeObject
{
private string _TagFullName = string.Empty;
/// <summary>
/// 变量名
/// </summary>
public string TagFullName
{
get
{
return _TagFullName;
}
set
{
_TagFullName = value;
}
}
private string _TagHandler = string.Empty;
/// <summary>
/// 变量索引
/// </summary>
public string TagHandler
{
get
{
return _TagHandler;
}
set
{
_TagHandler = value;
}
}
private string _TagValue = string.Empty;
/// <summary>
/// 变量值
/// </summary>
public string TagValue
{
get
{
return _TagValue.ToLower();
}
set
{
_TagValue = value;
}
}
private string _Qualitie = string.Empty;
public string Qualitie
{
get
{
return _Qualitie;
}
set
{
_Qualitie = value;
}
}
private string _TimeStamp = string.Empty;
public string TimeStamp
{
get
{
return _TimeStamp;
}
set
{
_TimeStamp = value;
}
}
private int _FlagNum = 0;
public int FlagNum
{
get
{
return _FlagNum;
}
set
{
_FlagNum = value;
}
}
private string _errors = "";
public string Errors
{
get
{
return _errors;
}
set
{
_errors = value;
}
}
}
class OpcGroup_Class
{
/// <summary>
/// OPC组
/// </summary>
public OPCGroup G = null;
/// <summary>
/// 组名称
/// </summary>
public string groupName = "";
/// <summary>
/// 是否异步读取
/// </summary>
public bool isAsyncRead = true;
/// <summary>
/// 是否异步写入
/// </summary>
public bool isAsyncWrite = true;
/// <summary>
/// 变动触发
/// </summary>
public bool isDataChange = true;
/// <summary>
/// 更新频率
/// </summary>
public int updateRate = 100;
/// <summary>
/// 是否激活
/// </summary>
public bool IsActive = true;
/// <summary>
/// 是否订阅(异步则订阅)
/// </summary>
public bool IsSubscribed = true;
/// <summary>
/// 死区值 变化量超过死区后将会触发DataChange事件,合理的设置该值可以提高程序性能
/// </summary>
public float Deadband = 0;
/// <summary>
/// 标签集合
/// </summary>
public string[] tags = null;
}
public class ToWrite
{
public string Tag { get; set; }
public string Val { get; set; }
public ToWrite(string _Tag, string _Val)
{
Tag = _Tag;
Val = _Val;
}
}
调用
#region OPC初始化
NewOPC opc=new NewOPC();
private bool InitOpc(string server, string ip)
{
if (!opc.ConnectRemoteServer(ip, server))
{
showMessage(opc.ErrorMsg, true);
opc.ErrorMsg = "";
return false;
}
showMessage("OPC:连接成功!", false);
OpcGroup_Class[] ocg = new OpcGroup_Class[3];
#region 采集
//触发采集 0-1, 1-0
OpcGroup_Class change1 = new OpcGroup_Class();
change1.groupName = "Change";
change1.updateRate = 10;
change1.IsActive = true;
change1.Deadband = 0;
change1.IsSubscribed = true;
change1.isAsyncRead = false; //是否异步读取
change1.isAsyncWrite = true; //是否异步写入
change1.isDataChange = true; //是否变化
ocg[0] = change1;
//数据只读区
OpcGroup_Class read1 = new OpcGroup_Class();
read1.groupName = "Read";
read1.updateRate = 500;
read1.IsActive = false;
read1.Deadband = 100;
read1.IsSubscribed = true;
read1.isAsyncRead = true;
read1.isAsyncWrite = false;
read1.isDataChange = false;
ocg[1] = read1;
//数据写入区域
OpcGroup_Class write1 = new OpcGroup_Class();
write1.groupName = "Write";
write1.updateRate = 500;
write1.IsActive = false;
write1.Deadband = 100;
write1.IsSubscribed = true;
write1.isAsyncRead = false;
write1.isAsyncWrite = true;
write1.isDataChange = false;
ocg[2] = write1;
#endregion
//节点赋值 根据实际需求
foreach (SpectInfo item in xxx)
{
if (item.ShiYangTag != "")
{
readNode.Add(item.ShiYangTag);
}
if (item.PinFanTag != "")
{
readNode.Add(item.PinFanTag);
}
if (item.ReadTag != "")
{
changeNode.Add(item.ReadTag);
}
if (item.SaveFinishTag != "")
{
writeNode.Add(item.SaveFinishTag);
}
}
//去重并赋值到Tag组
read1.tags = readNode.Where((x, i) => readNode.FindIndex(p => p.ToString() == x.ToString()) == i).ToArray();
write1.tags = writeNode.Where((x, i) => writeNode.FindIndex(p => p.ToString() == x.ToString()) == i).ToArray();
change1.tags = changeNode.Where((x, i) => changeNode.FindIndex(p => p.ToString() == x.ToString()) == i).ToArray();
if (!opc.CreateGroup(ocg))
{
showMessage(opc.ErrorMsg, true);
opc.ErrorMsg = "";
return false;
}
//事件
opc.DataChange += Opc_DataChange;
opc.AsyncReadComplete += Opc_AsyncReadComplete;
opc.AsyncWriteComplete += Opc_AsyncWriteComplete;
List<ToWrite> tw = new List<ToWrite>();
//复位
foreach (string item in change1.tags)
{
ToWrite _t = new ToWrite(item, "0");
tw.Add(_t);
}
if (!opc.AsyncWrite(tw.ToArray()))
{
showMessage("初始化写入0失败,原因:" + opc.ErrorMsg, false);
opc.ErrorMsg = "";
}
showMessage("********信号初始化完毕********", false);
return true;
}
#endregion
#region OPC 事件
private void Opc_DataChange(object sender, EventData e)
{
Object obj = e.ChangeValues as Object;
List<DataChangeObject> DataChangeList = obj as List<DataChangeObject>;
foreach (DataChangeObject dco in DataChangeList)
{
string tag = dco.TagFullName;
string val = dco.TagValue;
if (val == "true" || val == "1")
{
//数据并行处理
Task.Run(() => TagCollect(tag));
}
}
}
private void TagCollect(string tag)
{
//工位数据采集----1
SpectInfo spc = list_Spect.FirstOrDefault(p => p.ReadTag == tag);
if (spc != null)
{
string specid = spc.Specficationid;
List<CollectInfo> ac = list_Collect.Where(p => p.Specficationid == specid).ToList();
string[] tags = new string[ac.Count + 2];
tags[0] = spc.ShiYangTag;
tags[1] = spc.PinFanTag;
for (int i = 2; i < ac.Count + 2; i++)
{
tags[i] = ac[i - 2].DataTag;
}
//spc.Num 写入什么 opc读取完毕后 Opc_AsyncReadComplete 回传什么
//此处务必注意
opc.AsyncRead(tags, spc.Num);
}
else
{
//十万之后
CheckInfo ck = list_Check.FirstOrDefault(p => p.ReadTag == tag);
if (ck != null)
{
string[] tags = new string[2];
tags[0] = ck.ShiYangTag;
tags[1] = ck.PinFanTag;
opc.AsyncRead(tags, ck.Num);
}
}
}
private void Opc_AsyncReadComplete(object sender, EventData e)
{
List<DataChangeObject> DataChangeList = e.ChangeValues as List<DataChangeObject>;
if (DataChangeList[0].FlagNum < 100000)
{
Task.Run(() => SaveDate(DataChangeList));
}
else if (DataChangeList[0].FlagNum > 100000)
{
Task.Run(() => CheckDate(DataChangeList));
}
}
private void Opc_AsyncWriteComplete(object sender, EventData e)
{
Object obj = e.ChangeValues as Object;
List<DataChangeObject> DataChangeList = obj as List<DataChangeObject>;
foreach (DataChangeObject dco in DataChangeList)
{
showMessage("写----入----完----毕 :" + dco.TagFullName, false);
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult R = MessageBox.Show("您确定要关闭本系统吗?点击确定退出!", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2);
if (R == DialogResult.OK)
{
timer1.Enabled = false;
opc.DataChange -= Opc_DataChange;
opc.AsyncReadComplete -= Opc_AsyncReadComplete;
opc.AsyncWriteComplete -= Opc_AsyncWriteComplete;
opc.Quite();
//退出系统(其他线体的窗体可能在开启中,必须使用这个退出)
System.Environment.Exit(0);
}
else
{
e.Cancel = true;
}
}
欢迎使用测试!