OPC UA 统一架构) (二)
OPC UA (二)
重头戏,捞取数据,才是该干的事。想获取数据,先有数据源DataPrivade,DataPrivade的数据集合不能和BaseDataVariableState的集合存储同一地址,或者称为浅副本
需要提出下面类重新设计,按照自己的idea来做
public class ReferenceNodeManager : CustomNodeManager2
UA-.NETStandard设计的数据锁效果好,点数一多,多Client就比较卡。后来发现是Lock问题,Lock时间一长,其他Client就只能等待,目前想到的解决办法就是深拷贝数据,尽量缩短取值时间。就是上述说的不是同一片内存空间。Server的数据和DataPrivade数据不是同一个。
private BaseDataVariableState CreateVariable(NodeState parent, string path, string name, NodeId dataType, int valueRank)
{
BaseDataVariableState variable = new BaseDataVariableState(parent); variable.SymbolicName = name;
variable.ReferenceTypeId = ReferenceTypes.Organizes;
variable.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
variable.NodeId = new NodeId(path, NamespaceIndex);
variable.BrowseName = new QualifiedName(path, NamespaceIndex);
variable.DisplayName = new LocalizedText("en", name);
variable.WriteMask = AttributeWriteMask.DisplayName | AttributeWriteMask.Description;
variable.UserWriteMask = AttributeWriteMask.DisplayName | AttributeWriteMask.Description;
variable.DataType = dataType;
variable.ValueRank = valueRank;
variable.AccessLevel = AccessLevels.CurrentReadOrWrite;
variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite;
variable.Historizing = false;
variable.Value = GetNewValue(variable);
variable.StatusCode = StatusCodes.Good;
variable.Timestamp = DateTime.UtcNow;
四、DataPrivade
a) BaseDataVariableState 的属性
SymbolicName: A symbolic name for the node that is not expected to be globally unique.(节点的符号名,不应是全局唯一的。)(百度翻译)
NodeId:The identifier for the node.(节点的标识符)
BrowseName:The browse name of the node.(节点的浏览名称)
DisplayName:The display name for the node.(节点的显示名称)
DataType:The data type for the variable value.(变量值的数据类型)
ValueRank:The number of array dimensions permitted for the variable value.(变量值允许的数组维数)
Value:The value of the variable.(变量的值)(变量:或者称为节点)
个人认为上面属性比较重要,加黑字体的是用到的,其他暂时没用到。
b) 数据存储在不同区域,下面定义
可能有的用到,有的没用到
1 #region Read
2 // Real BaseDataVariableState
3 public Dictionary<string, BaseDataVariableState> BaseDataVariableStateDic = new Dictionary<string, BaseDataVariableState>();
4 // temp BaseDataVariableState
5 public Dictionary<string, BaseDataVariableState> BaseDataVariableStateTempDic = new Dictionary<string, BaseDataVariableState>();
6
7 // for example ***_***_*** ,OPC
8 private readonly Dictionary<string, String> baseDataVariableToXXXXDic = new Dictionary<string, String>();
9 // for example ***.***.*** ,IOServer
10 private Dictionary<string, String> XXXXToBaseDataVariableDic = new Dictionary<string, String>();
11 #endregion
12
13 #region Write
14 private List<InterfaceSample.Model.ValueItem> writeDataList = new List<InterfaceSample.Model.ValueItem>();
15 private Dictionary<string, BaseDataVariableState> baseDataVariableDicWrite = new Dictionary<string, BaseDataVariableState>();
16 #endregion
17
18 public InterfaceSample.OPCUADataProvide OpcuaDataPrivade = null;
19
20 private object _obj = new object();
21 #endregion
c) 获取与设置数据Value
1. 定时器更新数据,不要因为数据太多卡住,多次增加线程,争抢资源。放在了CreateAddressSpace里,在OPC UA(一)可以看到。Timer:System.Threading.Timer。
1 m_simulationTimer = new Timer(DoSimulation, cts, 1000, 1000);
2
回调DoSimulation(TimerCallback),cts(CancellationTokenSource cts)后面解释,DoSimulation里要使用Change,至于为什么需要自己查,不怎么用,用的不好。
1 private void DoSimulation(object state)
2 {
3 try
4 {
5 #region CancellationTokenSource
6 var source = state as CancellationTokenSource;
7
8 if (source == null || cts == null)
9 {
10 return;
11 }
12 if (source.Token.IsCancellationRequested && cts.Token.IsCancellationRequested)
13 {
14 return;
15 }
16 else
17 {
18 if (!cts.Token.IsCancellationRequested)
19 {
20 source = cts;
21 }
22 }
23 #endregion
24
25 if (m_dynamicNodes_temp == null)
26 {
27 return;
28 }
29 m_simulationTimer.Change(0, Timeout.Infinite);
30
31 #region
32 lock (_obj)
33 {
34 string[] strs = new string[baseDataVariableToRTDBDic.Count];
35 baseDataVariableToRTDBDic.Values.CopyTo(strs, 0);
36 List<string> li = new List<string>();
37 foreach (var str in strs)
38 {
39 if (source.Token.IsCancellationRequested)
40 {
41 m_simulationTimer.Change(1000, 1000);
42 return;
43 }
44 li.Add(str);
45 }
46 var obsli = OpcuaDataPrivade.GetItemDatas(li);
47
48 if (obsli == null)
49 {
50 m_simulationTimer.Change(1000, 1000);
51 return;
52 }
53 for (int i = 0; i < obsli.Count; i++)
54 {
55 if (source.Token.IsCancellationRequested)
56 {
57 m_simulationTimer.Change(900, 1000);
58 return;
59 }
60 m_dynamicNodes_temp[i].Value = obsli[i];
61 }
62 }
63
64 #endregion
65
66 lock (Lock)
67 {
68 int count = 0;
69 foreach (BaseDataVariableState variable in m_dynamicNodes_temp)
70 {
71 if (source.Token.IsCancellationRequested)
72 {
73 m_simulationTimer.Change(900, 1000);
74 return;
75 }
76 77 if (BaseDataVariableStateDic.ContainsKey(variable.NodeId.Identifier.ToString()))
78 {
79 m_dynamicNodes[count].Value = variable.Value;
80 m_dynamicNodes[count].Timestamp = DateTime.UtcNow;
81 m_dynamicNodes[count].ClearChangeMasks(SystemContext, false);
82 ++count;
83
84 }
85 }
86 m_simulationTimer.Change(1000, 1000);
87 //m_simulationTimer = new Timer(DoSimulation, null, 1000, 1000);
88 }
89 }
90 catch (Exception e)
91 {
92 Utils.Trace(e, "Unexpected error doing simulation.");
93 }
94 }
2. 一般地,Client用户端对Value的赋值(输入)在优先级上要高于读取,所以CancellationTokenSource的用处体现在这。
UA-.NETStandard里的BaseDataVariableState的Write集合,自己设计的,里面能到什么OnWrite或Write之类的,直接把CustomNodeManager2的Write直接拿过来
public override void Write( OperationContext context,IList<WriteValue> nodesToWrite,IList<ServiceResult> errors)
不整段代码,贴插入部分,里面有前后,找的话会找到,(override不一定成功,呵)
1 CheckIfSemanticsHaveChanged(systemContext, propertyState, propertyValue, previousPropertyValue);
2 }
3 var baseNode = handle.Node as BaseDataVariableState;
4 if(baseNode != null) nodesToWriteList.Add(baseNode);
5
6 handle.Node.ClearChangeMasks(systemContext, false);
7
8 }
9
10 // check for nothing to do.
11 if (nodesToValidate.Count == 0)
12 {
13 return;
14 }
另外的代码,遥相呼应一下,OPC UA(一) 里的CreateAddressSpace里的Task。
1 public void WriteProcHandle(CancellationTokenSource source)
2 {
3 //CancellationTokenSource source = new CancellationTokenSource();
4
5 while (true)
6 {
7 Thread.Sleep(500);
8 try
9 {
10 #region
11 lock (Lock)
12 {
13 if (baseDataVariableDicWrite.Count > 0)
14 {
15 foreach (var item in baseDataVariableDicWrite)
16 {
17 writeDataList.Add(new InterfaceSample.Model.ValueItem() { Key = baseDataVariableToRTDBDic[item.Key], Value = item.Value.Value });
18 }
19
20 baseDataVariableDicWrite.Clear();
21 }
22 }
23
24 lock (_obj)
25 {
26 if (writeDataList.Count <= 0)
27 {
28 continue;
29 }
30
31 source.Cancel();
32 List<string> keys = new List<string>();
33 List<object> values = new List<object>();
34 foreach (var item in writeDataList)
35 {
36 keys.Add(item.Key);
37 values.Add(item.Value);
38 }
39
40 if (writeDataList.Count > 0)
41 {
42 OpcuaDataPrivade.SetItemDatas(keys, values);
43 writeDataList.Clear();
44 cts = new CancellationTokenSource();
45 }
46
47 }
48
49 #endregion
50
51 }
52 catch (Exception)
53 {
54 //source = new CancellationTokenSource();
55 }
56 finally
57 {
58 if (cts.Token.IsCancellationRequested)
59 {
60 cts = new CancellationTokenSource();
61 }
62 }
63 }
64 }
大概就是这样。
OPC UA 统一架构) (二)的更多相关文章
- OPC UA 统一架构) (一)
OPC UA 一 .OPC UA简介 OPC UA(OPC Unified Architecture)是下一代OPC统一体系架构,是一种基于服务的.跨越平台的解决方案. OPC UA具有如下特点: 1 ...
- OPC UA (统一架构)的优势
OPC UA OPC统一架构(OPC Unified Architecture)是OPC基金会(OPC Foundation)创建的新技术,更加安全.可靠.中性(与供应商无关),为制造现场到生产计划或 ...
- OPC UA
OPC UA将来自不同厂商不同设备的数据进行统一格式.统一显示. OPC: originally knowns as “OLE for Process Control”, now “Open Plat ...
- OPC协议解析-OPC UA OPC统一架构
1 什么是OPC UA 为了应对标准化和跨平台的趋势,为了更好的推广OPC,OPC基金会近些年在之前OPC成功应用的基础上推出了一个新的OPC标准-OPC UA.OPC UA接口协议包含了之前的 ...
- 转:OPC协议解析-OPC UA OPC统一架构
1 什么是OPC UA 为了应对标准化和跨平台的趋势,为了更好的推广OPC,OPC基金会近些年在之前OPC成功应用的基础上推出了一个新的OPC标准-OPC UA.OPC UA接口协议包含了之前的 ...
- SharpNodeSettings项目,可配置的数据采集,统一的工业数据网关,OPC UA服务器开发,PLC数据发布到自身内存,redis,opc ua,以及数据可视化开发
本项目隶属于 HslCommunication 项目的SDK套件,如果不清楚HslCommunication组件的话,可以先了解那个项目,源代码地址:https://github.com/dathli ...
- C# 读写opc ua服务器,浏览所有节点,读写节点,读历史数据,调用方法,订阅,批量订阅操作
OPC UA简介 OPC是应用于工业通信的,在windows环境的下一种通讯技术,原有的通信技术难以满足日益复杂的环境,在可扩展性,安全性,跨平台性方面的不足日益明显,所以OPC基金会在几年前提出了面 ...
- C# 实现opc ua服务器的远程连接(转)
原文转自:https://www.cnblogs.com/dathlin/p/7724834.html OPC UA简介 OPC是应用于工业通信的,在windows环境的下一种通讯技术,原有的通信技术 ...
- 从 OPC 到 OPC UA
[前言]OPC是一个工业标准,所属国际组织是OPC基金会,现有会员已超过220家,包括世界上所有主要的自动化控制系统.仪器仪表及过程控制系统的公司. [经典 OPC]经典OPC规范基于微软Window ...
随机推荐
- flowable获取上级主管
//主管 Dept managerDept = deptUserUtil.getManagerDept(bean.getCreateDept(),bean.getCreateUser()); //上级 ...
- CMS、G1收集器
目录 CMS.G1收集器 1.CMS收集器 1.1.原理 1.2.不足 2.G1收集器 2.1.特点 2.2.执行过程 CMS.G1收集器 1.CMS收集器 CMS(Concurrent Mark S ...
- epoll原理与本质
我们知道IO模型中有一个NIO模型,像我们平时接触到的dubbo类的RPC框架底层基于Netty作为通讯框架,而Netty实现的IO模型就是NIO模型.而NIO模型中 底层技术就用到了Linux的ep ...
- git基础-远程仓库的使用
远程仓库的使用 为了能在任意 Git 项目上协作,你需要知道如何管理自己的远程仓库. 远程仓库是指托管在因特网或其他网络中的你的项目的版本库. 你可以有好几个远程仓库,通常有些仓库对你只读,有些则可以 ...
- 项目中处理数据常用Excel公式
="'"&A1&"'," 需求:是大佬给了excel,里面是700多个单号,要我从生产的数据库中查询出每个单号对应的类型,这时需要查数据库,我决 ...
- #2020征文-TV# Tab切换选项卡同时更换内容
Tab选项卡是应用程序中最最常用,也是最普遍存在的一种布局形态,无论是在PC端还是在移动端,都是一种清晰明了,层级关系简单的,能够使用户明确所处位置.Tab选项卡可以置于页面的底部,比如微信底部选项卡 ...
- vue的favicon.ico的不能修改替换问题解决。
vue的favicon.ico解决办法: 暴力替换图片: <link rel="icon" href="favicon.ico" type="i ...
- 用python+sklearn(机器学习)实现天气预报数据 模型和使用
用python+sklearn机器学习实现天气预报 模型和使用 项目地址 系列教程 0.前言 1.建立模型 a.准备 引入所需要的头文件 选择模型 选择评估方法 获取数据集 b.建立模型 c.获取模型 ...
- JAVA_基础反射创建运行时类的对象
通过反射去创建对应的运行时类的对象 newInstance():调用此方法,创建对应的运行时类的对象.内部调用的是空参的构造器. 要想此方法正常的创建运行时类的对象,要求: 1.运行时类必须提供空参构 ...
- LeetCode485 最大连续1的个数
给定一个二进制数组, 计算其中最大连续1的个数. 示例 1: 输入: [1,1,0,1,1,1] 输出: 3 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3. 注意: 输入的数组 ...