Example #1
0
        public DxpItemByteArray()
        {
            Result = new DaValue();
            Result.Subscribe(value =>
            {
                if (value != null)
                {
                    var t = value.GetType();
                    if (t.IsArray)
                    {
                        var arr = (Array)Result.Value;
                        if (t.GetElementType() == typeof(bool))
                        {
                        }
                    }
                }
                if (Node != null)
                {
                    switch (Node.Device.DeviceType)
                    {
                    case DxpDeviceType.Unknown:
                        break;

                    case DxpDeviceType.Bit:

                        break;

                    case DxpDeviceType.Byte:
                        if (Node.Size > 1)
                        {
                            Buffer = (byte[])Result.Value;
                        }
                        else
                        {
                            Buffer = new[] { (byte)Result.Value };
                        }
                        break;

                    case DxpDeviceType.Word:
                        if (Node.Size > 1)
                        {
                            Buffer = ((Int16[])Result.Value).SelectMany(_ => BitConverter.GetBytes(_)).ToArray();
                        }
                        else
                        {
                            Buffer = BitConverter.GetBytes((Int16)Result.Value);
                        }
                        break;

                    default:
                        break;
                    }
                }
            });
        }
        /// <summary>
        /// Reads the current values for the specified attributes.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="itemHandle">The item handle.</param>
        /// <param name="attributeIds">The attribute ids.</param>
        /// <returns></returns>
        public DaValue[] ReadCurrentValues(Session session, HdaItemHandle itemHandle, uint[] attributeIds)
        {
            DaValue[] results = new DaValue[attributeIds.Length];

            // check handle.
            InternalHandle handle = itemHandle as InternalHandle;

            if (handle == null)
            {
                for (int ii = 0; ii < results.Length; ii++)
                {
                    results[ii] = new DaValue();
                    results[ii].Error = ResultIds.E_INVALIDHANDLE;
                }

                return results;
            }

            // look up the supported attributes for an item.
            ReadValueIdCollection supportedAttributes = handle.Item.SupportedAttributes;

            if (supportedAttributes == null)
            {
                handle.Item.SupportedAttributes = supportedAttributes = GetAvailableAttributes(session, handle.NodeId);
            }

            // build list of values to read.
            ReadValueIdCollection valuesToRead = new ReadValueIdCollection();
            List<int> indexes = new List<int>();

            for (int ii = 0; ii < attributeIds.Length; ii++)
            {
                ReadValueId valueToRead = GetReadValueId(supportedAttributes, attributeIds[ii]);

                if (valueToRead == null)
                {
                    results[ii] = new DaValue();
                    results[ii].Error = ResultIds.E_INVALIDATTRID;
                    continue;
                }

                valuesToRead.Add(valueToRead);
                indexes.Add(ii);

                // need to fetch the value rank as well.
                if (attributeIds[ii] == Constants.OPCHDA_DATA_TYPE)
                {
                    valuesToRead.Add(GetReadValueId(supportedAttributes, ComHdaProxy.INTERNAL_ATTRIBUTE_VALUE_RANK));
                    indexes.Add(-1);
                }
            }

            // nothing to do.
            if (valuesToRead.Count == 0)
            {
                return results;
            }

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

            session.Read(
                null,
                0,
                TimestampsToReturn.Neither,
                valuesToRead,
                out values,
                out diagnosticInfos);

            // validate response from the UA server.
            ClientBase.ValidateResponse(values, valuesToRead);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToRead);

            // assign a local handle to all valid items.
            for (int ii = 0; ii < valuesToRead.Count; ii++)
            {
                int index = indexes[ii];
                uint attributeId = (uint)valuesToRead[ii].Handle;

                // check for values which are combined with other values to create the value (e.g. ValueRank).
                if (index == -1)
                {
                    continue;
                }

                results[index] = GetAttributeValue(session, attributeId, values, ii);

                // only support current value for now.
                if (results[index].Error == ResultIds.S_OK)
                {
                    results[index].Error = ResultIds.S_CURRENTVALUE;
                }
            }

            return results;
        }
        /// <summary>
        /// Gets the remote data value.
        /// </summary>
        /// <param name="localValue">The local value.</param>
        /// <param name="remoteType">The remote data type.</param>
        /// <returns>The remote data value.</returns>
        /// <exception cref="COMException">Thrown if a conversion error occurs.</exception>
        public DataValue GetRemoteDataValue(DaValue localValue, TypeInfo remoteType)
        {
            DataValue remoteValue = new DataValue();
            remoteValue.SourceTimestamp = localValue.Timestamp;

            if (localValue.Error < 0)
            {
                throw ComUtils.CreateComException(localValue.Error);
            }

            remoteValue.StatusCode = ComUtils.GetHdaQualityCode(localValue.HdaQuality);

            try
            {
                remoteValue.WrappedValue = GetRemoteValue(new Variant(localValue.Value), remoteType);
            }
            catch (Exception e)
            {
                throw ComUtils.CreateComException(e, ResultIds.E_BADTYPE);
            }
                        
            return remoteValue;
        }
