コード例 #1
0
        /// <summary>
        /// Clones the item.
        /// </summary>
        /// <param name="group">The group.</param>
        /// <returns>The new item.</returns>
        public ComDaGroupItem CloneItem(ComDaGroup group)
        {
            ComDaGroupItem copy = new ComDaGroupItem(group, this.ItemId);

            copy.m_nodeId             = this.m_nodeId;
            copy.m_serverHandle       = this.m_serverHandle;
            copy.m_clientHandle       = this.m_clientHandle;
            copy.m_active             = this.m_active;
            copy.m_requestedDataType  = this.m_requestedDataType;
            copy.m_canonicalDataType  = this.m_canonicalDataType;
            copy.m_accessRights       = this.m_accessRights;
            copy.m_euType             = this.m_euType;
            copy.m_euInfo             = this.m_euInfo;
            copy.m_samplingRate       = this.m_samplingRate;
            copy.m_bufferEnabled      = this.m_bufferEnabled;
            copy.m_actualSamplingRate = this.m_actualSamplingRate;
            copy.m_deadband           = this.m_deadband;

            // create new monitored item and use its client handle as the server handle.
            copy.m_monitoredItem = new MonitoredItem(this.MonitoredItem);

            return(copy);
        }
コード例 #2
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Sets the data types.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <param name="dataTypes">The data types.</param>
        /// <returns>Any errors.</returns>
        public int[] SetDataTypes(int[] serverHandles, short[] dataTypes)
        {
            TraceState("SetDataTypes", serverHandles.Length);
            ThrowIfDisposed();

            lock (m_lock)
            {
                int[] results = new int[serverHandles.Length];
                ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length];

                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = null;

                    if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item))
                    {
                        results[ii] = ResultIds.E_INVALIDHANDLE;
                        continue;
                    }

                    // validate the datatype.
                    if (dataTypes[ii] != 0)
                    {
                        NodeId dataTypeId = ComUtils.GetDataTypeId(dataTypes[ii]);

                        if (NodeId.IsNull(dataTypeId))
                        {
                            results[ii] = ResultIds.E_BADTYPE;
                            continue;
                        }

                        bool reqTypeIsArray = (dataTypes[ii] & (short)VarEnum.VT_ARRAY) != 0;
                        bool actualTypeIsArray = (item.CanonicalDataType & (short)VarEnum.VT_ARRAY) != 0;

                        if (reqTypeIsArray != actualTypeIsArray)
                        {
                            results[ii] = ResultIds.E_BADTYPE;
                            continue;
                        }
                    }

                    item.RequestedDataType = dataTypes[ii];
                    results[ii] = ResultIds.S_OK;
                }

                return results;
            }
        }
コード例 #3
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Sets the client handles.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <param name="clientHandles">The client handles.</param>
        /// <returns>Any errors.</returns>
        public int[] SetClientHandles(int[] serverHandles, int[] clientHandles)
        {
            TraceState("SetClientHandles", serverHandles.Length);
            ThrowIfDisposed();

            lock (m_lock)
            {
                int[] results = new int[serverHandles.Length];
                ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length];

                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = null;

                    if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item))
                    {
                        results[ii] = ResultIds.E_INVALIDHANDLE;
                        continue;
                    }

                    item.ClientHandle = clientHandles[ii];
                    results[ii] = ResultIds.S_OK;
                }

                return results;
            }
        }
コード例 #4
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Sets the active state for the items.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <param name="active">if set to <c>true</c> the items are activated.</param>
        /// <returns>Any error codes.</returns>
        public int[] SetActive(int[] serverHandles, bool active)
        {
            TraceState("SetActive", serverHandles.Length, active);
            ThrowIfDisposed();

            lock (m_lock)
            {
                // get net monitoring mode.
                MonitoringMode monitoringMode = MonitoringMode.Disabled;

                if (m_active && active)
                {
                    monitoringMode = MonitoringMode.Reporting;
                }

                // validate the handles.
                int[] results = new int[serverHandles.Length];
                ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length];
                List<MonitoredItem> monitoredItems = new List<MonitoredItem>();

                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = null;

                    if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item))
                    {
                        results[ii] = ResultIds.E_INVALIDHANDLE;
                        continue;
                    }

                    // nothing to do if already in the correct state.
                    if (item.MonitoredItem.Status.MonitoringMode == monitoringMode)
                    {
                        item.Active = active;
                        results[ii] = ResultIds.S_OK;
                        continue;
                    }

                    items[ii] = item;
                    monitoredItems.Add(item.MonitoredItem);
                }

                // update the subscription.
                try
                {
                    m_subscription.SetMonitoringMode(monitoringMode, monitoredItems);
                }
                catch (Exception e)
                {
                    SetFatalError(items, results, e, ResultIds.E_FAIL);
                }

                // update active state on success
                for (int ii = 0; ii < items.Length; ii++)
                {
                    if (items[ii] != null)
                    {
                        // clear the last sent value when deactivated.
                        // this prevents the change filter from suppressing
                        // updates if the item is reactivated and the value
                        // has not changed.
                        if (items[ii].Active && !active)
                        {
                            items[ii].LastSentValue = null;
                        }

                        items[ii].Active = active;
                    }
                }

                // return any errors.
                return results;
            }
        }
