//====================================================================== // GetStatus /// <summary> /// Returns the current server status. /// </summary> /// <returns>The current server status.</returns> public ServerStatus GetStatus() { lock (this) { if (m_proxy == null) { throw new NotConnectedException(); } OpcXml.Da10.RequestOptions options = OpcXml.Da10.Request.GetRequestOptions(m_options.Locale, m_options.Filters); OpcXml.Da10.ServerStatus remoteStatus = null; OpcXml.Da10.ReplyBase reply = m_proxy.GetStatus( options.LocaleID, options.ClientRequestHandle, out remoteStatus); CacheResponse(m_options.Locale, reply, null); // fill in the last update time. ServerStatus status = OpcXml.Da10.Request.GetServerStatus(reply, remoteStatus); status.LastUpdateTime = m_lastUpdateTime; return(status); } }
/// <summary> /// Causes the server to send a data changed notification for all active items. /// </summary> /// <param name="requestHandle">An identifier for the request assigned by the caller.</param> /// <param name="request">An object that contains the state of the request (used to cancel the request).</param> /// <returns>A set of results containing any errors encountered when the server validated the items.</returns> public virtual void Refresh( object requestHandle, out IRequest request) { lock (this) { request = null; // do nothing is subscription is no longer valid. if (m_state.ServerHandle == null) { return; } // begin the polled refresh. OpcXml.Da10.RequestOptions options = OpcXml.Da10.Request.GetRequestOptions(m_state.Locale, m_filters); // send a polled refresh that requests all items. m_proxy.BeginSubscriptionPolledRefresh( options, new string [] { (string)m_state.ServerHandle }, m_server.ServerTime, true, 0, true, new AsyncCallback(OnPollCompleted), new string[] { (string)m_state.ServerHandle, options.LocaleID, null }); } }
//====================================================================== // Write /// <summary> /// Writes the value, quality and timestamp for a set of items. /// </summary> /// <param name="items">The set of item values to write.</param> /// <returns>The results of the write operation for each item.</returns> public IdentifiedResult[] Write(ItemValue[] items) { if (items == null) { throw new ArgumentNullException("items"); } if (items.Length == 0) { return(new Opc.IdentifiedResult[0]); } lock (this) { if (m_proxy == null) { throw new NotConnectedException(); } ItemValueList list = new ItemValueList(); list.AddRange(items); OpcXml.Da10.RequestOptions options = OpcXml.Da10.Request.GetRequestOptions(m_options.Locale, m_options.Filters); OpcXml.Da10.WriteRequestItemList requestList = OpcXml.Da10.Request.GetItemValueList(list); OpcXml.Da10.ReplyItemList replyList = null; OpcXml.Da10.OPCError[] errors = null; OpcXml.Da10.ReplyBase reply = m_proxy.Write( options, requestList, false, out replyList, out errors); CacheResponse(m_options.Locale, reply, errors); ItemValueResultList valueList = OpcXml.Da10.Request.GetResultList(replyList); if (valueList == null) { throw new InvalidResponseException(); } IdentifiedResult[] results = new IdentifiedResult[valueList.Count]; for (int ii = 0; ii < valueList.Count; ii++) { ItemValueResult valueResult = valueList[ii]; results[ii] = new IdentifiedResult(valueResult); results[ii].ResultID = valueResult.ResultID; results[ii].DiagnosticInfo = valueResult.DiagnosticInfo; } return(results); } }
//====================================================================== // Read /// <summary> /// Reads the current values for a set of items. /// </summary> /// <param name="items">The set of items to read.</param> /// <returns>The results of the read operation for each item.</returns> public Opc.Da.ItemValueResult[] Read(Item[] items) { if (items == null) { throw new ArgumentNullException("items"); } if (items.Length == 0) { return(new Opc.Da.ItemValueResult[0]); } lock (this) { if (m_proxy == null) { throw new NotConnectedException(); } ItemList list = new ItemList(); list.AddRange(items); OpcXml.Da10.RequestOptions options = OpcXml.Da10.Request.GetRequestOptions(m_options.Locale, m_options.Filters); OpcXml.Da10.ReadRequestItemList requestList = OpcXml.Da10.Request.GetItemList(list); OpcXml.Da10.ReplyItemList replyList = null; OpcXml.Da10.OPCError[] errors = null; OpcXml.Da10.ReplyBase reply = m_proxy.Read( options, requestList, out replyList, out errors); CacheResponse(m_options.Locale, reply, errors); ItemValueResultList valueList = OpcXml.Da10.Request.GetResultList(replyList); if (valueList == null) { throw new InvalidResponseException(); } return((ItemValueResult[])valueList.ToArray(typeof(ItemValueResult))); } }
/// <summary> /// Starts polling for the current subscription. /// </summary> private void Poll(object state) { lock (this) { // do nothing is subscription is no longer valid. if (m_state.ServerHandle == null) { return; } TimeSpan holdTime = TimeSpan.Zero; TimeSpan waitTime = TimeSpan.Zero; // use simple client side polling if not enabled. if (m_enabled) { // hold time is the ping rate and the wait time is zero. if (m_pingRate < m_state.UpdateRate) { holdTime = new TimeSpan(m_pingRate * 10000); waitTime = TimeSpan.Zero; } // hold time is the update rate and the wait time is ping rate minus the update rate. else { holdTime = new TimeSpan(m_state.UpdateRate * 10000); waitTime = new TimeSpan((m_pingRate - m_state.UpdateRate) * 10000); } } // begin the polled refresh. OpcXml.Da10.RequestOptions options = OpcXml.Da10.Request.GetRequestOptions(m_state.Locale, m_filters); m_proxy.BeginSubscriptionPolledRefresh( options, new string [] { (string)m_state.ServerHandle }, m_server.ServerTime.Add(holdTime), true, (int)waitTime.TotalMilliseconds, false, new AsyncCallback(OnPollCompleted), new string[] { (string)m_state.ServerHandle, options.LocaleID, "" }); } }
//====================================================================== // GetProperties /// <summary> /// Returns the item properties for a set of items. /// </summary> /// <param name="itemIDs">A list of item identifiers.</param> /// <param name="propertyIDs">A list of properties to fetch for each item.</param> /// <param name="returnValues">Whether the property values should be returned with the properties.</param> /// <returns>A list of properties for each item.</returns> public ItemPropertyCollection[] GetProperties( ItemIdentifier[] itemIDs, PropertyID[] propertyIDs, bool returnValues) { if (itemIDs == null) { throw new ArgumentNullException("itemIDs"); } if (m_proxy == null) { throw new NotConnectedException(); } lock (this) { OpcXml.Da10.RequestOptions options = OpcXml.Da10.Request.GetRequestOptions(m_options.Locale, m_options.Filters); OpcXml.Da10.PropertyReplyList[] properties = null; OpcXml.Da10.OPCError[] errors = null; OpcXml.Da10.ReplyBase reply = m_proxy.GetProperties( OpcXml.Da10.Request.GetItemIdentifiers(itemIDs), OpcXml.Da10.Request.GetPropertyNames(propertyIDs), options.LocaleID, options.ClientRequestHandle, null, (propertyIDs == null), returnValues, options.ReturnErrorText, out properties, out errors); CacheResponse(options.LocaleID, reply, errors); return(OpcXml.Da10.Request.GetItemPropertyCollections(properties)); } }
/// <summary> /// Establishes a subscription for the current set of items. /// </summary> private ItemValueResultList Subscribe(ArrayList items) { lock (this) { // cancel any current subscription. Unsubscribe(); // check if there is nothing to do. if (items == null || items.Count == 0) { return(new ItemValueResultList()); } // create a single item list and use the subscription state to set list level parameters. ItemList itemList = new ItemList(); itemList.ClientHandle = Guid.NewGuid().ToString(); itemList.ItemPath = null; itemList.ReqType = null; itemList.Deadband = m_state.Deadband; itemList.DeadbandSpecified = true; itemList.SamplingRate = m_state.UpdateRate; itemList.SamplingRateSpecified = true; itemList.EnableBuffering = false; itemList.EnableBufferingSpecified = false; // set the ping rate based on the keep alive (if specified) or five times update rate. m_pingRate = (m_state.KeepAlive != 0)?m_state.KeepAlive:m_state.UpdateRate * 5; // stop any existing timer. if (m_pollTimer != null) { m_pollTimer.Dispose(); m_pollTimer = null; } // create copies of each and replace the client handle with the server handle. foreach (Item item in items) { Item clone = (Item)item.Clone(); clone.ClientHandle = clone.ServerHandle; itemList.Add(clone); } string subscription = null; // establish the subscription on the server. OpcXml.Da10.RequestOptions options = OpcXml.Da10.Request.GetRequestOptions(m_state.Locale, m_filters); OpcXml.Da10.SubscribeReplyItemList replyList = null; OpcXml.Da10.OPCError[] errors = null; OpcXml.Da10.ReplyBase reply = m_proxy.Subscribe( options, OpcXml.Da10.Request.GetSubscribeList(itemList), true, m_pingRate * 2, out replyList, out errors, out subscription); // cache results with the server object. m_server.CacheResponse(m_state.Locale, reply, errors); // save subscription handle. m_state.ServerHandle = subscription; // check for valid response. if (replyList == null) { throw new InvalidResponseException(); } // save the revised update rate. if (replyList.RevisedSamplingRateSpecified) { m_state.UpdateRate = (int)replyList.RevisedSamplingRate; } // update items. ItemValueResultList resultList = OpcXml.Da10.Request.GetSubscribeResultList(replyList); for (int ii = 0; ii < itemList.Count; ii++) { SubscribeItemValueResult resultItem = (SubscribeItemValueResult)resultList[ii]; // restore the client/server handles in the result. resultItem.ServerHandle = resultItem.ClientHandle; resultItem.ClientHandle = ((Item)items[ii]).ClientHandle; // check if the requested sampling rate was accepted. if (!resultItem.SamplingRateSpecified) { resultItem.SamplingRate = itemList[ii].SamplingRate; resultItem.SamplingRateSpecified = itemList[ii].SamplingRateSpecified; } } // schedule polling. SchedulePoll(); // return result list. return(resultList); } }