Example #4
0
        /// <summary>
        /// Reads the values of the properties from the server.
        /// </summary>
        /// <param name="itemId">The item id.</param>
        /// <param name="propertyIds">The list of property ids to read. All properties are read if null.</param>
        /// <returns>True if the element has properies.</returns>
        private DaValue[] ReadPropertyValues(string itemId, params int[] propertyIds)
        {
            string methodName = "IOPCItemProperties.GetItemProperties";

            // check for trivial case.
            if (propertyIds == null)
            {
                return null;
            }

            int count = propertyIds.Length;
            DaValue[] results = new DaValue[count];
            
            // check for empty list.
            if (count == 0)
            {
                return results;
            }

            // get the values from the server.
            IntPtr pValues = IntPtr.Zero;
            IntPtr pErrors = IntPtr.Zero;

            try
            {
                IOPCItemProperties server = BeginComCall<IOPCItemProperties>(methodName, true);

                server.GetItemProperties(
                    itemId,
                    count,
                    propertyIds,
                    out pValues,
                    out pErrors);
            }
            catch (Exception e)
            {
                if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_UNKNOWNITEMID, ResultIds.E_INVALIDITEMID))
                {
                    ComUtils.TraceComError(e, methodName);
                    return null;
                }

                for (int ii = 0; ii < count; ii++)
                {
                    DaValue result = results[ii] = new DaValue();
                    result.Value = null;
                    result.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD;
                    result.Timestamp = DateTime.UtcNow;
                    result.Error = Marshal.GetHRForException(e);
                }

                return results;
            }
            finally
            {
                EndComCall(methodName);
            }

            // unmarshal results.
            object[] values = ComUtils.GetVARIANTs(ref pValues, count, true);
            int[]    errors = ComUtils.GetInt32s(ref pErrors, count, true);

            for (int ii = 0; ii < count; ii++)
            {
                DaValue result = results[ii] = new DaValue();
                result.Value = ComUtils.ProcessComValue(values[ii]);
                result.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD;
                result.Timestamp = DateTime.UtcNow;
                result.Error = errors[ii];
            }

            return results;
        }
Example #5
0
 /// <summary>
 /// Called when a asynchronous read completes.
 /// </summary>
 /// <param name="requestId">The request id.</param>
 /// <param name="clientHandles">The client handles.</param>
 /// <param name="values">The values.</param>
 internal void OnReadComplete(int requestId, int[] clientHandles, DaValue[] values)
 {
 }
Example #6
0
        /// <summary>
        /// Creates an array of item value result objects from the callback data.
        /// </summary>
        internal static DaValue[] GetItemValues(
            int dwCount,
            object[] pvValues,
            short[] pwQualities,
            System.Runtime.InteropServices.ComTypes.FILETIME[] pftTimeStamps,
            int[] pErrors)
        {
            // contruct the item value results.
            DaValue[] values = new DaValue[dwCount];

            for (int ii = 0; ii < dwCount; ii++)
            {
                DaValue value = values[ii] = new DaValue();

                value.Error = pErrors[ii];

                if (pErrors[ii] >= 0)
                {
                    value.Value = ComUtils.ProcessComValue(pvValues[ii]);
                    value.Quality = pwQualities[ii];
                    value.Timestamp = ComUtils.GetDateTime(pftTimeStamps[ii]);
                }
            }

            // return results
            return values;
        }
Example #7
0
        /// <summary>
        /// Creates the update requests.
        /// </summary>
        private List<HdaUpdateRequest> CreateUpdateRequests(
            Session session,
            PerformUpdateType updateType,
            int[] serverHandles,
            DaValue[] values)
        {
            List<HdaUpdateRequest> requests = new List<HdaUpdateRequest>();

            for (int ii = 0; ii < serverHandles.Length; ii++)
            {
                HdaUpdateRequest request = new HdaUpdateRequest();
                requests.Add(request);

                // find handle.
                request.Handle = m_itemManager.LookupHandle(serverHandles[ii]);

                if (request.Handle == null)
                {
                    request.Error = ResultIds.E_INVALIDHANDLE;
                    continue;
                }

                request.ClientHandle = request.Handle.ClientHandle;

                // check if nothing to do.
                DaValue value = values[ii];

                if (value == null)
                {
                    request.Error = ResultIds.E_FAIL;
                    continue;
                }

                // specify the parameters for the request.
                UpdateDataDetails details = new UpdateDataDetails();

                details.NodeId = request.Handle.NodeId;
                details.PerformInsertReplace = updateType;

                DataValue value2 = m_mapper.GetRemoteDataValue(value, m_itemManager.GetRemoteDataType(request.Handle));

                value2.SourceTimestamp = value.Timestamp;
                value2.StatusCode = ComUtils.GetHdaQualityCode(value.HdaQuality);

                details.UpdateValues.Add(value2);

                request.Details = new ExtensionObject(details);
            }

            return requests;
        }
Example #8
0
        /// <summary>
        /// Updates the history.
        /// </summary>
        public int[] UpdateRaw(
            PerformUpdateType updateType,
            int[] serverHandles,
            DaValue[] values)
        {
            Session session = ThrowIfNotConnected();
            
            // create the update requests.
            List<HdaUpdateRequest> requests = CreateUpdateRequests(
                session,
                updateType,
                serverHandles,
                values);

            // update the server.
            return UpdateHistory(session, requests, true);
        }
Example #9
0
        /// <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);
            }
        }
Example #10
0
        /// <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;
        }
