예제 #1
0
        /// <summary>
        /// Fetches the children from the server.
        /// </summary>
        private List <AeBrowseElement> Browse(Session session, AeBrowseElement start, bool isArea)
        {
            // browse for notifiers and sources.
            BrowseDescription nodeToBrowse = new BrowseDescription();

            nodeToBrowse.NodeId          = start.NodeId;
            nodeToBrowse.BrowseDirection = BrowseDirection.Forward;
            nodeToBrowse.ResultMask      = (uint)(BrowseResultMask.BrowseName);
            nodeToBrowse.NodeClassMask   = (uint)0;

            if (isArea)
            {
                nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasNotifier;
                nodeToBrowse.IncludeSubtypes = true;
            }
            else
            {
                nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasEventSource;
                nodeToBrowse.IncludeSubtypes = true;
            }

            ReferenceDescriptionCollection references = ComAeUtils.Browse(
                session,
                nodeToBrowse,
                false);

            if (references == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            List <AeBrowseElement> hits = new List <AeBrowseElement>();

            for (int ii = 0; ii < references.Count; ii++)
            {
                // ignore remote references.
                if (references[ii].NodeId.IsAbsolute)
                {
                    continue;
                }

                // need to check if at the end of the tree.
                if (references[ii].ReferenceTypeId != ReferenceTypeIds.HasEventSource)
                {
                    nodeToBrowse.NodeId = (NodeId)references[ii].NodeId;

                    ReferenceDescriptionCollection children = ComAeUtils.Browse(session, nodeToBrowse, false);

                    if (!isArea)
                    {
                        if (children != null && children.Count > 0)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (children == null || children.Count == 0)
                        {
                            continue;
                        }
                    }
                }

                string browseText = m_mapper.GetLocalBrowseName(references[ii].BrowseName);

                // check for duplicate browse names.
                for (int jj = 0; jj < hits.Count; jj++)
                {
                    if (hits[jj].BrowseText == browseText)
                    {
                        hits[jj].Duplicated = true;
                        browseText          = null;
                        break;
                    }
                }

                // add new element.
                if (browseText != null)
                {
                    AeBrowseElement element = new AeBrowseElement();
                    element.Parent     = start;
                    element.NodeId     = (NodeId)references[ii].NodeId;
                    element.BrowseText = m_mapper.GetLocalBrowseName(references[ii].BrowseName);
                    element.IsArea     = isArea;
                    hits.Add(element);

                    StringBuilder itemId = new StringBuilder();
                    itemId.Append(start.ItemId);
                    itemId.Append('/');
                    itemId.Append(element.BrowseText);
                    element.ItemId = itemId.ToString();
                }
            }

            // remove any duplicates.
            for (int ii = 0; ii < hits.Count;)
            {
                if (hits[ii].Duplicated)
                {
                    hits.RemoveAt(ii);
                    continue;
                }

                ii++;
            }

            return(hits);
        }
예제 #2
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);
             */
        }
예제 #3
0
        /// <summary>
        /// Marshals an event for return to the client.
        /// </summary>
        private OpcRcw.Ae.ONEVENTSTRUCT Translate(AeEvent e)
        {
            OpcRcw.Ae.ONEVENTSTRUCT e2 = new ONEVENTSTRUCT();

            e2.wNewState       = 0;
            e2.wChangeMask     = 0xFF;
            e2.szSource        = e.SourceName;
            e2.wQuality        = ComUtils.GetQualityCode(e.Quality);
            e2.dwEventType     = e.Category.EventType;
            e2.dwEventCategory = (int)e.Category.LocalId;
            e2.bAckRequired    = 0;
            e2.dwSeverity      = e.Severity;
            e2.ftTime          = ComUtils.GetFILETIME(e.Time);
            e2.szMessage       = (e.Message != null) ? e.Message.Text : null;
            e2.szActorID       = e.AuditUserId;
            e2.dwCookie        = e.Cookie;

            if (e.AttributeValues != null && e.AttributeValues.Length > 0)
            {
                e2.dwNumEventAttrs  = e.AttributeValues.Length;
                e2.pEventAttributes = ComUtils.GetVARIANTs(e.AttributeValues, true);
            }

            if ((e2.dwEventType & OpcRcw.Ae.Constants.CONDITION_EVENT) != 0)
            {
                e2.szConditionName = e.ConditionName;
                e2.ftActiveTime    = ComUtils.GetFILETIME(e.ActiveTime);
                e2.bAckRequired    = (e.AckedState)?0:1;

                // set the condition state.
                e2.wNewState = 0;

                if (e.EnabledState)
                {
                    e2.wNewState |= OpcRcw.Ae.Constants.CONDITION_ENABLED;
                }

                if (e.AckedState)
                {
                    e2.wNewState |= OpcRcw.Ae.Constants.CONDITION_ACKED;
                }

                if (e.ActiveState)
                {
                    e2.wNewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE;
                }

                // set the subcondition if available.
                if (!LocalizedText.IsNullOrEmpty(e.LowState))
                {
                    e2.szSubconditionName = e.LowState.Text;
                }

                if (!LocalizedText.IsNullOrEmpty(e.HighState))
                {
                    e2.szSubconditionName = e.HighState.Text;
                }

                if (!LocalizedText.IsNullOrEmpty(e.LowLowState))
                {
                    e2.szSubconditionName = e.LowLowState.Text;
                }

                if (!LocalizedText.IsNullOrEmpty(e.HighHighState))
                {
                    e2.szSubconditionName = e.HighHighState.Text;
                }

                if (!LocalizedText.IsNullOrEmpty(e.LimitState))
                {
                    e2.szSubconditionName = e.LimitState.Text;
                }
            }

            if (e2.szMessage == null)
            {
                e2.szMessage = String.Empty;
            }
            if (e2.szSource == null)
            {
                e2.szSource = String.Empty;
            }
            if (e2.szConditionName == null)
            {
                e2.szConditionName = String.Empty;
            }
            if (e2.szSubconditionName == null)
            {
                e2.szSubconditionName = String.Empty;
            }
            if (e2.szActorID == null)
            {
                e2.szActorID = String.Empty;
            }

            return(e2);
        }
예제 #4
0
        /// <summary>
        /// Gets the result for the read operayoin.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="item">The item.</param>
        /// <param name="nodeToRead">The node to read.</param>
        /// <param name="value">The value.</param>
        /// <param name="diagnosticsMasks">The diagnostics masks.</param>
        /// <returns></returns>
        public ServiceResult GetResult(
            ISystemContext context,
            DaItemState item,
            ReadValueId nodeToRead,
            DataValue value,
            DiagnosticsMasks diagnosticsMasks)
        {
            if (nodeToRead.AttributeId == Attributes.Value)
            {
                ServiceResult result = GetItemValue(m_value, value, diagnosticsMasks);

                if (ServiceResult.IsBad(result))
                {
                    return(result);
                }

                return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value));
            }

            switch (nodeToRead.AttributeId)
            {
            case Attributes.Description:
            {
                string description = this.GetPropertyValue <string>(Opc.Ua.Com.PropertyIds.Description, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = new LocalizedText(description);
                }

                break;
            }

            case Attributes.DataType:
            {
                short datatype = this.GetPropertyValue <short>(Opc.Ua.Com.PropertyIds.DataType, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = ComUtils.GetDataTypeId(datatype);
                }

                break;
            }

            case Attributes.ValueRank:
            {
                short datatype = this.GetPropertyValue <short>(Opc.Ua.Com.PropertyIds.DataType, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = ComUtils.GetValueRank(datatype);
                }

                break;
            }

            case Attributes.AccessLevel:
            case Attributes.UserAccessLevel:
            {
                int accessRights = this.GetPropertyValue <int>(Opc.Ua.Com.PropertyIds.AccessRights, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = (byte)accessRights;
                }

                break;
            }

            case Attributes.MinimumSamplingInterval:
            {
                float scanRate = this.GetPropertyValue <float>(Opc.Ua.Com.PropertyIds.ScanRate, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = (double)scanRate;
                }

                break;
            }

            default:
            {
                return(StatusCodes.BadAttributeIdInvalid);
            }
            }

            // check if the property value is missing.
            if (value.StatusCode == StatusCodes.BadNotFound)
            {
                return(StatusCodes.BadAttributeIdInvalid);
            }

            return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value));
        }
