示例#1
0
        /// <summary>
        ///     <para> This callback method is implemented by the client to receive alarms and events. </para>
        ///     <para>
        ///         Servers send event messages to the client via this interface. Event messages are sent when there has been a
        ///         change to the specified event list. A new alarm or event that has been added to the list, a change to an alarm
        ///         already in the list, or the deletion of an alarm from the list constitutes a change to the list.
        ///     </para>
        ///     <para>
        ///         Once an event has been reported from the list, it is automatically deleted from the list. Alarms are only
        ///         deleted from the list when they transition to inactive and acknowledged.
        ///     </para>
        /// </summary>
        /// <param name="contextId"> The context identifier. </param>
        /// <param name="clientListId"> The client identifier of the list for which alarms/events are being reported. </param>
        /// <param name="eventsArray"> The list of alarms/events are being reported. </param>
        void ICallback.EventNotification(string contextId, uint clientListId, EventMessage[] eventsArray)
        {
            XiContext?context = XiContext.LookUpContext(contextId);

            if (context is not null)
            {
                context.NotifyCallbackRecieved();
                _xiCallbackDoer.BeginInvoke(ct => context.EventMessagesCallback(clientListId, eventsArray));
            }
        }
示例#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>
        ///     This method returns the results of invoking an asynchronous passthrough.
        /// </summary>
        /// <param name="contextId"> The context identifier. </param>
        /// <param name="invokeId"> The identifier for this invocation of the passthrough defined by the client in the request. </param>
        /// <param name="passthroughResult">
        ///     The result of executing the passthrough, consisting of the result code, the invokeId
        ///     supplied in the request, and a byte array. It is up to the client application to interpret this byte array.
        /// </param>
        void ICallback.PassthroughCallback(string contextId, int invokeId, PassthroughResult passthroughResult)
        {
            XiContext?context = XiContext.LookUpContext(contextId);

            if (context is not null)
            {
                context.NotifyCallbackRecieved();
                _xiCallbackDoer.BeginInvoke(ct => context.PassthroughCallback(invokeId, passthroughResult));
            }
        }
示例#4
0
        /// <summary>
        ///     <para>
        ///         This callback method is implemented by the client to be notified when the server server state changes to
        ///         Aborting. Clients that use the poll interface instead of this callback interface can add the ServerDescription
        ///         object to a data object list to be notified when the server state transitions to the aborting state.
        ///     </para>
        /// </summary>
        /// <param name="contextId"> The context identifier. </param>
        /// <param name="serverStatus"> The ServerStatus object that describes the server that is shutting down. </param>
        /// <param name="reason"> The reason the context is being closed. </param>
        void ICallback.Abort(string contextId, ServerStatus serverStatus, string reason)
        {
            XiContext?context = XiContext.LookUpContext(contextId);

            if (context is not null)
            {
                context.ServerContextIsClosing = true;
                context.NotifyCallbackRecieved();
                _xiCallbackDoer.BeginInvoke(ct => context.Abort(serverStatus, reason));
            }
        }