Example #11
0
        /// <summary>
        /// Performs n synchronous read operation.
        /// </summary>
        /// <param name="maxAge">The max age.</param>
        /// <param name="serverHandles">The server handles.</param>
        /// <param name="isInitialRefresh">if set to <c>true</c> the read is being done as part of the initial refresh for active items.</param>
        /// <param name="clientHandles">The client handles (must be allocated by the caller).</param>
        /// <returns>Any errors.</returns>
        public DaValue[] SyncRead(uint maxAge, int[] serverHandles, bool isInitialRefresh, int[] clientHandles)
        {
            TraceState("SyncRead", maxAge, serverHandles.Length);
            ThrowIfDisposed();

            DaValue[] results = new DaValue[serverHandles.Length];
            List<ComDaGroupItem> items = new List<ComDaGroupItem>(serverHandles.Length);
            ReadValueIdCollection valuesToRead = new ReadValueIdCollection();

            lock (m_lock)
            {
                // validate items.
                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    results[ii] = new DaValue();

                    ComDaGroupItem item = null;

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

                    if (clientHandles != null)
                    {
                        clientHandles[ii] = item.ClientHandle;
                    }

                    // check for cache read.
                    if (maxAge == UInt32.MaxValue)
                    {
                        // inactive items cannot be read from cache.
                        if (!item.Active || !m_active)
                        {
                            results[ii].Quality = OpcRcw.Da.Qualities.OPC_QUALITY_OUT_OF_SERVICE;
                            results[ii].Timestamp = DateTime.UtcNow;
                            continue;
                        }
                      
                        // check if waiting for initial data.
                        if (item.CacheEntry == null)
                        {
                            results[ii].Quality = OpcRcw.Da.Qualities.OPC_QUALITY_WAITING_FOR_INITIAL_DATA;
                            results[ii].Timestamp = DateTime.UtcNow;
                            continue;
                        }

                        // get the latest value from the cache.
                        item.CacheEntry.GetLatest(results[ii]);
                        UpdateReadResult(item, results[ii]);
                        continue;
                    }

                    // apply max age.
                    if (maxAge > 0)
                    {
                        if (item.CacheEntry != null)
                        {
                            if (item.CacheEntry.CacheTimestamp.AddMilliseconds(maxAge) > DateTime.UtcNow)
                            {
                                item.CacheEntry.GetLatest(results[ii]);
                                UpdateReadResult(item, results[ii]);
                                continue;
                            }
                        }
                    }

                    // schedule read from device.
                    ReadValueId valueToRead = new ReadValueId();

                    valueToRead.NodeId = item.NodeId;
                    valueToRead.AttributeId = Attributes.Value;
                    valueToRead.Handle = ii;

                    valuesToRead.Add(valueToRead);
                    items.Add(item);
                }
            }

            if (valuesToRead.Count  == 0)
            {
                return results;
            }

            // read the values from the server.
            DaValue[] remoteResults = m_manager.Read(valuesToRead);
            
            // copy results.
            for (int ii = 0; ii < valuesToRead.Count; ii++)
            {
                int index = (int)valuesToRead[ii].Handle;

                if (isInitialRefresh)
                {
                    UpdateCache(items[ii], remoteResults[ii], isInitialRefresh);
                }

                UpdateReadResult(items[ii], remoteResults[ii]);
                results[(int)valuesToRead[ii].Handle] = remoteResults[ii];
            }

            return results;
        }
Example #12
0
        /// <summary>
        /// Gets the property values.
        /// </summary>
        /// <param name="itemId">The item id.</param>
        /// <param name="propertyIds">The property ids.</param>
        /// <returns>The property values.</returns>
        public DaValue[] GetPropertyValues(string itemId, int[] propertyIds)
        {
            DaValue[] results = new DaValue[propertyIds.Length];

            for (int ii = 0; ii < results.Length; ii++)
            {
                results[ii] = new DaValue();
                results[ii].Error = ResultIds.E_UNKNOWNITEMID;
            }

            return results;
        }
Example #13
0
        /// <summary>
        /// Writes the values for the specified item ids.
        /// </summary>
        /// <param name="itemIds">The item ids.</param>
        /// <param name="values">The values.</param>
        /// <returns>The results.</returns>
        public int[] Write(string[] itemIds, DaValue[] values)
        {
            int[] results = new int[itemIds.Length];

            for (int ii = 0; ii < results.Length; ii++)
            {
                results[ii] = ResultIds.E_UNKNOWNITEMID;
            }

            return results;
        }
Example #14
0
        /// <summary>
        /// Reads the values for the specified item ids.
        /// </summary>
        /// <param name="itemIds">The item ids.</param>
        /// <returns>The values.</returns>
        public DaValue[] Read(string[] itemIds)
        {
            DaValue[] values = new DaValue[itemIds.Length];
            
            for (int ii = 0; ii < values.Length; ii++)
            {
                values[ii] = new DaValue();
                values[ii].Error = ResultIds.E_UNKNOWNITEMID;
            }

            return values;
        }
        /// <summary>
        /// Converts a UA value to an HDA attribute value.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="attributeId">The attribute id.</param>
        /// <param name="values">The values.</param>
        /// <param name="index">The index.</param>
        /// <returns></returns>
        private DaValue GetAttributeValue(Session session, uint attributeId, DataValueCollection values, int index)
        {
            switch (attributeId)
            {
                case Constants.OPCHDA_DATA_TYPE:
                {
                    DaValue result = new DaValue();
                    DataValue value = values[index];

                    // check for valid node.
                    if (StatusCode.IsBad(value.StatusCode))
                    {
                        result.Error = ResultIds.E_UNKNOWNITEMID;
                        return result;
                    }

                    // covert to var type.
                    NodeId dataTypeId = value.GetValue<NodeId>(DataTypeIds.BaseDataType);
                    int valueRank = values[index+1].GetValue<int>(ValueRanks.Scalar);

                    BuiltInType builtInType = DataTypes.GetBuiltInType(dataTypeId, session.TypeTree);
                    TypeInfo typeInfo = new TypeInfo(builtInType, valueRank);
                    short varType = (short)ComUtils.GetVarType(typeInfo);

                    result.Value = varType;
                    result.Quality = ComUtils.GetQualityCode(value.StatusCode);
                    result.Timestamp = value.ServerTimestamp;
                    result.Error = ResultIds.S_OK;

                    return result;
                }

                case Constants.OPCHDA_DESCRIPTION:
                {
                    DataValue value = values[index];

                    if (value.StatusCode == StatusCodes.BadAttributeIdInvalid)
                    {
                        DaValue result = new DaValue();
                        result.Error = ResultIds.E_INVALIDATTRID;
                        return result;
                    }

                    return m_mapper.GetLocalDataValue(value);
                }

                default:
                {
                    return ComHdaProxy.GetAttributeValue(session, m_mapper, attributeId, values[index]);
                }
            }
        }