예제 #5
0
        /// <summary>
        /// 增加设备
        /// </summary>
        /// <param name="dev"></param>
        /// <returns>设备ID</returns>
        public string AddDevice(IRunDevice dev)
        {
            if (dev == null)
            {
                throw new ArgumentNullException("设备驱动", "参数为空");
            }

            if (dev.DeviceParameter.DeviceID != dev.DeviceDynamic.DeviceID)
            {
                throw new NotEqualException("参数和动态数据的设备ID不相等");
            }

            String devid = String.Empty;

            if (dev.DeviceParameter.DeviceID == String.Empty ||
                dev.DeviceDynamic.DeviceID == String.Empty)
            {
                devid = this.DeviceManager.BuildDeviceID();
                dev.DeviceParameter.DeviceID = devid;
                dev.DeviceDynamic.DeviceID   = devid;
                try
                {
                    dev.Initialize(devid);
                }
                catch { throw; }
            }

            if (DeviceManager.ContainDevice(devid))
            {
                throw new ArgumentException("已经有相同的设备ID存在");
            }

            if (ServerConfig.ControlMode == ControlMode.Singleton)
            {
                if (dev.CommunicateType == CommunicateType.NET)
                {
                    IRunDevice[] netDevices = DeviceManager.GetDevices(CommunicateType.NET);

                    if (netDevices.Length >= 1) //如果是Singleton模式只能有一个网络设备驱动
                    {
                        throw new IndexOutOfRangeException("当为Singleton模式时,不能增加多个网络设备驱动");
                    }
                }
            }

            string desc = String.Empty;

            if (this.DeviceManager.AddDevice(dev.DeviceParameter.DeviceID, dev))
            {
                dev.Setup(this);

                this.BindDeviceHandler(dev, dev.DeviceType, true);

                if (dev.DeviceType == DeviceType.Virtual)
                {
                    desc = "增加虚拟设备";
                }
                else
                {
                    IController controller = null;
                    if (dev.CommunicateType == CommunicateType.COM)
                    {
                        #region 串口
                        string   key     = ComUtils.PortToString(dev.DeviceParameter.COM.Port);
                        IChannel channel = ChannelManager.GetChannel(key);
                        if (channel == null)
                        {
                            IComSession comChannel = new ComSession(dev.DeviceParameter.COM.Port, dev.DeviceParameter.COM.Baud);
                            comChannel.Setup(this);
                            comChannel.Initialize();
                            comChannel.COMOpen  += ComChannel_COMOpen;
                            comChannel.COMClose += ComChannel_COMClose;
                            comChannel.COMError += ComChannel_COMError;
                            comChannel.Open();
                            channel = (IChannel)comChannel;

                            ChannelManager.AddChannel(key, channel);
                        }

                        controller = ControllerManager.GetController(key);
                        if (controller == null)
                        {
                            controller = new ComController((IComSession)channel);
                            controller.Setup(this);
                            if (ControllerManager.AddController(controller.Key, controller))
                            {
                                controller.StartController();
                            }
                        }
                        else
                        {
                            IComController comController = (IComController)controller;
                            if (comController.ComChannel.GetHashCode() != channel.GetHashCode())
                            {
                                comController.ComChannel = (IComSession)channel;
                            }
                        }

                        desc = String.Format("增加'{0}'串口设备,串口:{1} 波特率:{2}", dev.DeviceParameter.DeviceName, dev.DeviceParameter.COM.Port.ToString(), dev.DeviceParameter.COM.Baud.ToString());
                        #endregion 串口
                    }
                    else if (dev.CommunicateType == CommunicateType.NET)
                    {
                        #region 网络
                        controller = ControllerManager.GetController(SocketController.ConstantKey);
                        if (controller == null)
                        {
                            controller = new SocketController();
                            controller.Setup(this);
                            if (ControllerManager.AddController(controller.Key, controller))
                            {
                                controller.StartController();
                            }
                        }

                        desc = String.Format("增加'{0}'网络设备,IP地址:{1} 端口:{2}", dev.DeviceParameter.DeviceName, dev.DeviceParameter.NET.RemoteIP, dev.DeviceParameter.NET.RemotePort.ToString());
                        #endregion 网络
                    }
                    else
                    {
                        desc = "无法识别设备的通讯类型";
                    }
                }

                if (_deviceContainer != null)
                {
                    _deviceContainer.UpdateDevice(dev.DeviceParameter.DeviceID, dev.GetDeviceContainerItem());
                }

                desc += ",成功";
                OnAddDeviceCompleted(dev.DeviceParameter.DeviceID, dev.DeviceParameter.DeviceName, true);
            }
            else
            {
                desc += ",失败";
                OnAddDeviceCompleted(dev.DeviceParameter.DeviceID, dev.DeviceParameter.DeviceName, false);
            }

            this.Logger.Info(true, desc);

            return(devid != String.Empty ? devid : dev.DeviceParameter.DeviceID);
        }
