Esempio n. 1
0
        /// <summary>
        /// Tells the node manager to refresh any conditions associated with the specified monitored items.
        /// </summary>
        /// <remarks>
        /// This method is called when the condition refresh method is called for a subscription.
        /// The node manager must create a refresh event for each condition monitored by the subscription.
        /// </remarks>
        public override ServiceResult ConditionRefresh(
            OperationContext context,
            IList <IEventMonitoredItem> monitoredItems)
        {
            ServerSystemContext serverSystemContext = SystemContext.Copy(context);

            foreach (MonitoredItem monitoredItem in monitoredItems)
            {
                if (monitoredItem == null)
                {
                    continue;
                }

                List <IFilterTarget> events         = new List <IFilterTarget>();
                List <NodeState>     nodesToRefresh = new List <NodeState>();

                lock (Lock)
                {
                    // check for server subscription.
                    if (monitoredItem.NodeId == ObjectIds.Server)
                    {
                        if (_rootNotifiers != null)
                        {
                            nodesToRefresh.AddRange(_rootNotifiers);
                        }
                    }
                    else
                    {
                        if (!MonitoredNodes.TryGetValue(monitoredItem.NodeId, out MonitoredNode2 monitoredNode))
                        {
                            continue;
                        }

                        // get the refresh events.
                        nodesToRefresh.Add(monitoredNode.Node);
                    }
                }

                foreach (var node in nodesToRefresh)
                {
                    node.ConditionRefresh(SystemContext, events, true);
                }

                foreach (var @event in events)
                {
                    monitoredItem.QueueEvent(@event);
                }
            }

            return(ServiceResult.Good);
        }
Esempio n. 2
0
        /// <summary>
        /// Subscribes or unsubscribes to events produced by all event sources.
        /// </summary>
        /// <remarks>
        /// This method is called when a event subscription is created or deleted. The node
        /// manager must start/stop reporting events for all objects that it manages.
        /// </remarks>
        public override ServiceResult SubscribeToAllEvents(
            Opc.Ua.Server.OperationContext context,
            uint subscriptionId,
            IEventMonitoredItem monitoredItem,
            bool unsubscribe)
        {
            ServerSystemContext serverSystemContext = SystemContext.Copy(context);

            lock (Lock)
            {
                // A client has subscribed to the Server object which means all events produced
                // by this manager must be reported. This is done by incrementing the monitoring
                // reference count for all root notifiers.
                if (_rootNotifiers != null)
                {
                    for (int ii = 0; ii < _rootNotifiers.Count; ii++)
                    {
                        SubscribeToEvents(serverSystemContext, _rootNotifiers[ii], monitoredItem, unsubscribe);
                    }
                }

                return(ServiceResult.Good);
            }
        }
        /// <summary>
        /// Subscribes or unsubscribes to events produced by all event sources.
        /// </summary>
        /// <remarks>
        /// This method is called when a event subscription is created or deleted. The node
        /// manager must start/stop reporting events for all objects that it manages.
        /// </remarks>
        public override ServiceResult SubscribeToAllEvents(
            OperationContext context,
            uint subscriptionId,
            IEventMonitoredItem monitoredItem,
            bool unsubscribe)
        {
            ServerSystemContext systemContext = SystemContext.Copy(context);
            ComAeClientManager  system        = (ComAeClientManager)this.SystemContext.SystemHandle;
            ComAeClient         client        = (ComAeClient)system.SelectClient(systemContext, false);

            // need to wait until the cache is refreshed for the first time.
            if (!WaitForTypeCache())
            {
                return(StatusCodes.BadOutOfService);
            }

            lock (Lock)
            {
                SubscriptionIndex index = new SubscriptionIndex();
                index.NodeId   = Opc.Ua.ObjectIds.Server;
                index.LocaleId = client.LocaleId;

                if (unsubscribe)
                {
                    ComAeSubscriptionClient subscription = null;

                    if (!m_monitoredItems.TryGetValue(monitoredItem.Id, out subscription))
                    {
                        return(ServiceResult.Good);
                    }

                    m_monitoredItems.Remove(monitoredItem.Id);
                    // Utils.Trace("REMOVED ITEM {0}", monitoredItem.Id);

                    if (subscription.RemoveItem(monitoredItem as MonitoredItem) == 0)
                    {
                        subscription.Delete();
                        m_subscriptions.Remove(index);
                        // Utils.Trace("DELETED SUBSCRIPTION {0}", index.NodeId);
                    }
                }
                else
                {
                    ComAeSubscriptionClient subscription = null;

                    if (!m_subscriptions.TryGetValue(index, out subscription))
                    {
                        subscription = new ComAeSubscriptionClient(systemContext, m_configuration, m_typeCache, NamespaceIndex, system, monitoredItem as MonitoredItem);
                        m_subscriptions.Add(index, subscription);
                        subscription.Create();
                        // Utils.Trace("ADDED NEW SUBSCRIPTION {0}", index.NodeId);
                    }
                    else
                    {
                        subscription.AddItem(monitoredItem as MonitoredItem);
                    }

                    m_monitoredItems[monitoredItem.Id] = subscription;
                    // Utils.Trace("ADDED NEW ITEM {0}", monitoredItem.Id);
                }
            }

            return(ServiceResult.Good);
        }
