Ejemplo n.º 1
0
 public OpcUaDataItem(string name, int updateRate, Type valueType, object oldValue, object newValue, OpcUaStatusCodes opcUaStatusCodes)
 {
     this.Name             = name;
     this.UpdateRate       = updateRate;
     this.ValueType        = valueType;
     this.OldValue         = oldValue;
     this.NewValue         = newValue;
     this.OpcUaStatusCodes = opcUaStatusCodes;
 }
Ejemplo n.º 2
0
 public OpcUaDataEventArgs(OpcUaStatusCodes opcUaStatusCodes, OpcUaDataItem opcUaDataItem)
 {
     this.OpcUaStatusCodes = opcUaStatusCodes;
     this.OpcUaDataItem    = opcUaDataItem;
 }
Ejemplo n.º 3
0
 public OpcUaErrorEventArgs(OpcUaStatusCodes opcUaStatusCodes, string message, Exception exception)
 {
     this.OpcUaStatusCodes = opcUaStatusCodes;
     this.Message          = message;
     this.Exception        = exception;
 }
Ejemplo n.º 4
0
        /// <summary>
        /// 注册监控的数据点
        /// </summary>
        /// <param name="nodes"></param>
        /// <returns></returns>
        public async Task <OpcUaStatusCodes> RegisterNodes(List <OpcUaDataItem> nodes)
        {
            this.OpcUaDataItems = nodes;
            daemonTimer.Enabled = false;
            daemonTimer.Stop();
            //如果未连接那么返回
            if (!this.IsConnected)
            {
                OnErrorHappened?.Invoke(this, new OpcUaErrorEventArgs(OpcUaStatusCodes.Bad, $"{ToString()},未连接OPCUA服务器,请先连接在订阅数据项,", null));
                return(OpcUaStatusCodes.Bad);
            }
            return(await Task <OpcUaStatusCodes> .Run(() =>
            {
                OpcUaStatusCodes opcUaStatusCodes = OpcUaStatusCodes.Bad;
                if (session == null)
                {
                    opcUaStatusCodes = OpcUaStatusCodes.BadSessionNotActivated;
                }
                try
                {
                    if (Equals(null, nodes) && nodes.Count() < 1)
                    {
                        //没有数据
                        opcUaStatusCodes = OpcUaStatusCodes.BadInvalidArgument;
                    }
                    // 根据更新频率分组
                    var OpcUaNodeGroups = from a in nodes
                                          group a by a.UpdateRate into g
                                          select new { UpdateRate = g.Key, OpcUaNodes = g };
                    foreach (var OpcUaNodeGroup in OpcUaNodeGroups)
                    {
                        var subscription = session.Subscriptions.FirstOrDefault(a => a.DisplayName == OpcUaNodeGroup.UpdateRate.ToString());
                        //未找到已经订阅的组,那么新建组并添加订阅项,并关联监视事件句柄
                        if (Equals(null, subscription))
                        {
                            #region 增加订阅
                            //创建订阅组。订阅组状态的名称是更新频率
                            //subscription = new Subscription();
                            subscription = new Subscription(session.DefaultSubscription);
                            bool isAddSession = session.AddSubscription(subscription);
                            subscription.Create();
                            subscription.PublishingInterval = OpcUaNodeGroup.UpdateRate;
                            subscription.PublishingEnabled = true;
                            subscription.LifetimeCount = 0;
                            subscription.KeepAliveCount = 0;
                            subscription.DisplayName = OpcUaNodeGroup.UpdateRate.ToString();
                            subscription.Priority = byte.MaxValue;
                            List <MonitoredItem> monitoredItems = new List <MonitoredItem>();

                            foreach (var v in OpcUaNodeGroup.OpcUaNodes)
                            {
                                monitoredItems.Add(new MonitoredItem()
                                {
                                    StartNodeId = new NodeId(v.Name),
                                });
                            }
                            //关联监视
                            monitoredItems.ForEach(a => a.Notification += OnMonitoredNotification);
                            //foreach (var monitoredItem in monitoredItems)
                            //{
                            //    monitoredItem.Notification += OnMonitoredNotification;
                            //}
                            subscription.AddItems(monitoredItems);
                            subscription.ApplyChanges();

                            if (isAddSession)
                            {
                                opcUaStatusCodes = OpcUaStatusCodes.BadSubscriptionIdInvalid;
                            }
                            else
                            {
                                opcUaStatusCodes = OpcUaStatusCodes.BadSubscriptionIdInvalid;
                            }
                            #endregion 增加订阅
                        }
                        else//已经有订阅组,那么更新订阅项,没有的订阅移除,原有的订阅保留,新增的订阅增加
                        {
                            //查询要删除的点
                            #region 更新订阅

                            //移除
                            //查询要删除的点
                            List <MonitoredItem> deleteItems = new List <MonitoredItem>();
                            foreach (var v in subscription.MonitoredItems)
                            {
                                if (!OpcUaNodeGroup.OpcUaNodes.Any(a => a.Name == v.StartNodeId))
                                {
                                    deleteItems.Add(v);
                                }
                            }
                            deleteItems.ForEach(a => a.Notification -= OnMonitoredNotification);
                            OnLogHappened?.BeginInvoke(this, new OpcUaLogEventArgs($"{ToString()},要删除的点数:{deleteItems.Count } "), new AsyncCallback((ia) =>
                            {
                                if (ia.IsCompleted)
                                {
                                    OnLogHappened.EndInvoke(ia);
                                }
                            }), null);

                            if (!Equals(null, deleteItems) && deleteItems.Count() > 0)
                            {
                                subscription.RemoveItems(deleteItems);
                                OnLogHappened?.Invoke(this, new OpcUaLogEventArgs($"{ToString()},已经删除的点数:{deleteItems.Count } "));
                                subscription.ApplyChanges();
                            }
                            //新增
                            //查询要新增加的点,
                            IList <OpcUaDataItem> addItems = new List <OpcUaDataItem>();
                            foreach (var v in OpcUaNodeGroup.OpcUaNodes)
                            {
                                if (!subscription.MonitoredItems.Any(a => a.StartNodeId.ToString() == v.Name))
                                {
                                    addItems.Add(v);
                                }
                            }
                            var addMonitoredItems = from a in addItems
                                                    select new MonitoredItem
                            {
                                StartNodeId = a.Name,
                                AttributeId = Attributes.Value,
                                DisplayName = a.Name,
                                SamplingInterval = OpcUaNodeGroup.UpdateRate,
                                MonitoringMode = MonitoringMode.Reporting,
                            };
                            //关联监视
                            //addMonitoredItems.ToList().ForEach(a => a.Notification += OnMonitoredNotification);
                            foreach (var monitoredItem in addMonitoredItems)
                            {
                                monitoredItem.Notification += OnMonitoredNotification;
                            }
                            //OnLogHappened?.Invoke(this, new OpcUaLogEventArgs($"{ToString()},要增加的点数:{addMonitoredItems.Count() } "));
                            OnLogHappened?.BeginInvoke(this, new OpcUaLogEventArgs($"{ToString()},要增加的点数:{addMonitoredItems.Count() } "), new AsyncCallback((ia) =>
                            {
                                if (ia.IsCompleted)
                                {
                                    OnLogHappened.EndInvoke(ia);
                                }
                            }), null);

                            subscription.AddItems(addMonitoredItems);
                            //OnLogHappened?.Invoke(this, new OpcUaLogEventArgs($"{ToString()},已经增加的点数:{addMonitoredItems.Count() } "));
                            OnLogHappened?.BeginInvoke(this, new OpcUaLogEventArgs($"{ToString()},已经增加的点数:{addMonitoredItems.Count() } "), new AsyncCallback((ia) =>
                            {
                                if (ia.IsCompleted)
                                {
                                    OnLogHappened.EndInvoke(ia);
                                }
                            }), null);
                            //subscription.Create();
                            subscription.ApplyChanges();
                            #endregion 增加订阅
                        }
                    }//endforeach

                    //删除订阅项后没有item了,那么删除订阅subscription
                    for (int i = session.Subscriptions.Count() - 1; i >= 0; i--)
                    {
                        var subscription = session.Subscriptions.ElementAt(i);
                        OnLogHappened?.Invoke(this, new OpcUaLogEventArgs($"{ToString()},Subscription:{subscription.DisplayName},MonitoredItemCount:{subscription.MonitoredItemCount}"));

                        if (subscription.MonitoredItemCount < 1)
                        {
                            subscription.Delete(false);
                            session.RemoveSubscription(subscription);
                            OnLogHappened?.Invoke(this, new OpcUaLogEventArgs($"{ToString()},Subscription:{subscription.DisplayName},MonitoredItemCount:{subscription.MonitoredItemCount}"));
                        }
                        //订阅组组减少时,需要删除组内的监视项,释放Notification,删除,订阅项
                        if (!OpcUaNodeGroups.Any(a => a.UpdateRate.ToString() == subscription.DisplayName))
                        {
                            if (subscription.MonitoredItemCount > 0)
                            {
                                foreach (var monitoredItem in subscription.MonitoredItems)
                                {
                                    monitoredItem.Notification -= OnMonitoredNotification;
                                }
                                OnLogHappened?.Invoke(this, new OpcUaLogEventArgs($"{ToString()},删除的点数:{subscription.MonitoredItems.Count() }"));
                                subscription.RemoveItems(subscription.MonitoredItems);
                            }
                            subscription.Delete(false);
                            session.RemoveSubscription(subscription);
                        }
                    }

                    foreach (var subs in session.Subscriptions)
                    {
                        StringBuilder stringBuilder = new StringBuilder();

                        var badCount = 0;
                        foreach (var v in subs.MonitoredItems)
                        {
                            if (!Equals(v.Status.Error, null) && v.Status.Error.StatusCode.Code != StatusCodes.Good)
                            {
                                stringBuilder.Append("点名:");
                                stringBuilder.Append(v?.StartNodeId?.ToString());
                                stringBuilder.Append(",状态:");
                                stringBuilder.Append(v?.Status?.Error?.StatusCode.ToString());
                                stringBuilder.AppendLine();
                                badCount = badCount + 1;
                            }
                        }
                        int tolal = subs.MonitoredItems.Count();
                        OnLogHappened?.
                        Invoke(this, new OpcUaLogEventArgs($"{ToString()},订阅组名:{subs.DisplayName},节点质量统计(Good/NotGood/Total):{tolal - badCount}/{badCount}/{tolal}{System.Environment.NewLine}{stringBuilder.ToString()}"));
                    }
                    opcUaStatusCodes = OpcUaStatusCodes.Good;
                }
                catch (ServiceResultException e)
                {
                    OnErrorHappened?.Invoke(this, new OpcUaErrorEventArgs((OpcUaStatusCodes)e.StatusCode, $"{ToString()},订阅数据时错误", e));
                    opcUaStatusCodes = OpcUaStatusCodes.BadServerHalted;
                }
                catch (Exception ex)
                {
                    OnErrorHappened?.Invoke(this, new OpcUaErrorEventArgs(OpcUaStatusCodes.Uncertain, $"{ToString()},订阅数据时发生未知错误", ex));
                    opcUaStatusCodes = OpcUaStatusCodes.Uncertain;
                }
                finally
                {
                    daemonTimer.Enabled = true;
                    daemonTimer.Start();
                }
                return opcUaStatusCodes;
            }));
        }