예제 #6
0
        /// <summary>
        /// Updates the EUInfo for the items.
        /// </summary>
        /// <param name="group">The group.</param>
        /// <param name="items">The items. Null entries are ignored.</param>
        public void UpdateItemEuInfo(
            ComDaGroup group,
            IList <ComDaGroupItem> items)
        {
            // get the session to use for the operation.
            Session session = m_session;

            if (session == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            // build list of properties that need to be read.
            BrowsePathCollection browsePaths = new BrowsePathCollection();

            for (int ii = 0; ii < items.Count; ii++)
            {
                ComDaGroupItem item = (ComDaGroupItem)items[ii];

                // ignore invalid items or items which have already checked their EU type.
                if (item == null || item.EuType >= 0)
                {
                    continue;
                }

                BrowsePath browsePath = new BrowsePath();
                browsePath.StartingNode = item.NodeId;
                RelativePathElement element = new RelativePathElement();
                element.ReferenceTypeId = ReferenceTypeIds.HasProperty;
                element.IsInverse       = false;
                element.IncludeSubtypes = false;
                element.TargetName      = Opc.Ua.BrowseNames.EURange;
                browsePath.RelativePath.Elements.Add(element);
                browsePath.Handle = item;
                browsePaths.Add(browsePath);

                browsePath = new BrowsePath();
                browsePath.StartingNode = item.NodeId;
                element = new RelativePathElement();
                element.ReferenceTypeId = ReferenceTypeIds.HasProperty;
                element.IsInverse       = false;
                element.IncludeSubtypes = false;
                element.TargetName      = Opc.Ua.BrowseNames.EnumStrings;
                browsePath.RelativePath.Elements.Add(element);
                browsePath.Handle = item;
                browsePaths.Add(browsePath);
            }

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

            // translate browse paths.
            BrowsePathResultCollection results         = null;
            DiagnosticInfoCollection   diagnosticInfos = null;

            try
            {
                session.TranslateBrowsePathsToNodeIds(
                    null,
                    browsePaths,
                    out results,
                    out diagnosticInfos);

                ClientBase.ValidateResponse(results, browsePaths);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browsePaths);
            }
            catch (Exception)
            {
                for (int ii = 0; ii < browsePaths.Count; ii++)
                {
                    ComDaGroupItem item = (ComDaGroupItem)browsePaths[ii].Handle;
                    item.EuType = 0;
                }

                return;
            }

            // build list of properties that need to be read.
            ReadValueIdCollection propertiesToRead = new ReadValueIdCollection();

            for (int ii = 0; ii < results.Count; ii++)
            {
                ComDaGroupItem   item   = (ComDaGroupItem)browsePaths[ii].Handle;
                BrowsePathResult result = results[ii];

                if (StatusCode.IsBad(result.StatusCode))
                {
                    if (item.EuType < 0 && result.StatusCode == StatusCodes.BadNoMatch)
                    {
                        item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM;
                    }

                    continue;
                }

                if (result.Targets.Count == 0 || result.Targets[0].TargetId.IsAbsolute)
                {
                    if (item.EuType < 0)
                    {
                        item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM;
                    }

                    continue;
                }

                ReadValueId propertyToRead = new ReadValueId();
                propertyToRead.NodeId      = (NodeId)result.Targets[0].TargetId;
                propertyToRead.AttributeId = Attributes.Value;
                propertyToRead.Handle      = item;
                propertiesToRead.Add(propertyToRead);

                if (browsePaths[ii].RelativePath.Elements[0].TargetName.Name == Opc.Ua.BrowseNames.EURange)
                {
                    item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG;
                }
                else
                {
                    item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED;
                }
            }

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

            // read attribute values from the server.
            DataValueCollection values = null;

            try
            {
                session.Read(
                    null,
                    0,
                    TimestampsToReturn.Neither,
                    propertiesToRead,
                    out values,
                    out diagnosticInfos);

                ClientBase.ValidateResponse(values, propertiesToRead);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, propertiesToRead);
            }
            catch (Exception)
            {
                for (int ii = 0; ii < propertiesToRead.Count; ii++)
                {
                    ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle;
                    item.EuType = 0;
                }

                return;
            }

            // process results.
            for (int ii = 0; ii < values.Count; ii++)
            {
                ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle;

                if (StatusCode.IsBad(values[ii].StatusCode))
                {
                    item.EuType = 0;
                    continue;
                }

                if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG)
                {
                    Range range = (Range)values[ii].GetValue <Range>(null);

                    if (range == null)
                    {
                        item.EuType = 0;
                        continue;
                    }

                    item.EuInfo = new double[] { range.Low, range.High };
                    continue;
                }

                if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED)
                {
                    LocalizedText[] texts = (LocalizedText[])values[ii].GetValue <LocalizedText[]>(null);

                    if (texts == null)
                    {
                        item.EuType = 0;
                        continue;
                    }

                    string[] strings = new string[texts.Length];

                    for (int jj = 0; jj < strings.Length; jj++)
                    {
                        if (!LocalizedText.IsNullOrEmpty(texts[jj]))
                        {
                            strings[jj] = texts[jj].Text;
                        }
                    }

                    item.EuInfo = strings;
                    continue;
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Validates the items by reading the attributes required to add them to the group.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="group">The group.</param>
        /// <param name="requests">The requests.</param>
        /// <param name="items">The items.</param>
        /// <param name="start">The start index.</param>
        /// <param name="count">The number of items to process.</param>
        private void ValidateItems(
            Session session,
            ComDaGroup group,
            ComDaCreateItemRequest[] requests,
            ComDaGroupItem[] items,
            int start,
            int count)
        {
            // build list of the UA attributes that need to be read.
            ReadValueIdCollection attributesToRead = new ReadValueIdCollection();

            for (int ii = start; ii < start + count && ii < requests.Length; ii++)
            {
                // create the group item.
                ComDaCreateItemRequest request = requests[ii];
                ComDaGroupItem         item    = items[ii] = new ComDaGroupItem(group, request.ItemId);

                item.NodeId            = m_mapper.GetRemoteNodeId(request.ItemId);
                item.Active            = request.Active;
                item.ClientHandle      = request.ClientHandle;
                item.RequestedDataType = request.RequestedDataType;
                item.SamplingRate      = -1;
                item.Deadband          = -1;

                // add attributes.
                ReadValueId attributeToRead;

                attributeToRead             = new ReadValueId();
                attributeToRead.NodeId      = item.NodeId;
                attributeToRead.AttributeId = Attributes.NodeClass;
                attributesToRead.Add(attributeToRead);

                attributeToRead             = new ReadValueId();
                attributeToRead.NodeId      = item.NodeId;
                attributeToRead.AttributeId = Attributes.DataType;
                attributesToRead.Add(attributeToRead);

                attributeToRead             = new ReadValueId();
                attributeToRead.NodeId      = item.NodeId;
                attributeToRead.AttributeId = Attributes.ValueRank;
                attributesToRead.Add(attributeToRead);

                attributeToRead             = new ReadValueId();
                attributeToRead.NodeId      = item.NodeId;
                attributeToRead.AttributeId = Attributes.UserAccessLevel;
                attributesToRead.Add(attributeToRead);
            }

            // read attribute values from the server.
            DataValueCollection      results         = null;
            DiagnosticInfoCollection diagnosticInfos = null;

            try
            {
                session.Read(
                    null,
                    0,
                    TimestampsToReturn.Neither,
                    attributesToRead,
                    out results,
                    out diagnosticInfos);

                ClientBase.ValidateResponse(results, attributesToRead);
                ClientBase.ValidateDiagnosticInfos(diagnosticInfos, attributesToRead);
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error reading attributes for items.");

                // set default values on error.
                for (int ii = start; ii < start + count && ii < requests.Length; ii++)
                {
                    requests[ii].Error = ResultIds.E_INVALIDITEMID;
                }

                return;
            }

            // process results.
            int first = 0;

            for (int ii = start; ii < start + count && ii < requests.Length; ii++, first += 4)
            {
                ComDaGroupItem item = items[ii];

                // verify node class.
                NodeClass nodeClass = (NodeClass)results[first].GetValue <int>((int)NodeClass.Unspecified);

                if (nodeClass != NodeClass.Variable)
                {
                    requests[ii].Error = ResultIds.E_INVALIDITEMID;
                    continue;
                }

                // verify data type.
                NodeId dataTypeId = results[first + 1].GetValue <NodeId>(null);

                if (dataTypeId == null)
                {
                    requests[ii].Error = ResultIds.E_INVALIDITEMID;
                    continue;
                }

                // get value rank.
                int valueRank = results[first + 2].GetValue <int>(ValueRanks.Scalar);

                // update datatypes.
                BuiltInType builtInType = DataTypes.GetBuiltInType(dataTypeId, session.TypeTree);
                item.RemoteDataType    = new TypeInfo(builtInType, valueRank);
                item.CanonicalDataType = (short)ComUtils.GetVarType(item.RemoteDataType);

                // update access rights.
                byte userAccessLevel = results[first + 3].GetValue <byte>(0);

                if ((userAccessLevel & AccessLevels.CurrentRead) != 0)
                {
                    item.AccessRights |= OpcRcw.Da.Constants.OPC_READABLE;
                }

                if ((userAccessLevel & AccessLevels.CurrentWrite) != 0)
                {
                    item.AccessRights |= OpcRcw.Da.Constants.OPC_WRITEABLE;
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Sets the filtering criteria to be used for the event subscription.
        /// </summary>
        /// <param name="dwEventType">Bit mask specifying which event types are of interest</param>
        /// <param name="dwNumCategories">Length of array of event categories. A length of 0 indicates all categories should be included in the filter.</param>
        /// <param name="pdwEventCategories">Array of event categories of interest.</param>
        /// <param name="dwLowSeverity">Lowest severity of interest (inclusive).</param>
        /// <param name="dwHighSeverity">Highest severity of interest (inclusive).</param>
        /// <param name="dwNumAreas">Length of array of areas. A length of 0 indicates all areas should be included in the filter.</param>
        /// <param name="pszAreaList">Array of process area strings of interest - only events or conditions in these areas will be reported.</param>
        /// <param name="dwNumSources">Length of array of event sources. A length of 0 indicates all sources should be included in the filter.</param>
        /// <param name="pszSourceList">Array of event sources of interest - only events from these sources will be reported.</param>
        public void SetFilter(int dwEventType, int dwNumCategories, int[] pdwEventCategories, int dwLowSeverity, int dwHighSeverity, int dwNumAreas, string[] pszAreaList, int dwNumSources, string[] pszSourceList)
        {
            try
            {
                if (dwEventType == 0 |
                    dwEventType > OpcRcw.Ae.Constants.ALL_EVENTS |
                    pdwEventCategories.Rank > 1 | dwNumCategories != pdwEventCategories.Length |
                    pszAreaList.Rank > 1 | dwNumAreas != pszAreaList.Length |
                    pszSourceList.Rank > 1 | dwNumSources != pszSourceList.Length |
                    dwLowSeverity < 1 | dwLowSeverity > 1000 | dwHighSeverity > 1000 | dwHighSeverity <1 |
                                                                                                       dwLowSeverity> dwHighSeverity)
                {
                    throw ComUtils.CreateComException("SetFilter", ResultIds.E_INVALIDARG);
                }

                if (dwNumCategories != 0)
                {
                    for (int i = 0; i < dwNumCategories; i++)
                    {
                        // Make sure we are passed a valid dwEventCategory
                        NodeId catNodeId = m_server.FindEventCatNodeId(pdwEventCategories[i]);
                        if (catNodeId == null)
                        {
                            throw ComUtils.CreateComException("SetFilter", ResultIds.E_INVALIDARG);
                        }
                    }
                }
                m_server.RemoveMonitoredItems(m_AreaVector);
                if (dwNumAreas != 0)
                {
                    List <string> szAreas = new List <string>();
                    for (int i = 0; i < dwNumAreas; i++)
                    {
                        szAreas.Add(pszAreaList[i]);
                    }
                    if (szAreas.Count > 0)
                    {
                        m_server.AddMonitoredItems(szAreas);
                    }
                }

                if (dwNumSources != 0)
                {
                    List <string> szSources = new List <string>();
                    for (int i = 0; i < dwNumSources; i++)
                    {
                        int wildCardLocation = 0;
                        if ((wildCardLocation = pszSourceList[i].IndexOfAny(new char[] { '*', '?', '#', '[', ']', '!', '-' })) != -1)
                        {
                            // The string contains wildcards
                            List <string> items = m_server.ProcessWildCardAreaName(pszSourceList[i], wildCardLocation);
                            if (items.Count == 0)
                            {
                                throw ComUtils.CreateComException("SetFilter", ResultIds.E_INVALIDARG);
                            }
                            foreach (string item in items)
                            {
                                szSources.Add(item);
                            }
                        }
                        else
                        {
                            szSources.Add(pszSourceList[i]);
                        }
                    }

                    //Translate the fully qualified source name to NodeId
                    BrowsePathResultCollection results = m_server.GetBrowseTargets(szSources);
                    for (int i = 0; i < dwNumSources; i++)
                    {
                        if (StatusCode.IsBad(results[i].StatusCode))
                        {
                            throw ComUtils.CreateComException("SetFilter", ResultIds.E_INVALIDARG);
                        }
                    }
                }

                m_dwEventType    = dwEventType;
                m_dwLowSeverity  = dwLowSeverity;
                m_dwHighSeverity = dwHighSeverity;
                m_EventCategoryVector.Clear();
                if (dwNumCategories != 0)
                {
                    for (int i = 0; i < dwNumCategories; i++)
                    {
                        m_EventCategoryVector.AddUnique(pdwEventCategories[i]);
                    }
                }

                m_server.RemoveMonitoredItems(m_AreaVector);
                m_AreaVector.Clear();
                if (dwNumAreas != 0)
                {
                    for (int i = 0; i < dwNumAreas; i++)
                    {
                        m_AreaVector.AddUnique(pszAreaList[i]);
                    }
                }

                m_SourceVector.Clear();
                if (dwNumSources != 0)
                {
                    for (int i = 0; i < dwNumSources; i++)
                    {
                        m_SourceVector.AddUnique(pszSourceList[i]);
                    }
                }
            }
            catch (COMException e)
            {
                throw ComUtils.CreateComException(e);
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error in SetFilter");
                throw ComUtils.CreateComException(e);
            }
        }
예제 #9
0
        /// <summary>
        /// Converts a remote value to a local value.
        /// </summary>
        /// <param name="srcValue">The remote value.</param>
        /// <param name="srcType">The data type of the remote value.</param>
        /// <param name="dstType">The data type of the local value.</param>
        /// <returns>The local value.</returns>
        private object ConvertRemoteToLocal(object srcValue, BuiltInType srcType, BuiltInType dstType)
        {
            // check for null.
            if (srcValue == null)
            {
                return(null);
            }

            // must determine the type from the source if the containing array is a variant.
            if (srcType == BuiltInType.Variant)
            {
                TypeInfo typeInfo = TypeInfo.Construct(srcValue);
                srcType = typeInfo.BuiltInType;

                if (typeInfo.ValueRank != ValueRanks.Scalar)
                {
                    return(TypeInfo.CastArray((Array)srcValue, srcType, BuiltInType.Null, ConvertRemoteToLocal));
                }
            }

            // no conversion by default.
            object dstValue = srcValue;

            // apply different conversions depending on the data type.
            switch (srcType)
            {
            case BuiltInType.Guid:
            {
                dstValue = ((Uuid)srcValue).ToString();
                break;
            }

            case BuiltInType.XmlElement:
            {
                dstValue = ((XmlElement)srcValue).OuterXml;
                break;
            }

            case BuiltInType.NodeId:
            {
                dstValue = GetLocalItemId((NodeId)srcValue);
                break;
            }

            case BuiltInType.ExpandedNodeId:
            {
                ExpandedNodeId nodeId = GetLocaleExpandedNodeId((ExpandedNodeId)srcValue);
                dstValue = nodeId.ToString();
                break;
            }

            case BuiltInType.QualifiedName:
            {
                dstValue = GetLocalBrowseName((QualifiedName)srcValue);
                break;
            }

            case BuiltInType.LocalizedText:
            {
                dstValue = ((LocalizedText)srcValue).Text;
                break;
            }

            case BuiltInType.StatusCode:
            {
                dstValue = ((StatusCode)srcValue).Code;
                break;
            }

            case BuiltInType.ExtensionObject:
            {
                BinaryEncoder encoder = new BinaryEncoder(m_localMessageContext);
                encoder.WriteExtensionObject(null, (ExtensionObject)srcValue);
                dstValue = encoder.CloseAndReturnBuffer();
                break;
            }

            case BuiltInType.Variant:
            {
                dstValue = ((Variant)srcValue).Value;
                break;
            }

            default:
            {
                if (dstType != srcType && dstType != BuiltInType.Variant && dstType != BuiltInType.Null)
                {
                    throw ComUtils.CreateComException(ResultIds.E_BADTYPE);
                }

                break;
            }
            }

            // all done.
            return(dstValue);
        }
예제 #10
0
 void onSwapChainResized(CSize newSize, double dpiScaling)
 {
     createStaticCBuffer(newSize, dpiScaling);
     ComUtils.clear(ref m_staticCBufferForText);
 }
예제 #11
0
 public static UID CreateUID(Guid guid)
 {
     return(new UIDClass {
         Value = ComUtils.FormatGuid(guid)
     });
 }
예제 #12
0
        /// <summary>
        /// Provides a way to move �up� or �down� in a hierarchical space from the current position, or a way to move to a specific position in the area space tree. The target szString must represent an area, rather than a source.
        /// </summary>
        /// <param name="dwBrowseDirection">OPCAE_BROWSE_UP, OPCAE_BROWSE_DOWN, or OPCAE_BROWSE_TO</param>
        /// <param name="szString">
        /// For DOWN, the partial area name of the area to move into. This would be one of the strings returned from BrowseOPCAreas.
        /// For UP this parameter is ignored and should point to a NULL string.
        /// For BROWSE_TO, the fully qualified area name (as obtained from GetQualifiedAreaName method) or a pointer to a NUL string to go to the root.
        /// </param>
        public void ChangeBrowsePosition(OPCAEBROWSEDIRECTION dwBrowseDirection, string szString)
        {
            lock (m_lock)
            {
                try
                {
                    switch (dwBrowseDirection)
                    {
                    // move to a specified position or root.
                    case OPCAEBROWSEDIRECTION.OPCAE_BROWSE_TO:
                    {
                        try
                        {
                            // move to root.
                            if (String.IsNullOrEmpty(szString))
                            {
                                m_browseStack.Clear();
                                m_browseStack.Push(m_session.NodeCache.Find(Objects.Server));
                                break;
                            }

                            // Translate the fully qualified area name to NodeId
                            List <string> szAreas = new List <string>();
                            szAreas.Add(szString);
                            BrowsePathResultCollection results = m_server.GetBrowseTargets(szAreas);
                            if (StatusCode.IsBad(results[0].StatusCode))
                            {
                                throw ComUtils.CreateComException(ResultIds.E_INVALIDBRANCHNAME);
                            }

                            BrowsePathTarget target = results[0].Targets[0];
                            INode            node   = m_session.NodeCache.Find(target.TargetId);
                            if (node == null)
                            {
                                throw ComUtils.CreateComException(ResultIds.E_INVALIDBRANCHNAME);
                            }

                            // build a new browse stack.
                            Stack <INode> browseStack = new Stack <INode>();

                            if (!FindPathToNode(node, browseStack))
                            {
                                throw ComUtils.CreateComException(ResultIds.E_INVALIDBRANCHNAME);
                            }

                            // push target node onto stack.
                            browseStack.Push(node);

                            m_browseStack = browseStack;
                        }
                        catch
                        {
                            throw ComUtils.CreateComException(ResultIds.E_INVALIDBRANCHNAME);
                        }
                        break;
                    }

                    // move to a child branch.
                    case OPCAEBROWSEDIRECTION.OPCAE_BROWSE_DOWN:
                    {
                        // check for invalid name.
                        if (String.IsNullOrEmpty(szString))
                        {
                            throw ComUtils.CreateComException(ResultIds.E_INVALIDBRANCHNAME);
                        }

                        // find the current node.
                        INode parent = m_browseStack.Peek();

                        if (parent == null)
                        {
                            throw ComUtils.CreateComException(ResultIds.E_FAIL);
                        }

                        // find the child.
                        INode child = FindChildByName(parent.NodeId, szString);

                        if (child == null)
                        {
                            throw ComUtils.CreateComException(ResultIds.E_INVALIDBRANCHNAME);
                        }
                        // save the new position.
                        m_browseStack.Push(child);
                        break;
                    }

                    // move to a parent branch.
                    case OPCAEBROWSEDIRECTION.OPCAE_BROWSE_UP:
                    {
                        // check for invalid name.
                        if (!String.IsNullOrEmpty(szString))
                        {
                            throw ComUtils.CreateComException(ResultIds.E_FAIL);
                        }

                        // can't move up from root.
                        if (m_browseStack.Count <= 1)
                        {
                            throw ComUtils.CreateComException(ResultIds.E_FAIL);
                        }

                        // move up the stack.
                        m_browseStack.Pop();
                        break;
                    }

                    default:
                    {
                        throw ComUtils.CreateComException(ResultIds.E_INVALIDARG);
                    }
                    }
                }
                catch (COMException e)
                {
                    throw ComUtils.CreateComException(e);
                }
                catch (Exception e)
                {
                    Utils.Trace(e, "Unexpected error in ChangeBrowsePosition");
                    throw ComUtils.CreateComException(e);
                }
            }
        }
예제 #13
0
        /// <summary>
        /// Return an IEnumString for a list of Areas as determined by the passed parameters.
        /// </summary>
        /// <param name="dwBrowseFilterType">
        /// OPC_AREA - returns only areas.
        /// OPC_SOURCE - returns only sources.</param>
        /// <param name="szFilterCriteria">A server specific filter string. A pointer to a NULL string indicates no filtering.</param>
        /// <param name="ppIEnumString">Where to save the returned interface pointer. NULL if the HRESULT is other than S_OK or S_FALSE.</param>
        public void BrowseOPCAreas(
            OPCAEBROWSETYPE dwBrowseFilterType,
            string szFilterCriteria,
            out OpcRcw.Comn.IEnumString ppIEnumString)
        {
            ppIEnumString = null;
            if (dwBrowseFilterType != OPCAEBROWSETYPE.OPC_AREA && dwBrowseFilterType != OPCAEBROWSETYPE.OPC_SOURCE)
            {
                throw ComUtils.CreateComException("BrowseOPCAreas", ResultIds.E_INVALIDARG);
            }
            try
            {
                lock (m_lock)
                {
                    // find the current node.
                    INode parent = null;

                    // ensure browse stack has been initialized.
                    if (m_browseStack.Count == 0)
                    {
                        parent = m_session.NodeCache.Find(Objects.Server);
                        m_browseStack.Push(parent);
                    }

                    parent = m_browseStack.Peek();

                    if (parent == null)
                    {
                        throw ComUtils.CreateComException("BrowseOPCAreas", ResultIds.E_FAIL);
                    }

                    List <string> names = new List <string>();
                    IList <INode> children;

                    ////// find children.
                    children = m_session.NodeCache.Find(parent.NodeId, ReferenceTypes.HasEventSource, false, true);    // This would also include
                                                                                                                       // the HasNotifier reference which is
                                                                                                                       // a subtype of HasEventSource

                    foreach (INode child in children)
                    {
                        // ignore external nodes.
                        if (child.NodeId.IsAbsolute)
                        {
                            continue;
                        }

                        // ignore non-objects/variables.
                        if ((child.NodeClass & (NodeClass.Object | NodeClass.Variable)) == 0)
                        {
                            continue;
                        }

                        // ignore duplicate browse names.
                        if (names.Contains(child.BrowseName.ToString()))
                        {
                            continue;
                        }

                        // For a node to be an area, it has to have the 'HasNotifier' reference and must
                        // allow event notification (the EventNotifier attribute is set to SubscribeToEvents)
                        // For a node to be a source, it should be the target of the HasEventSource reference
                        if (IsValidNode((NodeId)child.NodeId, child.BrowseName.ToString(), dwBrowseFilterType))
                        {
                            if (String.IsNullOrEmpty(szFilterCriteria))
                            {
                                names.Add(child.BrowseName.ToString());
                            }
                            else
                            {
                                // apply filters
                                if (ComUtils.Match(child.BrowseName.ToString(), szFilterCriteria, true))
                                {
                                    names.Add(child.BrowseName.ToString());
                                }
                            }
                        }
                    }

                    // create enumerator.
                    ppIEnumString = (OpcRcw.Comn.IEnumString) new EnumString(names);
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error in BrowseOPCAreas");
                throw ComUtils.CreateComException(e);
            }
        }
예제 #14
0
        /// <summary>
        /// Returns the areas or sources that meet search pattern.
        /// </summary>
        public List <NodeId> SearchByQualifiedName(string pattern, bool isArea)
        {
            Session session = m_server.Session;

            if (session == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            List <NodeId> hits = new List <NodeId>();

            // check if a wildcard has been specified.
            int start = -1;

            for (int ii = 0; ii < pattern.Length; ii++)
            {
                if (IsWildcardChar(pattern[ii]))
                {
                    start = ii;
                    break;
                }
            }

            lock (m_lock)
            {
                // no wildcard found.
                if (start == -1)
                {
                    AeBrowseElement target = Find(session, pattern, isArea);

                    if (target != null)
                    {
                        hits.Add(target.NodeId);
                    }

                    return(hits);
                }

                // find the root where no wildcards exist.
                int end = start;

                for (int ii = start; ii >= 0; ii--)
                {
                    if (pattern[ii] == '/')
                    {
                        end = ii;
                        break;
                    }
                }

                // check if the root exists.
                string          rootId = pattern.Substring(0, end);
                AeBrowseElement root   = Find(session, rootId, true);

                if (root == null)
                {
                    return(hits);
                }

                // update the pattern to look for children of root.
                pattern = pattern.Substring(end + 1);

                // check if the pattern has multiple levels.
                end = pattern.IndexOf('/');

                if (end == -1)
                {
                    List <AeBrowseElement> children = Browse(session, root, pattern, isArea);

                    // remove any duplicates.
                    for (int ii = 0; ii < children.Count; ii++)
                    {
                        hits.Add(children[ii].NodeId);
                    }

                    return(hits);
                }
            }

            return(hits);
        }
예제 #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DaItemState"/> class.
        /// </summary>
        /// <param name="configuration">The configuration.</param>
        /// <param name="itemId">The item id.</param>
        /// <param name="attribute">The attribute.</param>
        /// <param name="namespaceIndex">Index of the namespace.</param>
        public HdaAttributeState(
            ComHdaClientConfiguration configuration,
            string itemId,
            HdaAttribute attribute,
            ushort namespaceIndex)
            :
            base(null)
        {
            m_itemId    = itemId;
            m_attribute = attribute;

            this.NodeId                  = HdaModelUtils.ConstructIdForHdaItemAttribute(itemId, attribute.Id, namespaceIndex);
            this.SymbolicName            = attribute.Id.ToString();
            this.Description             = attribute.Description;
            this.AccessLevel             = AccessLevels.CurrentRead;
            this.UserAccessLevel         = AccessLevels.CurrentRead;
            this.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate;
            this.Historizing             = false;
            this.ReferenceTypeId         = Opc.Ua.ReferenceTypeIds.HasProperty;
            this.TypeDefinitionId        = Opc.Ua.VariableTypeIds.PropertyType;
            this.Value      = null;
            this.StatusCode = StatusCodes.BadWaitingForInitialData;

            bool isConfigItem = false;

            // handle built-in properties.
            switch (attribute.Id)
            {
            default:
            {
                bool isArray = false;
                this.BrowseName  = new QualifiedName(this.SymbolicName, namespaceIndex);
                this.DisplayName = attribute.Name;
                this.DataType    = ComUtils.GetDataTypeId(attribute.DataType, out isArray);
                this.ValueRank   = (isArray)?ValueRanks.OneDimension:ValueRanks.Scalar;
                break;
            }

            case Constants.OPCHDA_ENG_UNITS:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.EngineeringUnits;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.EUInformation;
                this.ValueRank   = ValueRanks.Scalar;
                break;
            }

            case Constants.OPCHDA_NORMAL_MAXIMUM:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.EURange;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Range;
                this.ValueRank   = ValueRanks.Scalar;
                break;
            }

            case Constants.OPCHDA_HIGH_ENTRY_LIMIT:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.InstrumentRange;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Range;
                this.ValueRank   = ValueRanks.Scalar;
                break;
            }

            case Constants.OPCHDA_STEPPED:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.Stepped;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Boolean;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_DERIVE_EQUATION:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.Definition;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.String;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_MIN_TIME_INT:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.MinTimeInterval;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Duration;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_MAX_TIME_INT:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.MaxTimeInterval;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Duration;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_EXCEPTION_DEV:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.ExceptionDeviation;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Double;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_EXCEPTION_DEV_TYPE:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.ExceptionDeviationFormat;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.ExceptionDeviationFormat;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }
            }

            // set the parent id.
            NodeId parentId = null;

            if (isConfigItem)
            {
                parentId = HdaParsedNodeId.Construct(HdaModelUtils.HdaItemConfiguration, itemId, null, namespaceIndex);
            }
            else
            {
                parentId = HdaModelUtils.ConstructIdForHdaItem(itemId, namespaceIndex);
            }

            this.AddReference(ReferenceTypeIds.HasProperty, true, parentId);
        }
예제 #16
0
        /// <summary>
        /// Converts a local value to a remote value.
        /// </summary>
        /// <param name="srcValue">The local value.</param>
        /// <param name="srcType">The data type of the local value.</param>
        /// <param name="dstType">The data type of the remote value.</param>
        /// <returns>The remote value.</returns>
        private object ConvertLocalToRemote(object srcValue, BuiltInType srcType, BuiltInType dstType)
        {
            // must determine the type from the source if the containing array is a variant.
            if (srcType == BuiltInType.Variant)
            {
                TypeInfo typeInfo = TypeInfo.Construct(srcValue);
                srcType = typeInfo.BuiltInType;
            }

            // no conversion by default.
            object dstValue = srcValue;

            // apply different conversions depending on the data type.
            switch (dstType)
            {
            case BuiltInType.Guid:
            {
                dstValue = new Uuid((string)srcValue);
                break;
            }

            case BuiltInType.XmlElement:
            {
                XmlDocument document = new XmlDocument();
                document.InnerXml = (string)srcValue;
                dstValue          = document.DocumentElement;
                break;
            }

            case BuiltInType.NodeId:
            {
                dstValue = GetRemoteNodeId((string)srcValue);
                break;
            }

            case BuiltInType.ExpandedNodeId:
            {
                ExpandedNodeId nodeId = ExpandedNodeId.Parse((string)srcValue);
                dstValue = GetRemoteExpandedNodeId(nodeId);
                break;
            }

            case BuiltInType.QualifiedName:
            {
                dstValue = GetRemoteBrowseName((string)srcValue);
                break;
            }

            case BuiltInType.LocalizedText:
            {
                dstValue = new LocalizedText((string)srcValue);
                break;
            }

            case BuiltInType.StatusCode:
            {
                dstValue = new StatusCode((uint)srcValue);
                break;
            }

            case BuiltInType.ExtensionObject:
            {
                BinaryDecoder decoder = new BinaryDecoder((byte[])srcValue, m_localMessageContext);
                dstValue = decoder.ReadExtensionObject(null);
                decoder.Close();
                break;
            }

            default:
            {
                if (dstType != srcType && dstType != BuiltInType.Variant && dstType != BuiltInType.Null)
                {
                    throw ComUtils.CreateComException(ResultIds.E_BADTYPE);
                }

                break;
            }
            }

            // all done.
            return(dstValue);
        }
예제 #17
0
        /// <summary>
        /// Adds the group.
        /// </summary>
        /// <param name="groupName">The group name.</param>
        /// <param name="active">if set to <c>true</c> the group is active.</param>
        /// <param name="updateRate">The update rate.</param>
        /// <param name="clientHandle">The client handle.</param>
        /// <param name="timeBias">The time bias.</param>
        /// <param name="deadband">The deadband.</param>
        /// <param name="lcid">The lcid.</param>
        /// <returns>The new group.</returns>
        public ComDaGroup AddGroup(
            string groupName,
            bool active,
            int updateRate,
            int clientHandle,
            int timeBias,
            float deadband,
            int lcid)
        {
            TraceState("AddGroup", groupName, active, updateRate, clientHandle, timeBias, deadband, lcid);

            // check for valid session.
            Session session = m_session;

            if (session == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            ComDaGroup group = null;

            // check for duplicate name.
            lock (m_lock)
            {
                // ensure the name is unique.
                if (!String.IsNullOrEmpty(groupName))
                {
                    if (GetGroupByName(groupName) != null)
                    {
                        throw ComUtils.CreateComException(ResultIds.E_DUPLICATENAME);
                    }
                }

                // assign a unique name.
                else
                {
                    groupName = Utils.Format("Group{0}", m_groupCounter + 1);
                }

                // validate the deadband.
                if (deadband < 0 || deadband > 100)
                {
                    throw ComUtils.CreateComException(ResultIds.E_INVALIDARG);
                }

                // create the group.
                group = new ComDaGroup(this, groupName, ++m_groupCounter);
                m_groups.Add(group);

                group.ClientHandle = clientHandle;
                group.Active       = active;
                group.UpdateRate   = updateRate;
                group.TimeBias     = timeBias;
                group.Deadband     = deadband;
                group.Lcid         = lcid;

                if (updateRate < 100)
                {
                    updateRate = 100;
                }

                // create a new subscription.
                Subscription subscription = new Subscription();
                subscription.DisplayName                = groupName;
                subscription.PublishingInterval         = updateRate / 2;
                subscription.KeepAliveCount             = 30;
                subscription.LifetimeCount              = 600;
                subscription.MaxNotificationsPerPublish = 10000;
                subscription.Priority                  = 1;
                subscription.PublishingEnabled         = active;
                subscription.DisableMonitoredItemCache = true;

                // create the subscription on the server.
                session.AddSubscription(subscription);

                try
                {
                    // create the initial subscription.
                    subscription.Create();

                    // set the keep alive interval to 30 seconds and the the lifetime interval to 5 minutes.
                    subscription.KeepAliveCount = (uint)((30000 / (int)subscription.CurrentPublishingInterval) + 1);
                    subscription.LifetimeCount  = (uint)((600000 / (int)subscription.CurrentPublishingInterval) + 1);

                    // update the subscription.
                    subscription.Modify();
                }
                catch (Exception e)
                {
                    session.RemoveSubscription(subscription);
                    Utils.Trace((int)Utils.TraceMasks.Error, "Create subscription failed: {0}", e.Message);
                    throw ComUtils.CreateComException(e, ResultIds.E_FAIL);
                }

                // update the group.
                group.ActualUpdateRate = (int)(subscription.CurrentPublishingInterval * 2);
                group.Subscription     = subscription;
            }

            return(group);
        }
예제 #18
0
 /// <summary>
 /// Enumerates hosts that may be accessed for server discovery.
 /// </summary>
 public string[] EnumerateHosts()
 {
     return(ComUtils.EnumComputers());
 }
예제 #19
0
        /// <summary>
        /// Validates the items.
        /// </summary>
        /// <param name="group">The group.</param>
        /// <param name="requests">The requests.</param>
        /// <returns>The items. May contain null is validation failed.</returns>
        public ComDaGroupItem[] ValidateItems(ComDaGroup group, ComDaCreateItemRequest[] requests)
        {
            TraceState("ValidateItems", group.Name);

            // get the session to use for the operation.
            Session session = m_session;

            if (session == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            // validate items.
            ComDaGroupItem[] items = new ComDaGroupItem[requests.Length];

            for (int ii = 0; ii < requests.Length; ii += 10000)
            {
                ValidateItems(session, group, requests, items, ii, 10000);
            }

            // process results.
            for (int ii = 0; ii < requests.Length; ii++)
            {
                // check for the results.
                ComDaCreateItemRequest request = requests[ii];

                if (request.Error < 0)
                {
                    items[ii] = null;
                    continue;
                }

                // check access path.
                if (!String.IsNullOrEmpty(request.AccessPath))
                {
                    items[ii]     = null;
                    request.Error = ResultIds.E_UNKNOWNPATH;
                    continue;
                }

                ComDaGroupItem item = items[ii];

                // validate the datatype.
                if (request.RequestedDataType != 0)
                {
                    NodeId dataTypeId = ComUtils.GetDataTypeId(request.RequestedDataType);

                    if (NodeId.IsNull(dataTypeId))
                    {
                        items[ii]     = null;
                        request.Error = ResultIds.E_BADTYPE;
                        continue;
                    }

                    bool reqTypeIsArray    = (request.RequestedDataType & (short)VarEnum.VT_ARRAY) != 0;
                    bool actualTypeIsArray = (item.CanonicalDataType & (short)VarEnum.VT_ARRAY) != 0;

                    if (reqTypeIsArray != actualTypeIsArray)
                    {
                        items[ii]     = null;
                        request.Error = ResultIds.E_BADTYPE;
                        continue;
                    }
                }

                // create a new monitored item.
                MonitoredItem monitoredItem = new MonitoredItem();

                monitoredItem.StartNodeId      = item.NodeId;
                monitoredItem.RelativePath     = null;
                monitoredItem.AttributeId      = Attributes.Value;
                monitoredItem.MonitoringMode   = (request.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled;
                monitoredItem.SamplingInterval = group.UpdateRate / 2;
                monitoredItem.QueueSize        = 0;
                monitoredItem.DiscardOldest    = true;
                monitoredItem.Filter           = null;

                // update item.
                item.ServerHandle  = (int)monitoredItem.ClientHandle;
                item.MonitoredItem = monitoredItem;

                // link the monitored item back to the group item.
                monitoredItem.Handle = item;

                // update return parameters.
                request.ServerHandle      = item.ServerHandle;
                request.CanonicalDataType = item.CanonicalDataType;
                request.AccessRights      = item.AccessRights;
                request.Error             = ResultIds.S_OK;
            }

            return(items);
        }
예제 #20
0
        /// <summary>
        /// Connects to the specified COM server server.
        /// </summary>
        public object CreateServer(Uri uri, UserIdentity identity)
        {
            // parse path to find prog id and clsid.
            string progID = uri.LocalPath;
            string clsid  = null;

            while (progID.StartsWith("/"))
            {
                progID = progID.Substring(1);
            }

            int index = progID.IndexOf('/');

            if (index >= 0)
            {
                clsid  = progID.Substring(index + 1);
                progID = progID.Substring(0, index);
            }

            // look up prog id if clsid not specified in the uri.
            Guid guid = Guid.Empty;

            if (String.IsNullOrEmpty(clsid))
            {
                // connect to enumerator.
                Connect(uri.Host, identity);

                // use OpcEnum to lookup the prog id.
                guid = CLSIDFromProgID(progID);

                // check if prog id is actually a clsid string.
                if (guid == Guid.Empty)
                {
                    clsid = progID;
                }
            }

            // convert CLSID to a GUID.
            if (guid == Guid.Empty)
            {
                try
                {
                    guid = new Guid(clsid);
                }
                catch (Exception e)
                {
                    throw ServiceResultException.Create(StatusCodes.BadCommunicationError, e, "COM server URI does not contain a valid CLSID or ProgID.");
                }
            }

            // use normal activation.
            return(ComUtils.CreateInstance(guid, uri.Host, identity));

            #if COM_IMPERSONATION_SUPPORT
            // set the current thread token.
            IPrincipal       existingPrincipal = Thread.CurrentPrincipal;
            WindowsPrincipal principal         = ComUtils.GetPrincipalFromUserIdentity(identity);

            try
            {
                if (principal != null)
                {
                    Thread.CurrentPrincipal = principal;
                }

                // activate with a license key if one provided.
                if (identity != null && !String.IsNullOrEmpty(identity.LicenseKey))
                {
                    return(ComUtils.CreateInstanceWithLicenseKey(guid, uri.Host, identity, identity.LicenseKey));
                }

                // use normal activation.
                return(ComUtils.CreateInstance(guid, uri.Host, identity));
            }
            finally
            {
                Thread.CurrentPrincipal = existingPrincipal;
            }
            #endif
        }
예제 #21
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);
 }
예제 #22
0
        /// <summary>
        /// Dispatches the event.
        /// </summary>
        private BaseEventState DispatchEvent(ONEVENTSTRUCT e)
        {
            NodeId typeId = AeParsedNodeId.Construct(e.dwEventType, e.dwEventCategory, e.szConditionName, m_namespaceIndex);

            // find the type.
            AeEventTypeState eventType = m_cache.FindType(m_defaultContext, typeId);

            if (eventType == null)
            {
                return(null);
            }

            // create a new instance.
            BaseEventState instance = m_cache.CreateInstance(m_defaultContext, eventType);

            if (instance == null)
            {
                return(null);
            }

            // fill in fields.
            UpdateBaseEvent(instance, eventType.EventType, e);

            if (instance is AuditEventState)
            {
                UpdateAuditEvent((AuditEventState)instance, eventType.EventType, e);
            }

            if (instance is AlarmConditionState)
            {
                UpdateAlarm((AlarmConditionState)instance, eventType.EventType, e);
            }

            if (instance is ExclusiveLimitAlarmState)
            {
                UpdateExclusiveLimitAlarm((ExclusiveLimitAlarmState)instance, eventType.EventType, e);
            }

            else if (instance is NonExclusiveLimitAlarmState)
            {
                UpdateNonExclusiveLimitAlarm((NonExclusiveLimitAlarmState)instance, eventType.EventType, e);
            }

            // process attributes.
            bool ackCommentFound = false;

            object[] values = ComUtils.GetVARIANTs(ref e.pEventAttributes, e.dwNumEventAttrs, false);

            for (int ii = 0; ii < eventType.EventType.Attributes.Count; ii++)
            {
                EventAttribute attribute = eventType.EventType.Attributes[ii];

                if (ii >= e.dwNumEventAttrs)
                {
                    continue;
                }

                if (!ackCommentFound && AeTypeCache.IsKnownName(attribute.Description, "ACK COMMENT"))
                {
                    ConditionState condition = instance as ConditionState;

                    if (condition != null)
                    {
                        condition.Comment            = new ConditionVariableState <LocalizedText>(condition);
                        condition.Comment.BrowseName = Opc.Ua.BrowseNames.Comment;
                        condition.Comment.Value      = new LocalizedText(values[ii] as string);
                    }

                    ackCommentFound = true;
                    continue;
                }

                PropertyState property = new PropertyState(instance);

                property.SymbolicName = attribute.Description;
                property.BrowseName   = new QualifiedName(property.SymbolicName, m_namespaceIndex);
                property.Value        = values[ii];

                instance.AddChild(property);
            }

            return(instance);
        }
예제 #23
0
        public void RemoveDevice(string devid)
        {
            IRunDevice dev = DeviceManager.GetDevice(devid);

            if (dev != null)
            {
                string desc    = String.Empty;
                string devname = dev.DeviceParameter.DeviceName;
                if (DeviceManager.RemoveDevice(dev.DeviceParameter.DeviceID))
                {
                    if (dev.DeviceType == DeviceType.Virtual)
                    {
                        desc = "删除虚拟设备";
                    }
                    else
                    {
                        #region
                        if (dev.CommunicateType == CommunicateType.COM)
                        {
                            IRunDevice[] comDevices = DeviceManager.GetDevices(dev.DeviceParameter.COM.Port.ToString(), CommunicateType.COM);

                            if (comDevices.Length == 0)
                            {
                                string      key        = ComUtils.PortToString(dev.DeviceParameter.COM.Port);
                                IController controller = ControllerManager.GetController(key);
                                if (controller != null)
                                {
                                    controller.IsWorking = false;
                                    if (ControllerManager.RemoveController(controller.Key))
                                    {
                                        controller.StopController();
                                        controller.Dispose();

                                        IComSession comChannel = (IComSession)((IComController)controller).ComChannel;
                                        comChannel.Close();
                                        comChannel.COMOpen  -= ComChannel_COMOpen;
                                        comChannel.COMClose -= ComChannel_COMClose;
                                        comChannel.COMError -= ComChannel_COMError;

                                        if (ChannelManager.RemoveChannel(comChannel.Key))
                                        {
                                            comChannel.Close();
                                            comChannel.Dispose();
                                        }
                                    }
                                }
                            }

                            desc = String.Format("{0},从串口'{1}'删除", dev.DeviceParameter.DeviceName, dev.DeviceParameter.COM.Port.ToString());
                        }
                        else if (dev.CommunicateType == CommunicateType.NET)
                        {
                            desc = String.Format("{0}-{1},从网络中删除成功", dev.DeviceParameter.DeviceName, dev.DeviceParameter.NET.RemoteIP);
                        }
                        #endregion
                    }

                    GraphicsShowManager.BatchRemoveDevice(dev.DeviceParameter.DeviceID);

                    ServiceManager.BatchRemoveDevice(dev.DeviceParameter.DeviceID);

                    if (_deviceContainer != null)
                    {
                        _deviceContainer.RemoveDevice(dev.DeviceParameter.DeviceID);
                    }

                    dev.DeviceParameter.Delete();
                    dev.DeviceDynamic.Delete();
                    dev.Delete();
                    dev.Dispose();

                    BindDeviceHandler(dev, dev.DeviceType, false);

                    desc += ",成功";
                    OnDeleteDeviceCompleted(dev.DeviceParameter.DeviceID, dev.DeviceParameter.DeviceName, true);
                }
                else
                {
                    desc += ",失败";
                    OnDeleteDeviceCompleted(dev.DeviceParameter.DeviceID, dev.DeviceParameter.DeviceName, false);
                }

                Logger.Info(true, desc);
            }
        }
예제 #24
0
        /// <summary>
        /// Updates the condition event.
        /// </summary>
        private void UpdateAlarm(AlarmConditionState instance, EventType eventType, ONEVENTSTRUCT e)
        {
            instance.NodeId = AeParsedNodeId.ConstructIdForCondition(e.szSource, e.dwEventCategory, e.szConditionName, m_namespaceIndex);

            // find the condition class.
            NodeId           classId            = AeParsedNodeId.Construct(e.dwEventType, e.dwEventCategory, null, m_namespaceIndex);
            AeEventTypeState conditionClassType = m_cache.FindType(m_defaultContext, classId);

            if (conditionClassType != null)
            {
                instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionClassId, classId, false);
                instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionClassName, conditionClassType.EventType.Description, false);
            }
            else
            {
                instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionClassId, Opc.Ua.ObjectTypeIds.BaseConditionClassType, false);
                instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionClassName, "BaseConditionClass", false);
            }

            instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionName, e.szConditionName, false);;
            instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ClientUserId, e.szActorID, false);
            instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Quality, ComUtils.GetQualityCode(e.wQuality), false);

            bool acknowledged = (e.wNewState & Constants.CONDITION_ACKED) != 0;
            bool active       = (e.wNewState & Constants.CONDITION_ACTIVE) != 0;
            bool enabled      = (e.wNewState & Constants.CONDITION_ENABLED) != 0;
            bool retain       = enabled & (active || !acknowledged);

            LocalizedText effectiveDisplayName = ConditionStateNames.Inactive;

            if (!enabled)
            {
                effectiveDisplayName = ConditionStateNames.Disabled;
            }
            else if (!acknowledged)
            {
                effectiveDisplayName = ConditionStateNames.Unacknowledged;
            }
            else if (active)
            {
                effectiveDisplayName = ConditionStateNames.Active;
            }

            instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Retain, true, false);

            instance.EnabledState            = new TwoStateVariableState(instance);
            instance.EnabledState.BrowseName = Opc.Ua.BrowseNames.EnabledState;
            instance.EnabledState.Value      = new LocalizedText((enabled) ? ConditionStateNames.Enabled : ConditionStateNames.Disabled);
            instance.EnabledState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, enabled, false);
            instance.EnabledState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.EffectiveDisplayName, effectiveDisplayName, false);

            instance.AckedState            = new TwoStateVariableState(instance);
            instance.AckedState.BrowseName = Opc.Ua.BrowseNames.AckedState;
            instance.AckedState.Value      = new LocalizedText((acknowledged) ? ConditionStateNames.Acknowledged : ConditionStateNames.Unacknowledged);
            instance.AckedState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, acknowledged, false);

            instance.ActiveState            = new TwoStateVariableState(instance);
            instance.ActiveState.BrowseName = Opc.Ua.BrowseNames.ActiveState;
            instance.ActiveState.Value      = new LocalizedText((active) ? ConditionStateNames.Active : ConditionStateNames.Inactive);
            instance.ActiveState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, active, false);
            instance.ActiveState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.TransitionTime, ComUtils.GetDateTime(e.ftActiveTime), false);

            if (!String.IsNullOrEmpty(e.szSubconditionName))
            {
                instance.ActiveState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.EffectiveDisplayName, e.szSubconditionName, false);
            }
        }
