Пример #1
0
        /// <summary>
        /// Called when thes status timer expires.
        /// </summary>
        /// <param name="state">The state.</param>
        private void OnStatusTimerExpired(object state)
        {
            try
            {
                // create the client if it has not already been created.
                if (m_defaultClient == null)
                {
                    m_defaultClient = CreateClient();
                    m_defaultClient.CreateInstance();
                    m_lastStatusUpdate = DateTime.UtcNow;
                }

                // check if the last status updates appear to be hanging.
                if (m_lastStatusUpdate.AddMilliseconds(m_statusUpdateInterval * 1.1) < DateTime.UtcNow)
                {
                    // dispose existing client in the background in case it blocks.
                    ThreadPool.QueueUserWorkItem(OnDisposeClient, m_defaultClient);

                    // create a new client.
                    m_defaultClient = CreateClient();
                    m_defaultClient.CreateInstance();
                }

                // fetches the status from the server and updates the status node.
                if (UpdateStatus())
                {
                    m_lastStatusUpdate = DateTime.UtcNow;
                }
            }
            catch (Exception e)
            {
                ComUtils.TraceComError(e, "Error fetching status from the COM server.");
            }
        }
Пример #2
0
        /// <summary>
        /// Gets the property item ids.
        /// </summary>
        /// <param name="itemId">The item id.</param>
        /// <param name="properties">The properties to update.</param>
        private void GetPropertyItemIds(string itemId, DaProperty[] properties)
        {
            string methodName = "IOPCItemProperties.LookupItemIDs";

            int count = properties.Length;

            // get list of ids to request.
            int[] propertyIds = new int[count];

            for (int ii = 0; ii < propertyIds.Length; ii++)
            {
                propertyIds[ii] = properties[ii].PropertyId;
            }

            // request the item ids.
            IntPtr pItemIds = IntPtr.Zero;
            IntPtr pErrors  = IntPtr.Zero;

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

                server.LookupItemIDs(
                    itemId,
                    count,
                    propertyIds,
                    out pItemIds,
                    out pErrors);
            }
            catch (Exception e)
            {
                if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_UNKNOWNITEMID, ResultIds.E_INVALIDITEMID))
                {
                    ComUtils.TraceComError(e, methodName);
                }

                return;
            }
            finally
            {
                EndComCall(methodName);
            }

            // unmarshal results.
            string[] itemIds = ComUtils.GetUnicodeStrings(ref pItemIds, count, true);
            int[]    errors  = ComUtils.GetInt32s(ref pErrors, count, true);

            // update the objects.
            for (int ii = 0; ii < count; ii++)
            {
                if (errors[ii] >= 0)
                {
                    properties[ii].ItemId = itemIds[ii];
                }
                else
                {
                    properties[ii].ItemId = null;
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Writes the values for a set of items.
        /// </summary>
        public int[] SyncWrite(int[] serverHandles, object[] values, int count)
        {
            // initialize output parameters.
            IntPtr pErrors = IntPtr.Zero;

            string methodName = "IOPCSyncIO.Write";

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

                server.Write(
                    count,
                    serverHandles,
                    values,
                    out pErrors);
            }
            catch (Exception e)
            {
                ComUtils.TraceComError(e, methodName);
                return(null);
            }
            finally
            {
                EndComCall(methodName);
            }

            // unmarshal output parameters.
            return(ComUtils.GetInt32s(ref pErrors, count, true));
        }
Пример #4
0
        /// <summary>
        /// Creates an instance of the COM server.
        /// </summary>
        public void CreateInstance()
        {
            // multiple calls are not allowed - may block for a while due to network operation.
            lock (m_lock)
            {
                ServerFactory factory = new ServerFactory();

                try
                {
                    // create the server.
                    Unknown = factory.CreateServer(new Uri(m_url), null);

                    // fetch the available locales.
                    m_availableLocaleIds = QueryAvailableLocales();

                    // do any post-connect processing.
                    OnConnected();
                }
                catch (Exception e)
                {
                    ComUtils.TraceComError(e, "Could not connect to server ({0}).", m_url);

                    // cleanup on error.
                    Close();
                }
                finally
                {
                    factory.Dispose();
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Modifies the group.
        /// </summary>
        /// <returns>The error. S_OK on success.</returns>
        public int ModifyGroup()
        {
            m_actualSamplingInterval = 0;

            int localeId = m_server.LocaleId;

            GCHandle hSamplingInterval = GCHandle.Alloc(m_samplingInterval, GCHandleType.Pinned);
            GCHandle hDeadband         = GCHandle.Alloc(m_deadband, GCHandleType.Pinned);

            string methodName = "IOPCGroupStateMgt.SetState";

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

                server.SetState(
                    hSamplingInterval.AddrOfPinnedObject(),
                    out m_actualSamplingInterval,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    hDeadband.AddrOfPinnedObject(),
                    IntPtr.Zero,
                    IntPtr.Zero);

                /*
                 * Utils.Trace(
                 *  "Group {0} Modified({4}) {1}/{2}ms {3}%",
                 *  m_clientHandle,
                 *  m_samplingInterval,
                 *  m_actualSamplingInterval,
                 *  m_deadband,
                 *  m_items.Count);
                 */

                return(ResultIds.S_OK);
            }
            catch (Exception e)
            {
                ComUtils.TraceComError(e, methodName);
                return(Marshal.GetHRForException(e));
            }
            finally
            {
                EndComCall(methodName);
                hSamplingInterval.Free();
                hDeadband.Free();
            }
        }
Пример #6
0
        /// <summary>
        /// Creates a group.
        /// </summary>
        public object CreateGroup(
            int groupId,
            int samplingInterval,
            float deadband,
            out int groupHandle,
            out int revisedSamplingInterval)
        {
            groupHandle             = 0;
            revisedSamplingInterval = 0;
            GCHandle hDeadband = GCHandle.Alloc(deadband, GCHandleType.Pinned);

            string methodName = "IOPCServer.AddGroup";

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

                object group = null;
                Guid   iid   = typeof(OpcRcw.Da.IOPCItemMgt).GUID;

                server.AddGroup(
                    String.Empty,
                    1,
                    samplingInterval,
                    0,
                    IntPtr.Zero,
                    hDeadband.AddrOfPinnedObject(),
                    ComUtils.LOCALE_SYSTEM_DEFAULT,
                    out groupHandle,
                    out revisedSamplingInterval,
                    ref iid,
                    out group);

                return(group);
            }
            catch (Exception e)
            {
                ComUtils.TraceComError(e, methodName);
                return(null);
            }
            finally
            {
                EndComCall(methodName);
                hDeadband.Free();
            }
        }
Пример #7
0
        /// <summary>
        /// Reads the values for a set of items.
        /// </summary>
        public DaValue[] SyncRead(int[] serverHandles, int count)
        {
            // initialize output parameters.
            IntPtr pValues = IntPtr.Zero;
            IntPtr pErrors = IntPtr.Zero;

            if (count > 0)
            {
                string methodName = "IOPCSyncIO.Read";

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

                    server.Read(
                        OPCDATASOURCE.OPC_DS_DEVICE,
                        count,
                        serverHandles,
                        out pValues,
                        out pErrors);
                }
                catch (Exception e)
                {
                    ComUtils.TraceComError(e, methodName);
                    return(null);
                }
                finally
                {
                    EndComCall(methodName);
                }
            }

            // unmarshal output parameters.
            DaValue[] values = GetItemValues(ref pValues, count, true);

            int[] errors = ComUtils.GetInt32s(ref pErrors, count, true);

            // save error codes.
            for (int ii = 0; ii < count; ii++)
            {
                values[ii].Error = errors[ii];
            }

            return(values);
        }
Пример #8
0
        /// <summary>
        /// Removes a group.
        /// </summary>
        public void RemoveGroup(int groupHandle)
        {
            string methodName = "IOPCServer.RemoveGroup";

            try
            {
                IOPCServer server = BeginComCall <IOPCServer>(methodName, true);
                server.RemoveGroup(groupHandle, 0);
            }
            catch (Exception e)
            {
                ComUtils.TraceComError(e, methodName);
                return;
            }
            finally
            {
                EndComCall(methodName);
            }
        }
Пример #9
0
        /// <summary>
        /// Creates an instance of the COM server.
        /// </summary>
        public void CreateInstance()
        {
            // multiple calls are not allowed - may block for a while due to network operation.
            lock (m_lock)
            {
                ServerFactory factory = new ServerFactory();

                try
                {
                    // create the server.
                    Unknown = factory.CreateServer(new Uri(m_url), null);

                    // set the locale.
                    SetLocale(LocaleId);

                    if (UserIdentity != null)
                    {
                        SetUserIdentity(UserIdentity);
                    }

                    // do any post-connect processing.
                    OnConnected();
                }
                catch (Exception e)
                {
                    ComUtils.TraceComError(e, "Could not connect to server ({0}).", m_url);

                    // cleanup on error.
                    Close();
                }
                finally
                {
                    factory.Dispose();
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Called when thes status timer expires.
        /// </summary>
        /// <param name="state">The state.</param>
        private void OnStatusTimerExpired(object state)
        {
            try
            {
                // create the client if it has not already been created.
                if (m_defaultClient == null)
                {
                    m_defaultClient     = CreateClient();
                    m_defaultClient.Key = String.Empty;

                    // set default locale.
                    if (AvailableLocaleIds != null && AvailableLocaleIds.Length > 0)
                    {
                        m_defaultClient.LocaleId = AvailableLocaleIds[0];
                    }
                    else
                    {
                        m_defaultClient.LocaleId = ComUtils.LOCALE_SYSTEM_DEFAULT;
                    }

                    m_defaultClient.CreateInstance();
                    m_lastStatusUpdate = DateTime.UtcNow;
                }

                // check if the last status updates appear to be hanging.
                bool reconnected = false;

                if (m_lastStatusUpdate.AddMilliseconds(m_statusUpdateInterval * 1.1) < DateTime.UtcNow)
                {
                    if (m_reconnecting)
                    {
                        return;
                    }

                    m_reconnecting = true;

                    try
                    {
                        Utils.Trace("Communication with COM server failed. Disposing server and reconnecting.");

                        // dispose existing client in the background in case it blocks.
                        ThreadPool.QueueUserWorkItem(OnDisposeClient, m_defaultClient);

                        // dispose localized clients.
                        if (m_localizedClients != null)
                        {
                            foreach (ComClient localizedClient in m_localizedClients.Values)
                            {
                                ThreadPool.QueueUserWorkItem(OnDisposeClient, localizedClient);
                            }

                            m_localizedClients.Clear();
                        }

                        // create a new client.
                        m_defaultClient = CreateClient();
                        m_defaultClient.CreateInstance();

                        reconnected = true;
                    }
                    finally
                    {
                        m_reconnecting = false;
                    }
                }

                // fetches the status from the server and updates the status node.
                if (UpdateStatus())
                {
                    AvailableLocaleIds = m_defaultClient.QueryAvailableLocales();
                    m_lastStatusUpdate = DateTime.UtcNow;

                    if (reconnected && m_reconnectCallback != null)
                    {
                        m_reconnectCallback(this);
                    }
                }
            }
            catch (Exception e)
            {
                ComUtils.TraceComError(e, "Error fetching status from the COM server.");
            }
        }
Пример #11
0
        /// <summary>
        /// Removes the items from the group that have been marked as deleted.
        /// </summary>
        public void RemoveItems()
        {
            // count the number of items to remove.
            List <GroupItem> itemsToRemove = new List <GroupItem>();

            lock (Lock)
            {
                List <GroupItem> itemsToKeep = new List <GroupItem>();

                for (int ii = 0; ii < m_items.Count; ii++)
                {
                    if (m_items[ii].Deleted && m_items[ii].Created)
                    {
                        itemsToRemove.Add(m_items[ii]);
                        continue;
                    }

                    itemsToKeep.Add(m_items[ii]);
                }

                m_items = itemsToKeep;
            }

            // check if nothing to do.
            if (itemsToRemove.Count == 0)
            {
                return;
            }

            // build list of items to remove.
            int count = itemsToRemove.Count;

            int[] serverHandles = new int[count];

            for (int ii = 0; ii < itemsToRemove.Count; ii++)
            {
                serverHandles[ii] = itemsToRemove[ii].ServerHandle;

                // remove the associated monitored items.
                if (m_monitoredItems != null)
                {
                    lock (m_monitoredItems)
                    {
                        m_monitoredItems.Remove(itemsToRemove[ii].ClientHandle);
                    }
                }
            }

            IntPtr pErrors = IntPtr.Zero;

            string methodName = "IOPCItemMgt.RemoveItems";

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

                // remove items.
                server.RemoveItems(
                    count,
                    serverHandles,
                    out pErrors);
            }
            catch (Exception e)
            {
                ComUtils.TraceComError(e, methodName);

                for (int ii = 0; ii < itemsToRemove.Count; ii++)
                {
                    itemsToRemove[ii].Created = false;
                    itemsToRemove[ii].ErrorId = Marshal.GetHRForException(e);
                }

                return;
            }
            finally
            {
                EndComCall(methodName);
            }

            // free returned error array.
            int[] errors = ComUtils.GetInt32s(ref pErrors, count, true);

            // save error codes.
            for (int ii = 0; ii < count; ii++)
            {
                itemsToRemove[ii].Created = false;
                itemsToRemove[ii].ErrorId = errors[ii];
            }

            /*
             * Utils.Trace(
             *  "Group {0} RemoveItems({4}/{5}) {1}/{2}ms {3}%",
             *  m_clientHandle,
             *  m_samplingInterval,
             *  m_actualSamplingInterval,
             *  m_deadband,
             *  itemsToRemove.Count,
             *  m_items.Count);
             */
        }
Пример #12
0
        /// <summary>
        /// Sets the active state for a set of items in a group.
        /// </summary>
        public void ActivateItems(bool active)
        {
            // count the number of items to activate.
            List <GroupItem> itemsToActivate = new List <GroupItem>();

            lock (Lock)
            {
                for (int ii = 0; ii < m_items.Count; ii++)
                {
                    if (m_items[ii].ActiveChanged && m_items[ii].Active == active && m_items[ii].Created)
                    {
                        itemsToActivate.Add(m_items[ii]);
                    }
                }
            }

            // check if nothing to do.
            if (itemsToActivate.Count == 0)
            {
                return;
            }

            // build list of items to remove.
            int count = itemsToActivate.Count;

            int[] serverHandles = new int[count];

            for (int ii = 0; ii < itemsToActivate.Count; ii++)
            {
                serverHandles[ii] = itemsToActivate[ii].ServerHandle;
            }

            // initialize output parameters.
            IntPtr pErrors = IntPtr.Zero;

            string methodName = "IOPCItemMgt.SetActiveState";

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

                server.SetActiveState(
                    count,
                    serverHandles,
                    (active) ? 1 : 0,
                    out pErrors);
            }
            catch (Exception e)
            {
                ComUtils.TraceComError(e, methodName);

                for (int ii = 0; ii < itemsToActivate.Count; ii++)
                {
                    itemsToActivate[ii].ActiveChanged = false;
                    itemsToActivate[ii].ErrorId       = Marshal.GetHRForException(e);
                }
            }
            finally
            {
                EndComCall(methodName);
            }

            // free returned error array.
            int[] errors = ComUtils.GetInt32s(ref pErrors, count, true);

            // save error codes.
            for (int ii = 0; ii < count; ii++)
            {
                itemsToActivate[ii].ActiveChanged = false;
                itemsToActivate[ii].ErrorId       = errors[ii];
            }

            /*
             * Utils.Trace(
             *  "Group {0} ActivateItems({4}/{5}) {1}/{2}ms {3}%",
             *  m_clientHandle,
             *  m_samplingInterval,
             *  m_actualSamplingInterval,
             *  m_deadband,
             *  active,
             *  itemsToActivate.Count);
             */
        }
Пример #13
0
        /// <summary>
        /// Adds all items to the group that have not already been added.
        /// </summary>
        public void AddItems()
        {
            // count the number of items to add.
            List <GroupItem> itemsToAdd = new List <GroupItem>();

            lock (Lock)
            {
                for (int ii = 0; ii < m_items.Count; ii++)
                {
                    if (!m_items[ii].Created)
                    {
                        itemsToAdd.Add(m_items[ii]);
                    }
                }
            }

            // check if nothing to do.
            if (itemsToAdd.Count == 0)
            {
                return;
            }

            // create item definitions.
            int count = itemsToAdd.Count;

            OpcRcw.Da.OPCITEMDEF[] definitions = new OpcRcw.Da.OPCITEMDEF[count];

            for (int ii = 0; ii < count; ii++)
            {
                definitions[ii] = new OpcRcw.Da.OPCITEMDEF();

                definitions[ii].szItemID            = itemsToAdd[ii].ItemId;
                definitions[ii].bActive             = (itemsToAdd[ii].Active) ? 1 : 0;
                definitions[ii].szAccessPath        = String.Empty;
                definitions[ii].vtRequestedDataType = (short)VarEnum.VT_EMPTY;
                definitions[ii].hClient             = itemsToAdd[ii].ClientHandle;
            }

            // initialize output parameters.
            IntPtr pResults = IntPtr.Zero;
            IntPtr pErrors  = IntPtr.Zero;

            // add items to group.
            string methodName = "IOPCItemMgt.AddItems";

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

                server.AddItems(
                    count,
                    definitions,
                    out pResults,
                    out pErrors);
            }
            catch (Exception e)
            {
                ComUtils.TraceComError(e, methodName);

                for (int ii = 0; ii < itemsToAdd.Count; ii++)
                {
                    itemsToAdd[ii].ErrorId = Marshal.GetHRForException(e);
                }

                return;
            }
            finally
            {
                EndComCall(methodName);
            }

            // unmarshal output parameters.
            int[] serverHandles = GetItemResults(ref pResults, count, true);
            int[] errors        = ComUtils.GetInt32s(ref pErrors, count, true);

            // save handles and error codes.
            for (int ii = 0; ii < count; ii++)
            {
                GroupItem item = itemsToAdd[ii];

                item.ServerHandle = serverHandles[ii];
                item.ErrorId      = errors[ii];

                if (item.ErrorId >= 0)
                {
                    itemsToAdd[ii].Created = true;
                }
            }

            /*
             * Utils.Trace(
             *  "Group {0} AddItems({4}/{5}) {1}/{2}ms {3}%",
             *  m_clientHandle,
             *  m_samplingInterval,
             *  m_actualSamplingInterval,
             *  m_deadband,
             *  itemsToAdd.Count,
             *  m_items.Count);
             */
        }
Пример #14
0
 /// <summary>
 /// Must called if a COM call returns an unexpected exception.
 /// </summary>
 /// <param name="methodName">Name of the method.</param>
 /// <param name="e">The exception.</param>
 /// <remarks>Note that some COM calls are expected to return errors.</remarks>
 protected void ComCallError(string methodName, Exception e)
 {
     ComUtils.TraceComError(e, methodName);
 }
Пример #15
0
        /// <summary>
        /// Reads the values of the properties from the server.
        /// </summary>
        /// <param name="itemId">The item id.</param>
        /// <param name="propertyIds">The list of property ids to read. All properties are read if null.</param>
        /// <returns>True if the element has properies.</returns>
        private DaValue[] ReadPropertyValues(string itemId, params int[] propertyIds)
        {
            string methodName = "IOPCItemProperties.GetItemProperties";

            // check for trivial case.
            if (propertyIds == null)
            {
                return(null);
            }

            int count = propertyIds.Length;

            DaValue[] results = new DaValue[count];

            // check for empty list.
            if (count == 0)
            {
                return(results);
            }

            // get the values from the server.
            IntPtr pValues = IntPtr.Zero;
            IntPtr pErrors = IntPtr.Zero;

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

                server.GetItemProperties(
                    itemId,
                    count,
                    propertyIds,
                    out pValues,
                    out pErrors);
            }
            catch (Exception e)
            {
                if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_UNKNOWNITEMID, ResultIds.E_INVALIDITEMID))
                {
                    ComUtils.TraceComError(e, methodName);
                    return(null);
                }

                for (int ii = 0; ii < count; ii++)
                {
                    DaValue result = results[ii] = new DaValue();
                    result.Value     = null;
                    result.Quality   = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD;
                    result.Timestamp = DateTime.UtcNow;
                    result.Error     = Marshal.GetHRForException(e);
                }

                return(results);
            }
            finally
            {
                EndComCall(methodName);
            }

            // unmarshal results.
            object[] values = ComUtils.GetVARIANTs(ref pValues, count, true);
            int[]    errors = ComUtils.GetInt32s(ref pErrors, count, true);

            for (int ii = 0; ii < count; ii++)
            {
                DaValue result = results[ii] = new DaValue();
                result.Value     = ComUtils.ProcessComValue(values[ii]);
                result.Quality   = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD;
                result.Timestamp = DateTime.UtcNow;
                result.Error     = errors[ii];
            }

            return(results);
        }
