C#开发的OPC客户端代码,比较简单可以实现搜索本地主机,IP以及本地OPC服务器功能,可以添加标签,实现数据的获取及修改。 using System;002using System.Collections.Generic;003using System.Componen
C#开发的OPC客户端代码,比较简单可以实现搜索本地主机,IP以及本地OPC服务器功能,可以添加标签,实现数据的获取及修改。
using System;
002 using System.Collections.Generic;
003 using System.ComponentModel;
004 using System.Data;
005 using System.Drawing;
006 using System.Linq;
007 using System.Text;
008 using System.Windows.Forms;
009 using System.Net;
010 using OPCAutomation;
011 using System.Net.Sockets;
012 using System.Collections.Specialized;
013
014 namespace OMTGate
015 {
016 public partial class MainForm : Form
017 {
018 public MainForm()
019 {
020 InitializeComponent();
021 }
022
023
024 #region 私有变量
025 /// <summary>
026 /// OPCServer Object
027 /// </summary>
028 OPCServer KepServer;
029 /// <summary>
030 /// OPCGroups Object
031 /// </summary>
032 OPCGroups KepGroups;
033 /// <summary>
034 /// OPCGroup Object
035 /// </summary>
036 OPCGroup KepGroup;
037 /// <summary>
038 /// OPCItems Object
039 /// </summary>
040 OPCItems KepItems;
041 /// <summary>
042 /// OPCItem Object
043 /// </summary>
044 OPCItem KepItem;
045 /// <summary>
046 /// 主机IP
047 /// </summary>
048 string strHostIP = "";
049 /// <summary>
050 /// 主机名称
051 /// </summary>
052 string strHostName = "";
053 /// <summary>
054 /// 连接状态
055 /// </summary>
056 bool opc_connected = false;
057 /// <summary>
058 /// 客户端句柄
059 /// </summary>
060 int itmHandleClient = 0;
061 /// <summary>
062 /// 服务端句柄
063 /// </summary>
064 int itmHandleServer = 0;
065
066 DataTable dt = new DataTable();
067
068 #endregion
069
070 private void btnNumeServer_Click(object sender, EventArgs e)
071 {
072 //获取计算机名
073 strHostName = Dns.GetHostName();
074 txtComputerName.Text = strHostName;
075
076 //获取IP地址
077 IPAddress[] localIPs;
078 localIPs = Dns.GetHostAddresses(strHostName);
079 StringCollection IpCollection = new StringCollection();
080 foreach (IPAddress ip in localIPs)
081 {
082 //根据AddressFamily判断是否为ipv4,如果是InterNetWorkV6则为ipv6
083 if (ip.AddressFamily == AddressFamily.InterNetwork)
084 IpCollection.Add(ip.ToString());
085 }
086 string[] IpArray = new string[IpCollection.Count];
087 IpCollection.CopyTo(IpArray, 0);
088 foreach (string ip in IpArray)
089 {
090 cmbIPAddress.Items.Add(ip);
091 }
092 cmbIPAddress.SelectedIndex = 0;
093
094 //获取本地计算机上的OPCServerName
095 try
096 {
097 KepServer = new OPCServer();
098 object serverList = KepServer.GetOPCServers(strHostName);
099
100 foreach (string turn in (Array)serverList)
101 {
102 cmbServerName.Items.Add(turn);
103 }
104 cmbServerName.SelectedIndex = 0;
105 btnConnectServer.Enabled = true;
106 }
107 catch (Exception err)
108 {
109 MessageBox.Show("枚举本地OPC服务器出错:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
110 }
111 }
112
113 private void btnConnectServer_Click(object sender, EventArgs e)
114 {
115 try
116 {
117 if (!ConnectRemoteServer(cmbIPAddress.Text, cmbServerName.Text))
118 {
119 return;
120 }
121
122 btnSet.Enabled = true;
123
124 opc_connected = true;
125
126 GetServerInfo();
127
128 RecurBrowse(KepServer.CreateBrowser());
129
130 if (!CreateGroup())
131 {
132 return;
133 }
134 }
135 catch (Exception err)
136 {
137 MessageBox.Show("初始化出错:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
138 }
139 }
140
141 private void btnSet_Click(object sender, EventArgs e)
142 {
143 SetGroupProperty();
144 }
145
146 List<string> itemList = new List<string>();
147 int count = 0;
148 private void btnAddItem_Click(object sender, EventArgs e)
149 {
150 try
151 {
152 //if (itmHandleClient != 0)
153 //{
154 // this.txtTagValue.Text = "";
155 // this.txtQualities.Text = "";
156 // this.txtTimeStamps.Text = "";
157
158 // Array Errors;
159 // OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
160 // //注:OPC中以1为数组的基数
161 // int[] temp = new int[2] { 0, bItem.ServerHandle };
162 // Array serverHandle = (Array)temp;
163 // //移除上一次选择的项
164 // KepItems.Remove(KepItems.Count, ref serverHandle, out Errors);
165 //}
166 itmHandleClient = count;
167 KepItem = KepItems.AddItem(lsbTagList.SelectedItem.ToString(), itmHandleClient);
168 //itemList.Add(lsbTagList.SelectedItem.ToString());
169 itmHandleServer = KepItem.ServerHandle;
170 count++;
171 textBox1.Text = KepItems.Count.ToString();
172 DataRow dr = dt.NewRow();
173 dr["标签"] = lsbTagList.SelectedItem.ToString();
174 dr["测量值"] = "";
175 dr["质量"] = "";
176 dr["时间戳"] = "";
177 dt.Rows.Add(dr);
178 }
179 catch (Exception err)
180 {
181 //没有任何权限的项,都是OPC服务器保留的系统项,此处可不做处理。
182 //itmHandleClient = 0;
183 //txtTagValue.Text = "Error ox";
184 //txtQualities.Text = "Error ox";
185 //txtTimeStamps.Text = "Error ox";
186 MessageBox.Show("此项为系统保留项:" + err.Message, "提示信息");
187 }
188 }
189
190 /// <summary>
191 /// 设置组属性
192 /// </summary>
193 private void SetGroupProperty()
194 {
195 KepServer.OPCGroups.DefaultGroupIsActive = Convert.ToBoolean(txtGroupIsActive.Text);
196 KepServer.OPCGroups.DefaultGroupDeadband = Convert.ToInt32(txtGroupDeadband.Text);
197 KepGroup.UpdateRate = Convert.ToInt32(txtUpdateRate.Text);
198 KepGroup.IsActive = Convert.ToBoolean(txtIsActive.Text);
199 KepGroup.IsSubscribed = Convert.ToBoolean(txtIsSubscribed.Text);
200 }
201
202 /// <summary>
203 /// 连接OPC服务器
204 /// </summary>
205 /// <param name="remoteServerIP">OPCServerIP</param>
206 /// <param name="remoteServerName">OPCServer名称</param>
207 private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName)
208 {
209 try
210 {
211 KepServer.Connect(remoteServerName, remoteServerIP);
212
213 if (KepServer.ServerState == (int)OPCServerState.OPCRunning)
214 {
215 tsslServerState.Text = "已连接到-" + KepServer.ServerName + " ";
216 }
217 else
218 {
219 //这里你可以根据返回的状态来自定义显示信息,请查看自动化接口API文档
220 tsslServerState.Text = "状态:" + KepServer.ServerState.ToString() + " ";
221 }
222 }
223 catch (Exception err)
224 {
225 MessageBox.Show("连接远程服务器出现错误:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
226 return false;
227 }
228 return true;
229 }
230
231 /// <summary>
232 /// 获取服务器信息,并显示在窗体状态栏上
233 /// </summary>
234 private void GetServerInfo()
235 {
236 tsslServerStartTime.Text = "开始时间:" + KepServer.StartTime.ToString() + " ";
237 tsslversion.Text = "版本:" + KepServer.MajorVersion.ToString() + "." + KepServer.MinorVersion.ToString() + "." + KepServer.BuildNumber.ToString();
238 }
239
240 /// <summary>
241 /// 列出OPC服务器中所有节点
242 /// </summary>
243 /// <param name="oPCBrowser"></param>
244 private void RecurBrowse(OPCBrowser oPCBrowser)
245 {
246 //展开分支
247 oPCBrowser.ShowBranches();
248 //展开叶子
249 oPCBrowser.ShowLeafs(true);
250 foreach (object turn in oPCBrowser)
251 {
252 lsbTagList.Items.Add(turn.ToString());
253 }
254 }
255
256 /// <summary>
257 /// 创建组
258 /// </summary>
259 private bool CreateGroup()
260 {
261 try
262 {
263 KepGroups = KepServer.OPCGroups;
264 KepGroup = KepGroups.Add("OPCDOTNETGROUP");
265 SetGroupProperty();
266 KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
267 KepGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete);
268 KepItems = KepGroup.OPCItems;
269 }
270 catch (Exception err)
271 {
272 MessageBox.Show("创建组出现错误:" + err.Message, "创建组出错", MessageBoxButtons.OK, MessageBoxIcon.Warning);
273 return false;
274 }
275 return true;
276 }
277
278 /// <summary>
279 /// 每当项数据有变化时执行的事件
280 /// </summary>
281 /// <param name="TransactionID">处理ID</param>
282 /// <param name="NumItems">项个数</param>
283 /// <param name="ClientHandles">项客户端句柄</param>
284 /// <param name="ItemValues">TAG值</param>
285 /// <param name="Qualities">品质</param>
286 /// <param name="TimeStamps">时间戳</param>
287 void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
288 {
289 //DataTable dt = new DataTable();
290 //dt.Columns.Add("标签", System.Type.GetType("System.String"));
291 //dt.Columns.Add("测量值", System.Type.GetType("System.String"));
292 //dt.Columns.Add("质量", System.Type.GetType("System.String"));
293 //dt.Columns.Add("时间戳", System.Type.GetType("System.String"));
294
295 //为了测试,所以加了控制台的输出,来查看事物ID号
296 //Console.WriteLine("********"+TransactionID.ToString()+"*********");
297 for (int i = 1; i <= NumItems; i++)
298 {
299 //DataRow dr = dt.NewRow();
300 //dr["标签"] = itemList[i-1];
301 //dt.Columns["测量值"][i] = ItemValues.GetValue(i).ToString();
302 //dt.Columns["质量"][i] = Qualities.GetValue(i).ToString();
303 //dt.Columns["时间戳"][i] = TimeStamps.GetValue(i).ToString();
304 textBox2.Text = ClientHandles.GetValue(i).ToString();
305 dt.Rows[Convert.ToInt32(ClientHandles.GetValue(i).ToString().Trim())][1] = ItemValues.GetValue(i).ToString();
306 dt.Rows[Convert.ToInt32(ClientHandles.GetValue(i).ToString().Trim())][2] = Qualities.GetValue(i).ToString();
307 dt.Rows[Convert.ToInt32(ClientHandles.GetValue(i).ToString().Trim())][3] = TimeStamps.GetValue(i).ToString();
308 //dt.Rows.Add(dr);
309 }
310 //dgvResultList.DataSource = dt;
311 }
312
313 /// <summary>
314 /// 写入TAG值时执行的事件
315 /// </summary>
316 /// <param name="TransactionID"></param>
317 /// <param name="NumItems"></param>
318 /// <param name="ClientHandles"></param>
319 /// <param name="Errors"></param>
320 void KepGroup_AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
321 {
322 lblState.Text = "";
323 for (int i = 1; i <= NumItems; i++)
324 {
325 lblState.Text += "Tran:" + TransactionID.ToString() + " CH:" + ClientHandles.GetValue(i).ToString() + " Error:" + Errors.GetValue(i).ToString();
326 }
327 }
328
329 private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
330 {
331 if (!opc_connected)
332 {
333 return;
334 }
335
336 if (KepGroup != null)
337 {
338 KepGroup.DataChange -= new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
339 }
340
341 if (KepServer != null)
342 {
343 KepServer.Disconnect();
344 KepServer = null;
345 }
346
347 opc_connected = false;
348 }
349
350 private void MainForm_Load(object sender, EventArgs e)
351 {
352 dt.Columns.Add("标签", System.Type.GetType("System.String"));
353 dt.Columns.Add("测量值", System.Type.GetType("System.String"));
354 dt.Columns.Add("质量", System.Type.GetType("System.String"));
355 dt.Columns.Add("时间戳", System.Type.GetType("System.String"));
356
357 dgvResultList.DataSource = dt;
358 }
359 }
360
http://bbs.51cto.com/thread-1065491-1-1.html
标签和数据的显示是设计了一个表格,可以动态添加标签,显示标签名称、实时值、质量及时间戳。用于实际项目尚需修改!
【本文来自:美国服务器 http://www.558idc.com/mg.html提供,感恩】