예제 #25
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);
             */
        }
예제 #26
0
        /// <summary>
        /// Acknowledges one or more events.
        /// </summary>
        public int[] AcknowledgeEvents(
            Session session,
            string comment,
            string acknowledgerId,
            AeAcknowledgeRequest[] requests)
        {
            if (session == null || !session.Connected)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            StringBuilder buffer = new StringBuilder();

            buffer.Append('[');
            buffer.Append(acknowledgerId);
            buffer.Append(']');

            if (!String.IsNullOrEmpty(comment))
            {
                buffer.Append(comment);
            }

            // wrap the comment once.
            Variant commentToWrite = new Variant(new LocalizedText(buffer.ToString()));

            int[] errors = new int[requests.Length];
            CallMethodRequestCollection methodsToCall = new CallMethodRequestCollection();

            for (int ii = 0; ii < requests.Length; ii++)
            {
                int cookie = requests[ii].Cookie;

                AeEvent e = null;

                lock (m_lock)
                {
                    // look up the event.
                    if (!m_events.TryGetValue(cookie, out e))
                    {
                        errors[ii] = ResultIds.E_INVALIDARG;

                        if (cookie < m_counter)
                        {
                            errors[ii] = ResultIds.S_ALREADYACKED;
                        }

                        continue;
                    }

                    if (e.SourceName != requests[ii].SourceName)
                    {
                        errors[ii] = ResultIds.E_INVALIDARG;
                        continue;
                    }

                    if (e.ConditionName != requests[ii].ConditionName)
                    {
                        errors[ii] = ResultIds.E_INVALIDARG;
                        continue;
                    }

                    if (e.ActiveTime != requests[ii].ActiveTime)
                    {
                        errors[ii] = ResultIds.E_INVALIDTIME;
                        continue;
                    }

                    // check that the cookie is still valid.
                    string conditionId    = GetConditionId(e);
                    int    expectedCookie = 0;

                    if (!m_cookies.TryGetValue(conditionId, out expectedCookie))
                    {
                        errors[ii] = ResultIds.S_ALREADYACKED;
                        continue;
                    }

                    // check cookie.
                    if (expectedCookie != cookie)
                    {
                        errors[ii] = ResultIds.E_INVALIDARG;
                        continue;
                    }

                    m_events.Remove(cookie);
                }

                CallMethodRequest request = new CallMethodRequest();
                request.MethodId = Opc.Ua.MethodIds.AcknowledgeableConditionType_Acknowledge;
                request.ObjectId = e.ConditionId;
                request.InputArguments.Add(new Variant(e.EventId));
                request.InputArguments.Add(commentToWrite);
                request.Handle = ii;
                methodsToCall.Add(request);
            }

            if (methodsToCall.Count > 0)
            {
                try
                {
                    // call the server.
                    CallMethodResultCollection results         = null;
                    DiagnosticInfoCollection   diagnosticInfos = null;

                    session.Call(
                        null,
                        methodsToCall,
                        out results,
                        out diagnosticInfos);

                    // verify that the server returned the correct number of results.
                    ClientBase.ValidateResponse(results, methodsToCall);
                    ClientBase.ValidateDiagnosticInfos(diagnosticInfos, methodsToCall);

                    // process results.
                    for (int ii = 0; ii < methodsToCall.Count; ii++)
                    {
                        int index = (int)methodsToCall[ii].Handle;

                        if (StatusCode.IsBad(results[ii].StatusCode))
                        {
                            errors[ii] = ResultIds.E_FAIL;
                            continue;
                        }
                    }
                }
                catch (Exception)
                {
                    // report error.
                    for (int ii = 0; ii < methodsToCall.Count; ii++)
                    {
                        int index = (int)methodsToCall[ii].Handle;
                        errors[ii] = ResultIds.E_FAIL;
                    }
                }
            }

            return(errors);
        }