コード例 #5
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Deletes the items.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <returns>Any errors.</returns>
        public int[] DeleteItems(int[] serverHandles)
        {
            TraceState("DeleteItems", serverHandles.Length);
            ThrowIfDisposed();

            lock (m_lock)
            {
                // validate the handles.
                int[] results = new int[serverHandles.Length];
                ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length];

                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = null;

                    if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item))
                    {
                        results[ii] = ResultIds.E_INVALIDHANDLE;
                        continue;
                    }

                    items[ii] = item;
                    RemoveItemFromSubscription(item);
                    m_itemsByHandle.Remove(serverHandles[ii]);
                    m_items.Remove(item);
                }

                // update the subscription.
                try
                {
                    m_subscription.ApplyChanges();
                }
                catch (Exception e)
                {
                    SetFatalError(items, results, e, ResultIds.E_FAIL);
                }

                // start the update timer.
                CheckUpdateTimerStatus();

                // return any errors.
                return results;
            }
        }
コード例 #6
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Updates the read result by converting the value to the requested data type.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="value">The value.</param>
        private void UpdateReadResult(ComDaGroupItem item, DaValue value)
        {
            if (value.Value == null || item.RequestedDataType == (short)VarEnum.VT_EMPTY)
            {
                return;
            }

            object convertedValue = null;
            
            int error = ComUtils.ChangeTypeForCOM(value.Value, (VarEnum)item.RequestedDataType, out convertedValue);

            if (error < 0)
            {
                value.Value = null;
                value.Error = error;
                return;
            }

            value.Value = convertedValue;
        }