Example #16
0
        /// <summary>
        /// Reads the attribute values from the server.
        /// </summary>
        /// <param name="valuesToRead">The values to read.</param>
        /// <returns>
        /// The values read.
        /// </returns>
        public DaValue[] Read(ReadValueIdCollection valuesToRead)
        {
            TraceState("Read", valuesToRead.Count);

            // check for valid session.
            Session session = m_session;

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

            int masterError = ResultIds.E_FAIL;
            DaValue[] results = new DaValue[valuesToRead.Count];

            if (session != null)
            {
                try
                {
                    // read the values.
                    DataValueCollection values = null;
                    DiagnosticInfoCollection diagnosticInfos = null;

                    session.Read(
                        null,
                        0,
                        TimestampsToReturn.Both,
                        valuesToRead,
                        out values,
                        out diagnosticInfos);

                    ClientBase.ValidateResponse(values, valuesToRead);
                    ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToRead);

                    // convert the response.
                    for (int ii = 0; ii < values.Count; ii++)
                    {
                        results[ii] = m_mapper.GetLocalDataValue(values[ii]);
                    }

                    // return the results.
                    return results;
                }
                catch (Exception e)
                {
                    masterError = ComUtils.GetErrorCode(e, ResultIds.E_FAIL);
                }
            }

            // report any unexpected errors.
            for (int ii = 0; ii < results.Length; ii++)
            {
                DaValue result = results[ii] = new DaValue();
                result.Error = masterError;
            }

            return results;
        }
Example #17
0
        /// <summary>
        /// Performs n synchronous write operation.
        /// </summary>
        /// <param name="serverHandles">The server handles.</param>
        /// <param name="values">The values.</param>
        /// <returns>Any errors.</returns>
        public int[] SyncWrite(int[] serverHandles, DaValue[] values)
        {
            TraceState("SyncWrite", serverHandles.Length);
            ThrowIfDisposed();

            int[] results = new int[serverHandles.Length];
            WriteValueCollection valuesToWrite = new WriteValueCollection();

            lock (m_lock)
            {
                // validate items.
                DaValue convertedValue = new DaValue();

                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;
                    }

                    // apply the COM type conversion.
                    DaValue requestedValue = values[ii];

                    if (requestedValue.Value == null)
                    {
                        results[ii] = ResultIds.E_BADTYPE;
                        continue;
                    }

                    if (item.CanonicalDataType != (short)VarEnum.VT_EMPTY)
                    {
                        object value = null;

                        int error = ComUtils.ChangeTypeForCOM(requestedValue.Value, (VarEnum)item.CanonicalDataType, out value);

                        if (error < 0)
                        {
                            results[ii] = error;
                            continue;
                        }

                        // could happen if there is a problem reading the datatype from the server.
                        if (requestedValue.Value == null)
                        {
                            results[ii] = ResultIds.E_BADTYPE;
                            continue;
                        }

                        // copy all of the attributes into the converted value.
                        convertedValue.Value = value;
                        convertedValue.Quality = requestedValue.Quality;
                        convertedValue.Timestamp = requestedValue.Timestamp;
                        convertedValue.Error = requestedValue.Error;

                        requestedValue = convertedValue;
                    }

                    WriteValue valueToWrite = new WriteValue();

                    valueToWrite.NodeId = item.NodeId;
                    valueToWrite.AttributeId = Attributes.Value;
                    valueToWrite.Handle = ii;

                    // convert value to UA data type.
                    try
                    {
                        valueToWrite.Value = m_manager.Mapper.GetRemoteDataValue(requestedValue, item.RemoteDataType);
                    }
                    catch (Exception e)
                    {
                        results[ii] = ComUtils.GetErrorCode(e, ResultIds.E_BADTYPE);
                        continue;
                    }

                    valuesToWrite.Add(valueToWrite);
                }
            }

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

            // write the values to the server.
            int[] remoteResults = m_manager.Write(valuesToWrite);

            // copy results.
            for (int ii = 0; ii < valuesToWrite.Count; ii++)
            {
                results[(int)valuesToWrite[ii].Handle] = remoteResults[ii];
            }

            return results;
        }