예제 #27
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);
             */
        }
예제 #28
0
        /// <summary>
        /// Writes the values for the specified item ids.
        /// </summary>
        /// <param name="itemIds">The item ids.</param>
        /// <param name="values">The values.</param>
        /// <returns>The results.</returns>
        public int[] Write(string[] itemIds, DaValue[] values)
        {
            int[] results = new int[itemIds.Length];
            WriteValueCollection valuesToWrite = new WriteValueCollection();

            ComDaReadPropertiesRequest[] requests = new ComDaReadPropertiesRequest[values.Length];

            // prepare request.
            for (int ii = 0; ii < itemIds.Length; ii++)
            {
                ComDaReadPropertiesRequest request = requests[ii] = new ComDaReadPropertiesRequest();
                request.ItemId = itemIds[ii];
            }

            // need to get the data type of the remote node.
            m_browseManager.GetPropertyValues(Session, requests, PropertyIds.UaBuiltInType, PropertyIds.UaValueRank);

            // validate items.
            for (int ii = 0; ii < requests.Length; ii++)
            {
                ComDaReadPropertiesRequest request = requests[ii];

                if (request.Error < 0)
                {
                    results[ii] = request.Error;
                    continue;
                }

                int?builtInType = request.Values[0].Value as int?;
                int?valueRank   = request.Values[1].Value as int?;

                if (builtInType == null || valueRank == null)
                {
                    results[ii] = ResultIds.E_UNKNOWNITEMID;
                    continue;
                }

                // convert value to UA data type.
                WriteValue valueToWrite = new WriteValue();

                valueToWrite.NodeId      = m_mapper.GetRemoteNodeId(itemIds[ii]);
                valueToWrite.AttributeId = Attributes.Value;
                valueToWrite.Handle      = ii;

                // convert value to UA data type.
                try
                {
                    TypeInfo remoteType = new TypeInfo((BuiltInType)builtInType.Value, valueRank.Value);
                    valueToWrite.Value = m_mapper.GetRemoteDataValue(values[ii], remoteType);
                }
                catch (Exception e)
                {
                    results[ii] = ComUtils.GetErrorCode(e, ResultIds.E_BADTYPE);
                    continue;
                }

                valuesToWrite.Add(valueToWrite);
            }

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

            // write the values to the server.
            int[] remoteResults = m_groupManager.Write(valuesToWrite);

            // copy results.
            for (int ii = 0; ii < valuesToWrite.Count; ii++)
            {
                results[(int)valuesToWrite[ii].Handle] = remoteResults[ii];
            }

            return(results);
        }
