예제 #1
0
        /// <summary>
        /// IOPCAsyncIO3::WriteVQT - Writes one or more values, qualities and timestamps for the items specified. 
        ///                          The results are returned via the client�s IOPCDataCallback connection established 
        ///                          through the server�s IConnectionPointContainer.
        /// </summary>
		public void WriteVQT(
            int dwCount, 
            int[] phServer, 
            OPCITEMVQT[] pItemVQT, 
            int dwTransactionID, 
            out int pdwCancelID, 
            out System.IntPtr ppErrors)
		{
            pdwCancelID = 0;

			// validate arguments.
			if (dwCount == 0 || phServer == null || pItemVQT == null || dwCount != phServer.Length || dwCount != pItemVQT.Length)
			{
				throw ComUtils.CreateComException(ResultIds.E_INVALIDARG);
			}
			
            // get callback object - nothing more to do if missing.
            IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID);

            if (callback == null)
            {
		        throw ComUtils.CreateComException(ResultIds.CONNECT_E_NOCONNECTION);
            }
            
			try
			{ 
                int[] errors = new int[dwCount];
                
                // build list of values to write.
                WriteValueCollection valuesToWrite = new WriteValueCollection();
                
		        lock (m_lock)
		        {
				    if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL);
                    
                    CallbackValue[] conversionErrors = null;

                    for (int ii = 0; ii < dwCount; ii++)
                    {
                        Item itemToWrite = null;

                        if (!m_items.TryGetValue(phServer[ii], out itemToWrite))
                        {
                            errors[ii] = ResultIds.E_INVALIDHANDLE;
                            continue;
                        }

                        VariableNode variable = itemToWrite.Variable;

                        WriteValue valueToWrite = new WriteValue();

                        valueToWrite.NodeId      = variable.NodeId;
                        valueToWrite.IndexRange  = null;
                        valueToWrite.AttributeId = Attributes.Value;

                        DataValue value = new DataValue();
                        
                        int error = 0;
                        value.Value = m_server.VariantValueToValue(variable, pItemVQT[ii].vDataValue, out error);

                        if (error != ResultIds.S_OK)
                        {
                            // only allocate this array when it is needed.
                            if (conversionErrors == null)
                            {
                                conversionErrors = new CallbackValue[dwCount];
                            }

                            // create the callback item.
                            CallbackValue conversionError = new CallbackValue();

                            conversionError.ClientHandle = itemToWrite.ClientHandle;
                            conversionError.Error = error;

                            conversionErrors[ii] = conversionError;

                            errors[ii] = error;
                            continue;
                        }

                        valueToWrite.Value = value;
                        
                        if (pItemVQT[ii].bQualitySpecified != 0)
                        {
                            value.StatusCode = ComUtils.GetQualityCode(pItemVQT[ii].wQuality);
                        }
                        
                        if (pItemVQT[ii].bTimeStampSpecified != 0)
                        {
                            value.SourceTimestamp = ComUtils.GetDateTime(pItemVQT[ii].ftTimeStamp);
                        }

                        // needed to correlate results to input.
                        valueToWrite.Handle = itemToWrite;
                        
                        valuesToWrite.Add(valueToWrite);
                    }
                    
                    // create transaction.
                    if (valuesToWrite.Count > 0 || conversionErrors != null)
                    {
                        pdwCancelID = Utils.IncrementIdentifier(ref m_nextHandle);
                        m_transactions[pdwCancelID] = new AsyncWriteTransaction(dwTransactionID, valuesToWrite);
                    }
                    
                    // send conversion errors in the callback if no valid items available (CTT bug workaround).
                    if (valuesToWrite.Count == 0 && conversionErrors != null)
                    {   
                        // must return S_OK from this function if sending the errors in the callback.
                        List<CallbackValue> errorsToSend = new List<CallbackValue>();
             
                        for (int ii = 0; ii < conversionErrors.Length; ii++)
                        {
                            if (conversionErrors[ii] != null)
                            {
                                errors[ii] = ResultIds.S_OK;
                                errorsToSend.Add(conversionErrors[ii]);
                            }
                        }

                        // queue the request.
                        CallbackRequest request = new CallbackRequest();

                        request.CallbackType = CallbackType.Write;
                        request.Callback = callback;
                        request.TransactionId = dwTransactionID;
                        request.GroupHandle = m_clientHandle;
                        request.ServerHandle = m_serverHandle;
                        request.Values = errorsToSend;

                        QueueCallbackRequest(request);
                    }
				}
                   
                // write values from server.                    
                if (valuesToWrite.Count > 0)
                {
                    m_session.BeginWrite(
                        null,
                        valuesToWrite,
                        new AsyncCallback(OnWriteComplete),
                        pdwCancelID);
                }
                
                // marshal error codes.
                ppErrors = ComUtils.GetInt32s(errors); 
			}
			catch (Exception e)
			{
                Utils.Trace(e, "Error writing items.");
				throw ComUtils.CreateComException(e);
			}
		}
