Пример #1
0
        /// <summary>
        /// Moves the value towards the target.
        /// </summary>
        private double Adjust(double value, double target, double step, Opc.Ua.Range range)
        {
            // convert percentage step to an absolute step if range is specified.
            if (range != null)
            {
                step = step * range.Magnitude;
            }

            double difference = target - value;

            if (difference < 0)
            {
                value -= step;

                if (value < target)
                {
                    return(target);
                }
            }
            else
            {
                value += step;

                if (value > target)
                {
                    return(target);
                }
            }

            return(value);
        }
Пример #2
0
        /// <summary>
        /// Validates a written value.
        /// </summary>
        public ServiceResult OnWriteAnalogValue(
            ISystemContext context,
            NodeState node,
            ref object value)
        {
            try
            {
                BaseVariableState euRange = node.FindChild(context, Opc.Ua.BrowseNames.EURange) as BaseVariableState;

                if (euRange == null)
                {
                    return(ServiceResult.Good);
                }

                Range range = euRange.Value as Range;

                if (range == null)
                {
                    return(ServiceResult.Good);
                }

                Array array = value as Array;

                if (array != null)
                {
                    for (int ii = 0; ii < array.Length; ii++)
                    {
                        object element = array.GetValue(ii);

                        if (typeof(Variant).IsInstanceOfType(element))
                        {
                            element = ((Variant)element).Value;
                        }

                        double elementNumber = Convert.ToDouble(element);

                        if (elementNumber > range.High || elementNumber < range.Low)
                        {
                            return(StatusCodes.BadOutOfRange);
                        }
                    }

                    return(ServiceResult.Good);
                }

                double number = Convert.ToDouble(value);

                if (number > range.High || number < range.Low)
                {
                    return(StatusCodes.BadOutOfRange);
                }

                return(ServiceResult.Good);
            }
            catch (Exception e)
            {
                throw e;
            }
        }
Пример #3
0
        /// <summary>
        /// Returns the value as a percentage of the range.
        /// </summary>
        private double GetValue(double value, Opc.Ua.Range range)
        {
            if (range != null)
            {
                return(value * range.Magnitude);
            }

            return(value);
        }
Пример #4
0
        private ServiceResult OnWriteAnalogRange(
            ISystemContext context,
            NodeState node,
            NumericRange indexRange,
            QualifiedName dataEncoding,
            ref object value,
            ref StatusCode statusCode,
            ref DateTime timestamp)
        {
            PropertyState <Opc.Ua.Range> variable = node as PropertyState <Opc.Ua.Range>;
            ExtensionObject extensionObject       = value as ExtensionObject;
            TypeInfo        typeInfo = TypeInfo.Construct(value);

            if (variable == null ||
                extensionObject == null ||
                typeInfo == null ||
                typeInfo == Opc.Ua.TypeInfo.Unknown)
            {
                return(StatusCodes.BadTypeMismatch);
            }

            Opc.Ua.Range    newRange = extensionObject.Body as Opc.Ua.Range;
            AnalogItemState parent   = variable.Parent as AnalogItemState;

            if (newRange == null ||
                parent == null)
            {
                return(StatusCodes.BadTypeMismatch);
            }

            if (indexRange != NumericRange.Empty)
            {
                return(StatusCodes.BadIndexRangeInvalid);
            }

            TypeInfo parentTypeInfo = TypeInfo.Construct(parent.Value);

            Opc.Ua.Range parentRange = GetAnalogRange(parentTypeInfo.BuiltInType);
            if (parentRange.High < newRange.High ||
                parentRange.Low > newRange.Low)
            {
                return(StatusCodes.BadOutOfRange);
            }

            value = newRange;

            return(ServiceResult.Good);
        }