Пример #16
0
        /// <summary>
        /// Read the available non-built in properties from the server.
        /// </summary>
        /// <param name="itemId">The item id.</param>
        /// <param name="updateCache">if set to <c>true</c> the cache is updated.</param>
        /// <returns>The array of properties.</returns>
        public DaProperty[] ReadAvailableProperties(string itemId, bool updateCache)
        {
            string methodName = "IOPCItemProperties.QueryAvailableProperties";

            // query for available properties.
            int count = 0;

            IntPtr pPropertyIds  = IntPtr.Zero;
            IntPtr pDescriptions = IntPtr.Zero;
            IntPtr pDataTypes    = IntPtr.Zero;

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

                server.QueryAvailableProperties(
                    itemId,
                    out count,
                    out pPropertyIds,
                    out pDescriptions,
                    out pDataTypes);
            }
            catch (Exception e)
            {
                if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_UNKNOWNITEMID, ResultIds.E_INVALIDITEMID))
                {
                    ComUtils.TraceComError(e, methodName);
                }

                return(null);
            }
            finally
            {
                EndComCall(methodName);
            }

            // unmarshal results.
            int[]    propertyIds  = ComUtils.GetInt32s(ref pPropertyIds, count, true);
            string[] descriptions = ComUtils.GetUnicodeStrings(ref pDescriptions, count, true);
            short[]  datatype     = ComUtils.GetInt16s(ref pDataTypes, count, true);

            List <DaProperty> properties = new List <DaProperty>();

            for (int ii = 0; ii < count; ii++)
            {
                // do not return any of the built in properties.
                if (propertyIds[ii] <= PropertyIds.TimeZone)
                {
                    continue;
                }

                DaProperty property = new DaProperty();

                property.PropertyId = propertyIds[ii];
                property.Name       = descriptions[ii];
                property.DataType   = datatype[ii];

                properties.Add(property);
            }

            // fetch the item ids.
            if (properties.Count > 0)
            {
                DaProperty[] array = properties.ToArray();

                GetPropertyItemIds(itemId, array);

                // update the cache.
                if (updateCache)
                {
                    lock (m_cache)
                    {
                        DaElement element = null;

                        if (m_cache.TryGetValue(itemId, out element))
                        {
                            element.Properties = array;
                        }
                    }
                }

                return(array);
            }

            return(null);
        }