コード例 #7
0
        /// <summary>
        /// Validates the items by reading the attributes required to add them to the group.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="group">The group.</param>
        /// <param name="requests">The requests.</param>
        /// <param name="items">The items.</param>
        /// <param name="start">The start index.</param>
        /// <param name="count">The number of items to process.</param>
        private void ValidateItems(
            Session session,
            ComDaGroup group,
            ComDaCreateItemRequest[] requests,
            ComDaGroupItem[] items,
            int start,
            int count)
        {
            // build list of the UA attributes that need to be read.
            ReadValueIdCollection attributesToRead = new ReadValueIdCollection();

            for (int ii = start; ii < start + count && ii < requests.Length; ii++)
            {
                // create the group item.
                ComDaCreateItemRequest request = requests[ii];
                ComDaGroupItem         item    = items[ii] = new ComDaGroupItem(group, request.ItemId);

                item.NodeId            = m_mapper.GetRemoteNodeId(request.ItemId);
                item.Active            = request.Active;
                item.ClientHandle      = request.ClientHandle;
                item.RequestedDataType = request.RequestedDataType;
                item.SamplingRate      = -1;
                item.Deadband          = -1;

                // add attributes.
                ReadValueId attributeToRead;

                attributeToRead             = new ReadValueId();
                attributeToRead.NodeId      = item.NodeId;
                attributeToRead.AttributeId = Attributes.NodeClass;
                attributesToRead.Add(attributeToRead);

                attributeToRead             = new ReadValueId();
                attributeToRead.NodeId      = item.NodeId;
                attributeToRead.AttributeId = Attributes.DataType;
                attributesToRead.Add(attributeToRead);

                attributeToRead             = new ReadValueId();
                attributeToRead.NodeId      = item.NodeId;
                attributeToRead.AttributeId = Attributes.ValueRank;
                attributesToRead.Add(attributeToRead);

                attributeToRead             = new ReadValueId();
                attributeToRead.NodeId      = item.NodeId;
                attributeToRead.AttributeId = Attributes.UserAccessLevel;
                attributesToRead.Add(attributeToRead);
            }

            // read attribute values from the server.
            DataValueCollection      results         = null;
            DiagnosticInfoCollection diagnosticInfos = null;

            try
            {
                session.Read(
                    null,
                    0,
                    TimestampsToReturn.Neither,
                    attributesToRead,
                    out results,
                    out diagnosticInfos);

                ClientBase.ValidateResponse(results, attributesToRead);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, attributesToRead);
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error reading attributes for items.");

                // set default values on error.
                for (int ii = start; ii < start + count && ii < requests.Length; ii++)
                {
                    requests[ii].Error = ResultIds.E_INVALIDITEMID;
                }

                return;
            }

            // process results.
            int first = 0;

            for (int ii = start; ii < start + count && ii < requests.Length; ii++, first += 4)
            {
                ComDaGroupItem item = items[ii];

                // verify node class.
                NodeClass nodeClass = (NodeClass)results[first].GetValue <int>((int)NodeClass.Unspecified);

                if (nodeClass != NodeClass.Variable)
                {
                    requests[ii].Error = ResultIds.E_INVALIDITEMID;
                    continue;
                }

                // verify data type.
                NodeId dataTypeId = results[first + 1].GetValue <NodeId>(null);

                if (dataTypeId == null)
                {
                    requests[ii].Error = ResultIds.E_INVALIDITEMID;
                    continue;
                }

                // get value rank.
                int valueRank = results[first + 2].GetValue <int>(ValueRanks.Scalar);

                // update datatypes.
                BuiltInType builtInType = DataTypes.GetBuiltInType(dataTypeId, session.TypeTree);
                item.RemoteDataType    = new TypeInfo(builtInType, valueRank);
                item.CanonicalDataType = (short)ComUtils.GetVarType(item.RemoteDataType);

                // update access rights.
                byte userAccessLevel = results[first + 3].GetValue <byte>(0);

                if ((userAccessLevel & AccessLevels.CurrentRead) != 0)
                {
                    item.AccessRights |= OpcRcw.Da.Constants.OPC_READABLE;
                }

                if ((userAccessLevel & AccessLevels.CurrentWrite) != 0)
                {
                    item.AccessRights |= OpcRcw.Da.Constants.OPC_WRITEABLE;
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Updates the EUInfo for the items.
        /// </summary>
        /// <param name="group">The group.</param>
        /// <param name="items">The items. Null entries are ignored.</param>
        public void UpdateItemEuInfo(
            ComDaGroup group,
            IList <ComDaGroupItem> items)
        {
            // get the session to use for the operation.
            Session session = m_session;

            if (session == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            // build list of properties that need to be read.
            BrowsePathCollection browsePaths = new BrowsePathCollection();

            for (int ii = 0; ii < items.Count; ii++)
            {
                ComDaGroupItem item = (ComDaGroupItem)items[ii];

                // ignore invalid items or items which have already checked their EU type.
                if (item == null || item.EuType >= 0)
                {
                    continue;
                }

                BrowsePath browsePath = new BrowsePath();
                browsePath.StartingNode = item.NodeId;
                RelativePathElement element = new RelativePathElement();
                element.ReferenceTypeId = ReferenceTypeIds.HasProperty;
                element.IsInverse       = false;
                element.IncludeSubtypes = false;
                element.TargetName      = Opc.Ua.BrowseNames.EURange;
                browsePath.RelativePath.Elements.Add(element);
                browsePath.Handle = item;
                browsePaths.Add(browsePath);

                browsePath = new BrowsePath();
                browsePath.StartingNode = item.NodeId;
                element = new RelativePathElement();
                element.ReferenceTypeId = ReferenceTypeIds.HasProperty;
                element.IsInverse       = false;
                element.IncludeSubtypes = false;
                element.TargetName      = Opc.Ua.BrowseNames.EnumStrings;
                browsePath.RelativePath.Elements.Add(element);
                browsePath.Handle = item;
                browsePaths.Add(browsePath);
            }

            // check if nothing to do.
            if (browsePaths.Count == 0)
            {
                return;
            }

            // translate browse paths.
            BrowsePathResultCollection results         = null;
            DiagnosticInfoCollection   diagnosticInfos = null;

            try
            {
                session.TranslateBrowsePathsToNodeIds(
                    null,
                    browsePaths,
                    out results,
                    out diagnosticInfos);

                ClientBase.ValidateResponse(results, browsePaths);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browsePaths);
            }
            catch (Exception)
            {
                for (int ii = 0; ii < browsePaths.Count; ii++)
                {
                    ComDaGroupItem item = (ComDaGroupItem)browsePaths[ii].Handle;
                    item.EuType = 0;
                }

                return;
            }

            // build list of properties that need to be read.
            ReadValueIdCollection propertiesToRead = new ReadValueIdCollection();

            for (int ii = 0; ii < results.Count; ii++)
            {
                ComDaGroupItem   item   = (ComDaGroupItem)browsePaths[ii].Handle;
                BrowsePathResult result = results[ii];

                if (StatusCode.IsBad(result.StatusCode))
                {
                    if (item.EuType < 0 && result.StatusCode == StatusCodes.BadNoMatch)
                    {
                        item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM;
                    }

                    continue;
                }

                if (result.Targets.Count == 0 || result.Targets[0].TargetId.IsAbsolute)
                {
                    if (item.EuType < 0)
                    {
                        item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM;
                    }

                    continue;
                }

                ReadValueId propertyToRead = new ReadValueId();
                propertyToRead.NodeId      = (NodeId)result.Targets[0].TargetId;
                propertyToRead.AttributeId = Attributes.Value;
                propertyToRead.Handle      = item;
                propertiesToRead.Add(propertyToRead);

                if (browsePaths[ii].RelativePath.Elements[0].TargetName.Name == Opc.Ua.BrowseNames.EURange)
                {
                    item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG;
                }
                else
                {
                    item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED;
                }
            }

            // check if nothing to do.
            if (propertiesToRead.Count == 0)
            {
                return;
            }

            // read attribute values from the server.
            DataValueCollection values = null;

            try
            {
                session.Read(
                    null,
                    0,
                    TimestampsToReturn.Neither,
                    propertiesToRead,
                    out values,
                    out diagnosticInfos);

                ClientBase.ValidateResponse(values, propertiesToRead);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, propertiesToRead);
            }
            catch (Exception)
            {
                for (int ii = 0; ii < propertiesToRead.Count; ii++)
                {
                    ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle;
                    item.EuType = 0;
                }

                return;
            }

            // process results.
            for (int ii = 0; ii < values.Count; ii++)
            {
                ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle;

                if (StatusCode.IsBad(values[ii].StatusCode))
                {
                    item.EuType = 0;
                    continue;
                }

                if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG)
                {
                    Range range = (Range)values[ii].GetValue <Range>(null);

                    if (range == null)
                    {
                        item.EuType = 0;
                        continue;
                    }

                    item.EuInfo = new double[] { range.Low, range.High };
                    continue;
                }

                if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED)
                {
                    LocalizedText[] texts = (LocalizedText[])values[ii].GetValue <LocalizedText[]>(null);

                    if (texts == null)
                    {
                        item.EuType = 0;
                        continue;
                    }

                    string[] strings = new string[texts.Length];

                    for (int jj = 0; jj < strings.Length; jj++)
                    {
                        if (!LocalizedText.IsNullOrEmpty(texts[jj]))
                        {
                            strings[jj] = texts[jj].Text;
                        }
                    }

                    item.EuInfo = strings;
                    continue;
                }
            }
        }