Example #18
0
        /// <summary>
        /// Updates the history.
        /// </summary>
        public int[] UpdateRaw(
            int transactionId,
            PerformUpdateType updateType,
            int[] serverHandles,
            DaValue[] values,
            out int cancelId)
        {
            Session session = ThrowIfNotConnected();
            
            // create the update requests.
            List<HdaUpdateRequest> requests = CreateUpdateRequests(
                session,
                updateType,
                serverHandles,
                values);

            // queue the transaction.
            int[] errors = CreateTransaction(
                TransationType.Update,
                transactionId, 
                requests,
                out cancelId);

            // return the initial results.
            return errors;
        }
Example #19
0
        /// <summary>
        /// Starts an asynchronous write operation.
        /// </summary>
        /// <param name="transactionId">The transaction id.</param>
        /// <param name="serverHandles">The server handles.</param>
        /// <param name="values">The values.</param>
        /// <param name="cancelId">The cancel id.</param>
        /// <returns>Any errors.</returns>
        public int[] AsyncWrite(int transactionId, int[] serverHandles, DaValue[] values, out int cancelId)
        {
            TraceState("AsyncWrite", transactionId, serverHandles.Length);
            ThrowIfDisposed();

            cancelId = 0;

            lock (m_lock)
            {
                int[] results = new int[serverHandles.Length];
                List<ComDaGroupItem> items = new List<ComDaGroupItem>(serverHandles.Length);
                List<DaValue> valuesToWrite = new List<DaValue>(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.Add(item);
                    valuesToWrite.Add(values[ii]);
                }

                if (items.Count > 0)
                {
                    ComDaAsnycWriteRequest request = new ComDaAsnycWriteRequest();

                    request.CancelId = ++m_transactionCounter;
                    request.TransactionId = transactionId;
                    request.ServerHandles = new int[items.Count];
                    request.ClientHandles = new int[items.Count];
                    request.Values = valuesToWrite.ToArray();

                    for (int ii = 0; ii < items.Count; ii++)
                    {
                        request.ServerHandles[ii] = items[ii].ServerHandle;
                        request.ClientHandles[ii] = items[ii].ClientHandle;
                    }

                    m_requests.Add(request);
                    cancelId = request.CancelId;

                    TraceState("AsyncWrite Queued", transactionId, request.CancelId);

                    // create a thread to process the request.
                    Thread thread = new Thread(OnAsyncWrite);
                    thread.IsBackground = true;
                    thread.Start(request);
                }

                return results;
            }
        }
Example #20
0
        /// <summary>
        /// Converts a UA value to an HDA attribute value.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="mapper">The mapper.</param>
        /// <param name="attributeId">The attribute id.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        internal static DaValue GetAttributeValue(Session session, ComNamespaceMapper mapper, uint attributeId, DataValue value)
        {
            switch (attributeId)
            {
                case INTERNAL_ATTRIBUTE_ANNOTATION:
                {
                    DaValue result = new DaValue();

                    Annotation annotation = value.GetValue<Annotation>(null);

                    if (annotation == null)
                    {
                        result.Error = ResultIds.E_BADTYPE;
                        return result;
                    }

                    result.Value = annotation;
                    result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode);
                    result.Timestamp = value.SourceTimestamp;
                    result.Error = ResultIds.S_OK;

                    return result;
                }

                case Constants.OPCHDA_ENG_UNITS:
                {
                    DaValue result = new DaValue();

                    EUInformation engineeringUnits = value.GetValue<EUInformation>(null);

                    if (engineeringUnits == null)
                    {
                        result.Error = ResultIds.E_INVALIDATTRID;
                        return result;
                    }

                    if (engineeringUnits.DisplayName != null)
                    {
                        result.Value = engineeringUnits.DisplayName.Text;
                    }

                    result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode);
                    result.Timestamp = value.SourceTimestamp;
                    result.Error = ResultIds.S_OK;

                    return result;
                }

                case Constants.OPCHDA_HIGH_ENTRY_LIMIT:
                case Constants.OPCHDA_NORMAL_MAXIMUM:
                {
                    DaValue result = new DaValue();

                    Range range = value.GetValue<Range>(null);

                    if (range == null)
                    {
                        result.Error = ResultIds.E_INVALIDATTRID;
                        return result;
                    }

                    result.Value = range.High;
                    result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode);
                    result.Timestamp = value.SourceTimestamp;
                    result.Error = ResultIds.S_OK;

                    return result;
                }

                case Constants.OPCHDA_LOW_ENTRY_LIMIT:
                case Constants.OPCHDA_NORMAL_MINIMUM:
                {
                    DaValue result = new DaValue();

                    Range range = value.GetValue<Range>(null);

                    if (range == null)
                    {
                        result.Error = ResultIds.E_INVALIDATTRID;
                        return result;
                    }

                    result.Value = range.Low;
                    result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode);
                    result.Timestamp = value.SourceTimestamp;
                    result.Error = ResultIds.S_OK;

                    return result;
                }

                case Constants.OPCHDA_MAX_TIME_INT:
                case Constants.OPCHDA_MIN_TIME_INT:
                {
                    DaValue result = new DaValue();

                    int error = ComHdaProxy.MapReadStatusToErrorCode(value.StatusCode);

                    if (error < 0)
                    {
                        result.Error = error;
                        return result;
                    }

                    // need to support the VT_CY type.
                    result.Value = (decimal)value.GetValue<double>(0);
                    result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode);
                    result.Timestamp = value.SourceTimestamp;
                    result.Error = ResultIds.S_OK;

                    return result;
                }

                default:
                case Constants.OPCHDA_ITEMID:
                case Constants.OPCHDA_ARCHIVING:
                case Constants.OPCHDA_STEPPED:
                case Constants.OPCHDA_EXCEPTION_DEV:
                case Constants.OPCHDA_EXCEPTION_DEV_TYPE:
                case Constants.OPCHDA_DERIVE_EQUATION:
                {
                    return mapper.GetLocalDataValue(value);
                }
            }
        }
