예제 #1
0
        /// <summary>
        ///     This method is used to write data of the specified list to the server.  It is called
        ///     by the ClientBase after the client application has prepared and committed the data
        ///     values.
        /// </summary>
        /// <param name="serverListId"> The server identifier of the list containing the data objects to write. </param>
        /// <param name="writeValueArrays"> The data values to write. </param>
        /// <returns>
        ///     The list server aliases and result codes for the data objects whose write failed. Returns null if all writes
        ///     succeeded or null if this is a keep-alive.
        /// </returns>
        public List <AliasResult>?WriteData(uint serverListId, DataValueArraysWithAlias writeValueArrays)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("Cannot access a disposed XiContext.");
            }

            if (_writeEndpoint is null)
            {
                throw new Exception("No Write Endpoint");
            }

            if (_writeEndpoint.Disposed)
            {
                return(null);
            }

            IWrite iWrite    = _writeEndpoint.Proxy;
            string contextId = ContextId;

            _writeEndpoint.LastCallUtc = DateTime.UtcNow;

            List <AliasResult>?listAliasResult = null;

            try
            {
                listAliasResult = iWrite.WriteVST(contextId, serverListId, writeValueArrays);
            }
            catch (Exception ex)
            {
                ProcessRemoteMethodCallException(ex);
            }

            return(listAliasResult);
        }
예제 #2
0
        /// <summary>
        ///     <para> This callback method is implemented by the client to receive data changes. </para>
        ///     <para>
        ///         Servers send data changes to the client that have not been reported to the client via this method. Changes
        ///         consists of:
        ///     </para>
        ///     <para> 1) values for data objects that were added to the list, </para>
        ///     <para>
        ///         2) values for data objects whose current values have changed since the last time they were reported to the
        ///         client via this interface. If a deadband filter has been defined for the list, floating point values are not
        ///         considered to have changed unless they have changed by the deadband amount.
        ///     </para>
        ///     <para> 3) historical values that meet the list filter criteria, including the deadband. </para>
        ///     <para>
        ///         In addition, the server may insert a special value that indicates the server or one of its wrapped servers
        ///         are shutting down.
        ///     </para>
        ///     <para>
        ///         This value is inserted as the first value in the list of values in the callback. Its ListId and ClientId are
        ///         both 0 and its data type is ServerStatus.
        ///     </para>
        /// </summary>
        /// <param name="contextId"> The context identifier. </param>
        /// <param name="clientListId"> The client identifier of the list for which data changes are being reported. </param>
        /// <param name="updatedValues"> The values being reported. </param>
        void ICallback.InformationReport(string contextId, uint clientListId, DataValueArraysWithAlias updatedValues)
        {
            XiContext?context = XiContext.LookUpContext(contextId);

            if (context is not null)
            {
                context.NotifyCallbackRecieved();
                _xiCallbackDoer.BeginInvoke(ct => context.ElementValuesCallback(clientListId, updatedValues));
            }
        }
예제 #3
0
        /// <summary>
        ///     <para> No throws.</para>
        ///     <para> This callback method is implemented by the client to receive data changes. </para>
        ///     <para>
        ///         Servers send data changes to the client that have not been reported to the client via this method. Changes
        ///         consists of:
        ///     </para>
        ///     <para> 1) values for data objects that were added to the list, </para>
        ///     <para>
        ///         2) values for data objects whose current values have changed since the last time they were reported to the
        ///         client via this interface. If a deadband filter has been defined for the list, floating point values are not
        ///         considered to have changed unless they have changed by the deadband amount.
        ///     </para>
        ///     <para> 3) historical values that meet the list filter criteria, including the deadband. </para>
        ///     <para>
        ///         In addition, the server may insert a special value that indicates the server or one of its wrapped servers
        ///         are shutting down.
        ///     </para>
        ///     <para>
        ///         This value is inserted as the first value in the list of values in the callback. Its ListId and ClientId are
        ///         both 0 and its data type is ServerStatus.
        ///     </para>
        /// </summary>
        /// <param name="clientListId"> The client identifier of the list for which data changes are being reported. </param>
        /// <param name="updatedValues"> The values being reported. </param>
        public void ElementValuesCallback(uint clientListId, DataValueArraysWithAlias updatedValues)
        {
            if (_disposed)
            {
                return;
            }

            if (_callbackEndpoint is not null)
            {
                _callbackEndpoint.LastCallUtc = DateTime.UtcNow;
            }

            XiDataList?datalist = GetDataList(clientListId);

            if (datalist is null)
            {
                return;
            }

            ElementValuesCallbackInternal(datalist, updatedValues);
        }