コード例 #9
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Clears the sampling rates for the items.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <returns>Any errors.</returns>
        public int[] ClearItemSamplingRates(int[] serverHandles)
        {
            TraceState("ClearItemSamplingRates", serverHandles.Length);
            ThrowIfDisposed();

            int[] errors = new int[serverHandles.Length];
            ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length];

            lock (m_lock)
            {
                // update the filter for analog items that have not overriden the deadband.
                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = null;

                    if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item))
                    {
                        errors[ii] = ResultIds.E_INVALIDHANDLE;
                        continue;
                    }

                    if (item.SamplingRate == -1)
                    {
                        errors[ii] = ResultIds.E_RATENOTSET;
                        continue;
                    }
                    
                    item.MonitoredItem.SamplingInterval = (int)(this.UpdateRate/2);
                    items[ii] = item;
                }

                // update the items on the server.
                try
                {
                    m_subscription.ApplyChanges();
                }
                catch (Exception e)
                {
                    int error = ComUtils.GetErrorCode(e, ResultIds.E_FAIL);

                    for (int ii = 0; ii < items.Length; ii++)
                    {
                        if (items[ii] != null)
                        {
                            errors[ii] = error;
                        }
                    }

                    return errors;
                }

                // check results for monitored items.
                for (int ii = 0; ii < items.Length; ii++)
                {
                    ComDaGroupItem item = items[ii];

                    if (item == null)
                    {
                        continue;
                    }

                    if (ServiceResult.IsBad(item.MonitoredItem.Status.Error))
                    {
                        errors[ii] = ResultIds.E_FAIL;
                        continue;
                    }

                    item.SamplingRate = -1;
                    item.ActualSamplingRate = 0;
                    item.NextUpdateTime = -1;
                }

                return errors;
            }
        }
コード例 #10
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Sets the sampling rate for the items.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <param name="samplingRates">The sampling rates.</param>
        /// <param name="revisedSamplingRates">The revised sampling rates.</param>
        /// <returns>Any errors.</returns>
        public int[] SetItemSamplingRates(int[] serverHandles, int[] samplingRates, int[] revisedSamplingRates)
        {
            TraceState("SetItemSamplingRates", serverHandles.Length);
            ThrowIfDisposed();

            int[] errors = new int[serverHandles.Length];
            ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length];

            lock (m_lock)
            {
                // update the filter for analog items that have not overriden the deadband.
                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = null;

                    if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item))
                    {
                        errors[ii] = ResultIds.E_INVALIDHANDLE;
                        continue;
                    }

                    item.MonitoredItem.SamplingInterval = (int)(samplingRates[ii]/2);
                    revisedSamplingRates[ii] = 0;
                    items[ii] = item;
                }

                // update the items on the server.
                try
                {
                    m_subscription.ApplyChanges();
                }
                catch (Exception e)
                {
                    int error = ComUtils.GetErrorCode(e, ResultIds.E_FAIL);

                    for (int ii = 0; ii < items.Length; ii++)
                    {
                        if (items[ii] != null)
                        {
                            errors[ii] = error;
                        }
                    }

                    return errors;
                }

                // check results for monitored items.
                for (int ii = 0; ii < items.Length; ii++)
                {
                    ComDaGroupItem item = items[ii];
                    
                    if (item == null)
                    {
                        continue;                    
                    }

                    if (ServiceResult.IsBad(item.MonitoredItem.Status.Error))
                    {
                        errors[ii] = ResultIds.E_FAIL;
                        continue;
                    }
                    
                    item.SamplingRate = samplingRates[ii];
                    item.ActualSamplingRate = (int)(items[ii].MonitoredItem.Status.SamplingInterval);

                    // if 1/2 the sampling rate is accepted then it is possible to guarantee the sampling rate.
                    if (item.ActualSamplingRate < item.SamplingRate)
                    {
                        item.ActualSamplingRate =  item.SamplingRate;
                    }

                    // can only guarantee a sampling rate of twice what the UA server can provide.
                    else
                    {
                        item.ActualSamplingRate *= 2;
                    }

                    revisedSamplingRates[ii] = item.ActualSamplingRate;
                    item.NextUpdateTime = HiResClock.UtcNow.Ticks + item.ActualSamplingRate*TimeSpan.TicksPerMillisecond;

                    if (revisedSamplingRates[ii] != samplingRates[ii])
                    {
                        errors[ii] = ResultIds.S_UNSUPPORTEDRATE;
                    }

                    TraceState(
                        "ItemSamplingUpdated",
                        this.ServerHandle,
                        item.ServerHandle,
                        item.ClientHandle,
                        m_subscription.CurrentPublishingEnabled,
                        m_subscription.CurrentPublishingInterval,
                        item.SamplingRate,
                        item.MonitoredItem.Status.SamplingInterval);
                }

                return errors;
            }
        }