Example #21
0
        /// <summary>
        /// Updates the cache with quality.
        /// </summary>
        /// <param name="quality">The quality.</param>
        public void UpdateCacheWithQuality(short quality)
        {
            lock (m_lock)
            {
                DateTime now = DateTime.UtcNow;

                foreach (ComDaGroupItem item in m_itemsByHandle.Values)
                {
                    if (null == item.CacheEntry) continue;
                    DaValue value = new DaValue();
                    item.CacheEntry.GetLatest(value);
                    value.Quality = quality;
                    value.Timestamp = now;
                    UpdateCache(item, value, false);
                }
            }
        }
Example #22
0
        /// <summary>
        /// Called when a data change event arrives.
        /// </summary>
        /// <param name="clientHandles">The client handles.</param>
        /// <param name="values">The values.</param>
        internal void OnDataChange(int[] clientHandles, DaValue[] values)
        {
            // check if callbacks are enabled.
            if (m_monitoredItems == null)
            {
                return;
            }

            // lookup client handle a report change directly to monitored item.
            lock (m_monitoredItems)
            {
                for (int ii = 0; ii < clientHandles.Length; ii++)
                {
                    DataChangeInfo info = null;

                    if (!m_monitoredItems.TryGetValue(clientHandles[ii], out info))
                    {
                        continue;
                    }

                    MonitoredItem[] monitoredItems = info.MonitoredItems;

                    // convert the value to a UA value.
                    info.LastValue = new DataValue();
                    info.LastError = ReadRequest.GetItemValue(values[ii], info.LastValue, DiagnosticsMasks.All);
                    info.LastValue.ServerTimestamp = DateTime.UtcNow;

                    // queue the values.
                    for (int jj = 0; jj < monitoredItems.Length; jj++)
                    {

                        if (info.LastValue.Value.GetType().IsArray
                            && monitoredItems[jj].IndexRange.Count != info.LastValue.Value.GetType().GetArrayRank()
                            && StatusCode.IsBad(info.LastValue.StatusCode))
                        {
                            info.LastValue.StatusCode = StatusCodes.BadIndexRangeNoData;
                        }

                        monitoredItems[jj].QueueValue(info.LastValue, info.LastError);
                    }
                }
            }
        }
Example #23
0
        /// <summary>
        /// Called when it is time to send an update.
        /// </summary>
        /// <param name="state">The state.</param>
        private void OnUpdate(object state)
        {
            try
            {
                IComDaGroupCallback callback = null;
                List<int> clientHandles = null;
                List<DaValue> values = null;
                long now = HiResClock.UtcNow.Ticks;

                lock (m_lock)
                {
                    // check if updates are required.
                    if (!AreUpdatesRequired || m_updateInProgress)
                    {
                        TraceState("OnUpdate Skipped");
                        return;
                    }

                    // check if enough time has elapsed.
                    if (m_nextUpdateTime == -1 || m_nextUpdateTime > (now + 50*TimeSpan.TicksPerMillisecond))
                    {             
                        return;
                    }

                    // Utils.Trace("NextUpdateTime={0:mm:ss.fff}, CurrentTime={1:mm:ss.fff}", new DateTime(m_nextUpdateTime), new DateTime(now));

                    // collect values to report.
                    for (int ii = 0; ii < m_items.Count; ii++)
                    {
                        ComDaGroupItem item = m_items[ii];

                        if (!item.Active)
                        {
                            continue;
                        }

                        if (item.CacheEntry == null || !item.CacheEntry.Changed)
                        {
                            continue;
                        }

                        // write buffered values first.
                        DaValue value = null;

                        if (item.CacheEntry.NextEntry != null)
                        {
                            Stack<DaCacheValue> stack = new Stack<DaCacheValue>();

                            for (DaCacheValue entry = item.CacheEntry; entry != null; entry = entry.NextEntry)
                            {
                                stack.Push(entry);
                            }

                            while (stack.Count > 1)
                            {
                                DaCacheValue entry = stack.Pop();

                                value = new DaValue();
                                entry.GetLatest(value);
                                UpdateReadResult(item, value);

                                if (item.LastSentValue != null)
                                {
                                    if (value.Quality == item.LastSentValue.Quality)
                                    {
                                        if (Utils.IsEqual(item.LastSentValue.Value, value.Value))
                                        {
                                            continue;
                                        }
                                    }
                                }

                                if (clientHandles == null)
                                {
                                    clientHandles = new List<int>();
                                    values = new List<DaValue>();
                                }

                                clientHandles.Add(item.ClientHandle);
                                values.Add(value);
                                item.LastSentValue = value;

                                /*
                                TraceState(
                                    "OnUpdate BUFFERED VALUE",
                                    this.m_serverHandle,
                                    item.ServerHandle,
                                    item.ClientHandle,
                                    new Variant(value.Value),
                                    value.Timestamp.ToString("HH:mm:ss.fff"),
                                    item.CacheEntry.Changed);
                                */
                            }

                            // clear cache.
                            item.CacheEntry.NextEntry = null;
                        }

                        // check if enough time has elapsed for this item (used if the sampling rate > update rate).
                        if (item.NextUpdateTime != -1 && item.NextUpdateTime > now)
                        {
                            continue;
                        }

                        // add latest values.
                        value = new DaValue();
                        item.CacheEntry.GetLatest(value);
                        UpdateReadResult(item, value);

                        if (item.LastSentValue != null)
                        {
                            if (value.Quality == item.LastSentValue.Quality)
                            {
                                if (Utils.IsEqual(item.LastSentValue.Value, value.Value))
                                {
                                    item.CacheEntry.Changed = false;
                                    continue;
                                }
                            }
                        }

                        if (clientHandles == null)
                        {
                            clientHandles = new List<int>();
                            values = new List<DaValue>();
                        }

                        clientHandles.Add(item.ClientHandle);
                        values.Add(value);
                        item.LastSentValue = value;

                        /*
                        TraceState(
                            "OnUpdate LATEST VALUE",
                            this.m_serverHandle,
                            item.ServerHandle,
                            item.ClientHandle,
                            new Variant(value.Value),
                            value.Timestamp.ToString("HH:mm:ss.fff"),
                            item.CacheEntry.Changed);
                        */

                        // clear change flag.
                        item.CacheEntry.Changed = false;
                    }

                    // nothing to report unless the keep alive expired.
                    if (clientHandles == null || clientHandles.Count == 0)
                    {
                        if (m_keepAliveTime == 0 || m_lastUpdateTime + m_keepAliveTime*TimeSpan.TicksPerMillisecond > now)
                        {
                            ScheduleNextUpdate();
                            return;
                        }
                    }

                    callback = m_callback;
                    m_updateInProgress = true;
                    m_lastUpdateTime = now;

                    // schedule next update.
                    ScheduleNextUpdate();
                }

                // send callback.
                try
                {
                    callback.ReadCompleted(
                        this.m_clientHandle,
                        false,
                        0,
                        0,
                        (clientHandles != null) ? clientHandles.ToArray() : new int[0],
                        (values != null) ? values.ToArray() : new DaValue[0]);

                    if (clientHandles.Count > 0)
                    {
                        m_manager.SetLastUpdateTime();
                    }
                    
                    /*
                    TraceState(
                        "OnUpdate Completed", 
                        this.m_serverHandle,
                        (values != null && values.Count > 0)?values[0].Value:"null", 
                        (m_nextUpdateTime-now)/TimeSpan.TicksPerMillisecond);
                    */
                }
                finally
                {
                    lock (m_lock)
                    {
                        m_updateInProgress = false;
                    }
                }
            }
            catch (Exception e)
            {
                Utils.Trace("Unexpected error during GroupUpdate. {0}", e.Message);
            }
        }
