|
|
using System;
|
|
|
using OPC;
|
|
|
using OPCDA;
|
|
|
using OPCDA.NET;
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
namespace Mesnac.Basic
|
|
|
{
|
|
|
// 定义用于返回发生变化的项的值和其对应的客户句柄
|
|
|
public delegate void DataChange(READRESULT[] values, string[] itemsID);
|
|
|
|
|
|
/// <summary>
|
|
|
/// 自定义的结构
|
|
|
/// 用来保存读取到的数据(值,品质,时间戳)
|
|
|
/// </summary>
|
|
|
public struct READRESULT
|
|
|
{
|
|
|
public string readValue;
|
|
|
public string readQuality;
|
|
|
public string readTimeStamp;
|
|
|
}
|
|
|
|
|
|
public class OPCComm
|
|
|
{
|
|
|
OpcServer myOPCServer;//server object
|
|
|
SyncIOGroup readWriteGroup;//group object
|
|
|
ItemDef itemData;
|
|
|
BrowseTree itemTree;
|
|
|
READRESULT readRes;
|
|
|
//供回调函数使用
|
|
|
RefreshGroup asyncRefrGroup;
|
|
|
DataChangeEventHandler dch;
|
|
|
READRESULT[] dataChangeRes; //用来保存变量值发生变化时服务器的回调函数得到的变量数据
|
|
|
|
|
|
public READRESULT[] DataChangeRes
|
|
|
{
|
|
|
get { return dataChangeRes; }
|
|
|
set { dataChangeRes = value; }
|
|
|
}
|
|
|
|
|
|
public BrowseTree ItemTree
|
|
|
{
|
|
|
get { return itemTree; }
|
|
|
set { itemTree = value; }
|
|
|
}
|
|
|
|
|
|
public ItemDef ItemData
|
|
|
{
|
|
|
get { return itemData; }
|
|
|
set { itemData = value; }
|
|
|
}
|
|
|
|
|
|
internal READRESULT ReadRes
|
|
|
{
|
|
|
get { return readRes; }
|
|
|
set { readRes = value; }
|
|
|
}
|
|
|
|
|
|
DataChange dtChange;
|
|
|
public OPCComm(DataChange dataChange)
|
|
|
{
|
|
|
dtChange = dataChange;
|
|
|
}
|
|
|
|
|
|
#region 获得可访问的服务器名字列表
|
|
|
/// <summary>
|
|
|
/// 获得服务器名字列表
|
|
|
/// </summary>
|
|
|
/// <returns>返回包含服务器名字的字符串数组</returns>
|
|
|
public string[] GetSerList(string host)
|
|
|
{
|
|
|
OpcServerBrowser serList = new OpcServerBrowser(new OPC.Common.Host(host));
|
|
|
string[] serNames;
|
|
|
serList.GetServerList(out serNames);
|
|
|
|
|
|
return serNames;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 浏览服务器地址空间
|
|
|
/// <summary>
|
|
|
/// 浏览服务器地址空间
|
|
|
/// </summary>
|
|
|
/// <returns>成功返回0, 失败返回-1</returns>
|
|
|
public int GetItemList()
|
|
|
{
|
|
|
itemTree = new BrowseTree(myOPCServer);
|
|
|
|
|
|
int res = itemTree.CreateTree(); // Browse server from root
|
|
|
if (HRESULTS.Succeeded(res))
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
return -1;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 连接服务器
|
|
|
/// <summary>
|
|
|
/// 连接服务器
|
|
|
/// </summary>
|
|
|
/// <param name="serName">服务器的名字</param>
|
|
|
/// <param name="serIP">服务器所在机器的IP</param>
|
|
|
/// <returns>成功返回0,失败返回-1</returns>
|
|
|
public int Conn2Server(string serName, string serIP,int refresh)
|
|
|
{
|
|
|
int res;
|
|
|
try
|
|
|
{
|
|
|
myOPCServer = new OpcServer();
|
|
|
|
|
|
res = myOPCServer.Connect(serIP, serName);
|
|
|
if (HRESULTS.Failed(res))
|
|
|
{
|
|
|
myOPCServer = null;
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
readWriteGroup = new SyncIOGroup(myOPCServer);
|
|
|
//供回调函数刷新变量值使用
|
|
|
dch = new DataChangeEventHandler(DataChangeHandler);
|
|
|
if (refresh<=0)
|
|
|
{
|
|
|
refresh = 1000;
|
|
|
}
|
|
|
asyncRefrGroup = new RefreshGroup(myOPCServer, dch, refresh);
|
|
|
}
|
|
|
catch
|
|
|
{
|
|
|
myOPCServer = null;
|
|
|
return -1;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 添加项
|
|
|
/// <summary>
|
|
|
/// 获得变量对象
|
|
|
/// </summary>
|
|
|
/// <param name="itemId">变量ID</param>
|
|
|
/// <returns>成功返回0, 失败返回-1</returns>
|
|
|
int AddItem(string itemId)
|
|
|
{
|
|
|
itemData = readWriteGroup.Item(itemId);
|
|
|
if (itemData == null)
|
|
|
{
|
|
|
readWriteGroup.Add(itemId);
|
|
|
itemData = readWriteGroup.Item(itemId);
|
|
|
if (itemData == null)
|
|
|
{
|
|
|
return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 读取一个变量
|
|
|
/// <summary>
|
|
|
/// 从服务器上读取数据,读取的数据保存在READRESULT结构中
|
|
|
/// </summary>
|
|
|
/// <param name="num">变量ID</param>
|
|
|
/// <returns>成功返回0, 失败返回-1</returns>
|
|
|
public int Read(string itemId)
|
|
|
{
|
|
|
if (AddItem(itemId) == 0)
|
|
|
{
|
|
|
OPCItemState Rslt;
|
|
|
OPCDATASOURCE dsrc = OPCDATASOURCE.OPC_DS_DEVICE;
|
|
|
int rtc = readWriteGroup.Read(dsrc, itemData, out Rslt);
|
|
|
|
|
|
if (HRESULTS.Succeeded(rtc)) // read from OPC server successful
|
|
|
{
|
|
|
if (Rslt != null)
|
|
|
{
|
|
|
if (HRESULTS.Succeeded(Rslt.Error)) // item read successful
|
|
|
{
|
|
|
readRes.readValue = Rslt.DataValue.ToString();
|
|
|
readRes.readQuality = readWriteGroup.GetQualityString(Rslt.Quality);
|
|
|
DateTime dt = DateTime.FromFileTime(Rslt.TimeStamp);
|
|
|
readRes.readTimeStamp = dt.ToString();
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return -1;
|
|
|
}
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 修改一个变量
|
|
|
/// <summary>
|
|
|
/// 修改一个变量
|
|
|
/// </summary>
|
|
|
/// <param name="itemId">变量ID</param>
|
|
|
/// <param name="value">变量的值</param>
|
|
|
/// <returns>返回写操作结果的字符串</returns>
|
|
|
public string Write(string itemId, object value)
|
|
|
{
|
|
|
if (AddItem(itemId) == 0)
|
|
|
{
|
|
|
int res = readWriteGroup.Write(itemData, value);
|
|
|
|
|
|
return readWriteGroup.GetErrorString(res);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 向RefreshGroup组中添加一个变量
|
|
|
/// <summary>
|
|
|
/// 向RefreshGroup组中添加一个变量
|
|
|
/// </summary>
|
|
|
/// <param name="itemId">变量ID</param>
|
|
|
/// <returns>成功返回0,失败返回-1</returns>
|
|
|
public int Add2RefrGroup2(string itemId,ref VarEnum DataType)
|
|
|
{
|
|
|
DataType = VarEnum.VT_EMPTY;
|
|
|
if (AddItem(itemId) == 0)
|
|
|
{
|
|
|
DataType = itemData.OpcIInfo.CanonicalDataType;
|
|
|
int res = asyncRefrGroup.Add(itemData.OpcIDef.ItemID);
|
|
|
if (HRESULTS.Failed(res))
|
|
|
{
|
|
|
return -1;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
public int Add2RefrGroup(string itemId)
|
|
|
{
|
|
|
|
|
|
if (AddItem(itemId) == 0)
|
|
|
{
|
|
|
|
|
|
int res = asyncRefrGroup.Add(itemData.OpcIDef.ItemID);
|
|
|
if (HRESULTS.Failed(res))
|
|
|
{
|
|
|
return -1;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 断开同服务器的连接
|
|
|
/// <summary>
|
|
|
/// 断开同服务器的连接
|
|
|
/// </summary>
|
|
|
/// <returns>成功返回0,失败返回-1</returns>
|
|
|
public void DisConn()
|
|
|
{
|
|
|
if (myOPCServer != null)
|
|
|
{
|
|
|
asyncRefrGroup.Dispose();
|
|
|
readWriteGroup.Dispose();
|
|
|
myOPCServer.Disconnect();
|
|
|
myOPCServer = null;
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 回调函数
|
|
|
/// <summary>
|
|
|
/// 回调函数,当RefreshGroup组里的数据发生变化时由服务器自动调用该函数
|
|
|
/// </summary>
|
|
|
/// <param name="sender"></param>
|
|
|
/// <param name="e"></param>
|
|
|
public void DataChangeHandler(object sender, DataChangeEventArgs e)
|
|
|
{
|
|
|
int count = e.sts.Length;
|
|
|
string[] itemsID = new string[count];
|
|
|
dataChangeRes = new READRESULT[count];
|
|
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
{
|
|
|
int hnd = e.sts[i].HandleClient;
|
|
|
ItemDef item = asyncRefrGroup.FindClientHandle(hnd);
|
|
|
if (item != null)
|
|
|
{
|
|
|
//保存变量的ItemID
|
|
|
itemsID[i] = item.OpcIDef.ItemID;
|
|
|
}
|
|
|
|
|
|
object val = e.sts[i].DataValue;
|
|
|
string qt = asyncRefrGroup.GetQualityString(e.sts[i].Quality);
|
|
|
DateTime dt = DateTime.FromFileTime(e.sts[i].TimeStamp);
|
|
|
//将变量的值保存在READRESULT结构中
|
|
|
dataChangeRes[i].readValue = val.ToString();
|
|
|
dataChangeRes[i].readQuality = qt;
|
|
|
dataChangeRes[i].readTimeStamp = dt.ToString();
|
|
|
}
|
|
|
|
|
|
dtChange(dataChangeRes, itemsID);
|
|
|
}
|
|
|
#endregion
|
|
|
}
|
|
|
} |