示例#5
0
 /// <summary>
 ///     Xi List Base is the common base class for all Xi Lists defined within
 ///     the Client Base Assembly.
 /// </summary>
 /// <param name="context"> </param>
 protected XiListRoot(XiContext context)
 {
     _context = context;
 }
        //connect to the OPC.NET server and get a read endpoint
        public bool Connect()
        {
            //set this to point to your OPC.Net server
            string serverUrl = "http://localhost:58080/XiServices/ServerDiscovery";

            bool bReturnVal = false;

            try
            {
                Console.WriteLine("Getting Endpoint Discovery from server:\n{0}\n", serverUrl);

                //This class is used to locate a server and obtain its list of ServiceEndpoints.
                iEndpointDiscovery = new XiEndpointDiscovery(serverUrl) as IXiEndpointDiscovery;

                //we have the server...now check for endpoints
                //there should always be TCP endpoints for a DeltaV OPC.NET server so we do not search HTTP and Named Pipes to find one
                //and we do not consider choosing the fastest option between the three (TCP/HTTP/NamedPipes). We just use the TCP/IP one.

                // GetServiceEndpointsByBinding searches the list of endpoints on the XiEndpointDiscovery connection with the specified contractType and binding type.
                // We use the ResourceManagement endpoint to find the the other open endpoints on the server (some might be disabled)
                IEnumerable <ServiceEndpoint> resourceEndpoints = iEndpointDiscovery.GetServiceEndpointsByBinding(typeof(IResourceManagement).Name, typeof(System.ServiceModel.NetTcpBinding));

                //use the first (probably only) resource endpoint for TCP/IP to open a context between client and server
                if ((resourceEndpoints != null) && (resourceEndpoints.Count() > 0))
                {
                    var serviceEndpoints = resourceEndpoints as IList <ServiceEndpoint> ?? resourceEndpoints.ToList();


                    //pick the first RM endpoint we found
                    RMSvcEndpt = ((IList <ServiceEndpoint>)serviceEndpoints).First();

                    //Open the Context using the RM endpoint and some other values including timeout, what we want to read (HDA), and the GUID for this context
                    Console.WriteLine("Opening Client Context with Initiate\n");
                    iContext = XiContext.Initiate(RMSvcEndpt,
                                                  iEndpointDiscovery.ServerEntry,
                                                  300000,
                                                  (uint)ContextOptions.EnableJournalDataAccess,             //HDA
                                                  (uint)System.Threading.Thread.CurrentThread.CurrentCulture.LCID,
                                                  Guid.NewGuid().ToString());

                    if (iContext != null)
                    {
                        //find a read endpoint using the XiEndpointDiscovery connection
                        IEnumerable <ServiceEndpoint> readseps = iEndpointDiscovery.GetServiceEndpointsByBinding(typeof(IRead).Name, RMSvcEndpt.Binding.GetType());

                        //if we found at least one read endpoint, connect the context to it
                        readEndpoint = null;
                        if (readseps != null)
                        {
                            Console.WriteLine("Adding Read endpoint to Context\n");
                            ServiceEndpoint sep = readseps.ElementAt <ServiceEndpoint>(0);
                            readEndpoint = iContext.OpenEndpoint(sep, 30000, new TimeSpan(5000));

                            if (readEndpoint != null)
                            {
                                bReturnVal = true;            //everything went OK
                            }
                            else
                            {
                                Console.WriteLine("Unable to add Read endpoint to Context\n");
                                bReturnVal = false;            //failed
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("Unable to open Client Context\n");
                        bReturnVal = false;
                    }
                }
            }
            catch (Exception)
            {
                bReturnVal = false;
            }

            return(bReturnVal);
        }
示例#7
0
 /// <summary>
 ///     This constructor creates a new Data List.
 /// </summary>
 /// <param name="context"> The context to which this data lList belongs. </param>
 /// <param name="updateRate"> The UpdateRate for this data list. </param>
 /// <param name="bufferingRate"> The BufferingRate for this data list. Set to 0 if not used. </param>
 /// <param name="filterSet"> The FilterSet for this data list. Set to null if not used. </param>
 public XiDataList(XiContext context, uint updateRate, uint bufferingRate, FilterSet?filterSet)
     : base(context)
 {
     StandardListType = global::Xi.Contracts.Constants.StandardListType.DataList;
     ListAttributes   = Context.DefineList(this, updateRate, bufferingRate, filterSet);
 }
 /// <summary>
 ///     This constructor creates a new data journal list for the specified context.
 /// </summary>
 /// <param name="context"> The context that owns the data journal list. </param>
 /// <param name="updateRate"> The update rate for the data journal list. </param>
 /// <param name="bufferingRate"> The BufferingRate for this data journal list. Set to 0 if not used. </param>
 /// <param name="filterSet"> The FilterSet for this data journal list. Set to null if not used. </param>
 internal XiDataJournalList(XiContext context, uint updateRate, uint bufferingRate, FilterSet?filterSet)
     : base(context)
 {
     StandardListType = StandardListType.DataJournalList;
     ListAttributes   = Context.DefineList(this, updateRate, bufferingRate, filterSet);
 }
示例#9
0
 /// <summary>
 ///     Xi List Base is the common base class for all Xi Lists defined within
 ///     the Client Base Assembly.
 /// </summary>
 /// <param name="context"> </param>
 protected internal XiDataAndDataJournalListBase(XiContext context)
     : base(context)
 {
 }
示例#10
0
        /// <summary>
        ///     This method is used to connect to the server and establish a context with it.
        /// </summary>
        public void InitiateXiContext(string serverDiscoveryEndpointHttpUrl, string applicationName,
                                      string workstationName, IDispatcher xiCallbackDoer)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(@"Cannot access a disposed XiServerProxy.");
            }

            if (_context is not null)
            {
                throw new Exception(@"Xi context already exists.");
            }

            var binding = new BasicHttpBinding(BasicHttpSecurityMode.None)
            {
                //HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
                ReceiveTimeout         = new TimeSpan(00, 10, 00),
                SendTimeout            = new TimeSpan(00, 10, 00),
                OpenTimeout            = new TimeSpan(00, 10, 00),
                CloseTimeout           = new TimeSpan(00, 10, 00),
                MaxReceivedMessageSize = 65536,
                MaxBufferSize          = 65536,
                MaxBufferPoolSize      = 524288,
                TransferMode           = TransferMode.Buffered,
                //MessageEncoding = WSMessageEncoding.Text,
                TextEncoding       = Encoding.UTF8,
                BypassProxyOnLocal = false,
                UseDefaultWebProxy = true
            };

            ServerEntry?serverEntry = null;
            List <EndpointConfigurationEx> endpointConfigurationExList = new List <EndpointConfigurationEx>();

            using (var cfIServerDiscovery = new ChannelFactory <IServerDiscovery>(binding, new EndpointAddress(serverDiscoveryEndpointHttpUrl)))
            {
                IServerDiscovery newServer = cfIServerDiscovery.CreateChannel();

                // Get its server item
                serverEntry = newServer.DiscoverServerInfo();
                endpointConfigurationExList = newServer.DiscoverAbbreviatedEndpointInfo();
                cfIServerDiscovery.Close();
            }

            // Servers behind a NAT firewall may not know their "outside"
            // IP address, so update the ServerDescription.ServerDiscoveryURL
            // with the one just used, and make sure there is a Mex URL with
            // hostname/IP address used in this URL
            //ServerUri.ReconcileServerEntryWithServerDiscoveryUrl(serverEntry, serverDiscoveryEndpointHttpUrl);

            if (serverEntry is null)
            {
                throw new Exception(@"The requried Server Entry is null.");
            }

            var serverDiscoveryEndpointHttpUri = new Uri(serverDiscoveryEndpointHttpUrl);

            try
            {
                _xiServerInfo = new XiServerInfo(serverEntry, endpointConfigurationExList, serverDiscoveryEndpointHttpUri.Host);
            }
            catch (Exception ex)
            {
                var sb =
                    new StringBuilder("The Xi Server could not be found - it may not be running. \n Details:\n");
                sb.Append(ex.Message);
                sb.Append("\nError During Server Endpoint Discovery");
                throw new Exception(sb.ToString(), ex);
            }

            try
            {
                foreach (
                    ServiceEndpoint resourceManagementServiceEndpoint in
                    _xiServerInfo.ResourceManagementServiceEndpoints)
                {
                    try
                    {
                        _context = new XiContext(_xiServerInfo, resourceManagementServiceEndpoint,
                                                 (uint)_contextTimeout.TotalMilliseconds,
                                                 _contextOptions, _localeId, applicationName, workstationName, _keepAliveSkipCount,
                                                 _callbackRate, xiCallbackDoer);

                        _xiServerInfo.RankReadWriteSubscribeEndpoints(resourceManagementServiceEndpoint);

                        _context.ContextNotifyEvent += XiContext_ContextNotifyEvent;

                        break;
                    }
                    catch (ResourceManagementInitiateException)
                    {
                        throw;
                    }
                    catch (SecurityNegotiationException)
                    {
                        throw;
                    }
                    catch
                    {
                        //Logger?.LogDebug(e, "Exception while connecting to {0}", resourceManagementServiceEndpoint.Address);
                    }
                }

                if (_context is null)
                {
                    throw new Exception("Failed to connect to the Xi Server.");
                }
            }
            catch
            {
                if (_context is not null)
                {
                    _context.ContextNotifyEvent -= XiContext_ContextNotifyEvent;
                    _context.Dispose();
                    _context = null;
                }

                _xiServerInfo.Dispose();
                _xiServerInfo = null;

                throw;
            }
        }