C#开发OPC客户端
第一个随笔,使用了open live write,作为客户端.最近使用c#开发一个小软件,主要功能是opc客户端.以后会开发各类别的协议,作为,协议的转发栈.
因为我本人是搞自动化的,所以搞自动化小伙伴像我这样喜欢编程的可能有,但是一般是逻辑思维强,但是底子相对还是弱的.
1,c# 开发opc的准备工作
软件:vs2019;
dll:c:\program files (x86)\common files\matrikonopc\common\opcdaauto.dll
并且将其拷贝到c:\windows\syswow64中,并且使用dll注册.(记得注册必须在这个文件夹中)
然后在,vs2019的引用添加引用
2, 查看opc手册,不过是英文的vb版本的,以上资料可以在我的百度网盘里面下载.或者私信我.
3, 如何查询 opc服务器数量和连接服务器
private void btgetlist_click(object sender, eventargs e) { kepserver = new opcserver(); messagebox.show(environment.machinename); object serverlist = kepserver.getopcservers(); //枚举网络所有opc服务器并写入combobox控件 foreach (string turn in (array)serverlist) { cmbservername.items.add(turn); } }
private void form1_load(object sender, eventargs e) { kepserver = new opcserver(); kepserver.connect("matrikon.opc.simulation.1"); if (kepserver.serverstate == (int)opcserverstate.opcrunning) { tsslserverstate.text = "已连接到-" + kepserver.servername + " "; opcbrowser = kepserver.createbrowser(); } treenode root = treeview1.nodes.add(kepserver.servername); root.tag = kepserver; opcbrowser.movetoroot(); showintreeview(opcbrowser,root); }
其中主要函数说明:
其同时支持ip或者计算机名的方式
本地计算机第二个参数.第一个参数是服务器名称.
5,对于opcbrower 对象.
从上面可以看到opcbrowser 来自 opcserver.createbrower(),其主要用来查看服务器相关信息.
其本身是一个集合(collection),但是,这个时候,其items=0;
showbranchs():该函数用于将当前节点的名称集合写入到collection中.
showleafs():该函数用于将当前节点的tags 写入到collection中.
showleafs(true):将显示该节点下面所有的itemsid--------------很重要,在添加item时可以用到.
private void showintreeview(opcbrowser brower,treenode node) { treenode childnode = null; brower.showbranches(); int branchcount = brower.count; list<string> lst = null; if (brower.count>0) //回溯的添加branch { lst = new list<string>(); foreach (string t in brower) lst.add(t); foreach (string branch in lst) { childnode = new treenode(branch); childnode.tag = brower.getitemid(branch); node.nodes.add(childnode); brower.movedown(branch); showintreeview(brower, childnode); brower.moveup(); } } brower.showleafs(); int leafscount = brower.count; foreach (string leaf in brower) { childnode = new treenode(brower.getitemid(leaf)); childnode.tag = brower.getitemid(leaf); node.nodes.add(childnode); } }
这样就可以把服务器的信息读取到树里面了.
brower对象主要作用就是可以知道服务器里面的信息了.
6,group对象及item对象.
首先:需要创建group对象:
private void button3_click(object sender, eventargs e) { kepgroups = kepserver.opcgroups; kepgroups.defaultgroupisactive = true; kepgroups.defaultgroupupdaterate = 200; kepgroups.defaultgroupdeadband = 0; kepgroup = kepgroups.add("mxb"); kepgroup.issubscribed = true; kepgroup.datachange += new diopcgroupevent_datachangeeventhandler( datachangehandlerfunc); kepitems = kepgroup.opcitems; // kepitem = kepitems.additem("random.arrayofreal8", 1); textbox1.text = kepitem.serverhandle + ":" + kepitem.requesteddatatype; }
说明:
如果该参数是issubscribed=true;则其支持订阅功能:也就是当改组中的参数有改变的时候,其会触发datachange事件.
其中:itemid是一个关键的参数,可以通过 opcbrower.showleafs(true)查看.
additem(string itemid,int clienthandle):其中client handle是客户端自行填写的.
一个item 有一个serverhandle,由服务器提供,itemid:由服务器提供;clienthandle:由客户端提供.
事件处理函数
private void datachangehandlerfunc(int transactionid, int numitems, ref array clienthandles, ref array itemvalues, ref array qualities, ref array timestamps) { // for(int i = 1;i<=numitems;i++) { if((int)clienthandles.getvalue(i) == kepitem.clienthandle) { dynamic t = itemvalues.getvalue(i); object[] ary; ary = array.convertall<double, object>(t, new converter<double, object>((x) =>x)); listbox1.items.clear(); listbox1.items.addrange(ary); } } }
使用该函数可以快速定位数据变更的item.注意:所有的array都是1开头的,所以不能直接转换成int[]或者double[];需要编写一个转换
的函数,转换成object[].另外,需要注意到 clienthandles虽然是一个int数组,但是是无法直接转换到int[]的,因为首先,其起始index=1.
其他还有一些异步写入啊,什么的,可以参考手册.