/// <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); } }