/// <summary> /// Validates the operand (sets the ParsedBrowsePath and ParsedIndexRange properties). /// </summary> public override ServiceResult Validate(FilterContext context, int index) { m_validated = false; // verify attribute id. if (!Attributes.IsValid(m_attributeId)) { return(ServiceResult.Create( StatusCodes.BadAttributeIdInvalid, "SimpleAttributeOperand does not specify a valid AttributeId ({0}).", m_attributeId)); } // initialize as empty. m_parsedIndexRange = NumericRange.Empty; // parse the index range. if (!String.IsNullOrEmpty(m_indexRange)) { try { m_parsedIndexRange = NumericRange.Parse(m_indexRange); } catch (Exception e) { return(ServiceResult.Create( e, StatusCodes.BadIndexRangeInvalid, "SimpleAttributeOperand does not specify a valid BrowsePath ({0}).", m_indexRange)); } if (m_attributeId != Attributes.Value) { return(ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "SimpleAttributeOperand specifies an IndexRange for an Attribute other than Value ({0}).", m_attributeId)); } } m_validated = true; return(ServiceResult.Good); }
/// <summary> /// Validates a read value id parameter. /// </summary> public static ServiceResult Validate(HistoryReadValueId valueId) { // check for null structure. if (valueId == null) { return(StatusCodes.BadStructureMissing); } // null node ids are always invalid. if (NodeId.IsNull(valueId.NodeId)) { return(StatusCodes.BadNodeIdInvalid); } // initialize as empty. valueId.ParsedIndexRange = NumericRange.Empty; // parse the index range if specified. if (!String.IsNullOrEmpty(valueId.IndexRange)) { try { valueId.ParsedIndexRange = NumericRange.Parse(valueId.IndexRange); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadIndexRangeInvalid, String.Empty)); } } else { valueId.ParsedIndexRange = NumericRange.Empty; } // passed basic validation. return(null); }
/// <summary> /// Handles a write operation for an individual tag. /// </summary> public ServiceResult WriteTagValue( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { MemoryTagState tag = node as MemoryTagState; if (tag == null) { return StatusCodes.BadNodeIdUnknown; } if (NumericRange.Empty != indexRange) { return StatusCodes.BadIndexRangeInvalid; } if (!QualifiedName.IsNull(dataEncoding)) { return StatusCodes.BadDataEncodingInvalid; } if (statusCode != StatusCodes.Good) { return StatusCodes.BadWriteNotSupported; } if (timestamp != DateTime.MinValue) { return StatusCodes.BadWriteNotSupported; } bool changed = false; int offset = (int)tag.Offset; lock (m_dataLock) { if (offset < 0 || offset >= m_buffer.Length) { return StatusCodes.BadNodeIdUnknown; } if (m_buffer == null) { return StatusCodes.BadOutOfService; } byte[] bytes = null; switch (m_elementType) { case BuiltInType.UInt32: { uint? valueToWrite = value as uint?; if (valueToWrite == null) { return StatusCodes.BadTypeMismatch; } bytes = BitConverter.GetBytes(valueToWrite.Value); break; } case BuiltInType.Double: { double? valueToWrite = value as double?; if (valueToWrite == null) { return StatusCodes.BadTypeMismatch; } bytes = BitConverter.GetBytes(valueToWrite.Value); break; } default: { return StatusCodes.BadNodeIdUnknown; } } for (int ii = 0; ii < bytes.Length; ii++) { if (!changed) { if (m_buffer[offset + ii] != bytes[ii]) { changed = true; } } m_buffer[offset + ii] = bytes[ii]; } } if (changed) { OnBufferChanged(offset); } return ServiceResult.Good; }
public ServiceResult OnChangeLockByWrite( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { DsatsDemo.LockConditionState condition = null; BaseInstanceState instance = node as BaseInstanceState; if (instance.Parent != null) { condition = instance.Parent as DsatsDemo.LockConditionState; } if (condition == null) { return StatusCodes.BadNotWritable; } string lockState = value as string; if (lockState == null) { return StatusCodes.BadTypeMismatch; } if (lockState == "Locked") { ServiceResult result = OnRequestLock(context, condition.Request, condition.NodeId, new object[0], new object[0]); value = condition.LockStateAsString.Value; return result; } else if (lockState == "Unlocked") { ServiceResult result = OnReleaseLock(context, condition.Request, condition.NodeId, new object[0], new object[0]); value = condition.LockStateAsString.Value; return result; } return StatusCodes.BadTypeMismatch; }
/// <summary> /// Handles the read operation for an invidual tag. /// </summary> public ServiceResult ReadTagValue( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { MemoryTagState tag = node as MemoryTagState; if (tag == null) { return StatusCodes.BadNodeIdUnknown; } if (NumericRange.Empty != indexRange) { return StatusCodes.BadIndexRangeInvalid; } if (!QualifiedName.IsNull(dataEncoding)) { return StatusCodes.BadDataEncodingInvalid; } int offset = (int)tag.Offset; lock (m_dataLock) { if (offset < 0 || offset >= m_buffer.Length) { return StatusCodes.BadNodeIdUnknown; } if (m_buffer == null) { return StatusCodes.BadOutOfService; } value = GetValueAtOffset(offset).Value; } statusCode = StatusCodes.Good; timestamp = m_lastScanTime; return ServiceResult.Good; }
/// <summary> /// Generates a new value each time the value is read. /// </summary> private ServiceResult DoDeviceRead( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { BaseVariableState variable = node as BaseVariableState; if (variable == null) { return ServiceResult.Good; } if (!SimulationActive.Value) { return ServiceResult.Good; } TestDataSystem system = context.SystemHandle as TestDataSystem; if (system == null) { return StatusCodes.BadOutOfService; } try { value = system.ReadValue(variable); statusCode = StatusCodes.Good; timestamp = DateTime.UtcNow; ServiceResult error = BaseVariableState.ApplyIndexRangeAndDataEncoding( context, indexRange, dataEncoding, ref value); if (ServiceResult.IsBad(error)) { statusCode = error.StatusCode; } return ServiceResult.Good; } catch (Exception e) { return new ServiceResult(e); } }
private ServiceResult OnChangePhaseByWrite( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { string phase = value as string; if (phase == null) { return StatusCodes.BadTypeMismatch; } List<IReference> references = new List<IReference>(); m_rig.Phases.GetReferences(context, references, Opc.Ua.ReferenceTypeIds.Organizes, false); foreach (IReference reference in references) { if (reference.TargetId.ToString().Contains(phase)) { return OnChangePhase(context, m_rig.ChangePhase, m_rig.NodeId, (NodeId)reference.TargetId); } } return StatusCodes.BadTypeMismatch; }
private ServiceResult OnWriteAnalog( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { AnalogItemState variable = node as AnalogItemState; // verify data type. Opc.Ua.TypeInfo typeInfo = Opc.Ua.TypeInfo.IsInstanceOfDataType( value, variable.DataType, variable.ValueRank, context.NamespaceUris, context.TypeTable); if (typeInfo == null || typeInfo == Opc.Ua.TypeInfo.Unknown) { return StatusCodes.BadTypeMismatch; } // check index range. if (variable.ValueRank >= 0) { if (indexRange != NumericRange.Empty) { object target = variable.Value; ServiceResult result = indexRange.UpdateRange(ref target, value); if (ServiceResult.IsBad(result)) { return result; } value = target; } } // check instrument range. else { if (indexRange != NumericRange.Empty) { return StatusCodes.BadIndexRangeInvalid; } double number = Convert.ToDouble(value); if (variable.InstrumentRange != null && (number < variable.InstrumentRange.Value.Low || number > variable.InstrumentRange.Value.High)) { return StatusCodes.BadOutOfRange; } } return ServiceResult.Good; }
/// <summary> /// Write the value for the value attribute. /// </summary> protected override ServiceResult WriteValueAttribute( ISystemContext context, NumericRange indexRange, object value, StatusCode statusCode, DateTime sourceTimestamp) { ServiceResult result = null; if ((WriteMask & AttributeWriteMask.ValueForVariableType) == 0) { return StatusCodes.BadNotWritable; } // ensure the source timestamp has a valid value. if (sourceTimestamp == DateTime.MinValue) { sourceTimestamp = DateTime.UtcNow; } // index range writes not supported. if (indexRange != NumericRange.Empty) { return StatusCodes.BadIndexRangeInvalid; } // verify data type. TypeInfo typeInfo = TypeInfo.IsInstanceOfDataType( value, m_dataType, m_valueRank, context.NamespaceUris, context.TypeTable); if (typeInfo == null || typeInfo == TypeInfo.Unknown) { return StatusCodes.BadTypeMismatch; } // check for simple write value handler. if (OnSimpleWriteValue != null) { result = OnSimpleWriteValue( context, this, ref value); if (ServiceResult.IsBad(result)) { return result; } } // update cached values. Value = value; return ServiceResult.Good; }
/// <summary> /// Parses a string representing a numeric range. /// </summary> /// <param name="textToParse">The text to parse, prior to checking it is within the allowed range</param> /// <param name="range">The parsed range.</param> /// <returns>The reason for any error.</returns> public static ServiceResult Validate(string textToParse, out NumericRange range) { range = NumericRange.Empty; if (String.IsNullOrEmpty(textToParse)) { return(ServiceResult.Good); } // check for multidimensional ranges. int index = textToParse.IndexOf(','); if (index >= 0) { int start = 0; List <NumericRange> subranges = new List <NumericRange>(); for (int ii = 0; ii < textToParse.Length; ii++) { char ch = textToParse[ii]; if (ch == ',' || ii == textToParse.Length - 1) { NumericRange subrange = new NumericRange(); string subtext = (ch == ',') ? textToParse.Substring(start, ii - start) : textToParse.Substring(start); ServiceResult result = Validate(subtext, out subrange); if (ServiceResult.IsBad(result)) { return(result); } subranges.Add(subrange); start = ii + 1; } } // must have at least two entries. if (subranges.Count < 2) { return(StatusCodes.BadIndexRangeInvalid); } range.m_begin = subranges[0].Begin; range.m_end = subranges[0].End; range.m_subranges = subranges.ToArray(); return(ServiceResult.Good); } try { index = textToParse.IndexOf(':'); if (index != -1) { range.Begin = Convert.ToInt32(textToParse.Substring(0, index), CultureInfo.InvariantCulture); range.End = Convert.ToInt32(textToParse.Substring(index + 1), CultureInfo.InvariantCulture); if (range.End < 0) { return(ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "NumericRange does not have a valid end index ({0}).", range.End)); } if (range.Begin >= range.End) { return(ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "NumericRange does not have a start index that is less than the end index ({0}).", range)); } } else { range.Begin = Convert.ToInt32(textToParse, CultureInfo.InvariantCulture); range.End = -1; } if (range.Begin < 0) { return(ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "NumericRange does not have a valid start index ({0}).", range.Begin)); } } catch (Exception e) { return(ServiceResult.Create( e, StatusCodes.BadIndexRangeInvalid, "NumericRange cannot be parsed ({0}).", textToParse)); } return(ServiceResult.Good); }
/// <summary> /// Validates a write value parameter. /// </summary> public static ServiceResult Validate(WriteValue value) { // check for null structure. if (value == null) { return(StatusCodes.BadStructureMissing); } // null node ids are always invalid. if (value.NodeId == null) { return(StatusCodes.BadNodeIdInvalid); } // must be a legimate attribute value. if (!Attributes.IsValid(value.AttributeId)) { return(StatusCodes.BadAttributeIdInvalid); } // initialize as empty. value.ParsedIndexRange = NumericRange.Empty; // parse the index range if specified. if (!String.IsNullOrEmpty(value.IndexRange)) { try { value.ParsedIndexRange = NumericRange.Parse(value.IndexRange); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadIndexRangeInvalid, String.Empty)); } if (value.ParsedIndexRange.SubRanges != null) { Matrix matrix = value.Value.Value as Matrix; if (matrix == null) { // Check for String or ByteString arrays. Those DataTypes have special handling // when using sub ranges. bool isArrayWithValidDataType = value.Value.Value is Array && value.Value.WrappedValue.TypeInfo.BuiltInType == BuiltInType.String || value.Value.WrappedValue.TypeInfo.BuiltInType == BuiltInType.ByteString; if (!isArrayWithValidDataType) { return(StatusCodes.BadTypeMismatch); } } } else { // check that value provided is actually an array. Array array = value.Value.Value as Array; string str = value.Value.Value as string; if (array != null) { NumericRange range = value.ParsedIndexRange; // check that the number of elements to write matches the index range. if (range.End >= 0 && (range.End - range.Begin != array.Length - 1)) { return(StatusCodes.BadIndexRangeNoData); } // check for single element. if (range.End < 0 && array.Length != 1) { return(StatusCodes.BadIndexRangeInvalid); } } else if (str != null) { NumericRange range = value.ParsedIndexRange; // check that the number of elements to write matches the index range. if (range.End >= 0 && (range.End - range.Begin != str.Length - 1)) { return(StatusCodes.BadIndexRangeNoData); } // check for single element. if (range.End < 0 && str.Length != 1) { return(StatusCodes.BadIndexRangeInvalid); } } else { return(StatusCodes.BadTypeMismatch); } } } else { value.ParsedIndexRange = NumericRange.Empty; } // passed basic validation. return(null); }
/// <summary> /// Continues a read raw operation. /// </summary> /// <param name="context">The context for the operation.</param> /// <param name="timestampsToReturn">The timestamps to return with the value.</param> /// <param name="indexRange">The range to return for array values.</param> /// <param name="dataEncoding">The data encoding to use for structured values.</param> /// <param name="values">The values to return.</param> /// <returns>False if the operation halted because the maximum number of values was discovered.</returns> public bool NextReadRaw( ServerSystemContext context, TimestampsToReturn timestampsToReturn, NumericRange indexRange, QualifiedName dataEncoding, DataValueCollection values) { DataValue value = null; do { // check for limit. if (m_request.NumValuesPerNode > 0 && values.Count >= m_request.NumValuesPerNode) { return false; } value = m_source.NextRaw(m_lastTime, m_isForward, m_request.IsReadModified, ref m_position); // no more data. if (value == null) { return true; } // check for bound. if ((m_isForward && value.ServerTimestamp >= m_endTime) || (!m_isForward && value.ServerTimestamp <= m_endTime)) { if (m_request.ReturnBounds) { AddValue(timestampsToReturn, indexRange, dataEncoding, values, value); return true; } } // add value. AddValue(timestampsToReturn, indexRange, dataEncoding, values, value); } while (value != null); return true; }
/// <summary> /// Adds a DataValue to a list of values to return. /// </summary> private void AddValue( TimestampsToReturn timestampsToReturn, NumericRange indexRange, QualifiedName dataEncoding, DataValueCollection values, DataValue value) { // ignore invalid case. if (value == null) { return; } // save the last timestamp returned. m_lastTime = value.ServerTimestamp; // check if the index range or data encoding can be applied. if (StatusCode.IsGood(value.StatusCode)) { object valueToReturn = value.Value; // apply the index range. if (indexRange != NumericRange.Empty) { StatusCode error = indexRange.ApplyRange(ref valueToReturn); if (StatusCode.IsBad(error)) { value.Value = null; value.StatusCode = error; } else { value.Value = valueToReturn; } } // apply the data encoding. if (!QualifiedName.IsNull(dataEncoding)) { value.Value = null; value.StatusCode = StatusCodes.BadDataEncodingUnsupported; } } // apply the timestamps filter. if (timestampsToReturn == TimestampsToReturn.Neither || timestampsToReturn == TimestampsToReturn.Server) { value.SourceTimestamp = DateTime.MinValue; } if (timestampsToReturn == TimestampsToReturn.Neither || timestampsToReturn == TimestampsToReturn.Source) { value.ServerTimestamp = DateTime.MinValue; } // add result. values.Add(value); }
/// <summary> /// Starts reading raw values. /// </summary> /// <param name="context">The context for the operation.</param> /// <param name="request">The request parameters.</param> /// <param name="timestampsToReturn">The timestamps to return with the value.</param> /// <param name="indexRange">The range to return for array values.</param> /// <param name="dataEncoding">The data encoding to use for structured values.</param> /// <param name="values">The values to return.</param> public void BeginReadRaw( ServerSystemContext context, ReadRawModifiedDetails request, TimestampsToReturn timestampsToReturn, NumericRange indexRange, QualifiedName dataEncoding, DataValueCollection values) { m_request = request; // initialize start and end. m_startTime = m_request.StartTime; m_endTime = m_request.EndTime; if (m_endTime == DateTime.MinValue) { m_endTime = DateTime.MaxValue; } // check the direction. m_isForward = m_startTime < m_endTime; m_position = -1; DataValue value = null; // get first bound. if (m_request.ReturnBounds) { value = m_source.FirstRaw(m_startTime, !m_isForward, m_request.IsReadModified, out m_position); if (value != null) { AddValue(timestampsToReturn, indexRange, dataEncoding, values, value); } } }
/// <summary> /// Parses a string representing a numeric range. /// </summary> /// <param name="textToParse">The text to parse, prior to checking it is within the allowed range</param> /// <param name="range">The parsed range.</param> /// <returns>The reason for any error.</returns> public static ServiceResult Validate(string textToParse, out NumericRange range) { range = NumericRange.Empty; if (String.IsNullOrEmpty(textToParse)) { return ServiceResult.Good; } // check for multidimensional ranges. int index = textToParse.IndexOf(','); if (index >= 0) { int start = 0; List<NumericRange> subranges = new List<NumericRange>(); for (int ii = 0; ii < textToParse.Length; ii++) { char ch = textToParse[ii]; if (ch == ',' || ii == textToParse.Length-1) { NumericRange subrange = new NumericRange(); string subtext = (ch == ',') ? textToParse.Substring(start, ii - start) : textToParse.Substring(start); ServiceResult result = Validate(subtext, out subrange); if (ServiceResult.IsBad(result)) { return result; } subranges.Add(subrange); start = ii+1; } } // must have at least two entries. if (subranges.Count < 2) { return StatusCodes.BadIndexRangeInvalid; } range.m_begin = subranges[0].Begin; range.m_end = subranges[0].End; range.m_subranges = subranges.ToArray(); return ServiceResult.Good; } try { index = textToParse.IndexOf(':'); if (index != -1) { range.Begin = Convert.ToInt32(textToParse.Substring(0, index), CultureInfo.InvariantCulture); range.End = Convert.ToInt32(textToParse.Substring(index + 1), CultureInfo.InvariantCulture); if (range.End < 0) { return ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "NumericRange does not have a valid end index ({0}).", range.End); } if (range.Begin >= range.End) { return ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "NumericRange does not have a start index that is less than the end index ({0}).", range); } } else { range.Begin = Convert.ToInt32(textToParse, CultureInfo.InvariantCulture); range.End = -1; } if (range.Begin < 0) { return ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "NumericRange does not have a valid start index ({0}).", range.Begin); } } catch (Exception e) { return ServiceResult.Create( e, StatusCodes.BadIndexRangeInvalid, "NumericRange cannot be parsed ({0}).", textToParse); } return ServiceResult.Good; }
/// <summary> /// Returns the value of the attribute for the specified child. /// </summary> /// <param name="context">The context to use when evaluating the operand.</param> /// <param name="typeDefinitionId">The type of the instance.</param> /// <param name="relativePath">The path from the instance to the node which defines the attribute.</param> /// <param name="attributeId">The attribute to return.</param> /// <param name="indexRange">The sub-set of an array value to return.</param> /// <returns> /// The attribute value. Returns null if the attribute does not exist. /// </returns> public object GetAttributeValue( FilterContext context, NodeId typeDefinitionId, IList<QualifiedName> relativePath, uint attributeId, NumericRange indexRange) { if (!NodeId.IsNull(typeDefinitionId)) { if (!context.TypeTree.IsTypeOf(m_typeDefinitionId, typeDefinitionId)) { return null; } } object value = GetAttributeValue( m_snapshot, relativePath, 0, attributeId); if (indexRange != NumericRange.Empty) { StatusCode error = indexRange.ApplyRange(ref value); if (StatusCode.IsBad(error)) { value = null; } } return value; }
/// <summary cref="IFilterTarget.GetAttributeValue" /> public virtual object GetAttributeValue( FilterContext context, NodeId typeDefinitionId, IList<QualifiedName> relativePath, uint attributeId, NumericRange indexRange) { // check the type definition. if (!NodeId.IsNull(typeDefinitionId) && typeDefinitionId != ObjectTypes.BaseEventType) { if (!context.TypeTree.IsTypeOf(TypeDefinitionId, typeDefinitionId)) { return null; } } // read the child attribute. DataValue dataValue = new DataValue(); ServiceResult result = ReadChildAttribute( null, relativePath, 0, attributeId, dataValue); if (ServiceResult.IsBad(result)) { return null; } // apply any index range. object value = dataValue.Value; if (value != null) { result = indexRange.ApplyRange(ref value); if (ServiceResult.IsBad(result)) { return null; } } // return the result. return value; }
private ServiceResult OnWriteDataItem( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { DataItemState variable = node as DataItemState; // verify data type. Opc.Ua.TypeInfo typeInfo = Opc.Ua.TypeInfo.IsInstanceOfDataType( value, variable.DataType, variable.ValueRank, context.NamespaceUris, context.TypeTable); if (typeInfo == null || typeInfo == Opc.Ua.TypeInfo.Unknown) { return StatusCodes.BadTypeMismatch; } if (typeInfo.BuiltInType != BuiltInType.DateTime) { double number = Convert.ToDouble(value); number = Math.Round(number, (int)variable.ValuePrecision.Value); value = Opc.Ua.TypeInfo.Cast(number, typeInfo.BuiltInType); } return ServiceResult.Good; }
/// <summary> /// Reads the value for the value attribute. /// </summary> protected override ServiceResult ReadValueAttribute( ISystemContext context, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref DateTime sourceTimestamp) { value = m_value; ServiceResult result = ServiceResult.Good; VariableCopyPolicy copyPolicy = VariableCopyPolicy.CopyOnRead; // use default behavoir. if (OnSimpleReadValue != null) { result = OnSimpleReadValue( context, this, ref value); if (ServiceResult.IsBad(result)) { return result; } copyPolicy = VariableCopyPolicy.Never; } else { // check if a valid value exists. if (value == null) { return StatusCodes.BadAttributeIdInvalid; } } // apply the index range and encoding. result = BaseVariableState.ApplyIndexRangeAndDataEncoding(context, indexRange, dataEncoding, ref value); if (ServiceResult.IsBad(result)) { return result; } // copy returned value. if (copyPolicy == VariableCopyPolicy.CopyOnRead) { value = Utils.Clone(value); } return result; }
private ServiceResult OnWriteDiscrete( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { MultiStateDiscreteState variable = node as MultiStateDiscreteState; // verify data type. Opc.Ua.TypeInfo typeInfo = Opc.Ua.TypeInfo.IsInstanceOfDataType( value, variable.DataType, variable.ValueRank, context.NamespaceUris, context.TypeTable); if (typeInfo == null || typeInfo == Opc.Ua.TypeInfo.Unknown) { return StatusCodes.BadTypeMismatch; } if (indexRange != NumericRange.Empty) { return StatusCodes.BadIndexRangeInvalid; } double number = Convert.ToDouble(value); if (number >= variable.EnumStrings.Value.Length | number < 0) { return StatusCodes.BadOutOfRange; } return ServiceResult.Good; }
/// <summary> /// Validates a write value parameter. /// </summary> public static ServiceResult Validate(WriteValue value) { // check for null structure. if (value == null) { return(StatusCodes.BadStructureMissing); } // null node ids are always invalid. if (value.NodeId == null) { return(StatusCodes.BadNodeIdInvalid); } // must be a legimate attribute value. if (!Attributes.IsValid(value.AttributeId)) { return(StatusCodes.BadAttributeIdInvalid); } // initialize as empty. value.ParsedIndexRange = NumericRange.Empty; // parse the index range if specified. if (!String.IsNullOrEmpty(value.IndexRange)) { try { value.ParsedIndexRange = NumericRange.Parse(value.IndexRange); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadIndexRangeInvalid, String.Empty)); } // check that value provided is actually an array. Array array = value.Value.Value as Array; if (array == null) { return(StatusCodes.BadTypeMismatch); } NumericRange range = value.ParsedIndexRange; // check that the number of elements to write matches the index range. if (range.End >= 0 && (range.End - range.Begin != array.Length - 1)) { return(StatusCodes.BadIndexRangeNoData); } // check for single element. if (range.End < 0 && array.Length != 1) { return(StatusCodes.BadIndexRangeInvalid); } } else { value.ParsedIndexRange = NumericRange.Empty; } // passed basic validation. return(null); }
/// <summary> /// Extracts and queues any processed values. /// </summary> private void QueueProcessedValues( ServerSystemContext context, IAggregateCalculator calculator, NumericRange indexRange, QualifiedName dataEncoding, bool applyIndexRangeOrEncoding, bool returnPartial, LinkedList<DataValue> values) { DataValue proccessedValue = calculator.GetProcessedValue(returnPartial); while (proccessedValue != null) { // apply any index range or encoding. if (applyIndexRangeOrEncoding) { object rawValue = proccessedValue.Value; ServiceResult result = BaseVariableState.ApplyIndexRangeAndDataEncoding(context, indexRange, dataEncoding, ref rawValue); if (ServiceResult.IsBad(result)) { proccessedValue.Value = rawValue; } else { proccessedValue.Value = null; proccessedValue.StatusCode = result.StatusCode; } } // queue the result. values.AddLast(proccessedValue); proccessedValue = calculator.GetProcessedValue(returnPartial); } }