コード例 #11
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Clears the deadbands for the items.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <returns>Any errors.</returns>
        public int[] ClearItemDeadbands(int[] serverHandles)
        {
            TraceState("ClearItemSamplingRates", serverHandles.Length);
            ThrowIfDisposed();

            int[] errors = new int[serverHandles.Length];
            ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length];
            int count = 0;

            lock (m_lock)
            {
                // update the filter for analog items that have not overriden the deadband.
                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = null;

                    if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item))
                    {
                        errors[ii] = ResultIds.E_INVALIDHANDLE;
                        continue;
                    }

                    if (item.EuType >= 0 && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG)
                    {
                        errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED;
                        continue;
                    }

                    if (item.Deadband == -1)
                    {
                        errors[ii] = ResultIds.E_DEADBANDNOTSET;
                        continue;
                    }

                    items[ii] = item;
                    item.Deadband = -1;
                    count++;
                }
            }

            if (count == 0)
            {
                return errors;
            }

            // need the EU Info if the deadband is specified.
            m_manager.UpdateItemEuInfo(this, items);
            
            lock (m_lock)
            {
                // need to check the EU type after updating the EU info.
                for (int ii = 0; ii < items.Length; ii++)
                {
                    ComDaGroupItem item = items[ii];

                    if (item != null && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG)
                    {
                        errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED;
                        items[ii] = null;
                        continue;
                    }
                }

                UpdateDeadbandFilters(items);

                // update the items on the server.
                try
                {
                    m_subscription.ApplyChanges();
                }
                catch (Exception e)
                {
                    int error = ComUtils.GetErrorCode(e, ResultIds.E_FAIL);

                    for (int ii = 0; ii < items.Length; ii++)
                    {
                        if (items[ii] != null)
                        {
                            errors[ii] = error;
                        }
                    }

                    return errors;
                }

                return errors;
            }
        }
コード例 #12
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Gets the deadband for the items.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <param name="deadbands">The deadbands.</param>
        /// <returns>Any errors.</returns>
        public int[] GetItemDeadbands(int[] serverHandles, float[] deadbands)
        {
            TraceState("GetItemDeadbands", serverHandles.Length);
            ThrowIfDisposed();

            int[] errors = new int[serverHandles.Length];
            ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length];
            int count = 0;

            lock (m_lock)
            {
                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = null;

                    if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item))
                    {
                        errors[ii] = ResultIds.E_INVALIDHANDLE;
                        continue;
                    }

                    if (item.EuType >= 0 && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG)
                    {
                        errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED;
                        continue;
                    }

                    if (item.Deadband == -1)
                    {
                        errors[ii] = ResultIds.E_DEADBANDNOTSET;
                        continue;
                    }
                    
                    deadbands[ii] = item.Deadband;

                    item.Deadband = deadbands[ii];
                    items[ii] = item;
                    count++;
                }
            }

            if (count == 0)
            {
                return errors;
            }

            // need the EU Info if the deadband is specified.
            m_manager.UpdateItemEuInfo(this, items);

            lock (m_lock)
            {
                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = items[ii];

                    if (item != null)
                    {
                        if (item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG)
                        {
                            errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED;
                            continue;
                        }

                        deadbands[ii] = item.Deadband;
                    }
                }
            }

            return errors;
        }
コード例 #13
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Sets the deadband for the items.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <param name="deadbands">The deadbands.</param>
        /// <returns>Any errors.</returns>
        public int[] SetItemDeadbands(int[] serverHandles, float[] deadbands)
        {
            TraceState("SetItemDeadbands", serverHandles.Length);
            ThrowIfDisposed();

            int[] errors = new int[serverHandles.Length];
            ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length];
            int count = 0;

            lock (m_lock)
            {
                // update the filter for analog items that have not overriden the deadband.
                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    ComDaGroupItem item = null;

                    if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item))
                    {
                        errors[ii] = ResultIds.E_INVALIDHANDLE;
                        continue;
                    }

                    if (item.EuType >= 0 && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG)
                    {
                        errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED;
                        continue;
                    }

                    if (deadbands[ii] < 0 || deadbands[ii] > 100)
                    {
                        errors[ii] = ResultIds.E_INVALIDARG;
                        continue;
                    }

                    item.Deadband = deadbands[ii];
                    items[ii] = item;
                    count++;
                }
            }

            if (count == 0)
            {
                return errors;
            }

            // need the EU Info if the deadband is specified.
            m_manager.UpdateItemEuInfo(this, items);

            lock (m_lock)
            {
                // need to check the EU type after updating the EU info.
                for (int ii = 0; ii < items.Length; ii++)
                {
                    ComDaGroupItem item = items[ii];

                    if (item != null && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG)
                    {
                        errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED;
                        items[ii] = null;
                        continue;
                    }
                }

                // update filters for selected items.
                UpdateDeadbandFilters(items);

                // update the items on the server.
                try
                {
                    m_subscription.ApplyChanges();
                }
                catch (Exception e)
                {
                    int error = ComUtils.GetErrorCode(e, ResultIds.E_FAIL);

                    for (int ii = 0; ii < items.Length; ii++)
                    {
                        if (items[ii] != null)
                        {
                            errors[ii] = error;
                        }
                    }

                    return errors;
                }

                // check results for monitored items.
                for (int ii = 0; ii < items.Length; ii++)
                {
                    ComDaGroupItem item = items[ii];

                    if (item == null)
                    {
                        continue;
                    }

                    if (ServiceResult.IsBad(item.MonitoredItem.Status.Error))
                    {
                        item.MonitoredItem.Filter = item.MonitoredItem.Status.Filter;
                        DataChangeFilter filter = item.MonitoredItem.Filter as DataChangeFilter;

                        if (filter != null)
                        {
                            item.Deadband = (float)filter.DeadbandValue;
                        }

                        errors[ii] = ResultIds.E_FAIL;
                        continue;
                    }
                }

                return errors;
            }
        }