예제 #29
0
        /// <summary>
        /// Sets the event filter.
        /// </summary>
        public void SetFilter(
            int eventTypes,
            ushort lowSeverity,
            ushort highSeverity,
            uint[] categoryIds,
            string[] areas,
            string[] sources)
        {
            ThrowIfDisposed();

            lock (m_lock)
            {
                // validate event types.
                if (eventTypes <= 0 || eventTypes > 0x7)
                {
                    throw ComUtils.CreateComException(ResultIds.E_INVALIDARG);
                }

                // validate severity.
                if (lowSeverity == 0 || highSeverity > 1000 || lowSeverity > highSeverity)
                {
                    throw ComUtils.CreateComException(ResultIds.E_INVALIDARG);
                }

                // validate categories.
                if (categoryIds != null)
                {
                    for (int ii = 0; ii < categoryIds.Length; ii++)
                    {
                        if (m_mapper.GetCategory(categoryIds[ii]) == null)
                        {
                            throw ComUtils.CreateComException(ResultIds.E_INVALIDARG);
                        }
                    }
                }

                // validate areas.
                List <NodeId> areasToUse = new List <NodeId>();

                if (areas != null)
                {
                    for (int ii = 0; ii < areas.Length; ii++)
                    {
                        List <NodeId> areaIds = m_browser.SearchByQualifiedName(areas[ii], true);

                        if (areaIds.Count == 0)
                        {
                            throw ComUtils.CreateComException(ResultIds.E_INVALIDARG);
                        }

                        areasToUse.AddRange(areaIds);
                    }
                }

                // validate sources.
                List <NodeId> sourcesToUse = new List <NodeId>();

                if (sources != null)
                {
                    for (int ii = 0; ii < sources.Length; ii++)
                    {
                        List <NodeId> sourceIds = m_browser.SearchByQualifiedName(sources[ii], false);

                        if (sourceIds.Count == 0)
                        {
                            throw ComUtils.CreateComException(ResultIds.E_INVALIDARG);
                        }

                        sourcesToUse.AddRange(sourceIds);
                    }
                }

                m_areas   = areas;
                m_sources = sources;

                UpdateAreaFilter(areasToUse);
                UpdateSourceFilter(sourcesToUse);
                m_filter.SetFilter(eventTypes, lowSeverity, highSeverity, categoryIds, m_sourceNodes);
            }
        }