Пример #5
0
        /// <summary>
        /// Returns the value as a percentage of the range.
        /// </summary>
        private double GetPercentage(AnalogItemState <double> value)
        {
            double percentage = value.Value;

            Opc.Ua.Range range = value.EURange.Value;

            if (range != null)
            {
                percentage /= Math.Abs(range.High - range.Low);

                if (Math.Abs(percentage) > 1.0)
                {
                    percentage = 1.0;
                }
            }

            return(percentage);
        }
		/// <summary>
		/// Initializes the object with its node type.
		/// </summary>
        public MemoryBufferMonitoredItem(
            IServerInternal     server,
            INodeManager        nodeManager,
            object              mangerHandle,
            uint                offset,
            uint                subscriptionId,
            uint                id,
            Session             session,
            ReadValueId         itemToMonitor,
            DiagnosticsMasks    diagnosticsMasks,
            TimestampsToReturn  timestampsToReturn,
            MonitoringMode      monitoringMode,
            uint                clientHandle,
            MonitoringFilter    originalFilter,
            MonitoringFilter    filterToUse,
            Range               range,
            double              samplingInterval,
            uint                queueSize,
            bool                discardOldest,
            double              minimumSamplingInterval)
        :
            base(
                server,
                nodeManager,
                mangerHandle,
                subscriptionId,
                id,
                session,
                itemToMonitor,
                diagnosticsMasks,
                timestampsToReturn,
                monitoringMode,
                clientHandle,
                originalFilter,
                filterToUse,
                range,
                samplingInterval,
                queueSize,
                discardOldest,
                minimumSamplingInterval)
		{
            m_offset = offset;
        }
 /// <summary>
 /// Initializes the object with its node type.
 /// </summary>
 public MemoryBufferMonitoredItem(
     IServerInternal server,
     INodeManager nodeManager,
     object mangerHandle,
     uint offset,
     uint subscriptionId,
     uint id,
     Session session,
     ReadValueId itemToMonitor,
     DiagnosticsMasks diagnosticsMasks,
     TimestampsToReturn timestampsToReturn,
     MonitoringMode monitoringMode,
     uint clientHandle,
     MonitoringFilter originalFilter,
     MonitoringFilter filterToUse,
     Opc.Ua.Range range,
     double samplingInterval,
     uint queueSize,
     bool discardOldest,
     double minimumSamplingInterval)
     :
     base(
         server,
         nodeManager,
         mangerHandle,
         subscriptionId,
         id,
         session,
         itemToMonitor,
         diagnosticsMasks,
         timestampsToReturn,
         monitoringMode,
         clientHandle,
         originalFilter,
         filterToUse,
         range,
         samplingInterval,
         queueSize,
         discardOldest,
         minimumSamplingInterval)
 {
     m_offset = offset;
 }
Пример #8
0
        /// <summary>
        /// Updates the measurement and calculates the new control output.
        /// </summary>
        public double UpdateMeasurement(AnalogItemState <double> source)
        {
            Range range = source.EURange.Value;

            m_measurement.Value = source.Value;

            // clamp the setpoint.
            if (range != null)
            {
                if (m_setPoint.Value > range.High)
                {
                    m_setPoint.Value = range.High;
                }

                if (m_setPoint.Value < range.Low)
                {
                    m_setPoint.Value = range.Low;
                }
            }

            // calculate error.
            m_controlOut.Value = m_setPoint.Value - m_measurement.Value;

            if (range != null)
            {
                m_controlOut.Value /= range.Magnitude;

                if (Math.Abs(m_controlOut.Value) > 1.0)
                {
                    m_controlOut.Value = (m_controlOut.Value < 0)?-1.0:+1.0;
                }
            }

            // return the new output.
            return(m_controlOut.Value);
        }
        /// <summary>
        /// Validates the monitoring filter specified by the client.
        /// </summary>
        protected virtual StatusCode ValidateMonitoringFilter(
            ServerSystemContext context,
            NodeHandle handle, 
            uint attributeId,
            double samplingInterval,
            uint queueSize,
            ExtensionObject filter,
            out MonitoringFilter filterToUse,
            out Range range,
            out MonitoringFilterResult result)
        {
            range = null;
            filterToUse = null;
            result = null;

            // nothing to do if the filter is not specified.
            if (ExtensionObject.IsNull(filter))
            {
                return StatusCodes.Good;
            }

            // extension objects wrap any data structure. must check that the client provided the correct structure.
            DataChangeFilter deadbandFilter = ExtensionObject.ToEncodeable(filter) as DataChangeFilter;

            if (deadbandFilter == null)
            {
                AggregateFilter aggregateFilter = ExtensionObject.ToEncodeable(filter) as AggregateFilter;

                if (aggregateFilter == null || attributeId != Attributes.Value)
                {
                    return StatusCodes.BadFilterNotAllowed;
                }

                if (!Server.AggregateManager.IsSupported(aggregateFilter.AggregateType))
                {
                    return StatusCodes.BadAggregateNotSupported;
                }

                ServerAggregateFilter revisedFilter = new ServerAggregateFilter();
                revisedFilter.AggregateType = aggregateFilter.AggregateType;
                revisedFilter.StartTime = aggregateFilter.StartTime;
                revisedFilter.ProcessingInterval = aggregateFilter.ProcessingInterval;
                revisedFilter.AggregateConfiguration = aggregateFilter.AggregateConfiguration;
                revisedFilter.Stepped = false;

                StatusCode error = ReviseAggregateFilter(context, handle, samplingInterval, queueSize, revisedFilter);

                if (StatusCode.IsBad(error))
                {
                    return error;
                }

                AggregateFilterResult aggregateFilterResult = new AggregateFilterResult();
                aggregateFilterResult.RevisedProcessingInterval = aggregateFilter.ProcessingInterval;
                aggregateFilterResult.RevisedStartTime = aggregateFilter.StartTime;
                aggregateFilterResult.RevisedAggregateConfiguration = aggregateFilter.AggregateConfiguration;

                filterToUse = revisedFilter;
                result = aggregateFilterResult;
                return StatusCodes.Good;
            }

            // deadband filters only allowed for variable values.
            if (attributeId != Attributes.Value)
            {
                return StatusCodes.BadFilterNotAllowed;
            }

            BaseVariableState variable = handle.Node as BaseVariableState;

            if (variable == null)
            {
                return StatusCodes.BadFilterNotAllowed;
            }

            // check for status filter.
            if (deadbandFilter.DeadbandType == (uint)DeadbandType.None)
            {
                filterToUse = deadbandFilter;
                return StatusCodes.Good;
            }

            // deadband filters can only be used for numeric values.
            if (!Server.TypeTree.IsTypeOf(variable.DataType, DataTypeIds.Number))
            {
                return StatusCodes.BadFilterNotAllowed;
            }
            
            // nothing more to do for absolute filters.
            if (deadbandFilter.DeadbandType == (uint)DeadbandType.Absolute)
            {
                filterToUse = deadbandFilter;
                return StatusCodes.Good;
            }

            // need to look up the EU range if a percent filter is requested.
            if (deadbandFilter.DeadbandType == (uint)DeadbandType.Percent)
            {
                PropertyState property = handle.Node.FindChild(context, Opc.Ua.BrowseNames.EURange) as PropertyState;

                if (property == null)
                {
                    return StatusCodes.BadFilterNotAllowed;
                }
                
                range = property.Value as Range;
                
                if (range == null)
                {
                    return StatusCodes.BadFilterNotAllowed;
                }

                filterToUse = deadbandFilter;

                return StatusCodes.Good;
            }

            // no other type of filter supported.
            return StatusCodes.BadFilterNotAllowed;
        }
        /// <summary>
        /// Returns the value as a percentage of the range.
        /// </summary>
        private double GetValue(double value, Range range)
        {
            if (range != null)
            {
                return value * range.Magnitude;
            }

            return value;
        }
        /// <summary>
        /// Moves the value towards the target.
        /// </summary>
        private double Adjust(double value, double target, double step, Range range)
        {
            // convert percentage step to an absolute step if range is specified.
            if (range != null)
            {
                step = step * range.Magnitude;
            }
            
            double difference = target - value;

            if (difference < 0)
            {
                value -= step;

                if (value < target)
                {
                   return target;
                }
            }
            else
            {
                value += step;

                if (value > target)
                {
                   return target;
                }
            }

            return value;
        }