コード例 #14
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Updates the cache.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="value">The value.</param>
        /// <param name="isInitialRefresh">if set to <c>true</c> the change flag is set to false because the values are sent in the refresh.</param>
        private void UpdateCache(ComDaGroupItem item, DaValue value, bool isInitialRefresh)
        {
            lock (m_lock)
            {
                
                // get sampling rate.
                long now = HiResClock.UtcNow.Ticks;
                int samplingRate = item.ActualSamplingRate;

                if (item.SamplingRate == -1)
                {
                    samplingRate = m_actualUpdateRate;
                }

                // check existing cache contents.
                DaValue oldValue = null;
                DaCacheValue entry = null;

                if (item.CacheEntry != null)
                {
                    // do not update cache if a newer value exists.
                    if (item.CacheEntry.Timestamp >= value.Timestamp)
                    {
                        /*
                        TraceState(
                            "UpdateCache OLD VALUE RECEIVED", 
                            this.m_serverHandle, 
                            item.ServerHandle, 
                            new Variant(item.CacheEntry.Value),
                            item.CacheEntry.Timestamp.ToString("HH:mm:ss.fff"),
                            new Variant(value.Value),
                            value.Timestamp.ToString("HH:mm:ss.fff"));
                        */

                        return;
                    }

                    oldValue = item.CacheEntry;

                    // replace the newest value if sampling interval has not elasped.

                    if (!item.BufferEnabled || item.NextUpdateTime > now)
                    {
                        // TraceState("UpdateCache ENTRY REPLACED", this.m_serverHandle, item.ServerHandle, samplingRate);
                        entry = item.CacheEntry;
                    }
                }

                // create a new cache entry.
                if (entry == null)
                {
                    entry = new DaCacheValue();
                    entry.CacheTimestamp =  DateTime.UtcNow;

                    if (item.BufferEnabled)
                    {
                        entry.NextEntry = item.CacheEntry;
                        item.NextUpdateTime += samplingRate*TimeSpan.TicksPerMillisecond;

                        if (entry.NextEntry != null)
                        {
                            // TraceState("UpdateCache ENTRY BUFFERED", this.m_serverHandle, item.ServerHandle, samplingRate);
                        }
                    }

                    item.CacheEntry = entry;
                }

                // check if the value has changed.
                bool changed = !isInitialRefresh;

                if (oldValue != null)
                {
                    if (oldValue.Error == value.Error)
                    {
                        if (oldValue.Quality == value.Quality)
                        {
                            if (Utils.IsEqual(oldValue.Value, value.Value))
                            {
                                changed = false;
                            }
                        }
                    }
                }

                // save values.
                item.CacheEntry.Value = value.Value;
                item.CacheEntry.Quality = value.Quality;
                item.CacheEntry.Timestamp = value.Timestamp;
                item.CacheEntry.Error = value.Error;
                item.CacheEntry.Changed = changed;

                TraceState(
                    "UpdateCache COMPLETE",
                    this.m_serverHandle,
                    item.ServerHandle,
                    item.ClientHandle,
                    new Variant(value.Value),
                    value.Timestamp.ToString("HH:mm:ss.fff"),
                    item.CacheEntry.Changed);
            }
        }