Example #24
0
        /// <summary>
        /// Unmarshals and deallocates a OPCITEMSTATE structures.
        /// </summary>
        internal static DaValue[] GetItemValues(ref IntPtr pInput, int count, bool deallocate)
        {
            DaValue[] output = null;

            if (pInput != IntPtr.Zero && count > 0)
            {
                output = new DaValue[count];

                IntPtr pos = pInput;

                for (int ii = 0; ii < count; ii++)
                {
                    OpcRcw.Da.OPCITEMSTATE result = (OpcRcw.Da.OPCITEMSTATE)Marshal.PtrToStructure(pos, typeof(OpcRcw.Da.OPCITEMSTATE));

                    DaValue value = new DaValue();

                    value.Value = ComUtils.ProcessComValue(result.vDataValue);
                    value.Quality = result.wQuality;
                    value.Timestamp = ComUtils.GetDateTime(result.ftTimeStamp);

                    output[ii] = value;

                    if (deallocate)
                    {
                        Marshal.DestroyStructure(pos, typeof(OpcRcw.Da.OPCITEMSTATE));
                    }

                    pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMSTATE)));
                }

                if (deallocate)
                {
                    Marshal.FreeCoTaskMem(pInput);
                    pInput = IntPtr.Zero;
                }
            }

            return output;
        }