Пример #12
0
        /// <summary>
        /// Updates a variable from a tag.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="tag">The tag.</param>
        /// <param name="variable">The variable to update.</param>
        private void UpdateVariable(ISystemContext context, UnderlyingSystemTag tag, BaseVariableState variable)
        {
            variable.Description = tag.Description;
            variable.Value = tag.Value;
            variable.Timestamp = tag.Timestamp;

            switch (tag.DataType)
            {
                case UnderlyingSystemDataType.Integer1: { variable.DataType = DataTypes.SByte;  break; }
                case UnderlyingSystemDataType.Integer2: { variable.DataType = DataTypes.Int16;  break; }
                case UnderlyingSystemDataType.Integer4: { variable.DataType = DataTypes.Int32;  break; }
                case UnderlyingSystemDataType.Real4:    { variable.DataType = DataTypes.Float;  break; }
                case UnderlyingSystemDataType.String:   { variable.DataType = DataTypes.String; break; }
            }

            variable.ValueRank = ValueRanks.Scalar;
            variable.ArrayDimensions = null;

            if (tag.IsWriteable)
            {
                variable.AccessLevel = AccessLevels.CurrentReadOrWrite;
                variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite;
            }
            else
            {
                variable.AccessLevel = AccessLevels.CurrentRead;
                variable.UserAccessLevel = AccessLevels.CurrentRead;
            }

            variable.MinimumSamplingInterval = MinimumSamplingIntervals.Continuous;
            variable.Historizing = false;
            
            switch (tag.TagType)
            {
                case UnderlyingSystemTagType.Analog:
                {
                    AnalogItemState node = variable as AnalogItemState;

                    if (tag.EuRange != null)
                    {
                        if (tag.EuRange.Length >= 2 && node.EURange != null)
                        {
                            Range range = new Range(tag.EuRange[0], tag.EuRange[1]);
                            node.EURange.Value = range;
                            node.EURange.Timestamp = tag.Block.Timestamp;
                        }

                        if (tag.EuRange.Length >= 4 && node.InstrumentRange != null)
                        {
                            Range range = new Range(tag.EuRange[2], tag.EuRange[3]);
                            node.InstrumentRange.Value = range;
                            node.InstrumentRange.Timestamp = tag.Block.Timestamp;
                        }
                    }

                    if (!String.IsNullOrEmpty(tag.EngineeringUnits) && node.EngineeringUnits != null)
                    {
                        EUInformation info = new EUInformation();
                        info.DisplayName = tag.EngineeringUnits;
                        info.NamespaceUri = Namespaces.HistoricalAccess;
                        node.EngineeringUnits.Value = info;
                        node.EngineeringUnits.Timestamp = tag.Block.Timestamp;
                    }

                    break;
                }

                case UnderlyingSystemTagType.Digital:
                {
                    TwoStateDiscreteState node = variable as TwoStateDiscreteState;

                    if (tag.Labels != null && node.TrueState != null && node.FalseState != null)
                    {
                        if (tag.Labels.Length >= 2)
                        {
                            node.TrueState.Value = new LocalizedText(tag.Labels[0]);
                            node.TrueState.Timestamp = tag.Block.Timestamp;
                            node.FalseState.Value = new LocalizedText(tag.Labels[1]);
                            node.FalseState.Timestamp = tag.Block.Timestamp;
                        }
                    }

                    break;
                }

                case UnderlyingSystemTagType.Enumerated:
                {
                    MultiStateDiscreteState node = variable as MultiStateDiscreteState;

                    if (tag.Labels != null)
                    {
                        LocalizedText[] strings = new LocalizedText[tag.Labels.Length];

                        for (int ii = 0; ii < tag.Labels.Length; ii++)
                        {
                            strings[ii] = new LocalizedText(tag.Labels[ii]);
                        }

                        node.EnumStrings.Value = strings;
                        node.EnumStrings.Timestamp = tag.Block.Timestamp;
                    }

                    break;
                }
            }
        }
