Stores the value of an HDA attribute.
        /// <summary>
        /// Nexts the value in the time series.
        /// </summary>
        private DataValue NextValue(
            ISystemContext context,
            NumericRange indexRange,
            QualifiedName dataEncoding)
        {
            DataValue value = new DataValue();

            if (m_mergedSeries == null)
            {
                // check for end of series.
                if (m_historyData == null || m_position >= m_historyData.Length)
                {
                    return(GetLastBound(context, indexRange, dataEncoding));
                }

                // process next value.
                HdaAttributeValue source = m_historyData[m_position++];
                GetAttributeValue(context, indexRange, dataEncoding, m_attributeId, value, source);

                return(value);
            }

            // check for end of series.
            if (m_mergedSeries == null || m_position >= m_mergedSeries.Count)
            {
                return(GetLastBound(context, indexRange, dataEncoding));
            }

            // process next value.
            HdaAttributeValue[] sources = m_mergedSeries[m_position++];
            GetAttributeValue(context, indexRange, dataEncoding, m_attributeId, value, sources);
            return(value);
        }
        /// <summary>
        /// Converts the attribute value to the specified type.
        /// </summary>
        protected T GetAttributeValue <T>(DataValue value, HdaAttributeValue source)
        {
            value.Value = null;

            // find the attribute value.
            if (source == null)
            {
                value.StatusCode = StatusCodes.BadOutOfService;
                return(default(T));
            }

            // set the appropriate error code if no value found.
            if (source == null || source.Error < 0 || source.Error == ResultIds.S_NODATA)
            {
                value.StatusCode = StatusCodes.BadNoData;
                return(default(T));
            }

            // update the source timestamp if a value is being read.
            value.SourceTimestamp = source.Timestamp;

            // check type conversion error.
            if (!typeof(T).IsInstanceOfType(source.Value))
            {
                value.StatusCode = StatusCodes.BadTypeMismatch;
                return(default(T));
            }

            // save the value and return the result.
            value.Value = (T)source.Value;
            return((T)source.Value);
        }
