using System; using OPC; using OPCDA; using OPCDA.NET; using System.Runtime.InteropServices; namespace Mesnac.Basic { // 定义用于返回发生变化的项的值和其对应的客户句柄 public delegate void DataChange(READRESULT[] values, string[] itemsID); /// /// 自定义的结构 /// 用来保存读取到的数据(值,品质,时间戳) /// 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 获得可访问的服务器名字列表 /// /// 获得服务器名字列表 /// /// 返回包含服务器名字的字符串数组 public string[] GetSerList(string host) { OpcServerBrowser serList = new OpcServerBrowser(new OPC.Common.Host(host)); string[] serNames; serList.GetServerList(out serNames); return serNames; } #endregion #region 浏览服务器地址空间 /// /// 浏览服务器地址空间 /// /// 成功返回0, 失败返回-1 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 连接服务器 /// /// 连接服务器 /// /// 服务器的名字 /// 服务器所在机器的IP /// 成功返回0,失败返回-1 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 添加项 /// /// 获得变量对象 /// /// 变量ID /// 成功返回0, 失败返回-1 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 读取一个变量 /// /// 从服务器上读取数据,读取的数据保存在READRESULT结构中 /// /// 变量ID /// 成功返回0, 失败返回-1 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 修改一个变量 /// /// 修改一个变量 /// /// 变量ID /// 变量的值 /// 返回写操作结果的字符串 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组中添加一个变量 /// /// 向RefreshGroup组中添加一个变量 /// /// 变量ID /// 成功返回0,失败返回-1 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 断开同服务器的连接 /// /// 断开同服务器的连接 /// /// 成功返回0,失败返回-1 public void DisConn() { if (myOPCServer != null) { asyncRefrGroup.Dispose(); readWriteGroup.Dispose(); myOPCServer.Disconnect(); myOPCServer = null; } } #endregion #region 回调函数 /// /// 回调函数,当RefreshGroup组里的数据发生变化时由服务器自动调用该函数 /// /// /// 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 } }