Пример #13
0
        private DataItemState CreateAnalogItemVariable(NodeState parent, string path, string name, NodeId dataType, int valueRank, object initialValues, Range customRange)
        {
            AnalogItemState variable = new AnalogItemState(parent);
            variable.BrowseName = new QualifiedName(path, NamespaceIndex);
            variable.EngineeringUnits = new PropertyState<EUInformation>(variable);
            variable.InstrumentRange = new PropertyState<Range>(variable);

            variable.Create(
                SystemContext,
                new NodeId(path, NamespaceIndex),
                variable.BrowseName,
                null,
                true);

            variable.NodeId = new NodeId(path, NamespaceIndex);            
            variable.SymbolicName = name;
            variable.DisplayName = new LocalizedText("en", name);
            variable.WriteMask = AttributeWriteMask.None;
            variable.UserWriteMask = AttributeWriteMask.None;            
            variable.ReferenceTypeId = ReferenceTypes.Organizes;
            variable.DataType = dataType;
            variable.ValueRank = valueRank;
            variable.AccessLevel = AccessLevels.CurrentReadOrWrite;
            variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite;
            variable.Historizing = false;
            

            if (customRange != null)
            {
                variable.EURange.Value = customRange;
            }
            else
            {
                variable.EURange.Value = new Range(100, 0);
            }

            variable.InstrumentRange.Value = new Range(120, -10);
            if (initialValues == null)
            {
                variable.Value = Opc.Ua.TypeInfo.GetDefaultValue(dataType, valueRank, Server.TypeTree);
            }
            else
            {
                variable.Value = initialValues;
            }

            variable.StatusCode = StatusCodes.Good;
            variable.Timestamp = DateTime.UtcNow;
            variable.EngineeringUnits.Value = new EUInformation("liters", Namespaces.ReferenceApplications);
            variable.OnWriteValue = OnWriteAnalog;
            variable.EURange.AccessLevel = AccessLevels.CurrentReadOrWrite;
            variable.EURange.UserAccessLevel = AccessLevels.CurrentReadOrWrite;
            variable.EngineeringUnits.AccessLevel = AccessLevels.CurrentReadOrWrite;
            variable.EngineeringUnits.UserAccessLevel = AccessLevels.CurrentReadOrWrite;
            variable.InstrumentRange.AccessLevel = AccessLevels.CurrentReadOrWrite;
            variable.InstrumentRange.UserAccessLevel = AccessLevels.CurrentReadOrWrite;

            if (parent != null)
            {
                parent.AddChild(variable);
            }

            return variable;
        }
Пример #14
0
 private DataItemState CreateAnalogItemVariable(NodeState parent, string path, string name, BuiltInType dataType, int valueRank, object initialValues, Range customRange)
 {
     return CreateAnalogItemVariable(parent, path, name, (uint)dataType, valueRank, initialValues, customRange);
 }