Beispiel #3
0
        /// <summary>
        /// Sets the error for all attributes.
        /// </summary>
        /// <param name="error">The error.</param>
        public void SetError(int error)
        {
            if (m_attributeIds != null)
            {
                m_attributeValues = new HdaAttributeValue[m_attributeIds.Count];

                for (int ii = 0; ii < m_attributeValues.Length; ii++)
                {
                    m_attributeValues[ii]             = new HdaAttributeValue();
                    m_attributeValues[ii].AttributeId = m_attributeIds[ii];
                    m_attributeValues[ii].Error       = error;
                }
            }
        }
        /// <summary>
        /// Sets the history for the attribute.
        /// </summary>
        public void SetHistoryResults(
            int[] attributeIds,
            HdaAttributeValue[][] results)
        {
            m_historyData = null;

            // save the primary series.
            if (results.Length > 0)
            {
                m_historyData = results[0];
            }

            // create a merged series from multiple streams.
            if (results.Length > 1)
            {
                m_mergedSeries = new List <HdaAttributeValue[]>();

                // find the first set.
                HdaAttributeValue[] tuple = new HdaAttributeValue[attributeIds.Length];

                for (int ii = 0; ii < tuple.Length; ii++)
                {
                    if (results[ii] != null)
                    {
                        tuple[ii] = results[ii][0];
                    }
                }

                m_mergedSeries.Add(tuple);

                // add in additional sets.
                int[] indexes = new int[attributeIds.Length];

                while (tuple != null)
                {
                    tuple = NextTuple(results, indexes);

                    if (tuple != null)
                    {
                        m_mergedSeries.Add(tuple);
                    }
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Gets the attribute value.
        /// </summary>
        /// <typeparam name="T">The expected type for the attribute value.</typeparam>
        /// <param name="attributeId">The attribute id.</param>
        /// <param name="value">The value to update.</param>
        /// <param name="isValue">if set to <c>true</c> if the attribute is required for the value attribute of a node.</param>
        /// <returns>The value cast to the type T.</returns>
        /// <remarks>
        /// This method sets the StatusCode in the DataValue if an error occurs and returns default(T).
        /// The DataValue.Value attribute is set to the value cast to type T.
        /// </remarks>
        public T GetAttributeValue <T>(uint attributeId, DataValue value, bool isValue)
        {
            value.Value = null;

            // find the attribute value.
            HdaAttributeValue result = GetAttributeValue(attributeId);

            if (result == null)
            {
                value.StatusCode = StatusCodes.BadOutOfService;
                return(default(T));
            }

            // set the appropriate error code if no value found.
            if (result == null || result.Error < 0 || result.Error == ResultIds.S_NODATA)
            {
                value.StatusCode = StatusCodes.BadNotFound;
                return(default(T));
            }

            // update the source timestamp if a value is being read.
            if (isValue)
            {
                value.SourceTimestamp = result.Timestamp;
            }

            // check type conversion error.
            if (!typeof(T).IsInstanceOfType(result.Value))
            {
                value.StatusCode = StatusCodes.BadTypeMismatch;
                return(default(T));
            }

            // save the value and return the result.
            value.Value = (T)result.Value;
            return((T)result.Value);
        }
Beispiel #6
0
        /// <summary>
        /// Updates the attributes for the items.
        /// </summary>
        public HdaAttributeValue[] ReadAttributeValues(int serverHandle, params int[] attributeIds)
        {
            string methodName = "IOPCHDA_SyncRead.ReadAttribute";

            OPCHDA_TIME htStartTime;
            htStartTime.bString = 1;
            htStartTime.szTime = "NOW";
            htStartTime.ftTime.dwHighDateTime = 0;
            htStartTime.ftTime.dwLowDateTime = 0;

            OPCHDA_TIME htEndTime;
            htEndTime.bString = 1;
            htEndTime.szTime = String.Empty;
            htEndTime.ftTime.dwHighDateTime = 0;
            htEndTime.ftTime.dwLowDateTime = 0;
            
            IntPtr ppAttributeValues;
            IntPtr ppErrors;

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

                server.ReadAttribute(
                    ref htStartTime,
                    ref htEndTime,
                    serverHandle,
                    attributeIds.Length,
                    attributeIds,
                    out ppAttributeValues,
                    out ppErrors);
            }
            catch (Exception e)
            {
                ComCallError(methodName, e);
                return null;
            }
            finally
            {
                EndComCall(methodName);
            }

            int[] errors = ComUtils.GetInt32s(ref ppErrors, attributeIds.Length, true);

            HdaAttributeValue[] results = new HdaAttributeValue[attributeIds.Length];
            IntPtr pos = ppAttributeValues;

            for (int ii = 0; ii < attributeIds.Length; ii++)
            {
                HdaAttributeValue result = results[ii] = new HdaAttributeValue();

                result.AttributeId = Utils.ToUInt32(attributeIds[ii]);
                result.Error = errors[ii];

                OPCHDA_ATTRIBUTE attributes = (OPCHDA_ATTRIBUTE)Marshal.PtrToStructure(pos, typeof(OPCHDA_ATTRIBUTE));

                if (attributes.dwNumValues > 0)
                {
                    object[] values = ComUtils.GetVARIANTs(ref attributes.vAttributeValues, attributes.dwNumValues, true);
                    DateTime[] timestamps = ComUtils.GetDateTimes(ref attributes.ftTimeStamps, attributes.dwNumValues, true);

                    result.Value = ComUtils.ProcessComValue(values[0]);
                    result.Timestamp = timestamps[0];
                }

                pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(OPCHDA_ATTRIBUTE)));
            }

            Marshal.FreeCoTaskMem(ppAttributeValues);

            return results;
        }