예제 #30
0
        /// <summary>
        /// Moves the current browse position to the specified item.
        /// </summary>
        public void BrowseTo(string itemId)
        {
            Session session = m_server.Session;

            if (session == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            lock (m_lock)
            {
                // check if value has been cached.
                if (itemId == null)
                {
                    itemId = String.Empty;
                }

                AeBrowseElement element = null;

                if (m_cache.TryGetValue(itemId, out element))
                {
                    m_position = element;
                    return;
                }

                // parse the item id looking for a known parent.
                Stack <string>  names     = new Stack <string>();
                AeBrowseElement root      = null;
                string          currentId = itemId;

                while (!String.IsNullOrEmpty(currentId))
                {
                    string parentId = null;
                    string itemName = currentId;

                    int index = currentId.LastIndexOf('/');

                    if (index >= 0)
                    {
                        parentId = currentId.Substring(0, index);
                        itemName = currentId.Substring(index + 1);
                    }

                    // save time by using an intermediate parent if it has already been cached.
                    if (!String.IsNullOrEmpty(parentId))
                    {
                        if (m_cache.TryGetValue(parentId, out root))
                        {
                            names.Push(itemName);
                            break;
                        }
                    }

                    currentId = parentId;
                    names.Push(itemName);
                    root = null;
                }

                // use root if no parent found.
                if (root == null)
                {
                    root = m_cache[String.Empty];
                }

                // find the element.
                element = Find(session, itemId, root, names, true);

                if (element == null)
                {
                    throw ComUtils.CreateComException(ResultIds.E_INVALIDBRANCHNAME);
                }

                // update cache and set position.
                m_cache[itemId] = element;
                m_position      = element;
            }
        }