コード例 #15
0
ファイル: ComDaGroupManager.cs プロジェクト: yuriik83/UA-.NET
        /// <summary>
        /// Validates the items.
        /// </summary>
        /// <param name="group">The group.</param>
        /// <param name="requests">The requests.</param>
        /// <returns>The items. May contain null is validation failed.</returns>
        public ComDaGroupItem[] ValidateItems(ComDaGroup group, ComDaCreateItemRequest[] requests)
        {
            TraceState("ValidateItems", group.Name);

            // get the session to use for the operation.
            Session session = m_session;

            if (session == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            // validate items.
            ComDaGroupItem[] items = new ComDaGroupItem[requests.Length];

            for (int ii = 0; ii < requests.Length; ii += 10000)
            {
                ValidateItems(session, group, requests, items, ii, 10000);
            }

            // process results.
            for (int ii = 0; ii < requests.Length; ii++)
            {
                // check for the results.
                ComDaCreateItemRequest request = requests[ii];

                if (request.Error < 0)
                {
                    items[ii] = null;
                    continue;
                }

                // check access path.
                if (!String.IsNullOrEmpty(request.AccessPath))
                {
                    items[ii] = null;
                    request.Error = ResultIds.E_UNKNOWNPATH;
                    continue;
                }

                ComDaGroupItem item = items[ii];

                // validate the datatype.
                if (request.RequestedDataType != 0)
                {
                    NodeId dataTypeId = ComUtils.GetDataTypeId(request.RequestedDataType);

                    if (NodeId.IsNull(dataTypeId))
                    {
                        items[ii] = null;
                        request.Error = ResultIds.E_BADTYPE;
                        continue;
                    }

                    bool reqTypeIsArray = (request.RequestedDataType & (short)VarEnum.VT_ARRAY) != 0;
                    bool actualTypeIsArray = (item.CanonicalDataType & (short)VarEnum.VT_ARRAY) != 0;

                    if (reqTypeIsArray != actualTypeIsArray)
                    {
                        items[ii] = null;
                        request.Error = ResultIds.E_BADTYPE;
                        continue;
                    }
                }

                // create a new monitored item.
                MonitoredItem monitoredItem = new MonitoredItem();

                monitoredItem.StartNodeId = item.NodeId;
                monitoredItem.RelativePath = null;
                monitoredItem.AttributeId = Attributes.Value;
                monitoredItem.MonitoringMode = (request.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled;
                monitoredItem.SamplingInterval = group.UpdateRate/2;
                monitoredItem.QueueSize = 0;
                monitoredItem.DiscardOldest = true;
                monitoredItem.Filter = null;

                // update item.
                item.ServerHandle = (int)monitoredItem.ClientHandle;
                item.MonitoredItem = monitoredItem;

                // link the monitored item back to the group item.
                monitoredItem.Handle = item;
                
                // update return parameters.
                request.ServerHandle = item.ServerHandle;
                request.CanonicalDataType = item.CanonicalDataType;
                request.AccessRights = item.AccessRights;
                request.Error = ResultIds.S_OK;
            }

            return items;
        }
コード例 #16
0
ファイル: ComDaGroupManager.cs プロジェクト: yuriik83/UA-.NET
        /// <summary>
        /// Validates the items by reading the attributes required to add them to the group.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="group">The group.</param>
        /// <param name="requests">The requests.</param>
        /// <param name="items">The items.</param>
        /// <param name="start">The start index.</param>
        /// <param name="count">The number of items to process.</param>
        private void ValidateItems(
            Session session,
            ComDaGroup group,
            ComDaCreateItemRequest[] requests,
            ComDaGroupItem[] items,
            int start,
            int count)
        {
            // build list of the UA attributes that need to be read.
            ReadValueIdCollection attributesToRead = new ReadValueIdCollection();

            for (int ii = start; ii < start + count && ii < requests.Length; ii++)
            {
                // create the group item.
                ComDaCreateItemRequest request = requests[ii];
                ComDaGroupItem item = items[ii] = new ComDaGroupItem(group, request.ItemId);

                item.NodeId = m_mapper.GetRemoteNodeId(request.ItemId);
                item.Active = request.Active;
                item.ClientHandle = request.ClientHandle;
                item.RequestedDataType = request.RequestedDataType;
                item.SamplingRate = -1;
                item.Deadband = -1;

                // add attributes.
                ReadValueId attributeToRead;

                attributeToRead = new ReadValueId();
                attributeToRead.NodeId = item.NodeId;
                attributeToRead.AttributeId = Attributes.NodeClass;
                attributesToRead.Add(attributeToRead);

                attributeToRead = new ReadValueId();
                attributeToRead.NodeId = item.NodeId;
                attributeToRead.AttributeId = Attributes.DataType;
                attributesToRead.Add(attributeToRead);

                attributeToRead = new ReadValueId();
                attributeToRead.NodeId = item.NodeId;
                attributeToRead.AttributeId = Attributes.ValueRank;
                attributesToRead.Add(attributeToRead);

                attributeToRead = new ReadValueId();
                attributeToRead.NodeId = item.NodeId;
                attributeToRead.AttributeId = Attributes.UserAccessLevel;
                attributesToRead.Add(attributeToRead);
            }

            // read attribute values from the server.
            DataValueCollection results = null;
            DiagnosticInfoCollection diagnosticInfos = null;

            try
            {
                session.Read(
                    null,
                    0,
                    TimestampsToReturn.Neither,
                    attributesToRead,
                    out results,
                    out diagnosticInfos);

                ClientBase.ValidateResponse(results, attributesToRead);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, attributesToRead);
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error reading attributes for items.");

                // set default values on error.
                for (int ii = start; ii < start + count && ii < requests.Length; ii++)
                {
                    requests[ii].Error = ResultIds.E_INVALIDITEMID;
                }

                return;
            }

            // process results.
            int first = 0;

            for (int ii = start; ii < start + count && ii < requests.Length; ii++, first += 4)
            {
                ComDaGroupItem item = items[ii];

                // verify node class.
                NodeClass nodeClass = (NodeClass)results[first].GetValue<int>((int)NodeClass.Unspecified);

                if (nodeClass != NodeClass.Variable)
                {
                    requests[ii].Error = ResultIds.E_INVALIDITEMID;
                    continue;
                }

                // verify data type.
                NodeId dataTypeId = results[first+1].GetValue<NodeId>(null);

                if (dataTypeId == null)
                {
                    requests[ii].Error = ResultIds.E_INVALIDITEMID;
                    continue;
                }

                // get value rank.
                int valueRank = results[first+2].GetValue<int>(ValueRanks.Scalar);

                // update datatypes.
                BuiltInType builtInType = DataTypes.GetBuiltInType(dataTypeId, session.TypeTree);
                item.RemoteDataType = new TypeInfo(builtInType, valueRank);
                item.CanonicalDataType = (short)ComUtils.GetVarType(item.RemoteDataType);

                // update access rights.
                byte userAccessLevel = results[first+3].GetValue<byte>(0);

                if ((userAccessLevel & AccessLevels.CurrentRead) != 0)
                {
                    item.AccessRights |= OpcRcw.Da.Constants.OPC_READABLE;
                }

                if ((userAccessLevel & AccessLevels.CurrentWrite) != 0)
                {
                    item.AccessRights |= OpcRcw.Da.Constants.OPC_WRITEABLE;
                }
            }
        }
コード例 #17
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
        /// <summary>
        /// Sets the error for all items after an unexpected error occurs.
        /// </summary>
        /// <param name="itemsInRequest">The items in request.</param>
        /// <param name="results">The results.</param>
        /// <param name="e">The exception.</param>
        /// <param name="defaultError">The default error.</param>
        private void SetFatalError(ComDaGroupItem[] itemsInRequest, int[] results, Exception e, int defaultError)
        {
            int error = ComUtils.GetErrorCode(e, defaultError);

            for (int ii = 0; ii < itemsInRequest.Length; ii++)
            {
                if (itemsInRequest[ii] != null)
                {
                    results[ii] = error;
                }
            }
        }
コード例 #18
0
        /// <summary>
        /// Validates the items.
        /// </summary>
        /// <param name="group">The group.</param>
        /// <param name="requests">The requests.</param>
        /// <returns>The items. May contain null is validation failed.</returns>
        public ComDaGroupItem[] ValidateItems(ComDaGroup group, ComDaCreateItemRequest[] requests)
        {
            TraceState("ValidateItems", group.Name);

            // get the session to use for the operation.
            Session session = m_session;

            if (session == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            // validate items.
            ComDaGroupItem[] items = new ComDaGroupItem[requests.Length];

            for (int ii = 0; ii < requests.Length; ii += 10000)
            {
                ValidateItems(session, group, requests, items, ii, 10000);
            }

            // process results.
            for (int ii = 0; ii < requests.Length; ii++)
            {
                // check for the results.
                ComDaCreateItemRequest request = requests[ii];

                if (request.Error < 0)
                {
                    items[ii] = null;
                    continue;
                }

                // check access path.
                if (!String.IsNullOrEmpty(request.AccessPath))
                {
                    items[ii]     = null;
                    request.Error = ResultIds.E_UNKNOWNPATH;
                    continue;
                }

                ComDaGroupItem item = items[ii];

                // validate the datatype.
                if (request.RequestedDataType != 0)
                {
                    NodeId dataTypeId = ComUtils.GetDataTypeId(request.RequestedDataType);

                    if (NodeId.IsNull(dataTypeId))
                    {
                        items[ii]     = null;
                        request.Error = ResultIds.E_BADTYPE;
                        continue;
                    }

                    bool reqTypeIsArray    = (request.RequestedDataType & (short)VarEnum.VT_ARRAY) != 0;
                    bool actualTypeIsArray = (item.CanonicalDataType & (short)VarEnum.VT_ARRAY) != 0;

                    if (reqTypeIsArray != actualTypeIsArray)
                    {
                        items[ii]     = null;
                        request.Error = ResultIds.E_BADTYPE;
                        continue;
                    }
                }

                // create a new monitored item.
                MonitoredItem monitoredItem = new MonitoredItem();

                monitoredItem.StartNodeId      = item.NodeId;
                monitoredItem.RelativePath     = null;
                monitoredItem.AttributeId      = Attributes.Value;
                monitoredItem.MonitoringMode   = (request.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled;
                monitoredItem.SamplingInterval = group.UpdateRate / 2;
                monitoredItem.QueueSize        = 0;
                monitoredItem.DiscardOldest    = true;
                monitoredItem.Filter           = null;

                // update item.
                item.ServerHandle  = (int)monitoredItem.ClientHandle;
                item.MonitoredItem = monitoredItem;

                // link the monitored item back to the group item.
                monitoredItem.Handle = item;

                // update return parameters.
                request.ServerHandle      = item.ServerHandle;
                request.CanonicalDataType = item.CanonicalDataType;
                request.AccessRights      = item.AccessRights;
                request.Error             = ResultIds.S_OK;
            }

            return(items);
        }
コード例 #19
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
 private void AddItemToSubscription(ComDaGroupItem item)
 {
     m_subscription.AddItem(item.MonitoredItem);
     m_itemsByMonitoredItem.Add(item.MonitoredItem.ClientHandle, item);
 }
コード例 #20
0
ファイル: ComDaGroup.cs プロジェクト: OPCFoundation/UA-.NET
 private void RemoveItemFromSubscription(ComDaGroupItem item)
 {
     m_itemsByMonitoredItem.Remove(item.MonitoredItem.ClientHandle);
     m_subscription.RemoveItem(item.MonitoredItem);
 }
コード例 #21
0
ファイル: ComDaGroupItem.cs プロジェクト: yuriik83/UA-.NET
        /// <summary>
        /// Clones the item.
        /// </summary>
        /// <param name="group">The group.</param>
        /// <returns>The new item.</returns>
        public ComDaGroupItem CloneItem(ComDaGroup group)
        {
            ComDaGroupItem copy = new ComDaGroupItem(group, this.ItemId);

            copy.m_nodeId = this.m_nodeId;
            copy.m_serverHandle = this.m_serverHandle;
            copy.m_clientHandle = this.m_clientHandle;
            copy.m_active = this.m_active;
            copy.m_requestedDataType = this.m_requestedDataType;
            copy.m_canonicalDataType = this.m_canonicalDataType;
            copy.m_accessRights = this.m_accessRights;
            copy.m_euType = this.m_euType;
            copy.m_euInfo = this.m_euInfo;
            copy.m_samplingRate = this.m_samplingRate;
            copy.m_bufferEnabled = this.m_bufferEnabled;
            copy.m_actualSamplingRate = this.m_actualSamplingRate;
            copy.m_deadband = this.m_deadband;

            // create new monitored item and use its client handle as the server handle.
            copy.m_monitoredItem = new MonitoredItem(this.MonitoredItem);

            return copy;
        }