You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lj_plc/Main/Mesnac.Basic/OPCComm.cs

310 lines
9.4 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}
}