Beispiel #7
0
        /// <summary>
        /// Reads the raw modified data for an item.
        /// </summary>
        private StatusCode ReadAttributes(HdaHistoryReadAttributeRequest request, params int[] attributeIds)
        {
            string methodName = "IOPCHDA_SyncRead.ReadAttribute";

            OPCHDA_TIME htStartTime = ConvertTime(request.StartTime);
            OPCHDA_TIME htEndTime = ConvertTime(request.EndTime);

            IntPtr ppAttributeValues;
            IntPtr ppErrors;

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

                server.ReadAttribute(
                    ref htStartTime,
                    ref htEndTime,
                    request.ServerHandle,
                    attributeIds.Length,
                    attributeIds,
                    out ppAttributeValues,
                    out ppErrors);
            }
            catch (Exception e)
            {
                ComCallError(methodName, e);
                return StatusCodes.BadUnexpectedError;
            }
            finally
            {
                EndComCall(methodName);
            }

            StatusCode status = StatusCodes.Good;

            // error in one attribute means operation failed.
            int[] errors = ComUtils.GetInt32s(ref ppErrors, attributeIds.Length, true);

            for (int ii = 0; ii < errors.Length; ii++)
            {
                if (errors[ii] < 0)
                {
                    status = StatusCodes.BadNodeIdUnknown;
                    break;
                }
            }

            // unmarshal results.
            HdaAttributeValue[][] results = new HdaAttributeValue[attributeIds.Length][];
            IntPtr pos = ppAttributeValues;

            for (int ii = 0; ii < attributeIds.Length; ii++)
            {
                OPCHDA_ATTRIBUTE attributes = (OPCHDA_ATTRIBUTE)Marshal.PtrToStructure(pos, typeof(OPCHDA_ATTRIBUTE));

                if (attributes.dwNumValues > 0)
                {
                    results[ii] = new HdaAttributeValue[attributes.dwNumValues];

                    object[] values = ComUtils.GetVARIANTs(ref attributes.vAttributeValues, attributes.dwNumValues, true);
                    DateTime[] timestamps = ComUtils.GetDateTimes(ref attributes.ftTimeStamps, attributes.dwNumValues, true);

                    for (int jj = 0; jj < values.Length; jj++)
                    {
                        HdaAttributeValue result = results[ii][jj] = new HdaAttributeValue();
                        result.AttributeId = Utils.ToUInt32(attributeIds[ii]);
                        result.Value = ComUtils.ProcessComValue(values[jj]);
                        result.Timestamp = timestamps[jj];
                        result.Error = ResultIds.S_OK;
                    }
                }
                else
                {
                    results[ii] = new HdaAttributeValue[1];
                    HdaAttributeValue result = results[ii][0] = new HdaAttributeValue();
                    result.AttributeId = Utils.ToUInt32(attributeIds[ii]);
                    result.Value = null;
                    result.Timestamp = request.StartTime;
                    result.Error = ResultIds.S_NODATA;
                }
                
                pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(OPCHDA_ATTRIBUTE)));
            }

            Marshal.FreeCoTaskMem(ppAttributeValues);
            
            // save the results.
            request.SetHistoryResults(attributeIds, results);
            
            return StatusCodes.Good;
        }
        private HdaAttributeValue[] NextTuple(HdaAttributeValue[][] results, int[] indexes)
        {
            int      soonest   = -1;
            DateTime timestamp = DateTime.MaxValue;

            for (int ii = 0; ii < indexes.Length; ii++)
            {
                // get the next index for the series.
                int index = indexes[ii] + 1;

                // check if at the end of the series.
                if (index >= results[ii].Length)
                {
                    continue;
                }

                // check the timestamp.
                HdaAttributeValue value = results[ii][index];

                if (value.Timestamp < timestamp)
                {
                    timestamp = value.Timestamp;
                    soonest   = ii;
                }
            }

            // check if at end.
            if (soonest == -1)
            {
                return(null);
            }

            // increment all series with a matching timestamp.
            for (int ii = 0; ii < indexes.Length; ii++)
            {
                // get the next index for the series.
                int index = indexes[ii] + 1;

                // check if at the end of the series.
                if (index >= results[ii].Length)
                {
                    continue;
                }

                // check the timestamp.
                HdaAttributeValue value = results[ii][index];

                if (value.Timestamp == timestamp)
                {
                    indexes[ii]++;
                }
            }

            // build the tuple.
            HdaAttributeValue[] tuple = new HdaAttributeValue[indexes.Length];

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

            return(tuple);
        }
