using System;
|
using System.Collections.Generic;
|
using System.Windows.Forms;
|
using System.Linq;
|
using System.Text;
|
using OPCAutomation;
|
using EventTool;
|
|
namespace M423project
|
{
|
public class OPC
|
{
|
public const int TransIDMainform = 2012;
|
|
private OPCServer opcServer;
|
private OPCGroups opcGroups;
|
private OPCGroup opcReadGroup;
|
private OPCGroup opcWriteGroup;
|
|
private int itmHandleClient;
|
private string serverName;
|
private string serverIP;
|
private GroupProperty groupProperty;
|
|
//public ListenEventCreater listenEventCreater;
|
public event Action<Item, int> OnReadItemValueChanged;
|
public class Item
|
{
|
public string name;
|
public int clientHandle;
|
public int serverHandle;
|
public object value;
|
public Control control;
|
public string onText;
|
public string offText;
|
}
|
|
public Dictionary<string, Item> itemReadDict;
|
public Dictionary<string, Item> itemWriteDict;
|
public Dictionary<int, Item> itemReadHandleDict;
|
|
public OPC(opcConfig opcConfig)
|
{
|
serverIP = opcConfig.serverIP;
|
serverName = opcConfig.serverName;
|
itmHandleClient = opcConfig.itmHandleClient;
|
groupProperty = opcConfig.groupProperty;
|
}
|
/// <summary>
|
/// 连接OPC服务器
|
/// </summary>
|
/// <returns></returns>
|
public bool Connect()
|
{
|
CommonUtil.WriteLog(LogType.Inf, "开始连接OPC Server...");
|
try
|
{
|
opcServer = new OPCServer();
|
opcServer.Connect(serverName, serverIP);
|
if (opcServer.ServerState==(int)OPCServerState.OPCRunning)
|
{
|
CommonUtil.WriteLog(LogType.Inf, string.Format("已连接到OPC Server(ServerName:{0}, IP:{1})", serverName, serverIP));
|
return true;
|
}
|
else
|
{
|
CommonUtil.WriteLog(LogType.Err, string.Format("连接OPC Server(ServerName:{0}, IP:{1})失败,状态:{2}",
|
serverName, serverIP, opcServer.ServerState));
|
}
|
}
|
catch (Exception ee)
|
{
|
CommonUtil.WriteLog(LogType.Exc,
|
string.Format("连接 OPC-Server 出现错误, ServerName:{0}, IP:{1}, 错误信息:{2}", serverName, serverIP,
|
ee.Message));
|
}
|
return false;
|
}
|
/// <summary>
|
/// 创建组
|
/// </summary>.
|
/// <returns></returns>
|
public bool CreateGroup()
|
{
|
CommonUtil.WriteLog(LogType.Inf, "开始连接创建OPC Server组列表...");
|
try
|
{
|
OPCBrowser browser = opcServer.CreateBrowser();
|
RecurBrowser(browser);
|
opcGroups = opcServer.OPCGroups;
|
opcReadGroup = opcGroups.Add("ReadGroup");
|
opcWriteGroup = opcGroups.Add("WriteGroup");
|
|
SetGroupProperty(opcReadGroup);
|
SetGroupProperty(opcWriteGroup);
|
|
//listenEventCreater = new ListenEventCreater();
|
opcReadGroup.DataChange+=new DIOPCGroupEvent_DataChangeEventHandler(opcReadGroup_DataChange);
|
|
SetHandles(opcReadGroup, itemReadDict, out itemReadHandleDict);
|
SetHandles(opcWriteGroup, itemWriteDict, out _);
|
CommonUtil.WriteLog(LogType.Inf, "OPC Server 组列表创建完成");
|
return true;
|
}
|
catch (Exception ee)
|
{
|
CommonUtil.WriteLog(LogType.Exc,
|
string.Format("创建OPCServer组列表出现异常:{0}", ee.Message));
|
|
}
|
return false;
|
|
}
|
/// <summary>
|
/// 列出OPC服务器中所有Tag 并加入到opcBrowser中
|
/// </summary>
|
/// <param name="opcBrowser"></param>
|
private void RecurBrowser(OPCBrowser opcBrowser)
|
{
|
//将所有子项全部展开,所有的Item
|
opcBrowser.ShowBranches();
|
opcBrowser.ShowLeafs(true);
|
|
// 初始化item列表
|
itemReadDict = new Dictionary<string, Item>();
|
itemWriteDict = new Dictionary<string, Item>();
|
|
foreach (object turn in opcBrowser)
|
{
|
Item item = new Item();
|
item.name = turn.ToString();
|
if (turn.ToString().Contains("Input"))
|
{
|
itemReadDict.Add(item.name, item);
|
}
|
else if (turn.ToString().Contains("Output"))
|
{
|
itemWriteDict.Add(item.name, item);
|
}
|
}
|
|
}
|
/// <summary>
|
/// 设置组属性
|
/// </summary>
|
/// <param name="opcGroup"></param>
|
private void SetGroupProperty(OPCGroup opcGroup)
|
{
|
opcServer.OPCGroups.DefaultGroupIsActive = groupProperty.defaultGroupIsActive;
|
opcServer.OPCGroups.DefaultGroupDeadband = groupProperty.defaultGroupDeadband;
|
opcGroup.UpdateRate = groupProperty.updateRate;
|
opcGroup.IsActive = groupProperty.isActive;
|
opcGroup.IsSubscribed = groupProperty.isSubscribed;
|
}
|
/// <summary>
|
/// ReadGroup组数据发生变化时发生的事件
|
/// </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 opcReadGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
|
{
|
//for (int i = 1; i <= NumItems; i++)
|
//{
|
// foreach (Item item in itemReadDict.Values)
|
// {
|
// if (item.clientHandle == Convert.ToInt32(ClientHandles.GetValue(i)))
|
// {
|
// itemReadDict[item.name].value = Convert.ToInt32(ItemValues.GetValue(i));
|
// string state = item.name; // 改变的item的名称
|
// item.value = ItemValues.GetValue(i);
|
// listenEventCreater.ChangeValue(new EventData(item));
|
// }
|
// }
|
//}
|
|
for (int i = 1; i <= NumItems; i++)
|
{
|
int clientHandle = Convert.ToInt32(ClientHandles.GetValue(i));
|
if (itemReadHandleDict.ContainsKey(clientHandle))
|
{
|
var item = itemReadHandleDict[clientHandle];
|
int itemValue = Convert.ToInt32(ItemValues.GetValue(i));
|
item.value = itemValue;
|
|
CommonUtil.WriteLog($"Receive PLC singal:Name:{item.name},value:{itemValue}");
|
OnReadItemValueChanged?.Invoke(item, itemValue);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 为组内每一个Item设置serverHandle与clientHandle
|
/// </summary>
|
/// <param name="opcGroup"></param>
|
/// <param name="itemDict"></param>
|
/// <returns></returns>
|
private bool SetHandles(OPCGroup opcGroup, Dictionary<string, Item> itemDict, out Dictionary<int, Item> itemHandleDict)
|
{
|
itemHandleDict = new Dictionary<int, Item>();
|
OPCItems opcItems;
|
OPCItem opcItem;
|
opcItems = opcGroup.OPCItems;
|
foreach (var item in itemDict.Values)
|
{
|
item.clientHandle = itmHandleClient;
|
opcItem = opcItems.AddItem(item.name, item.clientHandle);
|
item.serverHandle = opcItem.ServerHandle;
|
|
itemHandleDict[itmHandleClient] = item;
|
itmHandleClient++;
|
}
|
return true;
|
}
|
/// <summary>
|
/// 异步写
|
/// </summary>
|
/// <param name="name"></param>
|
/// <param name="value"></param>
|
/// <returns></returns>
|
public bool Write(string name, object value)
|
{
|
try
|
{
|
Array serverHandles = new int[2] { 0, itemWriteDict[name].serverHandle };
|
Array values; // = new object[2] { "", value.ToString()};
|
Array Errors;
|
int cancelID;
|
values = new object[2] { "", value.ToString() };
|
opcWriteGroup.AsyncWrite(1, ref serverHandles, ref values, out Errors, TransIDMainform, out cancelID);
|
GC.Collect();
|
return true;
|
}
|
catch (Exception ex)
|
{
|
CommonUtil.WriteLog(LogType.Inf, ex.ToString());
|
}
|
return false;
|
}
|
|
public bool Write(string name, object value, ref string warning)
|
{
|
Array serverHandles = new int[2] { 0, itemWriteDict[name].serverHandle };
|
Array values = new object[2] { "", value.ToString() };
|
Array Errors;
|
int cancelID;
|
|
try
|
{
|
opcWriteGroup.AsyncWrite(1, ref serverHandles, ref values, out Errors, TransIDMainform, out cancelID);
|
}
|
catch (Exception e)
|
{
|
warning = e.Message;
|
|
GC.Collect();
|
return false;
|
}
|
|
GC.Collect();
|
return true;
|
}
|
|
public bool Write(OPCGroup group, int handle, object value, ref string warning)
|
{
|
Array serverHandles = new int[2] { 0, handle };
|
Array values = new object[2] { "", value.ToString() };
|
Array Errors;
|
int cancelID;
|
|
try
|
{
|
group.AsyncWrite(1, ref serverHandles, ref values, out Errors, TransIDMainform, out cancelID);
|
}
|
catch (Exception e)
|
{
|
warning = e.Message;
|
|
GC.Collect();
|
return false;
|
}
|
|
GC.Collect();
|
return true;
|
}
|
|
public bool ReadOneItem_Wrapper(string name, ref object result)
|
{
|
Item item;
|
|
if (itemReadDict.ContainsKey(name))
|
{
|
item = itemReadDict[name];
|
ReadOneItem(ref item, opcReadGroup);
|
result = item.value;
|
itemReadDict[name].value = result;
|
}
|
else if (itemWriteDict.ContainsKey(name))
|
{
|
item = itemWriteDict[name];
|
ReadOneItem(ref item, opcWriteGroup);
|
result = item.value;
|
itemWriteDict[name].value = result;
|
}
|
else
|
{
|
return false;
|
}
|
|
return true;
|
}
|
|
public bool ReadOneItem(ref Item item, OPCGroup opcGroup)
|
{
|
Array serverHandles;
|
Array values;
|
Array errors;
|
object qualities;
|
object timeStamps;
|
|
serverHandles = new int[2] { 0, item.serverHandle };
|
opcGroup.SyncRead(1, 1, ref serverHandles, out values, out errors, out qualities, out timeStamps);
|
item.value = values.GetValue(1);
|
|
GC.Collect();
|
|
return true;
|
}
|
|
internal void Close()
|
{
|
opcServer.Disconnect();
|
}
|
}
|
}
|