예제 #2
0
        /// <summary>
        /// Called when an asynchronous write operation completes.
        /// </summary>
        private void OnWriteComplete(IAsyncResult result)
        {
            AsyncWriteTransaction transaction = null;
            
            lock (m_lock)
			{
                // complete the write operation.
                StatusCodeCollection results = null;
                DiagnosticInfoCollection diagnosticInfos = null;
                
                int serviceError = ResultIds.S_OK;

                try
                {
                    m_session.EndWrite(
                        result,
                        out results,
                        out diagnosticInfos);
                }
                catch (Exception)
                {
                    serviceError = ResultIds.E_FAIL;
                }                         

                try
                {
                    // check if transaction has been cancelled.
                    int cancelId = (int)result.AsyncState;

                    Transaction transaction2 = null;

                    if (!m_transactions.TryGetValue(cancelId, out transaction2))
                    {
                        return;
                    }

                    transaction = (AsyncWriteTransaction)transaction2;
                    m_transactions.Remove(cancelId);                   
                    
                    // get callback object - nothing more to do if missing.
                    IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID);

                    if (callback == null)
                    {
                        return;
                    }
     
                    // process results.
                    WriteValueCollection valuesToWrite = transaction.ValuesToWrite;
                    
                    List<CallbackValue> callbackValues = new List<CallbackValue>();

                    for (int ii = 0; ii < valuesToWrite.Count; ii++)
                    {
                        // get item originally written.
                        Item itemToWrite = (Item)valuesToWrite[ii].Handle;
                        
                        int error = serviceError;
                        
                        // get for operation level error.
                        if (serviceError >= 0)
                        {
                            error = Server.MapWriteStatusToErrorCode(results[ii]);
                        }

                        CallbackValue callbackValue = new CallbackValue();

                        callbackValue.ClientHandle = itemToWrite.ClientHandle;
                        callbackValue.Error        = error;

                        callbackValues.Add(callbackValue);
				    }

                    // queue the callback.
                    CallbackRequest request = new CallbackRequest();

                    request.CallbackType = CallbackType.Write;
                    request.Callback = callback;
                    request.TransactionId = transaction.TransactionId;
                    request.GroupHandle = m_clientHandle;
                    request.ServerHandle = m_serverHandle;
                    request.Values = callbackValues;

                    QueueCallbackRequest(request);
                }
                catch (Exception e)
                {
                    Utils.Trace(e, "Unexpected error processing asynchronous write callback.");
                }
			}
        }