Beispiel #9
0
        /// <summary>
        /// Gets the result for the read operation.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="attribute">The attribute.</param>
        /// <param name="nodeToRead">The node to read.</param>
        /// <param name="value">The value.</param>
        /// <param name="diagnosticsMasks">The diagnostics masks.</param>
        /// <returns></returns>
        public ServiceResult GetResult(
            ISystemContext context,
            HdaAttributeState attribute,
            ReadValueId nodeToRead,
            DataValue value,
            DiagnosticsMasks diagnosticsMasks)
        {
            if (nodeToRead.AttributeId != Attributes.Value)
            {
                // check if reading access level.
                if (nodeToRead.AttributeId == Attributes.AccessLevel || nodeToRead.AttributeId == Attributes.UserAccessLevel)
                {
                    HdaAttributeValue result = GetAttributeValue(attribute.Attribute.Id);

                    if (result == null || result.Error < 0 || result.Error == ResultIds.S_NODATA)
                    {
                        value.StatusCode = StatusCodes.BadNotFound;
                        return(value.StatusCode);
                    }

                    value.Value = AccessLevels.CurrentRead;

                    if (result.Error != ResultIds.S_CURRENTVALUE)
                    {
                        value.Value = (byte)(AccessLevels.CurrentRead | AccessLevels.HistoryRead);
                    }

                    return(value.StatusCode);
                }

                return(StatusCodes.BadAttributeIdInvalid);
            }

            // convert values when required.
            switch (attribute.Attribute.Id)
            {
            case Constants.OPCHDA_NORMAL_MAXIMUM:
            {
                double high = this.GetAttributeValue <double>(Constants.OPCHDA_NORMAL_MAXIMUM, value, true);

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

                double low = this.GetAttributeValue <double>(Constants.OPCHDA_NORMAL_MINIMUM, value, true);

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

                value.Value = new Range(high, low);
                break;
            }

            case Constants.OPCHDA_HIGH_ENTRY_LIMIT:
            {
                double high = this.GetAttributeValue <double>(Constants.OPCHDA_HIGH_ENTRY_LIMIT, value, true);

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

                double low = this.GetAttributeValue <double>(Constants.OPCHDA_LOW_ENTRY_LIMIT, value, true);

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

                value.Value = new Range(high, low);
                break;
            }

            case Constants.OPCHDA_ENG_UNITS:
            {
                string units = this.GetAttributeValue <string>(Constants.OPCHDA_ENG_UNITS, value, true);

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

                value.Value = new EUInformation(units, Namespaces.ComInterop);
                break;
            }

            case Constants.OPCHDA_MAX_TIME_INT:
            case Constants.OPCHDA_MIN_TIME_INT:
            {
                string number = this.GetAttributeValue <string>(attribute.Attribute.Id, value, true);

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

                try
                {
                    value.Value = Convert.ToDouble(number);
                }
                catch (Exception)
                {
                    value.StatusCode = StatusCodes.BadTypeMismatch;
                    return(value.StatusCode);
                }

                break;
            }

            case Constants.OPCHDA_EXCEPTION_DEV_TYPE:
            {
                short number = this.GetAttributeValue <short>(attribute.Attribute.Id, value, true);

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

                value.Value = (int)number;
                break;
            }

            default:
            {
                object result = this.GetAttributeValue <object>(attribute.Attribute.Id, value, true);

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

                value.Value = result;
                break;
            }
            }

            // check if the attribute value is missing.
            if (value.StatusCode == StatusCodes.BadNotFound)
            {
                return(StatusCodes.BadNodeIdUnknown);
            }

            return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value));
        }
Beispiel #10
0
        /// <summary>
        /// Finds the children for hda item configuration.
        /// </summary>
        /// <param name="client">The client.</param>
        /// <param name="children">The children.</param>
        /// <param name="attributes">The attribute values.</param>
        private void FindChildrenForHdaItemConfiguration(ComHdaClient client, List<BaseInstanceState> children, HdaAttributeValue[] attributes)
        {          
            BaseInstanceState child = null;

            if (IsRequired(ReferenceTypeIds.HasProperty, false))
            {
                for (int ii = 0; ii < attributes.Length; ii++)
                {
                    if (attributes[ii].Error < 0 || attributes[ii].Error == ResultIds.S_NODATA)
                    {
                        continue;
                    }

                    bool skip = true;

                    switch (attributes[ii].AttributeId)
                    {
                        case Constants.OPCHDA_DERIVE_EQUATION:
                        case Constants.OPCHDA_STEPPED:
                        case Constants.OPCHDA_MAX_TIME_INT:
                        case Constants.OPCHDA_MIN_TIME_INT:
                        case Constants.OPCHDA_EXCEPTION_DEV:
                        case Constants.OPCHDA_EXCEPTION_DEV_TYPE:
                        {
                            skip = false;
                            break;
                        }
                    }

                    if (skip)
                    {
                        continue;
                    }

                    child = client.FindItemAttribute(m_itemId, attributes[ii].AttributeId, m_namespaceIndex);

                    if (child != null)
                    {
                        children.Add(child);
                    }
                }
            }
        }