Example #25
0
        /// <summary>
        /// Gets the property value from the browse element.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="propertyId">The property id.</param>
        /// <returns>The value containing the property value.</returns>
        private DaValue GetPropertyValue(BrowseElement element, int propertyId)
        {
            DaValue value = new DaValue();
            value.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD;
            value.Timestamp = element.CacheTimestamp;

            // check for objects - they only support the description property.
            if (element.NodeClass == NodeClass.Object)
            {
                switch (propertyId)
                {
                    case PropertyIds.Description: { value.Value = element.BrowseName; break; }
                    case PropertyIds.UaBrowseName: { value.Value = element.UaBrowseName; break; }
                    case PropertyIds.UaDescription: { value.Value = element.UaDescription; break; }

                    default:
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        return value;
                    }
                }

                return value;
            }

            // handle variable properties.
            switch (propertyId)
            {
                case PropertyIds.Description: { value.Value = element.BrowseName; break; }
                case PropertyIds.DataType: { value.Value = element.CanonicalDataType; break; }
                case PropertyIds.ScanRate: { value.Value = element.ScanRate; break; }
                case PropertyIds.AccessRights: { value.Value = element.AccessRights; break; }
                case PropertyIds.EuType: { value.Value = element.EuType; break; }
                case PropertyIds.EuInfo: { value.Value = element.EuInfo; break; }
                case PropertyIds.UaBuiltInType: { value.Value = (int)element.BuiltInType; break; }
                case PropertyIds.UaDataTypeId: { value.Value = element.DataTypeId; break; }
                case PropertyIds.UaValueRank: { value.Value = element.ValueRank; break; }
                case PropertyIds.UaBrowseName: { value.Value = element.UaBrowseName; break; }
                case PropertyIds.UaDescription: { value.Value = element.UaDescription; break; }

                case PropertyIds.EngineeringUnits:
                {
                    if (element.EngineeringUnits == null)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.EngineeringUnits;
                    value.Value = element.EngineeringUnits;
                    break;
                }

                case PropertyIds.HighEU: 
                {
                    if (element.HighEU == Double.MaxValue)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.HighEU;
                    break;
                }

                case PropertyIds.LowEU:
                {
                    if (element.LowEU == Double.MaxValue)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.LowEU;
                    break;
                }

                case PropertyIds.HighIR:
                {
                    if (element.HighIR == Double.MaxValue)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.HighIR;
                    break;
                }

                case PropertyIds.LowIR:
                {
                    if (element.LowIR == Double.MaxValue)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.LowIR;
                    break;
                }

                case PropertyIds.CloseLabel:
                {
                    if (element.CloseLabel == null)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.CloseLabel;
                    break;
                }

                case PropertyIds.OpenLabel:
                {
                    if (element.OpenLabel == null)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.OpenLabel;
                    break;
                }

                case PropertyIds.TimeZone:
                {
                    if (element.TimeZone == Int32.MaxValue)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.TimeZone;
                    break;
                }
                
                case PropertyIds.Value:
                {
                    if (element.LastValue == null)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.LastValue.Value;
                    break;
                }

                case PropertyIds.Quality:
                {
                    if (element.LastValue == null)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.LastValue.Quality;
                    break;
                }

                case PropertyIds.Timestamp:
                {
                    if (element.LastValue == null)
                    {
                        value.Error = ResultIds.E_INVALID_PID;
                        break;
                    }

                    value.Value = element.LastValue.Timestamp;
                    break;
                }

                default:
                {
                    value.Error = ResultIds.E_INVALID_PID;
                    break;
                }
            }

            return value;
        }
Example #26
0
        /// <summary>
        /// Writes the values for the specified item ids.
        /// </summary>
        /// <param name="itemIds">The item ids.</param>
        /// <param name="values">The values.</param>
        /// <returns>The results.</returns>
        public int[] Write(string[] itemIds, DaValue[] values)
        {
            int[] results = new int[itemIds.Length];
            WriteValueCollection valuesToWrite = new WriteValueCollection();

            ComDaReadPropertiesRequest[] requests = new ComDaReadPropertiesRequest[values.Length];
            
            // prepare request.
            for (int ii = 0; ii < itemIds.Length; ii++)
            {
                ComDaReadPropertiesRequest request = requests[ii] = new ComDaReadPropertiesRequest();
                request.ItemId = itemIds[ii];
            }

            // need to get the data type of the remote node.
            m_browseManager.GetPropertyValues(Session, requests, PropertyIds.UaBuiltInType, PropertyIds.UaValueRank);

            // validate items.
            for (int ii = 0; ii < requests.Length; ii++)
            {
                ComDaReadPropertiesRequest request = requests[ii];

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

                int? builtInType = request.Values[0].Value as int?;
                int? valueRank = request.Values[1].Value as int?;

                if (builtInType == null || valueRank == null)
                {
                    results[ii] = ResultIds.E_UNKNOWNITEMID;
                    continue;
                }

                // convert value to UA data type.
                WriteValue valueToWrite = new WriteValue();

                valueToWrite.NodeId = m_mapper.GetRemoteNodeId(itemIds[ii]);
                valueToWrite.AttributeId = Attributes.Value;
                valueToWrite.Handle = ii;

                // convert value to UA data type.
                try
                {
                    TypeInfo remoteType = new TypeInfo((BuiltInType)builtInType.Value, valueRank.Value);
                    valueToWrite.Value = m_mapper.GetRemoteDataValue(values[ii], remoteType);
                }
                catch (Exception e)
                {
                    results[ii] = ComUtils.GetErrorCode(e, ResultIds.E_BADTYPE);
                    continue;
                }

                valuesToWrite.Add(valueToWrite);
            }

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

            // write the values to the server.
            int[] remoteResults = m_groupManager.Write(valuesToWrite);

            // copy results.
            for (int ii = 0; ii < valuesToWrite.Count; ii++)
            {
                results[(int)valuesToWrite[ii].Handle] = remoteResults[ii];
            }

            return results;
        }
        /// <summary>
        /// Gets the local data value.
        /// </summary>
        /// <param name="remoteValue">The remote value.</param>
        /// <returns>The local data value.</returns>
        public DaValue GetLocalDataValue(DataValue remoteValue)
        {
            DaValue localValue = new DaValue();

            localValue.Error = ComDaProxy.MapReadStatusToErrorCode(remoteValue.StatusCode);

            if (localValue.Error >= 0)
            {
                localValue.HdaQuality = ComUtils.GetHdaQualityCode(remoteValue.StatusCode);
                localValue.Timestamp = remoteValue.SourceTimestamp;
                localValue.Error = ResultIds.S_OK;

                if (localValue.Timestamp == DateTime.MinValue)
                {
                    localValue.Timestamp = remoteValue.ServerTimestamp;
                }

                try
                {
                    localValue.Value = GetLocalValue(remoteValue.WrappedValue);
                }
                catch
                {
                    localValue.Error = ResultIds.E_BADTYPE;
                }
            }

            return localValue;
        }