/// <summary> /// Validates the nodes and writes the value to the underlying system. /// </summary> /// <param name="context">The context.</param> /// <param name="nodesToWrite">The nodes to write.</param> /// <param name="errors">The errors.</param> /// <param name="nodesToValidate">The nodes to validate.</param> /// <param name="cache">The cache.</param> protected override void Write( ServerSystemContext context, IList <WriteValue> nodesToWrite, IList <ServiceResult> errors, List <NodeHandle> nodesToValidate, IDictionary <NodeId, NodeState> cache) { ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; ComDaClient client = system.SelectClient((ServerSystemContext)SystemContext, false); WriteRequestCollection requests = new WriteRequestCollection(); // validates the nodes and queues an write requests. for (int ii = 0; ii < nodesToValidate.Count; ii++) { NodeHandle handle = nodesToValidate[ii]; lock (Lock) { // validate node. NodeState source = ValidateNode(context, handle, cache); if (source == null) { continue; } // determine if request can be sent to the server. bool queued = false; WriteValue nodeToWrite = nodesToWrite[handle.Index]; errors[handle.Index] = requests.Add(source, nodeToWrite, handle.Index, out queued); if (queued) { continue; } // write the attribute value. errors[handle.Index] = source.WriteAttribute( context, nodeToWrite.AttributeId, nodeToWrite.ParsedIndexRange, nodeToWrite.Value); // updates to source finished - report changes to monitored items. source.ClearChangeMasks(context, false); } } // write to the server. client.Write(requests); // get the results from the requests sent to the server. for (int ii = 0; ii < requests.Count; ii++) { WriteRequest request = requests[ii]; errors[request.Index] = request.GetResult(); } }
private ServiceResult OnWriteValueDiscrete( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { MultiStateValueDiscreteState variable = node as MultiStateValueDiscreteState; TypeInfo typeInfo = TypeInfo.Construct(value); if (variable == null || typeInfo == null || typeInfo == Opc.Ua.TypeInfo.Unknown || !TypeInfo.IsNumericType(typeInfo.BuiltInType)) { return(StatusCodes.BadTypeMismatch); } if (indexRange != NumericRange.Empty) { return(StatusCodes.BadIndexRangeInvalid); } Int32 number = Convert.ToInt32(value); if (number >= variable.EnumValues.Value.Length || number < 0) { return(StatusCodes.BadOutOfRange); } if (!node.SetChildValue(context, BrowseNames.ValueAsText, variable.EnumValues.Value[number].DisplayName, true)) { return(StatusCodes.BadOutOfRange); } node.ClearChangeMasks(context, true); return(ServiceResult.Good); }
/// <summary> /// Recursively indexes the node and its children. /// </summary> protected virtual void RemovePredefinedNode( ISystemContext context, NodeState node, List<LocalReference> referencesToRemove) { m_predefinedNodes.Remove(node.NodeId); node.UpdateChangeMasks(NodeStateChangeMasks.Deleted); node.ClearChangeMasks(context, false); OnNodeRemoved(node); // remove from the parent. BaseInstanceState instance = node as BaseInstanceState; if (instance != null && instance.Parent != null) { instance.Parent.RemoveChild(instance); } // remove children. List<BaseInstanceState> children = new List<BaseInstanceState>(); node.GetChildren(context, children); for (int ii = 0; ii < children.Count; ii++) { node.RemoveChild(children[ii]); } for (int ii = 0; ii < children.Count; ii++) { RemovePredefinedNode(context, children[ii], referencesToRemove); } // remove from type table. BaseTypeState type = node as BaseTypeState; if (type != null) { m_server.TypeTree.Remove(type.NodeId); } // remove inverse references. List<IReference> references = new List<IReference>(); node.GetReferences(context, references); for (int ii = 0; ii < references.Count; ii++) { IReference reference = references[ii]; if (reference.TargetId.IsAbsolute) { continue; } LocalReference referenceToRemove = new LocalReference( (NodeId)reference.TargetId, reference.ReferenceTypeId, reference.IsInverse, node.NodeId); referencesToRemove.Add(referenceToRemove); } }
/// <summary> /// Handles a write operation. /// </summary> protected override void Write( ServerSystemContext context, IList <WriteValue> nodesToWrite, IList <ServiceResult> errors, List <NodeHandle> nodesToValidate, IDictionary <NodeId, NodeState> cache) { List <ReadWriteRequest> requests = new List <ReadWriteRequest>(); // validates the nodes and constructs requests for external nodes. for (int ii = 0; ii < nodesToValidate.Count; ii++) { WriteValue nodeToWrite = nodesToWrite[ii]; NodeHandle handle = nodesToValidate[ii]; lock (Lock) { // validate node. NodeState source = ValidateNode(context, handle, cache); if (source == null) { continue; } // determine if an external source is required. if (IsExternalSource(handle, nodeToWrite.AttributeId)) { errors[handle.Index] = AddWriteRequest(context, handle, nodeToWrite, requests); continue; } // write the attribute value. errors[handle.Index] = source.WriteAttribute( context, nodeToWrite.AttributeId, nodeToWrite.ParsedIndexRange, nodeToWrite.Value); // updates to source finished - report changes to monitored items. source.ClearChangeMasks(context, false); } } // send request to external system. try { ProcessWriteRequests(requests); } catch (Exception e) { // handle unexpected communication error. ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system."); for (int ii = 0; ii < requests.Count; ii++) { requests[ii].Result = error; } } // set results. for (int ii = 0; ii < requests.Count; ii++) { ReadWriteRequest request = requests[ii]; errors[request.Handle.Index] = request.Result; } }