예제 #3
0
        /// <summary>
        /// Queues a datachange.
        /// </summary>
        private void QueueDataChange(bool sendAll)
        {
            // dequeue values from monitored item caches.
            List<CallbackValue> changes = new List<CallbackValue>();
    
            foreach (Item item in this.m_items.Values)
            {
                IList<DataValue> values = item.MonitoredItem.DequeueValues();

                // send the cached value if an update must be sent.
                if (sendAll && values.Count == 0)
                {
                    values = new DataValue[1];

                    // look of value in the publishing cache.
                    DataValue dataValue = ReadCachedValue(item, Int32.MaxValue);

                    // create a dummy value if nothing in the cache.
                    if (dataValue == null)
                    {
                        dataValue = new DataValue();
                        dataValue.ServerTimestamp = DateTime.UtcNow;
                        dataValue.StatusCode = StatusCodes.BadWaitingForInitialData;
                    }

                    values[0] = dataValue;
                }
                
                //Utils.Trace(
                //    "Values Found: Group={0}, Changes={1}",
                //    m_clientHandle,
                //    values.Count);

                for (int ii = 0; ii < values.Count; ii++)
                {
                    // apply any type conversions.
                    object value;
                    short quality;
                    DateTime timestamp;
                    
                    int error = ProcessReadResult(
                        item.ServerHandle, 
                        item.ReqType, 
                        values[ii],
                        out value, 
                        out quality,
                        out timestamp);

                    item.LastValueSent = value;
                    item.LastQualitySent = quality;
                    item.LastTimestampSent = timestamp;

                    // update value in cache.
                    UpdateCachedValue(item, values[ii]);

                    // create callback value for active items
                    if (item.Active && m_active && m_enabled)
                    {
                        CallbackValue change = new CallbackValue();

                        change.ServerHandle = item.ServerHandle;
                        change.ClientHandle = item.ClientHandle;
                        change.Value        = value;
                        change.Quality      = quality;
                        change.Timestamp    = timestamp;
                        change.Error        = error;

                        changes.Add(change);
                    }
                }
            }

            // get callback object - do nothing if missing.
            IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID);

            if (callback == null)
            {
                return;
            }
            
            // check if there are changes to send.
            if (changes.Count > 0)
            {                   
                CallbackRequest request = new CallbackRequest();

                request.CallbackType = CallbackType.DataChange;
                request.Callback = callback;
                request.GroupHandle = m_clientHandle;
                request.ServerHandle = m_serverHandle;
                request.Values = changes;

                //Utils.Trace(
                //    "Callback Queued: Group={0}, Changes={1}, Value[0]={2}",
                //    m_clientHandle,
                //    changes.Count,
                //    changes[0].Value);
                
                QueueCallbackRequest(request);
            }
        }
예제 #4
0
        /// <summary>
        /// Called when an asynchronous read operation completes.
        /// </summary>
        private void OnReadComplete(IAsyncResult result)
        {
            AsyncReadTransaction transaction = null;
            
            lock (m_lock)
			{
                // complete the operation.
                DataValueCollection results = null;
                DiagnosticInfoCollection diagnosticInfos = null;
                
                int serviceError = ResultIds.S_OK;

                try
                {
                    m_session.EndRead(
                        result,
                        out results,
                        out diagnosticInfos);
                }
                catch (Exception)
                {
                    serviceError = ResultIds.E_FAIL;
                }                         

                try
                {
                    // check if transaction has been cancelled.
                    int cancelId = (int)result.AsyncState;

                    Transaction transaction2 = null;

                    if (!m_transactions.TryGetValue(cancelId, out transaction2))
                    {
                        return;
                    }

                    transaction = (AsyncReadTransaction)transaction2;
                    m_transactions.Remove(cancelId);                   
                    
                    // get callback object - nothing more to do if missing.
                    IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID);

                    if (callback == null)
                    {
                        return;
                    }
     
                    // process results.
                    ReadValueIdCollection nodesToRead = transaction.NodesToRead;

                    List<CallbackValue> callbackValues = new List<CallbackValue>();

                    for (int ii = 0; ii < nodesToRead.Count; ii++)
                    {
                        // get item in originally read.
                        Item itemToRead = (Item)nodesToRead[ii].Handle;
                        
                        // process the read result.
                        object value = null;
                        short quality = Qualities.OPC_QUALITY_BAD;
                        DateTime timestamp = DateTime.MinValue;
                        int error = serviceError;

                        if (serviceError >= 0)
                        {
                            error = ProcessReadResult(
                                itemToRead.ServerHandle, 
                                itemToRead.ReqType, 
                                results[ii],
                                out value, 
                                out quality,
                                out timestamp);
                            
                            // update the cache.
                            UpdateCachedValue(itemToRead, results[ii]);
                        }

                        CallbackValue callbackValue = new CallbackValue();

                        callbackValue.ClientHandle = itemToRead.ClientHandle;
                        callbackValue.Value        = value;
                        callbackValue.Quality      = quality;
                        callbackValue.Timestamp    = timestamp;
                        callbackValue.Error        = error;

                        callbackValues.Add(callbackValue);
				    }

                    // queue the callback.
                    CallbackRequest request = new CallbackRequest();

                    request.CallbackType = (transaction.IsRefresh)?CallbackType.DataChange:CallbackType.Read;
                    request.Callback = callback;
                    request.TransactionId = transaction.TransactionId;
                    request.GroupHandle = m_clientHandle;
                    request.ServerHandle = m_serverHandle;
                    request.Values = callbackValues;

                    QueueCallbackRequest(request);
                }
                catch (Exception e)
                {
                    Utils.Trace(e, "Unexpected error processing asynchronous read callback.");
                }
			}
        }