A generic implementation for ISystemContext interface.
Inheritance: ISystemContext, IOperationContext
Exemple #1
0
        /// <summary>
        /// Creates a copy of the context that can be used with the specified operation context.
        /// </summary>
        /// <param name="context">The operation context to use.</param>
        /// <returns>
        /// A copy of the system context that references the new operation context.
        /// </returns>
        public ISystemContext Copy(IOperationContext context)
        {
            SystemContext copy = (SystemContext)MemberwiseClone();

            if (context != null)
            {
                copy.m_operationContext = context;
            }

            return(copy);
        }
        /// <summary>
        /// Creates a new area.
        /// </summary>
        private BaseObjectState CreateArea(SystemContext context, BaseObjectState platforms, string areaName)
        {
            FolderState area = new FolderState(null);

            area.NodeId = new NodeId(areaName, NamespaceIndex);
            area.BrowseName = new QualifiedName(areaName, NamespaceIndex);
            area.DisplayName = area.BrowseName.Name;
            area.EventNotifier = EventNotifiers.SubscribeToEvents | EventNotifiers.HistoryRead | EventNotifiers.HistoryWrite;
            area.TypeDefinitionId = Opc.Ua.ObjectTypeIds.FolderType;

            platforms.AddNotifier(SystemContext, Opc.Ua.ReferenceTypeIds.HasNotifier, false, area);
            area.AddNotifier(SystemContext, Opc.Ua.ReferenceTypeIds.HasNotifier, true, platforms);

            AddPredefinedNode(SystemContext, area);

            return area;
        }
        /// <summary>
        /// Creates a new well.
        /// </summary>
        private void CreateWell(SystemContext context, BaseObjectState area, string wellId, string wellName)
        {
            WellState well = new WellState(null);

            well.NodeId = new NodeId(wellId, NamespaceIndex);
            well.BrowseName = new QualifiedName(wellName, NamespaceIndex);
            well.DisplayName = wellName;
            well.EventNotifier = EventNotifiers.SubscribeToEvents | EventNotifiers.HistoryRead | EventNotifiers.HistoryWrite;
            well.TypeDefinitionId = new NodeId(ObjectTypes.WellType, NamespaceIndex);

            area.AddNotifier(SystemContext, Opc.Ua.ReferenceTypeIds.HasNotifier, false, well);
            well.AddNotifier(SystemContext, Opc.Ua.ReferenceTypeIds.HasNotifier, true, area);

            AddPredefinedNode(SystemContext, well);
        }
        /// <summary>
        /// Creates a modification info record.
        /// </summary>
        private ModificationInfo GetModificationInfo(SystemContext context, HistoryUpdateType updateType)
        {
            ModificationInfo info = new ModificationInfo();
            info.UpdateType = updateType;
            info.ModificationTime = DateTime.UtcNow;

            if (context.OperationContext != null && context.OperationContext.UserIdentity != null)
            {
                info.UserName = context.OperationContext.UserIdentity.DisplayName;
            }

            return info;
        }
        /// <summary>
        /// Creates a boiler and adds it to the address space.
        /// </summary>
        /// <param name="context">The context to use.</param>
        /// <param name="unitNumber">The unit number for the boiler.</param>
        private void CreateBoiler(SystemContext context, int unitNumber)
        {
            BoilerState boiler = new BoilerState(null);

            string name = Utils.Format("Boiler #{0}", unitNumber);

            boiler.Create(
                context,
                null, 
                new QualifiedName(name, m_namespaceIndex),
                null, 
                true);

            NodeState folder = (NodeState)FindPredefinedNode(
                ExpandedNodeId.ToNodeId(ObjectIds.Boilers, Server.NamespaceUris),
                typeof(NodeState));

            folder.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, boiler.NodeId);
            boiler.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, true, folder.NodeId);

            string unitLabel = Utils.Format("{0}0", unitNumber);

            UpdateDisplayName(boiler.InputPipe, unitLabel);
            UpdateDisplayName(boiler.Drum, unitLabel);
            UpdateDisplayName(boiler.OutputPipe, unitLabel);
            UpdateDisplayName(boiler.LevelController, unitLabel);
            UpdateDisplayName(boiler.FlowController, unitLabel);
            UpdateDisplayName(boiler.CustomController, unitLabel);

            m_boilers.Add(boiler);

            AddPredefinedNode(context, boiler);
        }
        /// <summary>
        /// Deletes a property value from the history.
        /// </summary>
        public uint DeleteAnnotationHistory(SystemContext context, QualifiedName propertyName, DateTime sourceTimestamp)
        {
            bool deleted = false;

            string filter = String.Format(System.Globalization.CultureInfo.InvariantCulture, "SourceTimestamp = #{0}#", sourceTimestamp);

            DataView view = new DataView(
                SelectTable(propertyName),
                filter,
                null,
                DataViewRowState.CurrentRows);

            for (int ii = 0; ii < view.Count; ii++)
            {
                int updateType = (int)view[ii].Row[5];
            }

            if (!deleted)
            {
                return StatusCodes.BadNoEntryExists;
            }

            return StatusCodes.Good;
        }
        /// <summary>
        /// Deletes a value from the history.
        /// </summary>
        public uint DeleteHistory(SystemContext context, DateTime startTime, DateTime endTime, bool isModified)
        {
            // ensure time goes up.
            if (endTime < startTime)
            {
                DateTime temp = startTime;
                startTime = endTime;
                endTime = temp;
            }

            string filter = String.Format(
                System.Globalization.CultureInfo.InvariantCulture,
                "SourceTimestamp >= #{0}# AND SourceTimestamp < #{1}#", 
                startTime,
                endTime);

            // select the table.
            DataTable table = m_archiveItem.DataSet.Tables[0];

            if (isModified)
            {
                table = m_archiveItem.DataSet.Tables[1];
            }

            // delete the values.
            DataView view = new DataView(
                table,
                filter,
                null,
                DataViewRowState.CurrentRows);

            List<DataRow> rowsToDelete = new List<DataRow>();

            for (int ii = 0; ii < view.Count; ii++)
            {
                if (!isModified)
                {
                    DataRow modifiedRow = m_archiveItem.DataSet.Tables[1].NewRow();

                    modifiedRow[0] = view[ii].Row[0];
                    modifiedRow[1] = view[ii].Row[1];
                    modifiedRow[2] = view[ii].Row[2];
                    modifiedRow[3] = view[ii].Row[3];
                    modifiedRow[4] = view[ii].Row[4];
                    modifiedRow[5] = HistoryUpdateType.Delete;
                    modifiedRow[6] = GetModificationInfo(context, HistoryUpdateType.Delete);

                    m_archiveItem.DataSet.Tables[1].Rows.Add(modifiedRow);
                }

                rowsToDelete.Add(view[ii].Row);
            }

            // delete rows.
            foreach (DataRow row in rowsToDelete)
            {
                row.Delete();
            }

            // commit all changes.
            m_archiveItem.DataSet.AcceptChanges();

            return StatusCodes.Good;
        }
        /// <summary>
        /// Updates the history.
        /// </summary>
        public uint UpdateAnnotations(SystemContext context, Annotation annotation, DataValue value, PerformUpdateType performUpdateType)
        {
            bool replaced = false;

            string filter = String.Format(System.Globalization.CultureInfo.InvariantCulture, "SourceTimestamp = #{0}#", value.SourceTimestamp);

            DataView view = new DataView(
                m_archiveItem.DataSet.Tables[2],
                filter,
                null,
                DataViewRowState.CurrentRows);

            DataRow row = null;

            for (int ii = 0; ii < view.Count; ii++)
            {
                Annotation current = (Annotation)view[ii].Row[5];

                replaced = (current.UserName == annotation.UserName);

                if (performUpdateType == PerformUpdateType.Insert)
                {
                    if (replaced)
                    {
                        return StatusCodes.BadEntryExists;
                    }
                }

                if (replaced)
                {
                    row = view[ii].Row;
                    break;
                }
            }

            // add record indicating it was inserted.
            if (!replaced)
            {
                if (performUpdateType == PerformUpdateType.Replace || performUpdateType == PerformUpdateType.Remove)
                {
                    return StatusCodes.BadNoEntryExists;
                }

                row = m_archiveItem.DataSet.Tables[2].NewRow();
            }

            // add/update new record.
            if (performUpdateType != PerformUpdateType.Remove)
            {
                row[0] = value.SourceTimestamp;
                row[1] = value.ServerTimestamp;
                row[2] = new DataValue(new ExtensionObject(annotation), StatusCodes.Good, value.SourceTimestamp, value.ServerTimestamp);
                row[3] = BuiltInType.ExtensionObject;
                row[4] = ValueRanks.Scalar;
                row[5] = annotation;

                if (!replaced)
                {
                    m_archiveItem.DataSet.Tables[2].Rows.Add(row);
                }
            }

            // delete record.
            else
            {
                row.Delete();
            }

            // accept all changes.
            m_archiveItem.DataSet.AcceptChanges();

            return StatusCodes.Good;
        }
        /// <summary>
        /// Deletes a value from the history.
        /// </summary>
        public uint DeleteHistory(SystemContext context, DateTime sourceTimestamp)
        {
            bool deleted = false;

            string filter = String.Format(System.Globalization.CultureInfo.InvariantCulture, "SourceTimestamp = #{0}#", sourceTimestamp);

            DataView view = new DataView(
                m_archiveItem.DataSet.Tables[0],
                filter,
                null,
                DataViewRowState.CurrentRows);

            for (int ii = 0; ii < view.Count; ii++)
            {
                int updateType = (int)view[ii].Row[5];

                if (updateType == 0)
                {
                    view[ii].Row[5] = HistoryUpdateType.Delete;
                    view[ii].Row[6] = GetModificationInfo(context, HistoryUpdateType.Delete);
                    deleted = true;
                }
            }

            if (!deleted)
            {
                return StatusCodes.BadNoEntryExists;
            }

            return StatusCodes.Good;
        }
        /// <summary>
        /// Updates the history.
        /// </summary>
        public uint UpdateHistory(SystemContext context, DataValue value, PerformUpdateType performUpdateType)
        {
            bool replaced = false;

            if (performUpdateType == PerformUpdateType.Remove)
            {
                return StatusCodes.BadNotSupported;
            }

            if (StatusCode.IsNotBad(value.StatusCode))
            {
                TypeInfo typeInfo = value.WrappedValue.TypeInfo;

                if (typeInfo == null)
                {
                    typeInfo = TypeInfo.Construct(value.Value);
                }

                if (typeInfo == null || typeInfo.BuiltInType != m_archiveItem.DataType || typeInfo.ValueRank != ValueRanks.Scalar)
                {
                    return StatusCodes.BadTypeMismatch;
                }
            }

            string filter = String.Format(System.Globalization.CultureInfo.InvariantCulture, "SourceTimestamp = #{0}#", value.SourceTimestamp);

            DataView view = new DataView(
                m_archiveItem.DataSet.Tables[0],
                filter,
                null,
                DataViewRowState.CurrentRows);

            DataRow row = null;

            for (int ii = 0; ii < view.Count;)
            {
                if (performUpdateType == PerformUpdateType.Insert)
                {
                    return StatusCodes.BadEntryExists;
                }

                // add record indicating it was replaced.
                DataRow modifiedRow = m_archiveItem.DataSet.Tables[1].NewRow();

                modifiedRow[0] = view[ii].Row[0];
                modifiedRow[1] = view[ii].Row[1];
                modifiedRow[2] = view[ii].Row[2];
                modifiedRow[3] = view[ii].Row[3];
                modifiedRow[4] = view[ii].Row[4];
                modifiedRow[5] = HistoryUpdateType.Replace;
                modifiedRow[6] = GetModificationInfo(context, HistoryUpdateType.Replace);

                m_archiveItem.DataSet.Tables[1].Rows.Add(modifiedRow);

                replaced = true;
                row = view[ii].Row;
                break;
            }

            // add record indicating it was inserted.
            if (!replaced)
            {
                if (performUpdateType == PerformUpdateType.Replace)
                {
                    return StatusCodes.BadNoEntryExists;
                }

                DataRow modifiedRow = m_archiveItem.DataSet.Tables[1].NewRow();

                modifiedRow[0] = value.SourceTimestamp;
                modifiedRow[1] = value.ServerTimestamp;
                modifiedRow[2] = value;

                if (value.WrappedValue.TypeInfo != null)
                {
                    modifiedRow[3] = value.WrappedValue.TypeInfo.BuiltInType;
                    modifiedRow[4] = value.WrappedValue.TypeInfo.ValueRank;
                }
                else
                {
                    modifiedRow[3] = BuiltInType.Variant;
                    modifiedRow[4] = ValueRanks.Scalar;
                }

                modifiedRow[5] = HistoryUpdateType.Insert;
                modifiedRow[6] = GetModificationInfo(context, HistoryUpdateType.Insert);

                m_archiveItem.DataSet.Tables[1].Rows.Add(modifiedRow);

                row = m_archiveItem.DataSet.Tables[0].NewRow();
            }

            // add/update new record.
            row[0] = value.SourceTimestamp;
            row[1] = value.ServerTimestamp;
            row[2] = value;

            if (value.WrappedValue.TypeInfo != null)
            {
                row[3] = value.WrappedValue.TypeInfo.BuiltInType;
                row[4] = value.WrappedValue.TypeInfo.ValueRank;
            }
            else
            {
                row[3] = BuiltInType.Variant;
                row[4] = ValueRanks.Scalar;
            }

            if (!replaced)
            {
                m_archiveItem.DataSet.Tables[0].Rows.Add(row);
            }

            // accept all changes.
            m_archiveItem.DataSet.AcceptChanges();

            return StatusCodes.Good;
        }
        /// <summary>
        /// Creates a new sample.
        /// </summary>
        public List<DataValue> NewSamples(SystemContext context)
        {
            List<DataValue> newSamples = new List<DataValue>();

            while (m_pattern != null && m_nextSampleTime < DateTime.UtcNow)
            {
                DataValue value = new DataValue();
                value.WrappedValue = m_pattern[m_patternIndex].WrappedValue;
                value.ServerTimestamp = m_nextSampleTime;
                value.SourceTimestamp = m_nextSampleTime;
                value.StatusCode = m_pattern[m_patternIndex].StatusCode;
                m_nextSampleTime = value.SourceTimestamp.AddMilliseconds(m_archiveItem.SamplingInterval);
                newSamples.Add(value);

                DataRow row = m_archiveItem.DataSet.Tables[0].NewRow();

                row[0] = value.SourceTimestamp;
                row[1] = value.ServerTimestamp;
                row[2] = value;
                row[3] = value.WrappedValue.TypeInfo.BuiltInType;
                row[4] = value.WrappedValue.TypeInfo.ValueRank;

                m_archiveItem.DataSet.Tables[0].Rows.Add(row);
                m_patternIndex = (m_patternIndex + 1) % m_pattern.Count;
            }

            m_archiveItem.DataSet.AcceptChanges();
            return newSamples;
        }
        /// <summary>
        /// Loads the data.
        /// </summary>
        public void ReloadFromSource(SystemContext context)
        {
            LoadConfiguration(context);

            if (m_archiveItem.LastLoadTime == DateTime.MinValue || (m_archiveItem.Persistent && m_archiveItem.LastLoadTime.AddSeconds(10) < DateTime.UtcNow))
            {
                DataFileReader reader = new DataFileReader();
                reader.LoadHistoryData(context, m_archiveItem);

                // set the start of the archive.
                if (m_archiveItem.DataSet.Tables[0].DefaultView.Count > 0)
                {
                    m_configuration.StartOfArchive.Value = (DateTime)m_archiveItem.DataSet.Tables[0].DefaultView[0].Row[0];
                    m_configuration.StartOfOnlineArchive.Value = m_configuration.StartOfArchive.Value;
                }

                if (m_archiveItem.Archiving)
                {
                    // save the pattern used to produce new data.
                    m_pattern = new List<DataValue>();

                    foreach (DataRowView row in m_archiveItem.DataSet.Tables[0].DefaultView)
                    {
                        DataValue value = (DataValue)row.Row[2];
                        m_pattern.Add(value);
                        m_nextSampleTime = value.SourceTimestamp.AddMilliseconds(m_archiveItem.SamplingInterval);
                    }

                    // fill in data until the present time.
                    m_patternIndex = 0;
                    NewSamples(context);
                }
            }

            
        }
        /// <summary>
        /// Loads the configuration.
        /// </summary>
        public void LoadConfiguration(SystemContext context)
        {
            DataFileReader reader = new DataFileReader();

            if (reader.LoadConfiguration(context, m_archiveItem))
            {
                this.DataType = (uint)m_archiveItem.DataType;
                this.ValueRank = m_archiveItem.ValueRank;
                this.Historizing = m_archiveItem.Archiving;

                m_configuration.MinTimeInterval.Value = m_archiveItem.SamplingInterval;
                m_configuration.MaxTimeInterval.Value = m_archiveItem.SamplingInterval;
                m_configuration.Stepped.Value = m_archiveItem.Stepped;

                AggregateConfiguration configuration = m_archiveItem.AggregateConfiguration;
                m_configuration.AggregateConfiguration.PercentDataGood.Value = configuration.PercentDataGood;
                m_configuration.AggregateConfiguration.PercentDataBad.Value = configuration.PercentDataBad;
                m_configuration.AggregateConfiguration.UseSlopedExtrapolation.Value = configuration.UseSlopedExtrapolation;
                m_configuration.AggregateConfiguration.TreatUncertainAsBad.Value = configuration.TreatUncertainAsBad;
            }
        }
        /// <summary>
        /// Creates a boiler and adds it to the address space.
        /// </summary>
        /// <param name="context">The context to use.</param>
        /// <param name="unitNumber">The unit number for the boiler.</param>
        private void CreateBoiler(SystemContext context, int unitNumber)
        {
            BoilerState boiler = new BoilerState(null);

            string name = Utils.Format("Boiler #{0}", unitNumber);

            boiler.Create(
                context,
                null, 
                new QualifiedName(name, m_namespaceIndex),
                null, 
                true);

            NodeState folder = (NodeState)FindPredefinedNode(
                ExpandedNodeId.ToNodeId(ObjectIds.Boilers, Server.NamespaceUris),
                typeof(NodeState));

            folder.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, boiler.NodeId);
            boiler.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, true, folder.NodeId);

            string unitLabel = Utils.Format("{0}0", unitNumber);

            UpdateDisplayName(boiler.InputPipe, unitLabel);
            UpdateDisplayName(boiler.Drum, unitLabel);
            UpdateDisplayName(boiler.OutputPipe, unitLabel);
            UpdateDisplayName(boiler.LevelController, unitLabel);
            UpdateDisplayName(boiler.FlowController, unitLabel);
            UpdateDisplayName(boiler.CustomController, unitLabel);

            m_boilers.Add(boiler);

            AddPredefinedNode(context, boiler);

            // Autostart boiler simulation state machine
            MethodState start = boiler.Simulation.Start;
            IList<Variant> inputArguments = new List<Variant>();
            IList<Variant> outputArguments = new List<Variant>();
            List<ServiceResult> errors = new List<ServiceResult>();
            start.Call(context, boiler.NodeId, inputArguments, errors, outputArguments);

        }