Esempio n. 4
0
        /// <summary>
        /// Writes the value for the specified attributes.
        /// </summary>
        public override void Write(
            OperationContext context,
            IList <WriteValue> nodesToWrite,
            IList <ServiceResult> errors)
        {
            ServerSystemContext                  systemContext  = SystemContext.Copy(context);
            IDictionary <NodeId, NodeState>      operationCache = new NodeIdDictionary <NodeState>();
            List <DataSourceClient.WriteRequest> writeRequests  = new List <DataSourceClient.WriteRequest>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToWrite.Count; ii++)
                {
                    WriteValue nodeToWrite = nodesToWrite[ii];

                    // skip items that have already been processed.
                    if (nodeToWrite.Processed)
                    {
                        continue;
                    }

                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, nodeToWrite.NodeId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToWrite.Processed = true;

                    // index range is not supported.
                    if (nodeToWrite.AttributeId != Attributes.Value)
                    {
                        if (!String.IsNullOrEmpty(nodeToWrite.IndexRange))
                        {
                            errors[ii] = StatusCodes.BadWriteNotSupported;
                            continue;
                        }
                    }

                    // check if the node is a area in memory.
                    if (handle.Node == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        continue;
                    }

                    // check if the request if for a remote node.
                    RemoteNode remoteNode = null;

                    if (m_remoteNodes.TryGetValue(handle.NodeId, out remoteNode))
                    {
                        // check for theorectical access.
                        BaseVariableState variable = handle.Node as BaseVariableState;

                        if (variable == null || nodeToWrite.AttributeId != Attributes.Value || (variable.AccessLevel & AccessLevels.CurrentWrite) == 0)
                        {
                            errors[ii] = StatusCodes.BadNotWritable;
                            continue;
                        }

                        // check for access based on current user credentials.
                        if (!CheckWriteAccess(systemContext, remoteNode))
                        {
                            errors[ii] = StatusCodes.BadUserAccessDenied;
                            continue;
                        }

                        DataSourceClient.WriteRequest request = new DataSourceClient.WriteRequest();
                        request.RemoteId   = remoteNode.RemoteId;
                        request.WriteValue = nodeToWrite;
                        request.Index      = ii;
                        writeRequests.Add(request);

                        errors[ii] = StatusCodes.BadNoCommunication;
                        continue;
                    }

                    // write the attribute value.
                    errors[ii] = handle.Node.WriteAttribute(
                        systemContext,
                        nodeToWrite.AttributeId,
                        nodeToWrite.ParsedIndexRange,
                        nodeToWrite.Value);

                    // updates to source finished - report changes to monitored items.
                    handle.Node.ClearChangeMasks(systemContext, false);
                }

                // check for nothing to do.
                if (writeRequests.Count == 0)
                {
                    return;
                }
            }

            // update the remote data source.
            List <ServiceResult> results = m_source.Write(writeRequests);

            for (int ii = 0; ii < writeRequests.Count; ii++)
            {
                errors[writeRequests[ii].Index] = results[ii];
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Reads the value for the specified attribute.
        /// </summary>
        public override void Read(
            OperationContext context,
            double maxAge,
            IList <ReadValueId> nodesToRead,
            IList <DataValue> values,
            IList <ServiceResult> errors)
        {
            ServerSystemContext                 systemContext  = SystemContext.Copy(context);
            IDictionary <NodeId, NodeState>     operationCache = new NodeIdDictionary <NodeState>();
            List <DataSourceClient.ReadRequest> readRequests   = new List <DataSourceClient.ReadRequest>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToRead.Count; ii++)
                {
                    ReadValueId nodeToRead = nodesToRead[ii];

                    // skip items that have already been processed.
                    if (nodeToRead.Processed)
                    {
                        continue;
                    }

                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, nodeToRead.NodeId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToRead.Processed = true;

                    // create an initial value.
                    DataValue value = values[ii] = new DataValue();

                    value.Value           = null;
                    value.ServerTimestamp = DateTime.UtcNow;
                    value.SourceTimestamp = DateTime.MinValue;
                    value.StatusCode      = StatusCodes.Good;

                    // check if the node is a area in memory.
                    if (handle.Node == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        continue;
                    }

                    if (nodeToRead.AttributeId == Attributes.Value)
                    {
                        // check if the request if for a remote node.
                        RemoteNode remoteNode = null;

                        if (m_remoteNodes.TryGetValue(handle.NodeId, out remoteNode))
                        {
                            DataSourceClient.ReadRequest request = new DataSourceClient.ReadRequest();
                            request.RemoteId    = remoteNode.RemoteId;
                            request.ReadValueId = nodeToRead;
                            request.Value       = value;
                            request.Index       = ii;
                            readRequests.Add(request);

                            errors[ii] = StatusCodes.BadNoCommunication;
                            continue;
                        }
                    }

                    // read the attribute value.
                    errors[ii] = handle.Node.ReadAttribute(
                        systemContext,
                        nodeToRead.AttributeId,
                        nodeToRead.ParsedIndexRange,
                        nodeToRead.DataEncoding,
                        value);
                }

                // check for nothing to do.
                if (readRequests.Count == 0)
                {
                    return;
                }
            }

            // read from the remote data source.
            List <ServiceResult> results = m_source.Read(readRequests);

            for (int ii = 0; ii < readRequests.Count; ii++)
            {
                values[readRequests[ii].Index] = readRequests[ii].Value;
                errors[readRequests[ii].Index] = results[ii];
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Override ConditionRefresh.
        /// </summary>
        public override ServiceResult ConditionRefresh(
            OperationContext context,
            IList <IEventMonitoredItem> monitoredItems)
        {
            ServerSystemContext systemContext = SystemContext.Copy(context);

            for (int ii = 0; ii < monitoredItems.Count; ii++)
            {
                // the IEventMonitoredItem should always be MonitoredItems since they are created by the MasterNodeManager.
                MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem;

                if (monitoredItem == null)
                {
                    continue;
                }

                List <IFilterTarget> events         = new List <IFilterTarget>();
                List <NodeState>     nodesToRefresh = new List <NodeState>();

                lock (Lock)
                {
                    // check for server subscription.
                    if (monitoredItem.NodeId == ObjectIds.Server)
                    {
                        if (RootNotifiers != null)
                        {
                            nodesToRefresh.AddRange(RootNotifiers);
                        }
                    }
                    else
                    {
                        // check for existing monitored node.
                        MonitoredNode2 monitoredNode = null;

                        if (!MonitoredNodes.TryGetValue(monitoredItem.NodeId, out monitoredNode))
                        {
                            continue;
                        }

                        // get the refresh events.
                        nodesToRefresh.Add(monitoredNode.Node);
                    }
                }

                // block and wait for the refresh.
                for (int jj = 0; jj < nodesToRefresh.Count; jj++)
                {
                    nodesToRefresh[jj].ConditionRefresh(systemContext, events, true);
                }

                lock (Lock)
                {
                    // This is where I can add branch events
                    GetBranchesForConditionRefresh(events);
                }

                // queue the events.
                for (int jj = 0; jj < events.Count; jj++)
                {
                    monitoredItem.QueueEvent(events[jj]);
                }
            }

            // all done.
            return(ServiceResult.Good);
        }
Esempio n. 7
0
        /// <summary>
        /// Calls a method on the specified nodes.
        /// </summary>
        public override void Call(
            OperationContext context,
            IList <CallMethodRequest> methodsToCall,
            IList <CallMethodResult> results,
            IList <ServiceResult> errors)
        {
            ServerSystemContext             systemContext  = SystemContext.Copy(context);
            IDictionary <NodeId, NodeState> operationCache = new NodeIdDictionary <NodeState>();

            bool didRefresh = false;

            for (int ii = 0; ii < methodsToCall.Count; ii++)
            {
                CallMethodRequest methodToCall = methodsToCall[ii];

                bool refreshMethod = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.ConditionType_ConditionRefresh) ||
                                     methodToCall.MethodId.Equals(Opc.Ua.MethodIds.ConditionType_ConditionRefresh2);

                if (refreshMethod)
                {
                    if (didRefresh)
                    {
                        errors[ii]             = StatusCodes.BadRefreshInProgress;
                        methodToCall.Processed = true;
                        continue;
                    }
                    else
                    {
                        didRefresh = true;
                    }
                }

                bool ackMethod        = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.AcknowledgeableConditionType_Acknowledge);
                bool confirmMethod    = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.AcknowledgeableConditionType_Confirm);
                bool commentMethod    = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.ConditionType_AddComment);
                bool ackConfirmMethod = ackMethod || confirmMethod || commentMethod;

                // Need to try to capture any calls to ConditionType::Acknowledge
                if (methodToCall.ObjectId.Equals(Opc.Ua.ObjectTypeIds.ConditionType) && (ackConfirmMethod))
                {
                    // Mantis Issue 6944 which is a duplicate of 5544 - result is Confirm should be Bad_NodeIdInvalid
                    // Override any other errors that may be there, even if this is 'Processed'
                    errors[ii]             = StatusCodes.BadNodeIdInvalid;
                    methodToCall.Processed = true;
                    continue;
                }

                // skip items that have already been processed.
                if (methodToCall.Processed)
                {
                    continue;
                }

                MethodState method = null;

                lock (Lock)
                {
                    // check for valid handle.
                    NodeHandle initialHandle = GetManagerHandle(systemContext, methodToCall.ObjectId, operationCache);

                    if (initialHandle == null)
                    {
                        if (ackConfirmMethod)
                        {
                            // Mantis 6944
                            errors[ii]             = StatusCodes.BadNodeIdUnknown;
                            methodToCall.Processed = true;
                        }

                        continue;
                    }

                    // owned by this node manager.
                    methodToCall.Processed = true;

                    // Look for an alarm branchId to operate on.
                    NodeHandle handle = FindBranchNodeHandle(systemContext, initialHandle, methodToCall);

                    // validate the source node.
                    NodeState source = ValidateNode(systemContext, handle, operationCache);

                    if (source == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        continue;
                    }

                    // find the method.
                    method = source.FindMethod(systemContext, methodToCall.MethodId);

                    if (method == null)
                    {
                        // check for loose coupling.
                        if (source.ReferenceExists(ReferenceTypeIds.HasComponent, false, methodToCall.MethodId))
                        {
                            method = (MethodState)FindPredefinedNode(methodToCall.MethodId, typeof(MethodState));
                        }

                        if (method == null)
                        {
                            errors[ii] = StatusCodes.BadMethodInvalid;
                            continue;
                        }
                    }
                }

                // call the method.
                CallMethodResult result = results[ii] = new CallMethodResult();

                errors[ii] = Call(
                    systemContext,
                    methodToCall,
                    method,
                    result);
            }
        }