【OPCAutomation】 使用OPCAutomation实现对OPC数据的访问
折腾了一段时间研究OPC,理清了下位机、OPCServer 和OPCClient的关系和通信模型,终于能够来写一篇相关的博客了。
我们使用西门子的 S7 200 SMART作为下位机端,通过3G路由器从vpn与公司服务器通信,服务器运行配置好的PC Access SMART 作为OPC Server, 完成对下位机内存地址的定义后,使用自动化接口开发中间件负责将OPC Server得到的PLC数据存放至SQL Server
中间件和数据库的设计思路是:
数据库按真实设备类型分别建表用作存储,数据库建有数据字典表用作配置功能,包括配置内存地址和opc服务等。
中间件作用是调用OPCAutomation 类访问OPCServer端,并进行可控制读取间隔的OPC数据读取、存储工作。
由于第一次接触这类开发,在设计功能时花费了很多精力,从完全不懂到基本理解这种通信模式和原理,也绕了不少远路。
本文主要介绍OPCAutomation类的使用。
简单说下流程就是:
1. 创建OPC Server的连接
2. 创建OPC组对象并初始化设置
3. 获取组的OPCItems对象,为读取数据作准备
4. opcItem的操作。
5. 退出程序的资源释放
创建连接很简单,需要指定OPCServer所在的服务器(内网可以指定ip或者计算机名),指定OPC服务的名称(同一服务器可能运行多个OPC服务以适配同的下位机)
private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName)
{
try
{
this.opcServer.Connect(remoteServerName, remoteServerIP);
string status;
if (opcServer.ServerState == (int)OPCServerState.OPCRunning)
{
status = "已连接到-" + opcServer.ServerName + " ";
}
else
{
//这里你可以根据返回的状态来自定义显示信息,请查看自动化接口API文档
status = "状态:" + opcServer.ServerState.ToString() + " ";
}
Console.WriteLine(status);
}
catch (Exception err)
{
Console.WriteLine("连接远程服务器出现错误:" + err.Message, "提示信息");
return false;
}
return true;
}
其中 this.opcServer.Connect(remoteServerName, remoteServerIP);即OPCAutomation类提供的连接方法。
需要注意的是,在实际配置时,需要完全对OPC 服务端所在服务器上配置防火墙出入站规则后,OPC服务才能够被其他服务器上的中间件访问到。故我们选择最简单的方式,在本机运行中间件。
创建组相当于读取到OPC上特定的项目,而具体的数据值是在每个项目下根据开发人员的定义而确定。
opcGroups = opcServer.OPCGroups;
opcGroup = opcGroups.Add("OPCDOTNETGROUP");
SetGroupProperty();
opcGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(opcGroup_DataChange); //opcGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete); opcItems = opcGroup.OPCItems;
注释的代码是绑定写操作的事件。
这段代码是为OPCGroup对象进行初始化。 比较关键的是两句绑定事件的,第一个绑定的是每当OPC数据有变化时触发的事件。
数据变化的时间是由以下代码中UpdateRate控制。
private void SetGroupProperty()
{
opcServer.OPCGroups.DefaultGroupIsActive = true;
opcServer.OPCGroups.DefaultGroupDeadband = ;
opcGroup.UpdateRate = this.updateRate;
opcGroup.IsActive = true;
opcGroup.IsSubscribed = true;
}
关于逐项配置的具体说明,建议参考OPCAutomation的api,如果有看到翻译比较合适的后续会补充上来。
之后是为全局变量里的OPCGroup对象添加Items,在OPC中,每个opcItem会被分配一个客户端句柄值,同时会被配置上服务端句柄。几乎所有有关获取指定OpcItem对象的方法均要求指定客户端句柄值。
void AddAllOpcItem()
{
opcBrowser.ShowBranches();
opcBrowser.ShowLeafs(true);
int count = this.opcBrowser.Count;
if (this.opcItemsArray == null)
{
opcItemsArray = new List<string>();
}
foreach (var item in opcBrowser)
{
opcItemsArray.Add(item.ToString());
}
AddOpcItems();
}
//逐项绑定句柄值
void AddOpcItems()
{
foreach (var item in this.opcItemsArray)
{
itmHandleClient = ;
opcItem = opcItems.AddItem(item, itmHandleClient);
itmHandleServer = opcItem.ServerHandle;
}
}
这段代码是为了把获取到的全部OPCItem添加到所创建的OPCGroup对象的opcItem集合中,以便我们所绑定的DataChange事件能够被触发并且正确对应到每个地址值上。
基本上到此,只要在所绑定的DataChange的实现代码中完成具体的数据读取业务,中间件的核心部分已经完成。
稍微提一下,OPC的数据项主要包含:名称、条目id、地址、数据类型、数据值、工程单位上下限、时间戳和质量几项,在实际业务中我们关注条目ID、数据类型、值、时间戳和质量,对于读取的opc数据值而言,需要注意的是得到值是Dynamic类型的,需要正确进行判断和转换。质量返回值为0时基本可以认为下位机到服务端的数据链断了,或者下位机对应项目没有收到数据,据此可进行日志和提示的业务操作。
在OPC的数据类型中,REAL对应float, WORD对应16位整型,BOOL可以用bit或者Bool进行转换,用bit和sql server的数据项可以比较方便对接。
第一次做这类开发,谬误难免,希望多多指点。
感谢阅读。
【OPCAutomation】 使用OPCAutomation实现对OPC数据的访问的更多相关文章
- C# - VS2019 通过DataGridView实现对Oracle数据表的增删改查
前言 通过VS2019建立WinFrm应用程序,搭建桌面程序后,通过封装数据库操作OracleHelper类和业务逻辑操作OracleSQL类,进而通过DataGridView实现对Oracle数据表 ...
- 使用JWT来实现对API的授权访问
目录 什么是JWT JWT的结构 Header Payload Signature 解码后的JWT JWT是怎样工作的 在JAVA里使用JWT 引入依赖 JWT Service 生成JWT 解码JWT ...
- SILVERLIGHT实现对HTML DOM的访问
实现对HTML DOM的访问.Silverlight 2在命名空间System.Windows.Browser下内置了很多对于HTML DOM访问和操作的支持,我们最常用的一个对象是HtmlEleme ...
- js实现对json数据的序列化(兼容ie6以上浏览器)
/** * 增加对JSON数据的序列化方法, * 主要用于IE6.7不支持JSON对象的浏览器 */ var xue = xue || {};xue.json = xue.json || {}; xu ...
- python实现对excel数据进行修改/添加
import osimport xlrdfrom xlutils.copy import copydef base_dir(filename=None): return os.path.join(os ...
- C++实现对Json数据的友好处理
背景 C/C++客户端需要接收和发送JSON格式的数据到后端以实现通讯和数据交互.C++没有现成的处理JSON格式数据的接口,直接引用第三方库还是避免不了拆解拼接.考虑到此项目将会有大量JSON数据需 ...
- SQLite帮助类SQlitehelper 实现对SQLite数据的增删改查
public class SQLiteHelper { public const string sConn = "Data Source=" + @"path" ...
- Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问
本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这 ...
- 写出java8实现对List<User>中的username字段过滤出不等于张三的数据
写出java8实现对List<User>中的username字段过滤出不等于张三的数据... 对...这个是一道面试题.当时没有看过java8的新特性...所以有点懵. 看完之后感觉 真. ...
随机推荐
- Struts2的核心配置文件
Struts2的详细配置: 配置的是struts2的核心配置文件:,在struts2的核心配置文件中主要有三个标签需要进行配置:package,action,result. 1. 配置package标 ...
- 实验报告2&&第四周课程总结
实验报告: 写一个名为Rectangle的类表示矩形.其属性包括宽width.高height和颜色color,width和height都是double型的,而color则是String类型的.要求该类 ...
- JavaSE编码试题强化练习3
1.给20块钱买可乐,每瓶可乐3块钱,喝完之后退瓶子可以换回1块钱,问最多可以喝到多少瓶可乐. public class TestCirculation { public static void ma ...
- linux 截取变量字符串
STR=123456abc FINAL=`echo ${STR: -1}` 或者 FINAL=${STR: -1} 都可以让FINAL获得c这个最后一个字符 Linux 的字符串截取很有用.有八种 ...
- SSM框架—Spring+SpringMVC+MyBatis
1.环境搭建 1.1概念 Spring是一个Java应用的开源框架,Bean/Context/Core/IOC/AOP/MVC等是其重要组件,IOC控制反转,AOP面向切面编程,各种注入方式,实现方式 ...
- .net core 自定义中间件
public class MyMiddleware { //private IConfiguration _configuration; //第一步: private RequestDelegate ...
- HDU-1847 Good Luck in CET-4 Everybody! (博弈+找规律)
大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和Cici都是如此.当然,作为在考场浸润了十几载的当代大学生,Kiki和Cici更懂得考 ...
- jquery的点击事件
一.任务需求:两个按钮,一个DIV,点击显示按钮显示DIV,点击隐藏按钮,隐藏DIV. 二.任务分析:监听按钮的点击,操作DIV的显示隐藏效果. 三.代码实现: <body> <bu ...
- Taro -- 使用 Redux 来进行全局变量的管理
前言 Redux是JavaScript 状态容器,提供可预测化的状态管理.一般来说,规模比较大的小程序,页面状态,数据缓存,需要管理的东西太多,这时候引入Redux可以方便的管理这些状态,同一数据,一 ...
- How to Add Memory, vCPU, Hard Disk to Linux KVM Virtual Machine
ref: https://www.thegeekstuff.com/2015/02/add-memory-cpu-disk-to-kvm-vm/ In our previous article of ...