예제 #4
0
        /// <summary>
        ///     <para>
        ///         Writing data object values to the server is a two step process composed of preparing a list of data objects
        ///         to be written, followed by writing that list to the server.
        ///     </para>
        ///     <para>
        ///         This method is used in the first step to individually mark each data object in the Data List as ready for
        ///         writing. It examines all data objects in the Data List that are ready for writing and writes them to the server
        ///         .
        ///     </para>
        /// </summary>
        /// <returns>
        ///     The list of data objects whose write failed. Results are not returned data object whose writes succeeded. If
        ///     all writes succeeded, null is returned.
        /// </returns>
        public IEnumerable <IXiDataListItem>?CommitWriteDataListItems()
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("Cannot access a disposed XiDataList.");
            }

            DataValueArraysWithAlias?writeValueArrays = null;
            var writeValueDictionary = new Dictionary <uint, XiDataListItem>();

            int uintCount = 0;
            int dblCount  = 0;
            int objCount  = 0;

            foreach (XiDataListItem item in ListItemsManager)
            {
                if (item.PendingWriteValueStatusTimestamp is not null &&
                    item.PendingWriteValueStatusTimestamp.Value.ValueStatusCode != ValueStatusCode.Unknown)
                {
                    switch (item.PendingWriteValueStatusTimestamp.Value.Value.ValueStorageType)
                    {
                    case Any.StorageType.Double:
                        dblCount += 1;
                        break;

                    case Any.StorageType.UInt32:
                        uintCount += 1;
                        break;

                    case Any.StorageType.Object:
                        objCount += 1;
                        break;
                    }

                    writeValueDictionary.Add(item.ClientAlias, item);
                }
            }
            if (0 < dblCount || 0 < uintCount || 0 < objCount)
            {
                writeValueArrays = new DataValueArraysWithAlias(dblCount, uintCount, objCount);
                int intIdx = 0;
                int dblIdx = 0;
                int objIdx = 0;
                foreach (var kvp in writeValueDictionary)
                {
                    XiDataListItem item = kvp.Value;
                    if (item.PendingWriteValueStatusTimestamp is not null &&
                        item.PendingWriteValueStatusTimestamp.Value.ValueStatusCode != ValueStatusCode.Unknown)
                    {
                        var statusCode = XiStatusCode.MakeStatusCode(
                            XiStatusCode.MakeStatusByte((byte)XiStatusCodeStatusBits.GoodNonSpecific, 0),
                            XiStatusCode.MakeFlagsByte((byte)XiStatusCodeHistoricalValueType.NotUsed, false, false,
                                                       XiStatusCodeAdditionalDetailType.NotUsed),
                            0);
                        switch (item.PendingWriteValueStatusTimestamp.Value.Value.ValueStorageType)
                        {
                        case Any.StorageType.Double:
                            writeValueArrays.SetDouble(dblIdx++, item.ServerAlias,
                                                       statusCode,
                                                       item.PendingWriteValueStatusTimestamp.Value.TimestampUtc,
                                                       item.PendingWriteValueStatusTimestamp.Value.Value.StorageDouble);
                            break;

                        case Any.StorageType.UInt32:
                            writeValueArrays.SetUint(intIdx++, item.ServerAlias,
                                                     statusCode,
                                                     item.PendingWriteValueStatusTimestamp.Value.TimestampUtc,
                                                     item.PendingWriteValueStatusTimestamp.Value.Value.StorageUInt32);
                            break;

                        case Any.StorageType.Object:
                            writeValueArrays.SetObject(objIdx++, item.ServerAlias,
                                                       statusCode,
                                                       item.PendingWriteValueStatusTimestamp.Value.TimestampUtc,
                                                       item.PendingWriteValueStatusTimestamp.Value.Value.StorageObject);
                            break;
                        }
                    }
                    item.HasWritten(XiFaultCodes.S_OK);
                }
            }

            var listXiValues = new List <XiDataListItem>();

            if (writeValueArrays is not null)
            {
                List <AliasResult>?listAliasResult = Context.WriteData(ServerListId, writeValueArrays);
                if (listAliasResult is not null)
                {
                    foreach (AliasResult aliasResult in listAliasResult)
                    {
                        XiDataListItem?item = null;
                        if (writeValueDictionary.TryGetValue(aliasResult.ClientAlias, out item))
                        {
                            item.HasWritten(aliasResult.Result);
                            listXiValues.Add(item);
                        }
                    }
                }
            }
            writeValueDictionary.Clear();
            return((0 != listXiValues.Count) ? listXiValues : null);
        }