diff --git a/ComIOP/Common/Client/Ae/AeAreaBrowser.cs b/ComIOP/Common/Client/Ae/AeAreaBrowser.cs deleted file mode 100644 index 121696269..000000000 --- a/ComIOP/Common/Client/Ae/AeAreaBrowser.cs +++ /dev/null @@ -1,285 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Ae; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Client -{ - /// - /// Browses the children of a segment. - /// - public class AeAreaBrower : NodeBrowser - { - #region Constructors - /// - /// Creates a new browser object with a set of filters. - /// - /// The system context to use. - /// The view which may restrict the set of references/nodes found. - /// The type of references being followed. - /// Whether subtypes of the reference type are followed. - /// Which way the references are being followed. - /// The browse name of a specific target (used when translating browse paths). - /// Any additional references that should be included. - /// If true the browser should not making blocking calls to external systems. - /// Name of the qualified. - /// Index of the namespace. - public AeAreaBrower( - ISystemContext context, - ViewDescription view, - NodeId referenceType, - bool includeSubtypes, - BrowseDirection browseDirection, - QualifiedName browseName, - IEnumerable additionalReferences, - bool internalOnly, - string qualifiedName, - ushort namespaceIndex) - : - base( - context, - view, - referenceType, - includeSubtypes, - browseDirection, - browseName, - additionalReferences, - internalOnly) - { - m_qualifiedName = qualifiedName; - m_namespaceIndex = namespaceIndex; - m_stage = Stage.Begin; - } - #endregion - - #region Overridden Methods - /// - /// Returns the next reference. - /// - /// The next reference that meets the browse criteria. - public override IReference Next() - { - lock (DataLock) - { - IReference reference = null; - - // enumerate pre-defined references. - // always call first to ensure any pushed-back references are returned first. - reference = base.Next(); - - if (reference != null) - { - return reference; - } - - // don't start browsing huge number of references when only internal references are requested. - if (InternalOnly) - { - return null; - } - - // fetch references from the server. - do - { - // fetch next reference. - reference = NextChild(); - - if (reference != null) - { - return reference; - } - - // go to the next stage. - NextStage(); - } - while (m_stage != Stage.Done); - - // all done. - return null; - } - } - #endregion - - #region Private Methods - /// - /// Returns the next child. - /// - private IReference NextChild() - { - // check if a specific browse name is requested. - if (QualifiedName.IsNull(base.BrowseName)) - { - return NextChild(m_stage); - } - - // keep fetching references until a matching browse name if found. - NodeStateReference reference = null; - - do - { - reference = NextChild(m_stage); - - if (reference != null) - { - // need to let the caller look up the browse name. - if (reference.Target == null) - { - return reference; - } - - // check for browse name match. - if (reference.Target.BrowseName == base.BrowseName) - { - return reference; - } - } - } - while (reference != null); - - // no match - need to go onto the next stage. - return null; - } - - /// - /// Returns the next child. - /// - private NodeStateReference NextChild(Stage stage) - { - // fetch children. - if (stage == Stage.Children) - { - if (m_browser == null) - { - return null; - } - - BaseObjectState node = m_browser.Next(SystemContext, m_namespaceIndex); - - if (node != null) - { - return new NodeStateReference(ReferenceTypeIds.HasNotifier, false, node.NodeId); - } - - // all done. - return null; - } - - // fetch child parents. - if (stage == Stage.Parents) - { - return null; - } - - return null; - } - - /// - /// Initializes the next stage of browsing. - /// - private void NextStage() - { - ComAeClientManager system = (ComAeClientManager)this.SystemContext.SystemHandle; - ComAeClient client = system.SelectClient((ServerSystemContext)SystemContext, false); - - // determine which stage is next based on the reference types requested. - for (Stage next = m_stage+1; next <= Stage.Done; next++) - { - if (next == Stage.Children) - { - if (IsRequired(ReferenceTypeIds.HasNotifier, false)) - { - m_stage = next; - break; - } - } - - else if (next == Stage.Parents) - { - if (IsRequired(ReferenceTypeIds.HasNotifier, true)) - { - m_stage = next; - break; - } - } - - else if (next == Stage.Done) - { - m_stage = next; - break; - } - } - - // start enumerating areas. - if (m_stage == Stage.Children) - { - m_browser = new ComAeBrowserClient(client, m_qualifiedName); - return; - } - - // start enumerating parents. - if (m_stage == Stage.Parents) - { - return; - } - - // all done. - } - #endregion - - #region Stage Enumeration - /// - /// The stages available in a browse operation. - /// - private enum Stage - { - Begin, - Children, - Parents, - Done - } - #endregion - - #region Private Fields - private Stage m_stage; - private string m_qualifiedName; - private ushort m_namespaceIndex; - private ComAeBrowserClient m_browser; - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/AeAreaState.cs b/ComIOP/Common/Client/Ae/AeAreaState.cs deleted file mode 100644 index 618e82c86..000000000 --- a/ComIOP/Common/Client/Ae/AeAreaState.cs +++ /dev/null @@ -1,132 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// A object which maps a segment to a UA object. - /// - public partial class AeAreaState : FolderState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The qualified name for the area. - /// The name of the area. - /// Index of the namespace. - public AeAreaState( - ISystemContext context, - string qualifiedName, - string name, - ushort namespaceIndex) - : - base(null) - { - m_qualifiedName = qualifiedName; - - this.SymbolicName = name; - this.TypeDefinitionId = Opc.Ua.ObjectTypeIds.FolderType; - this.NodeId = AeModelUtils.ConstructIdForArea(qualifiedName, namespaceIndex); - this.BrowseName = new QualifiedName(name, namespaceIndex); - this.DisplayName = this.BrowseName.Name; - this.Description = null; - this.WriteMask = 0; - this.UserWriteMask = 0; - this.EventNotifier = EventNotifiers.SubscribeToEvents; - } - #endregion - - #region Public Properties - /// - /// Gets the qualified name for the area. - /// - /// The qualified name for the area. - public string QualifiedName - { - get { return m_qualifiedName; } - } - #endregion - - #region Overridden Methods - /// - /// Creates a browser that finds the references to the branch. - /// - /// The system context to use. - /// The view which may restrict the set of references/nodes found. - /// The type of references being followed. - /// Whether subtypes of the reference type are followed. - /// Which way the references are being followed. - /// The browse name of a specific target (used when translating browse paths). - /// Any additional references that should be included. - /// If true the browser should not making blocking calls to external systems. - /// The browse object (must be disposed). - public override INodeBrowser CreateBrowser( - ISystemContext context, - ViewDescription view, - NodeId referenceType, - bool includeSubtypes, - BrowseDirection browseDirection, - QualifiedName browseName, - IEnumerable additionalReferences, - bool internalOnly) - { - NodeBrowser browser = new AeAreaBrower( - context, - view, - referenceType, - includeSubtypes, - browseDirection, - browseName, - additionalReferences, - internalOnly, - m_qualifiedName, - this.NodeId.NamespaceIndex); - - PopulateBrowser(context, browser); - - return browser; - } - #endregion - - #region Private Fields - private string m_qualifiedName; - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/AeConditionState.cs b/ComIOP/Common/Client/Ae/AeConditionState.cs deleted file mode 100644 index bfe21b8ce..000000000 --- a/ComIOP/Common/Client/Ae/AeConditionState.cs +++ /dev/null @@ -1,79 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using OpcRcw.Ae; - -namespace Opc.Ua.Com.Client -{ - /// - /// A object which represents a COM AE condition. - /// - public partial class AeConditionState : AlarmConditionState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The handle. - /// The acknowledge method. - public AeConditionState(ISystemContext context, NodeHandle handle, AddCommentMethodState acknowledgeMethod) - : - base(null) - { - AeParsedNodeId parsedNodeId = (AeParsedNodeId)handle.ParsedNodeId; - - this.NodeId = handle.NodeId; - - this.TypeDefinitionId = AeParsedNodeId.Construct( - Constants.CONDITION_EVENT, - parsedNodeId.CategoryId, - parsedNodeId.ConditionName, - parsedNodeId.NamespaceIndex); - - this.Acknowledge = acknowledgeMethod; - this.AddChild(acknowledgeMethod); - } - #endregion - - #region Public Properties - #endregion - - #region Private Fields - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/AeEventTypeState.cs b/ComIOP/Common/Client/Ae/AeEventTypeState.cs deleted file mode 100644 index 9b4ea2792..000000000 --- a/ComIOP/Common/Client/Ae/AeEventTypeState.cs +++ /dev/null @@ -1,189 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; -using OpcRcw.Ae; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores information about an AE event type in the server address space. - /// - internal class AeEventTypeState : BaseObjectTypeState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public AeEventTypeState(EventType eventType, ushort namespaceIndex) - { - m_eventType = eventType; - - // create the name for the event type. - string name = eventType.Description; - - if (!String.IsNullOrEmpty(eventType.ConditionName)) - { - name = eventType.ConditionName; - } - - if (!name.EndsWith("Type")) - { - if (eventType.EventTypeId == OpcRcw.Ae.Constants.CONDITION_EVENT) - { - name += "AlarmType"; - } - else - { - name += "EventType"; - } - } - - // the attributes. - this.NodeId = AeParsedNodeId.Construct(eventType, null, namespaceIndex); - this.BrowseName = new QualifiedName(name, namespaceIndex); - this.DisplayName = eventType.Description; - this.IsAbstract = false; - this.SuperTypeId = AeParsedNodeId.Construct(eventType.EventTypeMapping, namespaceIndex); - - // add the attributes as properties. - if (eventType.Attributes != null) - { - for (int ii = 0; ii < eventType.Attributes.Count; ii++) - { - string propertyName = eventType.Attributes[ii].Description; - - if (AeTypeCache.IsKnownName(propertyName, "ACK COMMENT")) - { - continue; - } - - PropertyState property = new PropertyState(this); - - property.SymbolicName = propertyName; - property.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasProperty; - property.TypeDefinitionId = Opc.Ua.VariableTypeIds.PropertyType; - property.ModellingRuleId = Opc.Ua.ObjectIds.ModellingRule_Optional; - property.NodeId = AeParsedNodeId.Construct(eventType, propertyName, namespaceIndex); - property.BrowseName = new QualifiedName(propertyName, namespaceIndex); - property.DisplayName = property.BrowseName.Name; - property.AccessLevel = AccessLevels.None; - property.UserAccessLevel = AccessLevels.None; - property.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; - property.Historizing = false; - - bool isArray = false; - property.DataType = ComUtils.GetDataTypeId(eventType.Attributes[ii].VarType, out isArray); - property.ValueRank = (isArray) ? ValueRanks.OneDimension : ValueRanks.Scalar; - - this.AddChild(property); - } - } - } - #endregion - - #region Public Members - /// - /// Gets the event type metadata. - /// - public EventType EventType - { - get { return m_eventType; } - } - #endregion - - BaseEventState ConstructEvent(ONEVENTSTRUCT e) - { - return null; - } - - #region Private Fields - private EventType m_eventType; - #endregion - } - - /// - /// Stores information about an abstract event type that groups AE events in the type hierarchy. - /// - internal class AeEventTypeMappingState : BaseObjectTypeState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public AeEventTypeMappingState(EventTypeMapping eventType, ushort namespaceIndex) - { - m_eventType = eventType; - - // create the name for the event type. - string name = "COMAE" + eventType.ToString(); - - // the attributes. - this.NodeId = AeParsedNodeId.Construct(eventType, namespaceIndex); - this.BrowseName = new QualifiedName(name, namespaceIndex); - this.DisplayName = this.BrowseName.Name; - this.IsAbstract = true; - - // set the supertype. - switch (eventType) - { - case EventTypeMapping.AlarmConditionType: { SuperTypeId = Opc.Ua.ObjectTypeIds.AlarmConditionType; break; } - case EventTypeMapping.AuditEventType: { SuperTypeId = Opc.Ua.ObjectTypeIds.AuditEventType; break; } - case EventTypeMapping.BaseEventType: { SuperTypeId = Opc.Ua.ObjectTypeIds.BaseEventType; break; } - case EventTypeMapping.DeviceFailureEventType: { SuperTypeId = Opc.Ua.ObjectTypeIds.DeviceFailureEventType; break; } - case EventTypeMapping.DiscreteAlarmType: { SuperTypeId = Opc.Ua.ObjectTypeIds.DiscreteAlarmType; break; } - case EventTypeMapping.NonExclusiveDeviationAlarmType: { SuperTypeId = Opc.Ua.ObjectTypeIds.NonExclusiveDeviationAlarmType; break; } - case EventTypeMapping.ExclusiveLevelAlarmType: { SuperTypeId = Opc.Ua.ObjectTypeIds.ExclusiveLevelAlarmType; break; } - case EventTypeMapping.LimitAlarmType: { SuperTypeId = Opc.Ua.ObjectTypeIds.LimitAlarmType; break; } - case EventTypeMapping.NonExclusiveLevelAlarmType: { SuperTypeId = Opc.Ua.ObjectTypeIds.NonExclusiveLevelAlarmType; break; } - case EventTypeMapping.OffNormalAlarmType: { SuperTypeId = Opc.Ua.ObjectTypeIds.OffNormalAlarmType; break; } - case EventTypeMapping.SystemEventType: { SuperTypeId = Opc.Ua.ObjectTypeIds.SystemEventType; break; } - case EventTypeMapping.TripAlarmType: { SuperTypeId = Opc.Ua.ObjectTypeIds.TripAlarmType; break; } - case EventTypeMapping.ConditionClassType: { SuperTypeId = Opc.Ua.ObjectTypeIds.BaseConditionClassType; break; } - } - } - #endregion - - #region Public Members - /// - /// Gets the event type metadata. - /// - public EventTypeMapping EventType - { - get { return m_eventType; } - } - #endregion - - #region Private Fields - private EventTypeMapping m_eventType; - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/AeModelUtils.cs b/ComIOP/Common/Client/Ae/AeModelUtils.cs deleted file mode 100644 index 3a5b11f5e..000000000 --- a/ComIOP/Common/Client/Ae/AeModelUtils.cs +++ /dev/null @@ -1,142 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// A class that builds NodeIds used by the DataAccess NodeManager - /// - public static class AeModelUtils - { - /// - /// The RootType for a AE Simple Event Type node. - /// - public const int AeSimpleEventType = OpcRcw.Ae.Constants.SIMPLE_EVENT; - - /// - /// The RootType for a AE Tracking Event Type node. - /// - public const int AeTrackingEventType = OpcRcw.Ae.Constants.TRACKING_EVENT; - - /// - /// The RootType for a AE Condition Event Type node. - /// - public const int AeConditionEventType = OpcRcw.Ae.Constants.CONDITION_EVENT; - - /// - /// The RootType for a AE Area - /// - public const int AeArea = 5; - - /// - /// The RootType for an AE Source - /// - public const int AeSource = 6; - - /// - /// The RootType for an AE Condition - /// - public const int AeCondition = 7; - - /// - /// The RootType for a node defined by the UA server. - /// - public const int InternalNode = 8; - - /// - /// The RootType for an EventType defined by the AE server. - /// - public const int AeEventTypeMapping = 9; - - /// - /// The RootType for a ConditionClass defined by the AE server. - /// - public const int AeConditionClassMapping = 10; - - /// - /// Constructs a NodeId from the BrowseName of an internal node. - /// - /// The browse name. - /// Index of the namespace. - /// The node id. - public static NodeId ConstructIdForInternalNode(QualifiedName browseName, ushort namespaceIndex) - { - ParsedNodeId parsedNodeId = new ParsedNodeId(); - - parsedNodeId.RootId = browseName.Name; - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.RootType = InternalNode; - - return parsedNodeId.Construct(); - } - - /// - /// Constructs the id for an area. - /// - /// The area id. - /// Index of the namespace. - /// - public static NodeId ConstructIdForArea(string areaId, ushort namespaceIndex) - { - ParsedNodeId parsedNodeId = new ParsedNodeId(); - - parsedNodeId.RootId = areaId; - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.RootType = AeArea; - - return parsedNodeId.Construct(); - } - - /// - /// Constructs the id for a source. - /// - /// The area id. - /// Name of the source. - /// Index of the namespace. - /// - public static NodeId ConstructIdForSource(string areaId, string sourceName, ushort namespaceIndex) - { - ParsedNodeId parsedNodeId = new ParsedNodeId(); - - parsedNodeId.RootType = AeSource; - parsedNodeId.RootId = areaId; - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.ComponentPath = sourceName; - - return parsedNodeId.Construct(); - } - } -} diff --git a/ComIOP/Common/Client/Ae/AeParseNodeId.cs b/ComIOP/Common/Client/Ae/AeParseNodeId.cs deleted file mode 100644 index 415039bb3..000000000 --- a/ComIOP/Common/Client/Ae/AeParseNodeId.cs +++ /dev/null @@ -1,377 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Collections.Generic; -using System.Reflection; -using Opc.Ua; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - #region AeParsedNodeId Class - /// - /// Stores the elements of a NodeId after it is parsed. - /// - /// - /// The NodeIds used by the samples are strings with an optional path appended. - /// The RootType identifies the type of Root Node. The RootId is the unique identifier - /// for the Root Node. The ComponentPath is constructed from the SymbolicNames - /// of one or more children of the Root Node. - /// - public class AeParsedNodeId : ParsedNodeId - { - #region Public Interface - /// - /// Gets or sets the category id. - /// - /// The category id. - public int CategoryId - { - get { return m_categoryId; } - set { m_categoryId = value; } - } - - /// - /// Gets or sets the source for a condition. - /// - /// The source id of the condition. - public string SourceId - { - get { return m_sourceId; } - set { m_sourceId = value; } - } - - /// - /// Gets or sets the name of the condition. - /// - /// The name of the condition. - public string ConditionName - { - get { return m_conditionName; } - set { m_conditionName = value; } - } - - /// - /// Gets or sets the attribute id. - /// - /// The attribute id. - public string AttributeName - { - get { return m_attributeName; } - set { m_attributeName = value; } - } - - /// - /// Parses the specified node identifier. - /// - /// The node identifier. - /// The parsed node identifier. Null if the identifier cannot be parsed. - public static new AeParsedNodeId Parse(NodeId nodeId) - { - // can only parse non-null string node identifiers. - if (NodeId.IsNull(nodeId)) - { - return null; - } - - string identifier = nodeId.Identifier as string; - - if (String.IsNullOrEmpty(identifier)) - { - return null; - } - - AeParsedNodeId parsedNodeId = new AeParsedNodeId(); - parsedNodeId.NamespaceIndex = nodeId.NamespaceIndex; - - int start = 0; - - // extract the type of identifier. - parsedNodeId.RootType = (int)ExtractNumber(identifier, ref start); - - if (start >= identifier.Length || identifier[start] != ':') - { - return null; - } - - // extract any component path. - StringBuilder buffer = new StringBuilder(); - - int index = start+1; - - parsedNodeId.RootId = ExtractAndUnescapeString(identifier, ref index, '&', '?'); - - // extract any component. - int end = index+1; - parsedNodeId.ComponentPath = null; - - // extract the component path. - if (end < identifier.Length) - { - parsedNodeId.ComponentPath = identifier.Substring(end); - } - - // extract the category and condition name. - start = 0; - identifier = parsedNodeId.RootId; - - switch (parsedNodeId.RootType) - { - case AeModelUtils.AeEventTypeMapping: - { - EventTypeMapping mapping = (EventTypeMapping)(int)ExtractNumber(identifier, ref start); - - if (start < identifier.Length) - { - return null; - } - - parsedNodeId.CategoryId = (int)mapping; - break; - } - - case AeModelUtils.AeSimpleEventType: - case AeModelUtils.AeTrackingEventType: - { - parsedNodeId.CategoryId = Utils.ToInt32(ExtractNumber(identifier, ref start)); - - if (start < identifier.Length) - { - return null; - } - - break; - } - - case AeModelUtils.AeConditionEventType: - { - parsedNodeId.CategoryId = Utils.ToInt32(ExtractNumber(identifier, ref start)); - - if (start < identifier.Length) - { - if (identifier[start] != ':') - { - return null; - } - - parsedNodeId.ConditionName = identifier.Substring(start+1); - } - - break; - } - - case AeModelUtils.AeCondition: - { - parsedNodeId.SourceId = ExtractAndUnescapeString(identifier, ref start, '0', ':'); - - if (start < identifier.Length && identifier[start] != ':') - { - return null; - } - - start++; - - parsedNodeId.CategoryId = Utils.ToInt32(ExtractNumber(identifier, ref start)); - - if (start < identifier.Length) - { - if (identifier[start] != ':') - { - return null; - } - - parsedNodeId.ConditionName = identifier.Substring(start+1); - } - - break; - } - } - - // extract the attribute id. - if (!String.IsNullOrEmpty(parsedNodeId.ComponentPath)) - { - start = 0; - identifier = parsedNodeId.ComponentPath; - - switch (parsedNodeId.RootType) - { - case AeModelUtils.AeSimpleEventType: - case AeModelUtils.AeTrackingEventType: - case AeModelUtils.AeConditionEventType: - { - parsedNodeId.AttributeName = identifier.Substring(start+1); - break; - } - } - } - - return parsedNodeId; - } - - /// - /// Constructs a node identifier. - /// - /// The node identifier. - public new NodeId Construct() - { - return Construct(this.RootType, this.RootId, this.ComponentPath, this.NamespaceIndex); - } - - /// - /// Constructs the NodeId for the specified event type mapping node. - /// - internal static NodeId Construct(EventTypeMapping mapping, ushort namespaceIndex) - { - return Construct(AeModelUtils.AeEventTypeMapping, ((int)mapping).ToString(), null, namespaceIndex); - } - - /// - /// Constructs the NodeId for the specified event type node. - /// - internal static NodeId Construct(EventType eventType, string componentPath, ushort namespaceIndex) - { - StringBuilder buffer = new StringBuilder(); - - buffer.Append(Utils.ToUInt32(eventType.CategoryId)); - - if (!String.IsNullOrEmpty(eventType.ConditionName)) - { - buffer.Append(':'); - buffer.Append(eventType.ConditionName); - } - - return Construct(eventType.EventTypeId, buffer.ToString(), componentPath, namespaceIndex); - } - - /// - /// Constructs the NodeId for the specified event type. - /// - /// Type of the event. - /// The category id. - /// Name of the condition. - /// Index of the namespace. - /// The NodeId - public static NodeId Construct(int eventType, int categoryId, string conditionName, ushort namespaceIndex) - { - StringBuilder buffer = new StringBuilder(); - - buffer.Append(Utils.ToUInt32(categoryId)); - - if (!String.IsNullOrEmpty(conditionName)) - { - buffer.Append(':'); - buffer.Append(conditionName); - } - - return Construct(eventType, buffer.ToString(), null, namespaceIndex); - } - - /// - /// Constructs the NodeId for the attribute of the specified event type. - /// - /// Type of the event. - /// The category id. - /// The attribute id. - /// Index of the namespace. - /// The NodeId - public static NodeId Construct(int eventType, int categoryId, int attributeId, ushort namespaceIndex) - { - return Construct(eventType, categoryId.ToString(), attributeId.ToString(), namespaceIndex); - } - - /// - /// Constructs the NodeId for the attribute of the specified event type. - /// - /// Type of the event. - /// Index of the namespace. - /// The NodeId - public static NodeId Construct(int eventType, ushort namespaceIndex) - { - return Construct(eventType, String.Empty, null, namespaceIndex); - } - - /// - /// Constructs the id for condition. - /// - /// The source id. - /// The category id. - /// Name of the condition. - /// Index of the namespace. - /// - public static NodeId ConstructIdForCondition(string sourceId, int categoryId, string conditionName, ushort namespaceIndex) - { - StringBuilder buffer = new StringBuilder(); - - EscapeAndAppendString(buffer, sourceId, '0', ':'); - buffer.Append(':'); - buffer.Append(Utils.ToUInt32(categoryId)); - buffer.Append(':'); - buffer.Append(conditionName); - - return Construct(AeModelUtils.AeCondition, buffer.ToString(), null, namespaceIndex); - } - - /// - /// Constructs a node identifier. - /// - /// The node identifier. - public static NodeId Construct(int rootType, string rootId, string componentPath, ushort namespaceIndex) - { - StringBuilder buffer = new StringBuilder(); - - // add the root type. - buffer.Append(rootType); - buffer.Append(':'); - - // add the root identifier. - EscapeAndAppendString(buffer, rootId, '&', '?'); - - // add the component path. - if (!String.IsNullOrEmpty(componentPath)) - { - buffer.Append('?'); - buffer.Append(componentPath); - } - - // construct the node id with the namespace index provided. - return new NodeId(buffer.ToString(), namespaceIndex); - } - #endregion - - #region Private Fields - private string m_sourceId; - private int m_categoryId; - private string m_conditionName; - private string m_attributeName; - #endregion - } - #endregion -} diff --git a/ComIOP/Common/Client/Ae/AeSourceState.cs b/ComIOP/Common/Client/Ae/AeSourceState.cs deleted file mode 100644 index 5dea0e704..000000000 --- a/ComIOP/Common/Client/Ae/AeSourceState.cs +++ /dev/null @@ -1,96 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// A object which maps a segment to a UA object. - /// - public partial class AeSourceState : BaseObjectState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The area id. - /// The qualified name for the source. - /// The name of the source. - /// Index of the namespace. - public AeSourceState( - ISystemContext context, - string areaId, - string qualifiedName, - string name, - ushort namespaceIndex) - : - base(null) - { - m_areaId = areaId; - m_qualifiedName = qualifiedName; - - this.TypeDefinitionId = Opc.Ua.ObjectTypeIds.BaseObjectType; - this.NodeId = AeModelUtils.ConstructIdForSource(m_areaId, name, namespaceIndex); - this.BrowseName = new QualifiedName(name, namespaceIndex); - this.DisplayName = this.BrowseName.Name; - this.Description = null; - this.WriteMask = 0; - this.UserWriteMask = 0; - this.EventNotifier = EventNotifiers.None; - - this.AddReference(ReferenceTypeIds.HasNotifier, true, AeModelUtils.ConstructIdForArea(m_areaId, namespaceIndex)); - } - #endregion - - #region Public Properties - /// - /// Gets the qualified name for the source. - /// - /// The qualified name for the source. - public string QualifiedName - { - get { return m_qualifiedName; } - } - #endregion - - #region Private Fields - private string m_areaId; - private string m_qualifiedName; - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/AeTypeCache.cs b/ComIOP/Common/Client/Ae/AeTypeCache.cs deleted file mode 100644 index 4a49523e1..000000000 --- a/ComIOP/Common/Client/Ae/AeTypeCache.cs +++ /dev/null @@ -1,581 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; -using Opc.Ua.Server; -using OpcRcw.Ae; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the type information provided by the AE server. - /// - internal class AeTypeCache - { - /// - /// A table of event types returned from the server. - /// - public List EventTypes { get; set; } - - /// - /// A table of attributes for each event category supported by the server, - /// - public Dictionary Attributes { get; set; } - - /// - /// A table of node reprenting the AE event catgories and condtions. - /// - public NodeIdDictionary EventTypeNodes { get; set; } - - /// - /// Returns the node for the event type mapping identified by the node id. - /// - public AeEventTypeMappingState GetMappingNode(ServerSystemContext context, NodeId nodeId) - { - BaseObjectTypeState objectType = null; - - if (!EventTypeNodes.TryGetValue(nodeId, out objectType)) - { - return null; - } - - AeEventTypeMappingState mappingNode = objectType as AeEventTypeMappingState; - - if (mappingNode == null) - { - return null; - } - - if (context.TypeTable.FindSubTypes(mappingNode.NodeId).Count == 0) - { - return null; - } - - return mappingNode; - } - - /// - /// Returns the type identified by the category id and condition name. - /// - public AeEventTypeState FindType(ServerSystemContext context, NodeId nodeId) - { - if (NodeId.IsNull(nodeId)) - { - return null; - } - - BaseObjectTypeState eventType = null; - - if (!EventTypeNodes.TryGetValue(nodeId, out eventType)) - { - return null; - } - - return eventType as AeEventTypeState; - } - - /// - /// Creates an instance of an event. - /// - public BaseEventState CreateInstance(ServerSystemContext context, AeEventTypeState eventType) - { - BaseEventState instance = null; - - switch (eventType.EventType.EventTypeMapping) - { - case EventTypeMapping.AlarmConditionType: { instance = new AlarmConditionState(null); break; } - case EventTypeMapping.AuditEventType: { instance = new AuditEventState(null); break; } - case EventTypeMapping.BaseEventType: { instance = new BaseEventState(null); break; } - case EventTypeMapping.DeviceFailureEventType: { instance = new DeviceFailureEventState(null); break; } - case EventTypeMapping.DiscreteAlarmType: { instance = new DiscreteAlarmState(null); break; } - case EventTypeMapping.NonExclusiveDeviationAlarmType: { instance = new NonExclusiveDeviationAlarmState(null); break; } - case EventTypeMapping.ExclusiveLevelAlarmType: { instance = new ExclusiveLevelAlarmState(null); break; } - case EventTypeMapping.LimitAlarmType: { instance = new LimitAlarmState(null); break; } - case EventTypeMapping.NonExclusiveLevelAlarmType: { instance = new NonExclusiveLevelAlarmState(null); break; } - case EventTypeMapping.OffNormalAlarmType: { instance = new OffNormalAlarmState(null); break; } - case EventTypeMapping.SystemEventType: { instance = new SystemEventState(null); break; } - case EventTypeMapping.TripAlarmType: { instance = new TripAlarmState(null); break; } - } - - return instance; - } - - /// - /// Updates the event types in cache with the most recent info fetched from the AE server. - /// - public void UpdateCache(ServerSystemContext context, ushort namespaceIndex) - { - // clear the existing nodes. - EventTypeNodes = new NodeIdDictionary(); - Attributes = new Dictionary(); - TypeTable typeTable = context.TypeTable as TypeTable; - - // rebuild from the recently fetched list. - for (int ii = 0; ii < EventTypes.Count; ii++) - { - // save the attributes for use when creating filters. - if (EventTypes[ii].EventTypeMapping != EventTypeMapping.ConditionClassType && !Attributes.ContainsKey(EventTypes[ii].CategoryId)) - { - EventType eventType = EventTypes[ii]; - - int[] attributeIds = new int[eventType.Attributes.Count]; - - for (int jj = 0; jj < attributeIds.Length; jj++) - { - attributeIds[jj] = eventType.Attributes[jj].Id; - } - - Attributes.Add(EventTypes[ii].CategoryId, attributeIds); - } - - AeEventTypeState node = new AeEventTypeState(EventTypes[ii], namespaceIndex); - - BaseObjectTypeState mappingNode = null; - - if (!EventTypeNodes.TryGetValue(node.SuperTypeId, out mappingNode)) - { - mappingNode = new AeEventTypeMappingState(node.EventType.EventTypeMapping, namespaceIndex); - EventTypeNodes.Add(mappingNode.NodeId, mappingNode); - - // ensure the mapping node is in the type table. - if (typeTable != null) - { - if (!typeTable.IsKnown(mappingNode.NodeId)) - { - typeTable.AddSubtype(mappingNode.NodeId, mappingNode.SuperTypeId); - } - } - } - - EventTypeNodes.Add(node.NodeId, node); - - // ensure the type node is in the type table. - if (typeTable != null) - { - if (!typeTable.IsKnown(node.NodeId)) - { - typeTable.AddSubtype(node.NodeId, mappingNode.NodeId); - } - } - } - } - - /// - /// Fetches the event type information from the AE server. - /// - public void LoadEventTypes(ComAeClient client) - { - EventTypes = new List(); - LoadEventType(client, OpcRcw.Ae.Constants.SIMPLE_EVENT); - LoadEventType(client, OpcRcw.Ae.Constants.TRACKING_EVENT); - LoadEventType(client, OpcRcw.Ae.Constants.CONDITION_EVENT); - } - - /// - /// Fetches the event categories for the specified event type. - /// - public void LoadEventType(ComAeClient client, int eventTypeId) - { - int[] ids = null; - string[] descriptions = null; - - try - { - client.GetEventCategories(eventTypeId, out ids, out descriptions); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error fetching event categories."); - } - - if (ids != null) - { - for (int ii = 0; ii < ids.Length; ii++) - { - List attributes = LoadEventAttributes(client, eventTypeId, ids[ii]); - - if (eventTypeId == OpcRcw.Ae.Constants.CONDITION_EVENT) - { - LoadConditionEvent(client, eventTypeId, ids[ii], descriptions[ii], attributes); - continue; - } - - EventType eventType = new EventType(); - eventType.EventTypeId = eventTypeId; - eventType.CategoryId = ids[ii]; - eventType.Description = descriptions[ii]; - eventType.ConditionName = null; - eventType.SubConditionNames = null; - eventType.Attributes = attributes; - DetermineMapping(eventType); - EventTypes.Add(eventType); - } - } - } - - /// - /// Uses the recommended names in the AE specification to map to predefined UA event types. - /// - private void DetermineMapping(EventType eventType) - { - for (int ii = 0; ii < eventType.Attributes.Count; ii++) - { - if (AeTypeCache.IsKnownName(eventType.Attributes[ii].Description, "ACK COMMENT")) - { - eventType.AckComment = eventType.Attributes[ii]; - break; - } - } - - eventType.EventTypeMapping = EventTypeMapping.BaseEventType; - - if (eventType.EventTypeId == OpcRcw.Ae.Constants.SIMPLE_EVENT) - { - if (AeTypeCache.IsKnownName(eventType.Description, "Device Failure")) - { - eventType.EventTypeMapping = EventTypeMapping.DeviceFailureEventType; - return; - } - - if (AeTypeCache.IsKnownName(eventType.Description, "System Message")) - { - eventType.EventTypeMapping = EventTypeMapping.SystemEventType; - return; - } - - eventType.EventTypeMapping = EventTypeMapping.BaseEventType; - return; - } - - if (eventType.EventTypeId == OpcRcw.Ae.Constants.TRACKING_EVENT) - { - eventType.EventTypeMapping = EventTypeMapping.AuditEventType; - return; - } - - if (eventType.EventTypeId == OpcRcw.Ae.Constants.CONDITION_EVENT) - { - if (eventType.ConditionName == null) - { - eventType.EventTypeMapping = EventTypeMapping.ConditionClassType; - return; - } - - eventType.EventTypeMapping = EventTypeMapping.AlarmConditionType; - - if (AeTypeCache.IsKnownName(eventType.Description, "Level")) - { - if (AeTypeCache.IsKnownName(eventType.ConditionName, "PVLEVEL")) - { - eventType.EventTypeMapping = EventTypeMapping.ExclusiveLevelAlarmType; - return; - } - - if (AeTypeCache.IsKnownName(eventType.ConditionName, "SPLEVEL")) - { - eventType.EventTypeMapping = EventTypeMapping.ExclusiveLevelAlarmType; - return; - } - - if (AeTypeCache.IsKnownName(eventType.ConditionName, "HI HI")) - { - eventType.EventTypeMapping = EventTypeMapping.NonExclusiveLevelAlarmType; - return; - } - - if (AeTypeCache.IsKnownName(eventType.ConditionName, "HI")) - { - eventType.EventTypeMapping = EventTypeMapping.NonExclusiveLevelAlarmType; - return; - } - - if (AeTypeCache.IsKnownName(eventType.ConditionName, "LO")) - { - eventType.EventTypeMapping = EventTypeMapping.NonExclusiveLevelAlarmType; - return; - } - - if (AeTypeCache.IsKnownName(eventType.ConditionName, "LO LO")) - { - eventType.EventTypeMapping = EventTypeMapping.NonExclusiveLevelAlarmType; - return; - } - - eventType.EventTypeMapping = EventTypeMapping.LimitAlarmType; - return; - } - - if (AeTypeCache.IsKnownName(eventType.Description, "Deviation")) - { - eventType.EventTypeMapping = EventTypeMapping.NonExclusiveDeviationAlarmType; - return; - } - - if (AeTypeCache.IsKnownName(eventType.Description, "Discrete")) - { - if (AeTypeCache.IsKnownName(eventType.ConditionName, "CFN")) - { - eventType.EventTypeMapping = EventTypeMapping.OffNormalAlarmType; - return; - } - - if (AeTypeCache.IsKnownName(eventType.ConditionName, "TRIP")) - { - eventType.EventTypeMapping = EventTypeMapping.TripAlarmType; - return; - } - - eventType.EventTypeMapping = EventTypeMapping.DiscreteAlarmType; - return; - } - } - } - - private void LoadConditionEvent(ComAeClient client, int eventTypeId, int categoryId, string description, List attributes) - { - string[] conditionNames = null; - - try - { - client.GetConditionNames(categoryId, out conditionNames); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error fetching condition names."); - conditionNames = null; - } - - if (conditionNames != null) - { - // create a condition class for the category. - EventType eventType = new EventType(); - eventType.EventTypeId = eventTypeId; - eventType.CategoryId = categoryId; - eventType.Description = description; - eventType.ConditionName = null; - eventType.SubConditionNames = null; - eventType.Attributes = new List(); - DetermineMapping(eventType); - EventTypes.Add(eventType); - - // create event types for each condition name. - for (int ii = 0; ii < conditionNames.Length; ii++) - { - eventType = new EventType(); - eventType.EventTypeId = eventTypeId; - eventType.CategoryId = categoryId; - eventType.Description = description; - eventType.ConditionName = conditionNames[ii]; - eventType.SubConditionNames = null; - eventType.Attributes = attributes; - DetermineMapping(eventType); - - string[] subConditionNames = null; - - try - { - client.GetSubConditionNames(eventType.ConditionName, out subConditionNames); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error fetching sub-condition names."); - subConditionNames = null; - } - - if (subConditionNames != null) - { - eventType.SubConditionNames = new List(subConditionNames); - } - - EventTypes.Add(eventType); - } - } - } - - /// - /// Fetches the attributes for the category from the AE server. - /// - private List LoadEventAttributes(ComAeClient client, int eventTypeId, int categoryId) - { - List attributes = new List(); - - int[] ids = null; - string[] descriptions = null; - short[] dataTypes = null; - - try - { - client.GetEventAttributes(categoryId, out ids, out descriptions, out dataTypes); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error fetching event attributes."); - ids = null; - } - - if (ids != null) - { - for (int ii = 0; ii < ids.Length; ii++) - { - EventAttribute attribute = new EventAttribute(); - attribute.Id = ids[ii]; - attribute.Description = descriptions[ii]; - attribute.VarType = dataTypes[ii]; - attributes.Add(attribute); - } - } - - return attributes; - } - - /// - /// Checks for alternate spellings of a well known name defined by the AE specification. - /// - public static bool IsKnownName(string description, params string[] names) - { - if (names != null) - { - for (int ii = 0; ii < names.Length; ii++) - { - string name = names[ii]; - - if (String.Compare(name, description, StringComparison.OrdinalIgnoreCase) == 0) - { - return true; - } - - name = names[ii].Replace(' ', '_'); - - if (String.Compare(name, description, StringComparison.OrdinalIgnoreCase) == 0) - { - return true; - } - - name = names[ii].Replace(" ", ""); - - if (String.Compare(name, description, StringComparison.OrdinalIgnoreCase) == 0) - { - return true; - } - } - } - - return false; - } - } - - /// - /// Stores the metadata about an event type defined by the AE server. - /// - internal class EventType - { - /// - /// The AE event type. - /// - public int EventTypeId { get; set; } - - /// - /// The AE event category. - /// - public int CategoryId { get; set; } - - /// - /// The AE event category description. - /// - public string Description { get; set; } - - /// - /// The AE condition name. - /// - public string ConditionName { get; set; } - - /// - /// The AE sub-condition names. - /// - public List SubConditionNames { get; set; } - - /// - /// The list of AE attrivutes for the category. - /// - public List Attributes { get; set; } - - /// - /// The AE attribute for the ACK COMMENT ` - /// - public EventAttribute AckComment { get; set; } - - /// - /// The mapping to a UA event type. - /// - public EventTypeMapping EventTypeMapping { get; set; } - } - - /// - /// The set of possible UA event/condition class mappings. - /// - internal enum EventTypeMapping - { - BaseEventType, - DeviceFailureEventType, - SystemEventType, - AuditEventType, - AlarmConditionType, - LimitAlarmType, - ExclusiveLevelAlarmType, - NonExclusiveLevelAlarmType, - NonExclusiveDeviationAlarmType, - DiscreteAlarmType, - OffNormalAlarmType, - TripAlarmType, - ConditionClassType - } - - /// - /// Stores the metadata for an AE event attribute. - /// - internal class EventAttribute - { - /// - /// The attribute id. - /// - public int Id { get; set; } - - /// - /// The attribute description. - /// - public string Description { get; set; } - - /// - /// The attribute COM data type. - /// - public short VarType { get; set; } - } -} diff --git a/ComIOP/Common/Client/Ae/ComAeBrowserClient.cs b/ComIOP/Common/Client/Ae/ComAeBrowserClient.cs deleted file mode 100644 index be93a57b5..000000000 --- a/ComIOP/Common/Client/Ae/ComAeBrowserClient.cs +++ /dev/null @@ -1,440 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Ae; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Client -{ - /// - /// Browses areas and sources in the AE server. - /// - public class ComAeBrowserClient : ComObject - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The client. - /// The qualified area name. - public ComAeBrowserClient( - ComAeClient client, - string qualifiedName) - { - m_client = client; - m_qualifiedName = qualifiedName; - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - Utils.SilentDispose(m_enumerator); - m_enumerator = null; - } - - base.Dispose(disposing); - } - #endregion - - #region Public Methods - /// - /// Returns the next AE area or source. - /// - /// A DA element. Null if nothing left to browse. - public BaseObjectState Next(ISystemContext context, ushort namespaceIndex) - { - // check if already completed. - if (m_completed) - { - return null; - } - - // create the browser. - if (base.Unknown == null) - { - base.Unknown = m_client.CreateAreaBrowser(); - - if (base.Unknown == null) - { - return null; - } - - if (!ChangeBrowsePosition(OPCAEBROWSEDIRECTION.OPCAE_BROWSE_TO, m_qualifiedName)) - { - return null; - } - } - - // create the enumerator if not already created. - if (m_enumerator == null) - { - m_enumerator = CreateEnumerator(false); - m_sources = false; - - // a null indicates an error. - if (m_enumerator == null) - { - m_completed = true; - return null; - } - } - - // need a loop in case errors occur fetching element metadata. - BaseObjectState node = null; - - do - { - // fetch the next name. - string name = m_enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - if (!m_sources) - { - m_enumerator.Dispose(); - m_enumerator = CreateEnumerator(true); - m_sources = true; - continue; - } - - m_completed = true; - return null; - } - - // create the node. - if (m_sources) - { - string qualifiedName = GetQualifiedSourceName(name); - - if (String.IsNullOrEmpty(qualifiedName)) - { - continue; - } - - node = new AeSourceState(context, m_qualifiedName, qualifiedName, name, namespaceIndex); - } - else - { - string qualifiedName = GetQualifiedAreaName(name); - - if (String.IsNullOrEmpty(qualifiedName)) - { - continue; - } - - node = new AeAreaState(context, qualifiedName, name, namespaceIndex); - } - - break; - } - while (node == null); - - // return node. - return node; - } - - /// - /// Finds the area. - /// - /// The context. - /// Name of the qualified. - /// Index of the namespace. - /// - public BaseObjectState FindArea(ISystemContext context, string qualifiedName, ushort namespaceIndex) - { - // create the browser. - if (base.Unknown == null) - { - base.Unknown = m_client.CreateAreaBrowser(); - - if (base.Unknown == null) - { - return null; - } - } - - // goto area. - if (!ChangeBrowsePosition(OPCAEBROWSEDIRECTION.OPCAE_BROWSE_TO, qualifiedName)) - { - return null; - } - - // find browse name via parent. - if (!ChangeBrowsePosition(OPCAEBROWSEDIRECTION.OPCAE_BROWSE_UP, String.Empty)) - { - return null; - } - - // remove the enumerator. - if (m_enumerator != null) - { - m_enumerator.Dispose(); - m_enumerator = null; - } - - m_enumerator = CreateEnumerator(false); - - do - { - // fetch the next name. - string name = m_enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - m_completed = true; - return null; - } - - // create the node. - if (qualifiedName == GetQualifiedAreaName(name)) - { - return new AeAreaState(context, qualifiedName, name, namespaceIndex); - } - } - while (!m_completed); - - // return node. - return null; - } - - /// - /// Finds the source. - /// - /// The context. - /// Name of the area. - /// Name of the source. - /// Index of the namespace. - /// The source. - public BaseObjectState FindSource(ISystemContext context, string areaName, string sourceName, ushort namespaceIndex) - { - // create the browser. - if (base.Unknown == null) - { - base.Unknown = m_client.CreateAreaBrowser(); - - if (base.Unknown == null) - { - return null; - } - } - - if (!ChangeBrowsePosition(OPCAEBROWSEDIRECTION.OPCAE_BROWSE_TO, areaName)) - { - return null; - } - - // remove the enumerator. - if (m_enumerator != null) - { - m_enumerator.Dispose(); - m_enumerator = null; - } - - m_enumerator = CreateEnumerator(true); - - do - { - // fetch the next name. - string name = m_enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - m_completed = true; - return null; - } - - // create the node. - if (sourceName == name) - { - string qualifiedName = GetQualifiedSourceName(name); - return new AeSourceState(context, m_qualifiedName, qualifiedName, name, namespaceIndex); - } - } - while (!m_completed); - - // return node. - return null; - } - #endregion - - #region Private Methods - /// - /// Changes the browse position. - /// - /// The direction. - /// The qualified area name. - private bool ChangeBrowsePosition(OPCAEBROWSEDIRECTION direction, string qualifiedName) - { - string methodName = "IOPCEventAreaBrowser.CreateAreaBrowser"; - - try - { - IOPCEventAreaBrowser server = BeginComCall(methodName, true); - server.ChangeBrowsePosition(direction, qualifiedName); - return true; - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL)) - { - ComCallError(methodName, e); - } - - return false; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Gets the qualified name for the area. - /// - /// The name. - /// The qualified name for the area. - private string GetQualifiedAreaName(string name) - { - string methodName = "IOPCEventAreaBrowser.GetQualifiedAreaName"; - - string qualifiedName = null; - - try - { - IOPCEventAreaBrowser server = BeginComCall(methodName, true); - server.GetQualifiedAreaName(name, out qualifiedName); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - return qualifiedName; - } - - /// - /// Gets the qualified name for the source. - /// - /// The name. - /// The qualified name for the area. - private string GetQualifiedSourceName(string name) - { - string methodName = "IOPCEventAreaBrowser.GetQualifiedSourceName"; - - string qualifiedName = null; - - try - { - IOPCEventAreaBrowser server = BeginComCall(methodName, true); - server.GetQualifiedSourceName(name, out qualifiedName); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - return qualifiedName; - } - - /// - /// Creates an enumerator for the current browse position. - /// - /// if set to true then sources are enumerated. - /// The wrapped enumerator. - private EnumString CreateEnumerator(bool sources) - { - IEnumString unknown = null; - - string methodName = "IOPCEventAreaBrowser.BrowseOPCAreas"; - - try - { - IOPCEventAreaBrowser server = BeginComCall(methodName, true); - - OPCAEBROWSETYPE browseType = OPCAEBROWSETYPE.OPC_AREA; - - if (sources) - { - browseType = OPCAEBROWSETYPE.OPC_SOURCE; - } - - server.BrowseOPCAreas(browseType, String.Empty, out unknown); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - // wrapper the enumrator. hardcoding a buffer size of 256. - return new EnumString(unknown, 256); - } - #endregion - - #region Private Fields - private ComAeClient m_client; - private string m_qualifiedName; - private Opc.Ua.Com.Client.EnumString m_enumerator; - private bool m_completed; - private bool m_sources; - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/ComAeClient.cs b/ComIOP/Common/Client/Ae/ComAeClient.cs deleted file mode 100644 index 02a0f4c2b..000000000 --- a/ComIOP/Common/Client/Ae/ComAeClient.cs +++ /dev/null @@ -1,454 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using OpcRcw.Comn; -using OpcRcw.Ae; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; - -namespace Opc.Ua.Com.Client -{ - /// - /// Provides access to a COM DA server. - /// - public class ComAeClient : ComClient - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// - public ComAeClient(ComAeClientConfiguration configuration) : base(configuration) - { - m_configuration = configuration; - } - #endregion - - #region Public Methods - /// - /// Creates a new instance of the client with the same configuration. - /// - /// The copy of the client. - public ComAeClient CloneClient() - { - return new ComAeClient(m_configuration); - } - - /// - /// Reads the status from the server. - /// - public OPCEVENTSERVERSTATUS? GetStatus() - { - string methodName = "IOPCEventServer.GetStatus"; - - try - { - IOPCEventServer server = BeginComCall(methodName, true); - - IntPtr ppServerStatus; - server.GetStatus(out ppServerStatus); - - OPCEVENTSERVERSTATUS pStatus = (OPCEVENTSERVERSTATUS)Marshal.PtrToStructure(ppServerStatus, typeof(OPCEVENTSERVERSTATUS)); - - Marshal.DestroyStructure(ppServerStatus, typeof(OPCEVENTSERVERSTATUS)); - Marshal.FreeCoTaskMem(ppServerStatus); - - return pStatus; - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - } - #endregion - - #region Private Methods - /// - /// Creates the area browser. - /// - /// An object which browses areas and sources. - public IOPCEventAreaBrowser CreateAreaBrowser() - { - object unknown = null; - - string methodName = "IOPCEventServer.CreateAreaBrowser"; - - try - { - IOPCEventServer server = BeginComCall(methodName, true); - Guid riid = typeof(IOPCEventAreaBrowser).GUID; - server.CreateAreaBrowser(ref riid, out unknown); - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_NOTIMPL)) - { - ComCallError(methodName, e); - } - - return null; - } - finally - { - EndComCall(methodName); - } - - return (IOPCEventAreaBrowser)unknown; - } - - /// - /// Creates an event subscription. - /// - /// An object which manages a subscription. - public IOPCEventSubscriptionMgt CreateEventSubscription() - { - object unknown = null; - - string methodName = "IOPCEventServer.CreateEventSubscription"; - - try - { - IOPCEventServer server = BeginComCall(methodName, true); - Guid riid = typeof(IOPCEventSubscriptionMgt).GUID; - - int revisedBufferTime = 0; - int revisedMaxSize = 0; - - server.CreateEventSubscription( - 1, - 0, - 0, - 0, - ref riid, - out unknown, - out revisedBufferTime, - out revisedMaxSize); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - return (IOPCEventSubscriptionMgt)unknown; - } - - /// - /// Acknowledges the specified context. - /// - /// The context. - /// The event id. - /// The comment. - /// - public uint Acknowledge( - ServerSystemContext context, - byte[] eventId, - LocalizedText comment) - { - // get the user name from the context. - string userName = String.Empty; - - if (context.UserIdentity != null) - { - userName = context.UserIdentity.DisplayName; - } - - // get the comment. - string commentText = String.Empty; - - if (comment != null) - { - commentText = comment.Text; - } - - System.Runtime.InteropServices.ComTypes.FILETIME ftActiveTime; - - // unpack the event id. - ServiceMessageContext messageContext = new ServiceMessageContext(); - - messageContext.NamespaceUris = context.NamespaceUris; - messageContext.ServerUris = context.ServerUris; - messageContext.Factory = context.EncodeableFactory; - - BinaryDecoder decoder = new BinaryDecoder(eventId, messageContext); - - string source = decoder.ReadString(null); - string conditionName = decoder.ReadString(null); - ftActiveTime.dwHighDateTime = decoder.ReadInt32(null); - ftActiveTime.dwLowDateTime = decoder.ReadInt32(null); - int cookie = decoder.ReadInt32(null); - - decoder.Close(); - - string methodName = "IOPCEventServer.AckCondition"; - - IntPtr pErrors = IntPtr.Zero; - - try - { - IOPCEventServer server = BeginComCall(methodName, true); - - server.AckCondition( - 1, - userName, - commentText, - new string[] { source }, - new string[] { conditionName }, - new System.Runtime.InteropServices.ComTypes.FILETIME[] { ftActiveTime }, - new int[] { cookie }, - out pErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return StatusCodes.BadUnexpectedError; - } - finally - { - EndComCall(methodName); - } - - // unmarshal results. - int[] errors = ComUtils.GetInt32s(ref pErrors, 1, true); - - if (errors[0] == ResultIds.S_ALREADYACKED) - { - return StatusCodes.BadConditionBranchAlreadyAcked; - } - else if (errors[0] < 0) - { - return StatusCodes.BadEventIdUnknown; - } - - return StatusCodes.Good; - } - - /// - /// Gets the event categories. - /// - /// Type of the event. - /// The categories. - /// The descriptions. - public void GetEventCategories(int eventType, out int[] categories, out string[] descriptions) - { - string methodName = "IOPCEventServer.QueryEventCategories"; - - int count = 0; - IntPtr pCategories = IntPtr.Zero; - IntPtr pDescriptions = IntPtr.Zero; - - try - { - IOPCEventServer server = BeginComCall(methodName, true); - - server.QueryEventCategories( - eventType, - out count, - out pCategories, - out pDescriptions); - } - catch (Exception e) - { - ComCallError(methodName, e); - } - finally - { - EndComCall(methodName); - } - - // unmarshal results. - categories = ComUtils.GetInt32s(ref pCategories, count, true); - descriptions = ComUtils.GetUnicodeStrings(ref pDescriptions, count, true); - } - - /// - /// Returns the condition names for the event category. - /// - public void GetConditionNames(int eventCategory, out string[] conditionNames) - { - conditionNames = null; - string methodName = "IOPCEventServer.QueryConditionNames"; - - int count = 0; - IntPtr pConditionNames = IntPtr.Zero; - - try - { - IOPCEventServer server = BeginComCall(methodName, true); - - server.QueryConditionNames( - eventCategory, - out count, - out pConditionNames); - } - catch (Exception e) - { - ComCallError(methodName, e); - } - finally - { - EndComCall(methodName); - } - - // unmarshal results. - conditionNames = ComUtils.GetUnicodeStrings(ref pConditionNames, count, true); - } - - /// - /// Returns the sub-condition names for the event condition. - /// - public void GetSubConditionNames(string conditionName, out string[] subConditionNames) - { - subConditionNames = null; - string methodName = "IOPCEventServer.QuerySubConditionNames"; - - int count = 0; - IntPtr pSubConditionNames = IntPtr.Zero; - - try - { - IOPCEventServer server = BeginComCall(methodName, true); - - server.QuerySubConditionNames( - conditionName, - out count, - out pSubConditionNames); - } - catch (Exception e) - { - ComCallError(methodName, e); - } - finally - { - EndComCall(methodName); - } - - // unmarshal results. - subConditionNames = ComUtils.GetUnicodeStrings(ref pSubConditionNames, count, true); - } - - /// - /// Gets the event attributes. - /// - /// The category id. - /// The attribute ids. - /// The descriptions. - /// The datatypes. - public bool GetEventAttributes( - int categoryId, - out int[] attributeIds, - out string[] descriptions, - out short[] datatypes) - { - string methodName = "IOPCEventServer.QueryEventAttributes"; - - int count = 0; - IntPtr pAttributeIds = IntPtr.Zero; - IntPtr pDescriptions = IntPtr.Zero; - IntPtr pDataTypes = IntPtr.Zero; - - try - { - IOPCEventServer server = BeginComCall(methodName, true); - - server.QueryEventAttributes( - categoryId, - out count, - out pAttributeIds, - out pDescriptions, - out pDataTypes); - } - catch (Exception e) - { - ComCallError(methodName, e); - } - finally - { - EndComCall(methodName); - } - - // unmarshal results. - attributeIds = ComUtils.GetInt32s(ref pAttributeIds, count, true); - descriptions = ComUtils.GetUnicodeStrings(ref pDescriptions, count, true); - datatypes = ComUtils.GetInt16s(ref pDataTypes, count, true); - - // remove the AREAS attribute which is never exposed. - for (int ii = 0; ii < count; ii++) - { - if (String.Compare(descriptions[ii], "AREAS", StringComparison.OrdinalIgnoreCase) == 0) - { - int[] attributeIds2 = new int[count-1]; - string[] descriptions2 = new string[count-1]; - short[] datatypes2 = new short[count-1]; - - if (ii > 0) - { - Array.Copy(attributeIds, attributeIds2, ii); - Array.Copy(descriptions, descriptions2, ii); - Array.Copy(datatypes, datatypes2, ii); - } - - if (ii < count-1) - { - Array.Copy(attributeIds, ii+1, attributeIds2, ii, count-ii-1); - Array.Copy(descriptions, ii+1, descriptions2, ii, count-ii-1); - Array.Copy(datatypes, ii+1, datatypes2, ii, count-ii-1); - } - - attributeIds = attributeIds2; - descriptions = descriptions2; - datatypes = datatypes2; - break; - } - } - - return count > 0; - } - #endregion - - #region Private Fields - private ComAeClientConfiguration m_configuration; - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/ComAeClientConfiguration.cs b/ComIOP/Common/Client/Ae/ComAeClientConfiguration.cs deleted file mode 100644 index 9440d7430..000000000 --- a/ComIOP/Common/Client/Ae/ComAeClientConfiguration.cs +++ /dev/null @@ -1,76 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.ServiceModel; -using System.Runtime.Serialization; -using System.Collections.Generic; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the configuration the alarms and events node manager. - /// - [DataContract(Namespace = Namespaces.ComInterop)] - public class ComAeClientConfiguration : ComClientConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public ComAeClientConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - } - #endregion - - #region Public Properties - #endregion - - #region Private Members - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/ComAeClientManager.cs b/ComIOP/Common/Client/Ae/ComAeClientManager.cs deleted file mode 100644 index 37a7ea692..000000000 --- a/ComIOP/Common/Client/Ae/ComAeClientManager.cs +++ /dev/null @@ -1,141 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Ae; - -namespace Opc.Ua.Com.Client -{ - /// - /// Manages the AE COM connections used by the UA server. - /// - public class ComAeClientManager : ComClientManager - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComAeClientManager() - { - } - #endregion - - #region Public Members - /// - /// Selects the AE COM client to use for the current context. - /// - /// The context. - /// If true the default instance is used. - /// A AE COM client instance. - public new ComAeClient SelectClient(ServerSystemContext context, bool useDefault) - { - return (ComAeClient)base.SelectClient(context, useDefault); - } - #endregion - - #region Protected Members - /// - /// Gets or sets the default COM client instance. - /// - /// The default client. - protected new ComAeClient DefaultClient - { - get { return base.DefaultClient as ComAeClient; } - set { base.DefaultClient = value; } - } - - /// - /// Gets the configuration. - /// - /// The configuration. - protected new ComAeClientConfiguration Configuration - { - get { return base.Configuration as ComAeClientConfiguration; } - } - - /// - /// Creates a new client object. - /// - protected override ComClient CreateClient() - { - return new ComAeClient(Configuration); - } - - /// - /// Updates the status node. - /// - protected override bool UpdateStatus() - { - // get the status from the server. - ComAeClient client = DefaultClient; - OPCEVENTSERVERSTATUS? status = client.GetStatus(); - - // check the client has been abandoned. - if (!Object.ReferenceEquals(client, DefaultClient)) - { - return false; - } - - // update the server status. - lock (StatusNodeLock) - { - StatusNode.ServerUrl.Value = Configuration.ServerUrl; - - if (status != null) - { - StatusNode.SetStatusCode(DefaultSystemContext, StatusCodes.Good, DateTime.UtcNow); - - StatusNode.ServerState.Value = Utils.Format("{0}", status.Value.dwServerState); - StatusNode.CurrentTime.Value = ComUtils.GetDateTime(status.Value.ftCurrentTime); - StatusNode.LastUpdateTime.Value = ComUtils.GetDateTime(status.Value.ftLastUpdateTime); - StatusNode.StartTime.Value = ComUtils.GetDateTime(status.Value.ftStartTime); - StatusNode.VendorInfo.Value = status.Value.szVendorInfo; - StatusNode.SoftwareVersion.Value = Utils.Format("{0}.{1}.{2}", status.Value.wMajorVersion, status.Value.wMinorVersion, status.Value.wBuildNumber); - } - else - { - StatusNode.SetStatusCode(DefaultSystemContext, StatusCodes.BadOutOfService, DateTime.UtcNow); - } - - StatusNode.ClearChangeMasks(DefaultSystemContext, true); - return status != null; - } - } - #endregion - - #region Private Fields - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/ComAeClientNodeManager.cs b/ComIOP/Common/Client/Ae/ComAeClientNodeManager.cs deleted file mode 100644 index 8535c42e4..000000000 --- a/ComIOP/Common/Client/Ae/ComAeClientNodeManager.cs +++ /dev/null @@ -1,823 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using System.Xml; -using System.IO; -using System.Threading; -using System.Reflection; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// A node manager for a server that exposes several variables. - /// - public class ComAeClientNodeManager : ComClientNodeManager - { - #region Constructors - /// - /// Initializes the node manager. - /// - public ComAeClientNodeManager(IServerInternal server, string namespaceUri, ComAeClientConfiguration configuration, bool ownsTypeModel) - : - base(server, namespaceUri, ownsTypeModel) - { - SystemContext.SystemHandle = m_system = new ComAeClientManager(); - SystemContext.NodeIdFactory = this; - - // save the configuration for the node manager. - m_configuration = configuration; - - // set the alias root. - AliasRoot = m_configuration.ServerName; - - if (String.IsNullOrEmpty(AliasRoot)) - { - AliasRoot = "AE"; - } - - m_subscriptions = new Dictionary(); - m_monitoredItems = new Dictionary(); - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - m_system.Dispose(); - } - - base.Dispose(disposing); - } - #endregion - - #region INodeIdFactory Members - /// - /// Creates the NodeId for the specified node. - /// - /// The context. - /// The node. - /// The new NodeId. - /// - /// This method is called by the NodeState.Create() method which initializes a Node from - /// the type model. During initialization a number of child nodes are created and need to - /// have NodeIds assigned to them. This implementation constructs NodeIds by constructing - /// strings. Other implementations could assign unique integers or Guids and save the new - /// Node in a dictionary for later lookup. - /// - public override NodeId New(ISystemContext context, NodeState node) - { - if (node is ServerStatusState) - { - return node.NodeId; - } - - return ParsedNodeId.ConstructIdForComponent(node, NamespaceIndex); - } - #endregion - - #region INodeManager Members - /// - /// Does any initialization required before the address space can be used. - /// - /// - /// The externalReferences is an out parameter that allows the node manager to link to nodes - /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and - /// should have a reference to the root folder node(s) exposed by this node manager. - /// - public override void CreateAddressSpace(IDictionary> externalReferences) - { - lock (Lock) - { - // check if the type model needs to be loaded. - if (NamespaceIndexes.Length > 1) - { - LoadPredefinedNodes(SystemContext, externalReferences); - } - - IList references = null; - - // create the root node. - string serverName = m_configuration.ServerName; - - if (String.IsNullOrEmpty(serverName)) - { - serverName = "ComAeServer"; - } - - AeAreaState root = new AeAreaState(SystemContext, String.Empty, serverName, NamespaceIndex); - root.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); - - // link root to objects folder. - if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) - { - externalReferences[ObjectIds.ObjectsFolder] = references = new List(); - } - - references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, root.NodeId)); - - // link root to server object. - if (!externalReferences.TryGetValue(ObjectIds.Server, out references)) - { - externalReferences[ObjectIds.Server] = references = new List(); - } - - references.Add(new NodeStateReference(ReferenceTypeIds.HasNotifier, false, root.NodeId)); - - // create the status node. - ComServerStatusState status = new ComServerStatusState(root); - status.ReferenceTypeId = ReferenceTypeIds.Organizes; - - // get the type namepace for the browse name. - int typeNamepaceIndex = Server.NamespaceUris.GetIndex(Namespaces.ComInterop); - - if (typeNamepaceIndex < 0) - { - typeNamepaceIndex = NamespaceIndex; - } - - status.Create( - SystemContext, - AeModelUtils.ConstructIdForInternalNode("ServerStatus", NamespaceIndex), - new QualifiedName("ServerStatus", (ushort)typeNamepaceIndex), - null, - true); - - root.AddChild(status); - - // store root folder in the pre-defined nodes. - AddPredefinedNode(SystemContext, root); - AddRootNotifier(root); - - // create the COM server. - m_system.Initialize(SystemContext, m_configuration, status, Lock, OnServerReconnected); - - // create a template condition that can be used to initialize static metadata. - m_templateAlarm = new AlarmConditionState(null); - m_templateAlarm.SymbolicName = "TemplateAlarm"; - - m_templateAlarm.Create( - SystemContext, - null, - new QualifiedName(m_templateAlarm.SymbolicName, NamespaceIndex), - null, - false); - - m_templateAlarm.Acknowledge.OnCall = OnAcknowledge; - StartMetadataUpdates(DoMetadataUpdate, null, 5000, m_configuration.MaxReconnectWait); - } - } - - /// - /// Frees any resources allocated for the address space. - /// - public override void DeleteAddressSpace() - { - lock (Lock) - { - base.DeleteAddressSpace(); - } - } - - /// - /// Returns a unique handle for the node. - /// - protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) - { - lock (Lock) - { - // quickly exclude nodes that are not in the namespace. - if (!IsNodeIdInNamespace(nodeId)) - { - return null; - } - - // check cache. - if (cache != null) - { - NodeState node = null; - - if (cache.TryGetValue(nodeId, out node)) - { - return new NodeHandle(nodeId, node); - } - } - - NodeHandle handle = null; - - try - { - // check if node already being monitored. - if (MonitoredNodes != null) - { - MonitoredNode2 monitoredNode2 = null; - - if (MonitoredNodes.TryGetValue(nodeId, out monitoredNode2)) - { - handle = new NodeHandle(nodeId, monitoredNode2.Node); - handle.MonitoredNode = monitoredNode2; - return handle; - } - } - - // check for predefined nodes. - if (PredefinedNodes != null) - { - NodeState node = null; - - if (PredefinedNodes.TryGetValue(nodeId, out node)) - { - return handle = new NodeHandle(nodeId, node); - } - } - - // parse the identifier. - AeParsedNodeId parsedNodeId = AeParsedNodeId.Parse(nodeId); - - if (parsedNodeId != null) - { - if (parsedNodeId.RootType == AeModelUtils.AeEventTypeMapping && m_typeCache != null) - { - AeEventTypeMappingState mappingNode = m_typeCache.GetMappingNode(SystemContext, nodeId); - - if (mappingNode != null) - { - return handle = new NodeHandle(nodeId, mappingNode); - } - - return null; - } - - handle = new NodeHandle(); - - handle.NodeId = nodeId; - handle.Validated = false; - handle.Node = null; - handle.ParsedNodeId = parsedNodeId; - - return handle; - } - } - finally - { - if (handle != null && handle.Node != null && cache != null) - { - cache.Add(nodeId, handle.Node); - } - } - - return null; - } - } - - /// - /// Verifies that the specified node exists. - /// - protected override NodeState ValidateNode( - ServerSystemContext context, - NodeHandle handle, - IDictionary cache) - { - // not valid if no root. - if (handle == null) - { - return null; - } - - // check if previously validated. - if (handle.Validated) - { - return handle.Node; - } - - NodeState target = null; - - // check if already in the cache. - if (cache != null) - { - if (cache.TryGetValue(handle.NodeId, out target)) - { - // nulls mean a NodeId which was previously found to be invalid has been referenced again. - if (target == null) - { - return null; - } - - handle.Node = target; - handle.Validated = true; - return handle.Node; - } - - target = null; - } - - try - { - // check if the node id has been parsed. - AeParsedNodeId parsedNodeId = handle.ParsedNodeId as AeParsedNodeId; - - if (parsedNodeId == null) - { - return null; - } - - ComAeClient client = m_system.SelectClient(context, false); - - switch (parsedNodeId.RootType) - { - case AeModelUtils.AeSimpleEventType: - case AeModelUtils.AeTrackingEventType: - case AeModelUtils.AeConditionEventType: - { - if (m_typeCache == null) - { - return null; - } - - BaseObjectTypeState eventTypeNode = null; - NodeId rootId = AeParsedNodeId.Construct(parsedNodeId.RootType, parsedNodeId.CategoryId, parsedNodeId.ConditionName, parsedNodeId.NamespaceIndex); - - if (!m_typeCache.EventTypeNodes.TryGetValue(rootId, out eventTypeNode)) - { - return null; - } - - target = eventTypeNode; - break; - } - - case AeModelUtils.AeArea: - { - ComAeBrowserClient browser = new ComAeBrowserClient(client, null); - target = browser.FindArea(context, parsedNodeId.RootId, NamespaceIndex); - browser.Dispose(); - - handle.Validated = true; - handle.Node = target; - return handle.Node; - } - - case AeModelUtils.AeSource: - { - ComAeBrowserClient browser = new ComAeBrowserClient(client, null); - target = browser.FindSource(context, parsedNodeId.RootId, parsedNodeId.ComponentPath, NamespaceIndex); - browser.Dispose(); - - handle.Validated = true; - handle.Node = target; - return handle.Node; - } - - case AeModelUtils.AeCondition: - { - target = new AeConditionState(context, handle, m_templateAlarm.Acknowledge); - break; - } - } - - // node does not exist. - if (target == null) - { - return null; - } - - if (!String.IsNullOrEmpty(parsedNodeId.ComponentPath)) - { - // validate component. - NodeState component = target.FindChildBySymbolicName(context, parsedNodeId.ComponentPath); - - // component does not exist. - if (component == null) - { - return null; - } - - target = component; - } - - // found a valid component. - handle.Validated = true; - handle.Node = target; - return handle.Node; - } - finally - { - // store the node in the cache to optimize subsequent lookups. - if (cache != null) - { - cache.Add(handle.NodeId, target); - } - } - } - - /// - /// Called when client manager has reconnected to the COM server. - /// - public void OnServerReconnected(object state) - { - try - { - // refetch the type information. - DoMetadataUpdate(null); - - lock (Lock) - { - foreach (ComAeSubscriptionClient subscription in m_subscriptions.Values) - { - subscription.Create(); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Could not re-create subscription after reconnect."); - } - } - - /// - /// Called when the alarm is acknowledged. - /// - private ServiceResult OnAcknowledge( - ISystemContext context, - MethodState method, - NodeId objectId, - byte[] eventId, - LocalizedText comment) - { - ComAeClientManager system = (ComAeClientManager)this.SystemContext.SystemHandle; - ComAeClient client = (ComAeClient)system.SelectClient((ServerSystemContext)context, false); - - try - { - return client.Acknowledge((ServerSystemContext)context, eventId, comment); - } - catch (Exception e) - { - return ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not acknowledge event."); - } - } - #endregion - - #region Overridden Methods - /// - /// Loads a node set from a file or resource and addes them to the set of predefined nodes. - /// - protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) - { - NodeStateCollection predefinedNodes = new NodeStateCollection(); - predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.Com.Common.Opc.Ua.Com.PredefinedNodes.uanodes", Assembly.GetAssembly(this.GetType()), true); - return predefinedNodes; - } - - /// - /// Waits for the type cache to be initialized. - /// - private bool WaitForTypeCache() - { - // need to wait until the cache is refreshed for the first time. - for (int ii = 0; Object.ReferenceEquals(m_typeCache, null) && ii < 200 && Server.IsRunning; ii++) - { - Thread.Sleep(100); - } - - return !Object.ReferenceEquals(m_typeCache, null); - } - - /// - /// Subscribes or unsubscribes to events produced by all event sources. - /// - /// - /// This method is called when a event subscription is created or deleted. The node - /// manager must start/stop reporting events for all objects that it manages. - /// - public override ServiceResult SubscribeToAllEvents( - OperationContext context, - uint subscriptionId, - IEventMonitoredItem monitoredItem, - bool unsubscribe) - { - ServerSystemContext systemContext = SystemContext.Copy(context); - ComAeClientManager system = (ComAeClientManager)this.SystemContext.SystemHandle; - ComAeClient client = (ComAeClient)system.SelectClient(systemContext, false); - - // need to wait until the cache is refreshed for the first time. - if (!WaitForTypeCache()) - { - return StatusCodes.BadOutOfService; - } - - lock (Lock) - { - SubscriptionIndex index = new SubscriptionIndex(); - index.NodeId = Opc.Ua.ObjectIds.Server; - index.LocaleId = client.LocaleId; - - if (unsubscribe) - { - ComAeSubscriptionClient subscription = null; - - if (!m_monitoredItems.TryGetValue(monitoredItem.Id, out subscription)) - { - return ServiceResult.Good; - } - - m_monitoredItems.Remove(monitoredItem.Id); - // Utils.Trace("REMOVED ITEM {0}", monitoredItem.Id); - - if (subscription.RemoveItem(monitoredItem as MonitoredItem) == 0) - { - subscription.Delete(); - m_subscriptions.Remove(index); - // Utils.Trace("DELETED SUBSCRIPTION {0}", index.NodeId); - } - } - else - { - ComAeSubscriptionClient subscription = null; - - if (!m_subscriptions.TryGetValue(index, out subscription)) - { - subscription = new ComAeSubscriptionClient(systemContext, m_configuration, m_typeCache, NamespaceIndex, system, monitoredItem as MonitoredItem); - m_subscriptions.Add(index, subscription); - subscription.Create(); - // Utils.Trace("ADDED NEW SUBSCRIPTION {0}", index.NodeId); - } - else - { - subscription.AddItem(monitoredItem as MonitoredItem); - } - - m_monitoredItems[monitoredItem.Id] = subscription; - // Utils.Trace("ADDED NEW ITEM {0}", monitoredItem.Id); - } - } - - return ServiceResult.Good; - } - - /// - /// Subscribes to events. - /// - protected override ServiceResult SubscribeToEvents( - ServerSystemContext context, - NodeState source, - IEventMonitoredItem monitoredItem, - bool unsubscribe) - { - ComAeClientManager system = (ComAeClientManager)this.SystemContext.SystemHandle; - ComAeClient client = (ComAeClient)system.SelectClient(context, false); - - // need to wait until the cache is refreshed for the first time. - if (!WaitForTypeCache()) - { - return StatusCodes.BadOutOfService; - } - - lock (Lock) - { - SubscriptionIndex index = new SubscriptionIndex(); - index.NodeId = source.NodeId; - index.LocaleId = client.LocaleId; - - if (unsubscribe) - { - ComAeSubscriptionClient subscription = null; - - if (!m_monitoredItems.TryGetValue(monitoredItem.Id, out subscription)) - { - return ServiceResult.Good; - } - - m_monitoredItems.Remove(monitoredItem.Id); - // Utils.Trace("REMOVED ITEM {0}", monitoredItem.Id); - - if (subscription.RemoveItem(monitoredItem as MonitoredItem) == 0) - { - subscription.Delete(); - m_subscriptions.Remove(index); - // Utils.Trace("DELETED SUBSCRIPTION {0}", index.NodeId); - } - } - else - { - ComAeSubscriptionClient subscription = null; - - if (!m_subscriptions.TryGetValue(index, out subscription)) - { - subscription = new ComAeSubscriptionClient(context, m_configuration, m_typeCache, NamespaceIndex, system, monitoredItem as MonitoredItem); - m_subscriptions.Add(index, subscription); - subscription.Create(); - // Utils.Trace("ADDED NEW SUBSCRIPTION {0}", index.NodeId); - } - else - { - subscription.AddItem(monitoredItem as MonitoredItem); - } - - m_monitoredItems[monitoredItem.Id] = subscription; - // Utils.Trace("ADDED NEW ITEM {0}", monitoredItem.Id); - } - } - - // all done. - return ServiceResult.Good; - } - - /// - /// Tells the node manager to refresh any conditions associated with the specified monitored items. - /// - public override ServiceResult ConditionRefresh( - OperationContext context, - IList monitoredItems) - { - List itemsToRefresh = new List(); - List subscriptionsToRefresh = new List(); - - lock (Lock) - { - // build list of subscriptions that have to be refreshed. - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem; - - if (monitoredItem == null) - { - continue; - } - - ComAeSubscriptionClient subscription = null; - - if (!m_monitoredItems.TryGetValue(monitoredItem.Id, out subscription)) - { - continue; - } - - itemsToRefresh.Add(monitoredItem); - subscriptionsToRefresh.Add(subscription); - } - } - - for (int ii = 0; ii < subscriptionsToRefresh.Count; ii++) - { - // collect the events. - List events = new List(); - subscriptionsToRefresh[ii].Refresh(events); - - // queue the events. - for (int jj = 0; jj < events.Count; jj++) - { - itemsToRefresh[ii].QueueEvent(events[jj]); - } - } - - return ServiceResult.Good; - } - #endregion - - #region Private Methods - /// - /// Updates the type cache. - /// - private void DoMetadataUpdate(object state) - { - try - { - if (!Server.IsRunning) - { - return; - } - - ComAeClientManager system = (ComAeClientManager)SystemContext.SystemHandle; - ComAeClient client = (ComAeClient)system.SelectClient(SystemContext, true); - - AeTypeCache cache = new AeTypeCache(); - cache.LoadEventTypes(client); - - lock (Lock) - { - if (m_typeCache == null) - { - m_typeCache = cache; - } - - m_typeCache.EventTypes = cache.EventTypes; - m_typeCache.UpdateCache(SystemContext, NamespaceIndex); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error updating event type cache."); - } - } - #endregion - - #region SubscriptionIndex Class - /// - /// Used to maintain an index of current subscriptions. - /// - private class SubscriptionIndex - { - /// - /// The locale id for the subscription. - /// - public int LocaleId { get; set; } - - /// - /// The node id for the subscription. - /// - public NodeId NodeId { get; set; } - - /// - /// Returns true if the object is equal to the instance. - /// - public override bool Equals(object obj) - { - if (Object.ReferenceEquals(this, obj)) - { - return true; - } - - SubscriptionIndex index = obj as SubscriptionIndex; - - if (index == null) - { - return false; - } - - if (index.LocaleId != this.LocaleId) - { - return false; - } - - if (index.NodeId != this.NodeId) - { - return false; - } - - return true; - } - - /// - /// Returns a hash code for the instantce. - /// - public override int GetHashCode() - { - int hash = LocaleId.GetHashCode(); - - if (NodeId != null) - { - hash ^= NodeId.GetHashCode(); - } - - return hash; - } - } - #endregion - - #region Private Fields - private ComAeClientManager m_system; - private ComAeClientConfiguration m_configuration; - private AlarmConditionState m_templateAlarm; - private Dictionary m_subscriptions; - private Dictionary m_monitoredItems; - private AeTypeCache m_typeCache; - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/ComAeEventCallback.cs b/ComIOP/Common/Client/Ae/ComAeEventCallback.cs deleted file mode 100644 index 6899f78cc..000000000 --- a/ComIOP/Common/Client/Ae/ComAeEventCallback.cs +++ /dev/null @@ -1,151 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; -using OpcRcw.Ae; - -namespace Opc.Ua.Com.Client -{ - /// - /// A class that implements the IOPCEventSink interface. - /// - internal class ComAeEventSink : OpcRcw.Ae.IOPCEventSink, IDisposable - { - #region Constructors - /// - /// Initializes the object with the containing subscription object. - /// - public ComAeEventSink(ComAeSubscriptionClient subscription) - { - // save group. - m_subscription = subscription; - - // create connection point. - m_connectionPoint = new ConnectionPoint(subscription.Unknown, typeof(IOPCEventSink).GUID); - - // advise. - m_connectionPoint.Advise(this); - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (m_connectionPoint != null) - { - if (disposing) - { - m_connectionPoint.Dispose(); - m_connectionPoint = null; - } - } - } - #endregion - - #region Public Properties - /// - /// Whether the callback is connected. - /// - public bool Connected - { - get - { - return m_connectionPoint != null; - } - } - - /// - /// Gets the cookie returned by the server. - /// - /// The cookie. - public int Cookie - { - get - { - if (m_connectionPoint != null) - { - return m_connectionPoint.Cookie; - } - - return 0; - } - } - #endregion - - #region ComAeEventSink Members - /// - /// Called when one or events are produce by the server. - /// - public void OnEvent( - int hClientSubscription, - int bRefresh, - int bLastRefresh, - int dwCount, - ONEVENTSTRUCT[] pEvents) - { - try - { - if (bRefresh == 0) - { - m_subscription.OnEvent(pEvents); - } - else - { - m_subscription.OnRefresh(pEvents, bLastRefresh != 0); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnEvent callback."); - } - } - #endregion - - #region Private Members - private ComAeSubscriptionClient m_subscription; - private ConnectionPoint m_connectionPoint; - #endregion - } -} diff --git a/ComIOP/Common/Client/Ae/ComAeSubscriptionClient.cs b/ComIOP/Common/Client/Ae/ComAeSubscriptionClient.cs deleted file mode 100644 index 1f68febc2..000000000 --- a/ComIOP/Common/Client/Ae/ComAeSubscriptionClient.cs +++ /dev/null @@ -1,762 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Ae; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Client -{ - /// - /// Browses areas and sources in the AE server. - /// - internal class ComAeSubscriptionClient : ComObject - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The configuration. - /// The cache for known types. - /// The namespace index for the event types. - /// The manager. - /// The monitored item. - public ComAeSubscriptionClient( - ServerSystemContext context, - ComAeClientConfiguration configuration, - AeTypeCache cache, - ushort namespaceIndex, - ComAeClientManager manager, - MonitoredItem monitoredItem) - { - m_defaultContext = context; - m_separators = configuration.SeperatorChars; - m_cache = cache; - m_namespaceIndex = namespaceIndex; - m_manager = manager; - m_refreshComplete = new ManualResetEvent(false); - m_monitoredItems = new List(); - m_monitoredItems.Add(monitoredItem); - m_qualifiedName = null; - m_isSource = false; - - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - AeAreaState area = handle.Node as AeAreaState; - - if (area != null) - { - m_qualifiedName = area.QualifiedName; - m_isSource = false; - } - else - { - AeSourceState source = handle.Node as AeSourceState; - - if (source != null) - { - m_qualifiedName = source.QualifiedName; - m_isSource = true; - } - } - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - Utils.SilentDispose(m_callback); - m_callback = null; - } - - base.Dispose(disposing); - } - - /// - /// Releases all references to the server. - /// - protected override void ReleaseServer() - { - Utils.SilentDispose(m_callback); - m_callback = null; - base.ReleaseServer(); - } - #endregion - - #region Public Methods - /// - /// The locale id for the subscription. - /// - public int LocaleId { get; set; } - - /// - /// Creates the subscription. - /// - public void Create() - { - ComAeClient client = m_manager.SelectClient(m_defaultContext, false); - - // release existing server. - if (this.Unknown != null) - { - ReleaseServer(); - } - - // create the subscription. - this.Unknown = client.CreateEventSubscription(); - - // select the attributes. - foreach (KeyValuePair entry in m_cache.Attributes) - { - SelectReturnedAttributes(entry.Key, entry.Value); - } - - // set the filter. - SetFilter(m_qualifiedName, m_isSource); - - // set up callback. - try - { - m_callback = new ComAeEventSink(this); - } - catch (Exception e) - { - Utils.Trace("Could not establish event callback.", e); - } - } - - /// - /// Deletes the subscription. - /// - public void Delete() - { - if (this.Unknown != null) - { - ReleaseServer(); - } - } - - /// - /// Refreshes the conditions monitored by the subscription. - /// - /// The events. - public void Refresh(List events) - { - // ensure multiple refreshes cannot occur simutaneously. - try - { - lock (m_refreshLock) - { - // save the list for updates. - lock (m_callbackLock) - { - m_refreshEvents = events; - m_refreshComplete.Reset(); - } - - if (m_callback != null) - { - if (!Refresh()) - { - return; - } - - if (!m_refreshComplete.WaitOne(30000)) - { - CancelRefresh(); - } - } - } - } - finally - { - // all done. - lock (m_callbackLock) - { - m_refreshEvents = null; - } - } - } - - /// - /// Adds an item to a subscription. - /// - public void AddItem(MonitoredItem monitoredItem) - { - lock (m_monitoredItems) - { - m_monitoredItems.Add(monitoredItem); - } - } - - /// - /// Removes an item from the subscription. - /// - public int RemoveItem(MonitoredItem monitoredItem) - { - lock (m_monitoredItems) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - if (m_monitoredItems[ii].Id == monitoredItem.Id) - { - m_monitoredItems.RemoveAt(ii); - break; - } - } - - return m_monitoredItems.Count; - } - } - - /// - /// Called when events arrive from the server. - /// - /// The events. - public void OnEvent(ONEVENTSTRUCT[] events) - { - for (int ii = 0; ii < events.Length; ii++) - { - BaseEventState e = DispatchEvent(events[ii]); - - if (e != null) - { - lock (m_monitoredItems) - { - for (int jj = 0; jj < m_monitoredItems.Count; jj++) - { - m_monitoredItems[jj].QueueEvent(e); - } - } - } - } - } - - /// - /// Dispatches the event. - /// - 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(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; - } - - /// - /// Updates the base event. - /// - private void UpdateBaseEvent(BaseEventState instance, EventType eventType, ONEVENTSTRUCT e) - { - BinaryEncoder encoder = new BinaryEncoder(ServiceMessageContext.GlobalContext); - - encoder.WriteString(null, e.szSource); - encoder.WriteString(null, e.szConditionName); - encoder.WriteInt32(null, e.ftActiveTime.dwHighDateTime); - encoder.WriteInt32(null, e.ftActiveTime.dwLowDateTime); - encoder.WriteInt32(null, e.dwCookie); - - byte[] eventId = encoder.CloseAndReturnBuffer(); - NodeId eventTypeId = AeParsedNodeId.Construct(e.dwEventType, e.dwEventCategory, e.szConditionName, m_namespaceIndex); - NodeId sourceNode = AeModelUtils.ConstructIdForSource(e.szSource, null, m_namespaceIndex); - string sourceName = e.szSource; - DateTime time = ComUtils.GetDateTime(e.ftTime); - DateTime receiveTime = DateTime.UtcNow; - LocalizedText message = e.szMessage; - ushort severity = (ushort)e.dwSeverity; - - instance.TypeDefinitionId = eventTypeId; - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.EventId, eventId, false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.EventType, eventTypeId, false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.SourceNode, sourceNode, false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.SourceName, sourceName, false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Time, time, false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ReceiveTime, receiveTime, false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Message, message, false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Severity, severity, false); - } - - /// - /// Updates the audit event. - /// - private void UpdateAuditEvent(AuditEventState instance, EventType eventType, ONEVENTSTRUCT e) - { - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ActionTimeStamp, instance.Time.Value, false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Status, true, false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ServerId, m_defaultContext.NamespaceUris.GetString(m_namespaceIndex), false); - instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ClientUserId, e.szActorID, false); - } - - /// - /// Updates the condition event. - /// - 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); - } - } - - /// - /// Updates the exclusive limit alarm event. - /// - private void UpdateExclusiveLimitAlarm(ExclusiveLimitAlarmState instance, EventType eventType, ONEVENTSTRUCT e) - { - NodeId state = null; - string text = null; - - if (AeTypeCache.IsKnownName(e.szSubconditionName, "HI HI")) - { - state = Opc.Ua.ObjectIds.ExclusiveLimitStateMachineType_HighHigh; - text = ConditionStateNames.HighHighActive; - } - - if (AeTypeCache.IsKnownName(e.szSubconditionName, "HI")) - { - state = Opc.Ua.ObjectIds.ExclusiveLimitStateMachineType_High; - text = ConditionStateNames.HighActive; - } - - if (AeTypeCache.IsKnownName(e.szSubconditionName, "LO")) - { - state = Opc.Ua.ObjectIds.ExclusiveLimitStateMachineType_Low; - text = ConditionStateNames.LowActive; - } - - if (AeTypeCache.IsKnownName(e.szSubconditionName, "LO LO")) - { - state = Opc.Ua.ObjectIds.ExclusiveLimitStateMachineType_LowLow; - text = ConditionStateNames.LowLowActive; - } - - instance.LimitState = new ExclusiveLimitStateMachineState(instance); - instance.LimitState.BrowseName = Opc.Ua.BrowseNames.LimitState; - instance.LimitState.CurrentState = new FiniteStateVariableState(instance.LimitState); - instance.LimitState.CurrentState.BrowseName = Opc.Ua.BrowseNames.CurrentState; - instance.LimitState.CurrentState.Value = text; - - instance.LimitState.CurrentState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, state, false); - } - - /// - /// Updates the non-exclusive limit event. - /// - private void UpdateNonExclusiveLimitAlarm(NonExclusiveLimitAlarmState instance, EventType eventType, ONEVENTSTRUCT e) - { - bool active = (e.wNewState & Constants.CONDITION_ACTIVE) != 0; - TwoStateVariableState state = null; - - if (AeTypeCache.IsKnownName(e.szConditionName, "HI HI")) - { - instance.HighHighState = state = new TwoStateVariableState(instance); - instance.HighHighState.BrowseName = Opc.Ua.BrowseNames.HighHighState; - } - - else if (AeTypeCache.IsKnownName(e.szSubconditionName, "HI") || AeTypeCache.IsKnownName(e.szSubconditionName, "DV HI")) - { - instance.HighState = state = new TwoStateVariableState(instance); - instance.HighState.BrowseName = Opc.Ua.BrowseNames.HighState; - } - - else if (AeTypeCache.IsKnownName(e.szSubconditionName, "LO") || AeTypeCache.IsKnownName(e.szSubconditionName, "DV LO")) - { - instance.LowState = state = new TwoStateVariableState(instance); - instance.LowState.BrowseName = Opc.Ua.BrowseNames.LowState; - } - - else if (AeTypeCache.IsKnownName(e.szSubconditionName, "LO LO")) - { - instance.LowLowState = state = new TwoStateVariableState(instance); - instance.LowLowState.BrowseName = Opc.Ua.BrowseNames.LowLowState; - } - - if (state != null) - { - state.Value = new LocalizedText((active) ? ConditionStateNames.Active : ConditionStateNames.Inactive); - state.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, active, false); - } - } - - /// - /// Called when refresh events arrive from the server. - /// - /// The events. - /// if set to true if the refresh is complete. - public void OnRefresh(ONEVENTSTRUCT[] events, bool lastRefresh) - { - lock (m_callbackLock) - { - // check if refresh was abandoned. - if (m_refreshEvents == null) - { - return; - } - - // dispatch events. - for (int ii = 0; ii < events.Length; ii++) - { - BaseEventState e = DispatchEvent(events[ii]); - - if (e != null) - { - m_refreshEvents.Add(e); - } - } - - // signal end of refresh. - if (lastRefresh) - { - m_refreshComplete.Set(); - } - } - } - #endregion - - #region Private Methods - /// - /// Refreshes all conditions. - /// - /// - private bool Refresh() - { - string methodName = "IOPCEventSubscriptionMgt.Refresh"; - - try - { - IOPCEventSubscriptionMgt server = BeginComCall(methodName, true); - server.Refresh(m_callback.Cookie); - return true; - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_BUSY, ResultIds.E_NOTIMPL)) - { - ComCallError(methodName, e); - } - - return false; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Cancels the refresh for all conditions. - /// - /// - private bool CancelRefresh() - { - string methodName = "IOPCEventSubscriptionMgt.CancelRefresh"; - - try - { - IOPCEventSubscriptionMgt server = BeginComCall(methodName, true); - server.CancelRefresh(m_callback.Cookie); - return true; - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_INVALIDARG, ResultIds.E_NOTIMPL)) - { - ComCallError(methodName, e); - } - - return false; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Selects the returned attributes. - /// - /// The category id. - /// The attribute ids. - /// - private bool SelectReturnedAttributes(int categoryId, int[] attributeIds) - { - string methodName = "IOPCEventSubscriptionMgt.SelectReturnedAttributes"; - - try - { - IOPCEventSubscriptionMgt server = BeginComCall(methodName, true); - server.SelectReturnedAttributes(categoryId, attributeIds.Length, attributeIds); - return true; - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL)) - { - ComCallError(methodName, e); - } - - return false; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Sets the filter. - /// - /// Name of the qualified. - /// if set to true if filtering by source. - /// - private bool SetFilter(string qualifiedName, bool isSource) - { - string methodName = "IOPCEventSubscriptionMgt.SetFilter"; - - try - { - IOPCEventSubscriptionMgt server = BeginComCall(methodName, true); - - string[] filter = null; - - if (!String.IsNullOrEmpty(qualifiedName)) - { - filter = new string[] { qualifiedName }; - - // need to use a wild card to include sub-areas. - if (!String.IsNullOrEmpty(m_separators)) - { - filter = new string[m_separators.Length+1]; - filter[0] = qualifiedName; - - for (int ii = 0; ii < m_separators.Length; ii++) - { - filter[ii + 1] = Utils.Format("{0}{1}*", qualifiedName, m_separators[ii]); - } - } - } - else - { - filter = new string[0]; - } - - server.SetFilter( - Constants.ALL_EVENTS, - 0, - new int[0], - 1, - 1000, - (isSource)?0:filter.Length, - filter, - (!isSource)?0:filter.Length, - filter); - - return true; - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL)) - { - ComCallError(methodName, e); - } - - return false; - } - finally - { - EndComCall(methodName); - } - } - #endregion - - #region Private Fields - private ServerSystemContext m_defaultContext; - private string m_separators; - private AeTypeCache m_cache; - private ushort m_namespaceIndex; - private ComAeClientManager m_manager; - private string m_qualifiedName; - private bool m_isSource; - private ComAeEventSink m_callback; - private List m_monitoredItems; - private object m_refreshLock = new object(); - private object m_callbackLock = new object(); - private ManualResetEvent m_refreshComplete; - private List m_refreshEvents; - #endregion - } -} diff --git a/ComIOP/Common/Client/ComClient.cs b/ComIOP/Common/Client/ComClient.cs deleted file mode 100644 index 62c5b4879..000000000 --- a/ComIOP/Common/Client/ComClient.cs +++ /dev/null @@ -1,315 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.IdentityModel.Selectors; -using System.IdentityModel.Tokens; -using System.Security.Principal; -using OpcRcw.Comn; -using OpcRcw.Da; -using OpcRcw.Security; -using Opc.Ua; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; - -namespace Opc.Ua.Com.Client -{ - /// - /// Provides access to a COM server. - /// - public class ComClient : ComObject - { - #region Constructors - /// - /// Initializes the object with the ProgID of the server being accessed. - /// - public ComClient(ComClientConfiguration configuration) - { - if (configuration == null) throw new ArgumentNullException("configuration"); - m_url = configuration.ServerUrl; - } - #endregion - - #region Public Methods - /// - /// A key that combines the user name and locale id. - /// - public string Key { get; set; } - - /// - /// The locale id associated with the instance. - /// - public int LocaleId { get; set; } - - /// - /// The user identity associated with the instance. - /// - public IUserIdentity UserIdentity { get; set; } - - /// - /// Creates an instance of the COM server. - /// - public void CreateInstance() - { - // multiple calls are not allowed - may block for a while due to network operation. - lock (m_lock) - { - ServerFactory factory = new ServerFactory(); - - try - { - // create the server. - Unknown = factory.CreateServer(new Uri(m_url), null); - - // set the locale. - SetLocale(LocaleId); - - if (UserIdentity != null) - { - SetUserIdentity(UserIdentity); - } - - // do any post-connect processing. - OnConnected(); - } - catch (Exception e) - { - ComUtils.TraceComError(e, "Could not connect to server ({0}).", m_url); - - // cleanup on error. - Close(); - } - finally - { - factory.Dispose(); - } - } - } - - /// - /// Fetches the error string from the server. - /// - public string GetErrorString(int error) - { - string methodName = "IOPCCommon.GetErrorString"; - - try - { - IOPCCommon server = BeginComCall(methodName, true); - string ppString = null; - server.GetErrorString(error, out ppString); - return ppString; - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Sets the current locale. - /// - public void SetLocale(int localeId) - { - string methodName = "IOPCCommon.SetLocaleID"; - - try - { - IOPCCommon server = BeginComCall(methodName, true); - server.SetLocaleID(localeId); - } - catch (Exception e) - { - ComCallError(methodName, e); - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Sets the current user identity. - /// - public void SetUserIdentity(IUserIdentity identity) - { - string methodName = "IOPCSecurityPrivate.Logon"; - - try - { - IOPCSecurityPrivate server = BeginComCall(methodName, true); - - if (server != null) - { - int bAvailable = 0; - server.IsAvailablePriv(out bAvailable); - - if (bAvailable != 0) - { - bool logoff = true; - - if (identity != null && identity.TokenType == UserTokenType.UserName) - { - UserNameIdentityToken identityToken = identity.GetIdentityToken() as UserNameIdentityToken; - - if (identityToken != null) - { - server.Logon(identityToken.UserName, identityToken.Password.ToString()); - logoff = false; - } - } - - if (logoff) - { - server.Logoff(); - } - } - } - } - catch (Exception e) - { - ComCallError(methodName, e); - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Fetches the available locales. - /// - public int[] QueryAvailableLocales() - { - string methodName = "IOPCCommon.QueryAvailableLocales"; - - try - { - IOPCCommon server = BeginComCall(methodName, true); - - // query for available locales. - int count = 0; - IntPtr pLocaleIDs = IntPtr.Zero; - - server.QueryAvailableLocaleIDs(out count, out pLocaleIDs); - - // unmarshal results. - return ComUtils.GetInt32s(ref pLocaleIDs, count, true); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Selects the best matching locale id. - /// - public static int SelectLocaleId(IList availableLocaleIds, IList preferredLocales) - { - // choose system default if no available locale ids. - if (availableLocaleIds == null || availableLocaleIds.Count == 0) - { - return ComUtils.LOCALE_SYSTEM_DEFAULT; - } - - // choose system default if no preferred locales. - if (preferredLocales == null || preferredLocales.Count == 0) - { - return availableLocaleIds[0]; - } - - // look for an exact match. - for (int ii = 0; ii < preferredLocales.Count; ii++) - { - for (int jj = 0; jj < availableLocaleIds.Count; jj++) - { - if (ComUtils.CompareLocales(availableLocaleIds[jj], preferredLocales[ii], false)) - { - return availableLocaleIds[jj]; - } - } - } - - // look for a match on the language only. - for (int ii = 0; ii < preferredLocales.Count; ii++) - { - for (int jj = 0; jj < availableLocaleIds.Count; jj++) - { - if (ComUtils.CompareLocales(availableLocaleIds[jj], preferredLocales[ii], true)) - { - return availableLocaleIds[jj]; - } - } - } - - // return the first avialable locale. - return availableLocaleIds[0]; - } - - /// - /// Gracefully closes the connection to the server. - /// - public void Close() - { - Dispose(); - } - #endregion - - #region Protected Members - /// - /// Called immediately after connecting to the server. - /// - protected virtual void OnConnected() - { - } - #endregion - - #region Private Methods - #endregion - - #region Private Fields - private object m_lock = new object(); - private string m_url; - #endregion - } -} diff --git a/ComIOP/Common/Client/ComClientConfiguration.cs b/ComIOP/Common/Client/ComClientConfiguration.cs deleted file mode 100644 index 2b6ebfeac..000000000 --- a/ComIOP/Common/Client/ComClientConfiguration.cs +++ /dev/null @@ -1,160 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.ServiceModel; -using System.Runtime.Serialization; -using System.Collections.Generic; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the configuration the data access node manager. - /// - [KnownType(typeof(ComDaClientConfiguration))] - [KnownType(typeof(ComAeClientConfiguration))] - [KnownType(typeof(ComHdaClientConfiguration))] - [DataContract(Namespace = Namespaces.ComInterop)] - public class ComClientConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public ComClientConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - } - #endregion - - #region Public Properties - /// - /// The URL of the COM server which has the form: opc.com://hostname/progid/clsid - /// - [DataMember(Order = 1)] - public string ServerUrl { get; set; } - - /// - /// The name for the server that will used for the root in the UA server address space. - /// - [DataMember(Order = 2)] - public string ServerName { get; set; } - - /// - /// The number of milliseconds to wait between reconnect attempts. - /// - [DataMember(Order = 3)] - public int MaxReconnectWait { get; set; } - - /// - /// A list of characters used in item ids to seperate elements. - /// - /// - /// If specified the wrapper attempts to parse the item ids by looking for the one of these - /// characters starting from the end of the item id. All text after this character is assumed - /// to be the name of the item or branch. - /// - [DataMember(Order = 4)] - public string SeperatorChars - { - get - { - return m_seperatorChars; - } - - set - { - if (String.IsNullOrEmpty(value)) - { - m_seperatorChars = String.Empty; - return; - } - - m_seperatorChars = value.Trim(); - } - } - - /// - /// A list of locales supported by the server that should made visible as locales for the UA server. - /// - [DataMember(Order = 5)] - public StringCollection AvailableLocales { get; set; } - - /// - /// Gets or sets the item id parser. - /// - /// The item id parser. - public IItemIdParser ItemIdParser { get; set; } - #endregion - - #region Private Members - private string m_seperatorChars; - #endregion - } - - /// - /// A collection of COM WrapperConfiguration objects. - /// - [CollectionDataContract(Name="ListOfComClientConfiguration", Namespace=Namespaces.ComInterop, ItemName="ComClientConfiguration")] - public partial class ComClientConfigurationCollection : List - { - /// - /// Initializes an empty collection. - /// - public ComClientConfigurationCollection() { } - - /// - /// Initializes the collection with the specified capacity. - /// - public ComClientConfigurationCollection(int capacity) : base(capacity) { } - - /// - /// Initializes the collection from another collection. - /// - /// A collection of used to pre-populate the collection. - public ComClientConfigurationCollection(IEnumerable collection) : base(collection) { } - } -} diff --git a/ComIOP/Common/Client/ComClientManager.cs b/ComIOP/Common/Client/ComClientManager.cs deleted file mode 100644 index e538162e6..000000000 --- a/ComIOP/Common/Client/ComClientManager.cs +++ /dev/null @@ -1,388 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Da; - -namespace Opc.Ua.Com.Client -{ - /// - /// Manages the COM connections used by the UA server. - /// - public class ComClientManager : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComClientManager() - { - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - Utils.SilentDispose(m_statusTimer); - m_statusTimer = null; - - Utils.SilentDispose(m_defaultClient); - m_defaultClient = null; - } - } - #endregion - - #region Public Members - /// - /// Selects the COM client to use for the current context. - /// - /// The context. - /// The whether to use the default context. - /// A COM client instance. - public virtual ComClient SelectClient(ServerSystemContext context, bool useDefault) - { - if (useDefault) - { - return DefaultClient; - } - - return GetLocalizedClient(context.UserIdentity, context.PreferredLocales); - } - - /// - /// Initializes the manager by creating the default instance. - /// - public void Initialize( - ServerSystemContext context, - ComClientConfiguration configuration, - ComServerStatusState statusNode, - object statusNodeLock, - WaitCallback reconnectCallback) - { - m_defaultSystemContext = context; - m_configuration = configuration; - m_statusNode = statusNode; - m_statusNodeLock = statusNodeLock; - m_statusUpdateInterval = m_configuration.MaxReconnectWait; - m_reconnectCallback = reconnectCallback; - - // limit status updates to once per 10 seconds. - if (m_statusUpdateInterval < 10000) - { - m_statusUpdateInterval = 10000; - } - - StartStatusTimer(OnStatusTimerExpired); - } - - /// - /// Returns a localized client based on the preferred locales. - /// - /// The identity to use. - /// The locales to use. - /// A localized client. - public ComClient GetLocalizedClient(IUserIdentity identity, IList preferredLocales) - { - return GetLocalizedClient(identity, ComClient.SelectLocaleId(AvailableLocaleIds, preferredLocales)); - } - - /// - /// Returns a localized client for the specified locale id. - /// - /// The identity. - /// The locales id. - /// A localized client. - public ComClient GetLocalizedClient(IUserIdentity identity, int localeId) - { - // check if a logon is required. - string userName = null; - - if (identity != null && identity.TokenType == UserTokenType.UserName) - { - userName = (identity.GetIdentityToken() as UserNameIdentityToken).UserName; - } - - if (String.IsNullOrEmpty(userName) && localeId == ComUtils.LOCALE_SYSTEM_DEFAULT) - { - Utils.Trace("COM Client Selected: DEFAULT (no match for locale)"); - return DefaultClient; - } - - // create the key. - StringBuilder buffer = new StringBuilder(); - buffer.Append(localeId); - - if (!String.IsNullOrEmpty(userName)) - { - buffer.Append(':'); - buffer.Append(userName); - } - - string key = buffer.ToString(); - - if (m_localizedClients == null) - { - m_localizedClients = new Dictionary(); - } - - ComClient client = null; - - if (!m_localizedClients.TryGetValue(key, out client)) - { - client = CreateClient(); - client.Key = key; - client.LocaleId = localeId; - client.UserIdentity = identity; - client.CreateInstance(); - m_localizedClients[key] = client; - } - - // Utils.Trace("COM Client Seleted: {0}", key); - return client; - } - #endregion - - #region Protected Members - /// - /// Gets the default system context. - /// - /// The default system context. - protected ServerSystemContext DefaultSystemContext - { - get { return m_defaultSystemContext; } - } - - /// - /// Gets the configuration. - /// - /// The configuration. - protected ComClientConfiguration Configuration - { - get { return m_configuration; } - } - - /// - /// Gets or sets the default COM client instance. - /// - /// The default client. - protected ComClient DefaultClient - { - get { return m_defaultClient; } - set { m_defaultClient = value; } - } - - /// - /// The locale ids supported by the server. - /// - protected int[] AvailableLocaleIds { get; private set; } - - /// - /// Gets the status node. - /// - /// The status node. - protected ComServerStatusState StatusNode - { - get { return m_statusNode; } - } - - /// - /// Gets the synchronization object for the status node. - /// - /// The ynchronization object for the status node. - protected object StatusNodeLock - { - get { return m_statusNodeLock; } - } - - /// - /// Starts the status timer. - /// - /// The callback to use when the timer expires. - protected void StartStatusTimer(TimerCallback callback) - { - if (m_statusTimer != null) - { - m_statusTimer.Dispose(); - m_statusTimer = null; - } - - m_statusTimer = new Timer(callback, null, 0, m_statusUpdateInterval); - } - - /// - /// Creates a new client object. - /// - protected virtual ComClient CreateClient() - { - return null; - } - - /// - /// Updates the status node. - /// - /// True if the update was successful. - protected virtual bool UpdateStatus() - { - return false; - } - #endregion - - #region Private Methods - /// - /// Called when thes status timer expires. - /// - /// The state. - private void OnStatusTimerExpired(object state) - { - try - { - // create the client if it has not already been created. - if (m_defaultClient == null) - { - m_defaultClient = CreateClient(); - m_defaultClient.Key = String.Empty; - - // set default locale. - if (AvailableLocaleIds != null && AvailableLocaleIds.Length > 0) - { - m_defaultClient.LocaleId = AvailableLocaleIds[0]; - } - else - { - m_defaultClient.LocaleId = ComUtils.LOCALE_SYSTEM_DEFAULT; - } - - m_defaultClient.CreateInstance(); - m_lastStatusUpdate = DateTime.UtcNow; - } - - // check if the last status updates appear to be hanging. - bool reconnected = false; - - if (m_lastStatusUpdate.AddMilliseconds(m_statusUpdateInterval*1.1) < DateTime.UtcNow) - { - if (m_reconnecting) - { - return; - } - - m_reconnecting = true; - - try - { - Utils.Trace("Communication with COM server failed. Disposing server and reconnecting."); - - // dispose existing client in the background in case it blocks. - ThreadPool.QueueUserWorkItem(OnDisposeClient, m_defaultClient); - - // dispose localized clients. - if (m_localizedClients != null) - { - foreach (ComClient localizedClient in m_localizedClients.Values) - { - ThreadPool.QueueUserWorkItem(OnDisposeClient, localizedClient); - } - - m_localizedClients.Clear(); - } - - // create a new client. - m_defaultClient = CreateClient(); - m_defaultClient.CreateInstance(); - - reconnected = true; - } - finally - { - m_reconnecting = false; - } - } - - // fetches the status from the server and updates the status node. - if (UpdateStatus()) - { - AvailableLocaleIds = m_defaultClient.QueryAvailableLocales(); - m_lastStatusUpdate = DateTime.UtcNow; - - if (reconnected && m_reconnectCallback != null) - { - m_reconnectCallback(this); - } - } - } - catch (Exception e) - { - ComUtils.TraceComError(e, "Error fetching status from the COM server."); - } - } - - /// - /// Called when a misbehaving client object needs to be disposed. - /// - /// The client object. - private void OnDisposeClient(object state) - { - Utils.SilentDispose(state); - } - #endregion - - #region Private Fields - private ComClientConfiguration m_configuration; - private ServerSystemContext m_defaultSystemContext; - private ComServerStatusState m_statusNode; - private object m_statusNodeLock; - private ComClient m_defaultClient; - private Timer m_statusTimer; - private DateTime m_lastStatusUpdate; - private int m_statusUpdateInterval; - private WaitCallback m_reconnectCallback; - private bool m_reconnecting; - private Dictionary m_localizedClients; - #endregion - } -} diff --git a/ComIOP/Common/Client/ComClientNodeManager.cs b/ComIOP/Common/Client/ComClientNodeManager.cs deleted file mode 100644 index c60271236..000000000 --- a/ComIOP/Common/Client/ComClientNodeManager.cs +++ /dev/null @@ -1,190 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using System.Xml; -using System.IO; -using System.Threading; -using System.Reflection; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// A node manager for a server that exposes several variables. - /// - public class ComClientNodeManager : CustomNodeManager2 - { - #region Constructors - /// - /// Initializes the node manager. - /// - public ComClientNodeManager(IServerInternal server, string namespaceUri, bool ownsTypeModel) - : - base(server) - { - // check if this node manager owns the COM Interop type model. - if (ownsTypeModel) - { - SetNamespaces(namespaceUri, Namespaces.ComInterop); - } - else - { - SetNamespaces(namespaceUri); - } - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - Utils.SilentDispose(m_metadataUpdateTimer); - m_metadataUpdateTimer = null; - } - - base.Dispose(disposing); - } - #endregion - - #region Protected Methods - /// - /// Updates the type cache. - /// - protected void StartMetadataUpdates(WaitCallback callback, object callbackData, int initialDelay, int period) - { - lock (Lock) - { - if (m_metadataUpdateTimer != null) - { - m_metadataUpdateTimer.Dispose(); - m_metadataUpdateTimer = null; - } - - m_metadataUpdateCallback = callback; - m_metadataUpdateTimer = new Timer(DoMetadataUpdate, callbackData, initialDelay, period); - } - } - #endregion - - #region Private Methods - /// - /// Updates the metadata cached for the server. - /// - private void DoMetadataUpdate(object state) - { - try - { - if (!Server.IsRunning) - { - return; - } - - ComClientManager system = (ComClientManager)SystemContext.SystemHandle; - ComClient client = (ComClient)system.SelectClient(SystemContext, true); - - int[] availableLocales = client.QueryAvailableLocales(); - - if (availableLocales != null) - { - lock (Server.DiagnosticsLock) - { - // check if the server is running. - if (!Server.IsRunning) - { - return; - } - - // get the LocaleIdArray property. - BaseVariableState localeArray = Server.DiagnosticsNodeManager.Find(Opc.Ua.VariableIds.Server_ServerCapabilities_LocaleIdArray) as BaseVariableState; - - List locales = new List(); - - // preserve any existing locales. - string[] existingLocales = localeArray.Value as string[]; - - if (existingLocales != null) - { - locales.AddRange(existingLocales); - } - - for (int ii = 0; ii < availableLocales.Length; ii++) - { - if (availableLocales[ii] == 0 || availableLocales[ii] == ComUtils.LOCALE_SYSTEM_DEFAULT || availableLocales[ii] == ComUtils.LOCALE_USER_DEFAULT) - { - continue; - } - - try - { - System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.GetCultureInfo(availableLocales[ii]); - - if (!locales.Contains(culture.Name)) - { - locales.Add(culture.Name); - } - } - catch (Exception e) - { - Utils.Trace(e, "Can't process an invalid locale id: {0:X4}.", availableLocales[ii]); - } - } - - localeArray.Value = locales.ToArray(); - } - } - - // invoke callback. - if (m_metadataUpdateCallback != null) - { - m_metadataUpdateCallback(state); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error updating HDA server metadata."); - } - } - #endregion - - #region Private Fields - private Timer m_metadataUpdateTimer; - private WaitCallback m_metadataUpdateCallback; - #endregion - } -} diff --git a/ComIOP/Common/Client/ComConnectionPoint.cs b/ComIOP/Common/Client/ComConnectionPoint.cs deleted file mode 100644 index 9ccba429c..000000000 --- a/ComIOP/Common/Client/ComConnectionPoint.cs +++ /dev/null @@ -1,140 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Runtime.InteropServices; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Client -{ - /// - /// Manages a connection point with a COM server. - /// - public class ConnectionPoint : IDisposable - { - #region Constructors - /// - /// Initializes the object by finding the specified connection point. - /// - public ConnectionPoint(object server, Guid iid) - { - OpcRcw.Comn.IConnectionPointContainer cpc = server as OpcRcw.Comn.IConnectionPointContainer; - - if (cpc == null) - { - throw ServiceResultException.Create(StatusCodes.BadCommunicationError, "Server does not support the IConnectionPointContainer interface."); - } - - cpc.FindConnectionPoint(ref iid, out m_server); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - m_server = null; - m_cookie = 0; - m_refs = 0; - } - #endregion - - #region IDisposable Members - /// - /// The finializer implementation. - /// - ~ConnectionPoint() - { - Dispose(false); - } - - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - object server = System.Threading.Interlocked.Exchange(ref m_server, null); - - if (server != null) - { - ComUtils.ReleaseServer(server); - } - } - #endregion - - #region Public Properties - /// - /// The cookie returned by the server. - /// - public int Cookie - { - get { return m_cookie; } - } - #endregion - - #region IConnectionPoint Members - /// - /// Establishes a connection, if necessary and increments the reference count. - /// - public int Advise(object callback) - { - if (m_refs++ == 0) - { - m_server.Advise(callback, out m_cookie); - } - - return m_refs; - } - - /// - /// Decrements the reference count and closes the connection if no more references. - /// - public int Unadvise() - { - if (--m_refs == 0) m_server.Unadvise(m_cookie); - return m_refs; - } - #endregion - - #region Private Members - private OpcRcw.Comn.IConnectionPoint m_server; - private int m_cookie; - private int m_refs; - #endregion - } -} diff --git a/ComIOP/Common/Client/ComEnumString.cs b/ComIOP/Common/Client/ComEnumString.cs deleted file mode 100644 index a3e8e8810..000000000 --- a/ComIOP/Common/Client/ComEnumString.cs +++ /dev/null @@ -1,257 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Runtime.InteropServices; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Client -{ - /// - /// A wrapper for the COM IEnumString interface. - /// - public class EnumString : IDisposable - { - #region Constructors - /// - /// Initializes the object with an enumerator. - /// - public EnumString(object enumerator, int bufferLength) - { - m_enumerator = enumerator as IEnumString; - - if (m_enumerator == null) - { - throw new ArgumentNullException("enumerator", "Object does not support IEnumString interface."); - } - - m_buffer = new string[bufferLength]; - m_position = 0; - m_fetched = 0; - } - #endregion - - #region IDisposable Members - /// - /// The finializer implementation. - /// - ~EnumString() - { - Dispose(false); - } - - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - object enumerator = System.Threading.Interlocked.Exchange(ref m_enumerator, null); - - if (enumerator != null) - { - ComUtils.ReleaseServer(enumerator); - } - } - #endregion - - #region IEnumString Members - /// - /// Fetches the next string (returns null if no more data). - /// - public string Next() - { - // return null if at end of list. - if (m_fetched == -1) - { - return null; - } - - // see if next item is available. - if (m_position < m_fetched) - { - return m_buffer[m_position++]; - } - - m_position = 0; - - try - { - // fetch next batch. - m_fetched = 0; - - IntPtr pBuffer = Marshal.AllocCoTaskMem(IntPtr.Size*m_buffer.Length); - - try - { - int error = m_enumerator.RemoteNext(m_buffer.Length, pBuffer, out m_fetched); - - if (error < 0 || m_fetched == 0) - { - return null; - } - - IntPtr[] pStrings = new IntPtr[m_fetched]; - Marshal.Copy(pBuffer, pStrings, 0, m_fetched); - - for (int ii = 0; ii < m_fetched; ii++) - { - m_buffer[ii] = Marshal.PtrToStringUni(pStrings[ii]); - Marshal.FreeCoTaskMem(pStrings[ii]); - } - } - finally - { - Marshal.FreeCoTaskMem(pBuffer); - } - - // check if end of list. - if (m_fetched == 0) - { - m_fetched = -1; - return null; - } - - // return first item. - return m_buffer[m_position++]; - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL)) - { - throw ComUtils.CreateException(e, "IEnumString.RemoteNext"); - } - - // some (incorrect) implementations return E_FAIL at the end of the list. - m_fetched = -1; - return null; - } - } - - /// - /// Fetches the next group of strings. - /// - public int Next(string[] buffer, int count) - { - // can't use simple interface after calling this method. - m_fetched = -1; - - try - { - int fetched = 0; - - IntPtr pBuffer = Marshal.AllocCoTaskMem(IntPtr.Size*count); - - try - { - int error = m_enumerator.RemoteNext( - count, - pBuffer, - out fetched); - - if (error >= 0 && fetched > 0) - { - IntPtr[] pStrings = new IntPtr[m_fetched]; - Marshal.Copy(pBuffer, pStrings, 0, fetched); - - for (int ii = 0; ii < fetched; ii++) - { - m_buffer[ii] = Marshal.PtrToStringUni(pStrings[ii]); - Marshal.FreeCoTaskMem(pStrings[ii]); - } - } - - return fetched; - } - finally - { - Marshal.FreeCoTaskMem(pBuffer); - } - } - catch (Exception e) - { - // some (incorrect) implementations return E_FAIL at the end of the list. - if (Marshal.GetHRForException(e) == ResultIds.E_FAIL) - { - return 0; - } - - throw ComUtils.CreateException(e, "IEnumString.RemoteNext"); - } - } - - /// - /// Skips a number of strings. - /// - public void Skip(int count) - { - m_enumerator.Skip(count); - - // can't use simple interface after calling this method. - m_fetched = -1; - } - - /// - /// Sets pointer to the start of the list. - /// - public void Reset() - { - m_enumerator.Reset(); - - // can't use simple interface after calling this method. - m_fetched = -1; - } - - /// - /// Clones the enumerator. - /// - public EnumString Clone() - { - IEnumString enumerator = null; - m_enumerator.Clone(out enumerator); - return new EnumString(enumerator, m_buffer.Length); - } - #endregion - - #region Private Members - private OpcRcw.Comn.IEnumString m_enumerator; - private string[] m_buffer; - private int m_position; - private int m_fetched; - #endregion - } -} diff --git a/ComIOP/Common/Client/ComItemIdParser.cs b/ComIOP/Common/Client/ComItemIdParser.cs deleted file mode 100644 index 2785cc794..000000000 --- a/ComIOP/Common/Client/ComItemIdParser.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using System.Xml; -using System.IO; -using System.Threading; -using System.Reflection; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// An interface to an object that parses item ids. - /// - public interface IItemIdParser - { - /// - /// Parses the specified item id. - /// - /// The COM server that provided the item id. - /// The COM wrapper configuration. - /// The item id to parse. - /// The name of the item. - /// True if the item id could be parsed. - bool Parse( - ComObject server, - ComClientConfiguration configuration, - string itemId, - out string browseName); - } - - /// - /// The default item id parser that uses the settings in the configuration. - /// - public class ComItemIdParser : IItemIdParser - { - #region IItemIdParser Members - /// - /// Parses the specified item id. - /// - /// The COM server that provided the item id. - /// The COM wrapper configuration. - /// The item id to parse. - /// The name of the item. - /// True if the item id could be parsed. - public bool Parse(ComObject server, ComClientConfiguration configuration, string itemId, out string browseName) - { - browseName = null; - - if (configuration == null || itemId == null) - { - return false; - } - - if (String.IsNullOrEmpty(configuration.SeperatorChars)) - { - return false; - } - - for (int ii = 0; ii < configuration.SeperatorChars.Length; ii++) - { - int index = itemId.LastIndexOf(configuration.SeperatorChars[ii]); - - if (index >= 0) - { - browseName = itemId.Substring(index + 1); - return true; - } - } - - return false; - } - #endregion - } -} diff --git a/ComIOP/Common/Client/ComObject.cs b/ComIOP/Common/Client/ComObject.cs deleted file mode 100644 index 9c9efb7c1..000000000 --- a/ComIOP/Common/Client/ComObject.cs +++ /dev/null @@ -1,226 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Globalization; -using System.Security.Principal; -using System.Threading; -using System.Runtime.InteropServices; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Da; - -namespace Opc.Ua.Com.Client -{ - /// - /// A base class for COM server wrappers. - /// - public class ComObject : IDisposable - { - #region IDisposable Members - /// - /// The finializer implementation. - /// - ~ComObject() - { - Dispose(false); - } - - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - // release references to the server during garbage collection. - if (!disposing) - { - ReleaseServer(); - } - - // clean up managed objects if - if (disposing) - { - lock (m_lock) - { - m_disposed = true; - - // only release server if there are no outstanding calls. - // if it is not released here it will be released when the last call completes. - if (m_outstandingCalls <= 0) - { - ReleaseServer(); - } - } - } - } - #endregion - - #region Public Properties - /// - /// Gets an object which is used to synchronize access to the COM object. - /// - /// An object which is used to synchronize access to the COM object. - public object Lock - { - get { return m_lock; } - } - - /// - /// Gets a value indicating whether this is disposed. - /// - /// true if disposed; otherwise, false. - public bool Disposed - { - get { return m_disposed; } - } - - /// - /// Gets or sets the COM server. - /// - /// The COM server. - public object Unknown - { - get { return m_unknown; } - set { m_unknown = value; } - } - #endregion - - #region Protected Members - /// - /// Releases all references to the server. - /// - protected virtual void ReleaseServer() - { - lock (m_lock) - { - ComUtils.ReleaseServer(m_unknown); - m_unknown = null; - } - } - - /// - /// Checks if the server supports the specified interface. - /// - /// The interface to check. - /// True if the server supports the interface. - protected bool SupportsInterface() where T : class - { - lock (m_lock) - { - return m_unknown is T; - } - } - - /// - /// Must be called before any COM call. - /// - /// The interface to used when making the call. - /// Name of the method. - /// if set to true an exception is thrown on error. - /// - protected T BeginComCall(string methodName, bool throwOnError) where T : class - { - Utils.Trace(Utils.TraceMasks.ExternalSystem, "{0} called.", methodName); - - lock (m_lock) - { - m_outstandingCalls++; - - if (m_disposed) - { - if (throwOnError) - { - throw new ObjectDisposedException("The COM server has been disposed."); - } - - return null; - } - - T server = m_unknown as T; - - if (throwOnError && server == null) - { - throw new NotSupportedException(Utils.Format("COM interface '{0}' is not supported by server.", typeof(T).Name)); - } - - return server; - } - } - - /// - /// Must called if a COM call returns an unexpected exception. - /// - /// Name of the method. - /// The exception. - /// Note that some COM calls are expected to return errors. - protected void ComCallError(string methodName, Exception e) - { - ComUtils.TraceComError(e, methodName); - } - - /// - /// Must be called in the finally block after making a COM call. - /// - /// Name of the method. - protected void EndComCall(string methodName) - { - Utils.Trace(Utils.TraceMasks.ExternalSystem, "{0} completed.", methodName); - - lock (m_lock) - { - m_outstandingCalls--; - - if (m_disposed && m_outstandingCalls <= 0) - { - ComUtils.ReleaseServer(m_unknown); - } - } - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private int m_outstandingCalls; - private bool m_disposed; - private object m_unknown; - #endregion - } -} diff --git a/ComIOP/Common/Client/ComShutdownCallback.cs b/ComIOP/Common/Client/ComShutdownCallback.cs deleted file mode 100644 index 0084ccdaf..000000000 --- a/ComIOP/Common/Client/ComShutdownCallback.cs +++ /dev/null @@ -1,117 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; - -namespace Opc.Ua.Com.Client -{ - /// - /// A class that implements the IOPCShutdown interface. - /// - public class ShutdownCallback : OpcRcw.Comn.IOPCShutdown, IDisposable - { - #region Constructors - /// - /// Initializes the object with the containing subscription object. - /// - public ShutdownCallback(object server, ServerShutdownEventHandler handler) - { - try - { - m_server = server; - m_handler = handler; - - // create connection point. - m_connectionPoint = new ConnectionPoint(server, typeof(OpcRcw.Comn.IOPCShutdown).GUID); - - // advise. - m_connectionPoint.Advise(this); - } - catch (Exception e) - { - throw new ServiceResultException(e, StatusCodes.BadOutOfService); - } - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (m_connectionPoint != null) - { - m_connectionPoint.Dispose(); - m_connectionPoint = null; - } - } - #endregion - - #region IOPCShutdown Members - /// - /// Called when a data changed event is received. - /// - public void ShutdownRequest(string szReason) - { - try - { - if (m_handler != null) - { - m_handler(m_server, szReason); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing callback."); - } - } - #endregion - - #region Private Members - private object m_server; - private ServerShutdownEventHandler m_handler; - private ConnectionPoint m_connectionPoint; - #endregion - } - - /// - /// A delegate used to receive server shutdown events. - /// - public delegate void ServerShutdownEventHandler(object sender, string reason); -} diff --git a/ComIOP/Common/Client/ComWrapperServer.cs b/ComIOP/Common/Client/ComWrapperServer.cs deleted file mode 100644 index 91c4bd6e8..000000000 --- a/ComIOP/Common/Client/ComWrapperServer.cs +++ /dev/null @@ -1,322 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Globalization; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// Implements a basic UA Data Access Server. - /// - /// - /// Each server instance must have one instance of a StandardServer object which is - /// responsible for reading the configuration file, creating the endpoints and dispatching - /// incoming requests to the appropriate handler. - /// - /// This sub-class specifies non-configurable metadata such as Product Name and initializes - /// the DataAccessServerNodeManager which provides access to the data exposed by the Server. - /// - public partial class ComWrapperServer : ReverseConnectServer - { - #region Public Interface - /// - /// Returns the current server instance. - /// - public IServerInternal ServerInstance - { - get { return this.ServerInternal; } - } - - /// - /// Returns the UserNameValidator. - /// - public UserNameValidator UserNameValidator - { - get { return m_userNameValidator; } - } - - #endregion - - #region Overridden Methods - /// - /// Creates the node managers for the server. - /// - /// - /// This method allows the sub-class create any additional node managers which it uses. The SDK - /// always creates a CoreNodeManager which handles the built-in nodes defined by the specification. - /// Any additional NodeManagers are expected to handle application specific nodes. - /// - protected override MasterNodeManager CreateMasterNodeManager(IServerInternal server, ApplicationConfiguration configuration) - { - List nodeManagers = new List(); - m_availableLocales = new List(); - - // get the configuration for the wrapper. - ComWrapperServerConfiguration wrapperConfiguration = configuration.ParseExtension(); - - if (wrapperConfiguration != null && wrapperConfiguration.WrappedServers != null) - { - // create a new node manager for each wrapped COM server. - bool loadTypeModel = true; - Dictionary namespaceUris = new Dictionary(); - - foreach (ComClientConfiguration clientConfiguration in wrapperConfiguration.WrappedServers) - { - // add the available locales. - if (clientConfiguration.AvailableLocales != null && clientConfiguration.AvailableLocales.Count > 0) - { - foreach (string locale in clientConfiguration.AvailableLocales) - { - try - { - CultureInfo culture = CultureInfo.GetCultureInfo(locale); - - if (!m_availableLocales.Contains(culture.Name)) - { - m_availableLocales.Add(culture.Name); - } - } - catch (Exception e) - { - Utils.Trace(e, "Can't process an invalid locale: {0}.", locale); - } - } - } - - string namespaceUri = clientConfiguration.ServerUrl; - - if (clientConfiguration is ComDaClientConfiguration) - { - namespaceUri += "/DA"; - - if (namespaceUris.ContainsKey(namespaceUri)) - { - Utils.Trace("COM server has already been wrapped {0}.", namespaceUri); - continue; - } - - namespaceUris.Add(namespaceUri, clientConfiguration); - - ComDaClientNodeManager manager = new ComDaClientNodeManager( - server, - namespaceUri, - (ComDaClientConfiguration)clientConfiguration, - loadTypeModel); - - nodeManagers.Add(manager); - loadTypeModel = false; - continue; - } - - if (clientConfiguration is ComAeClientConfiguration) - { - namespaceUri += "/AE"; - - if (namespaceUris.ContainsKey(namespaceUri)) - { - Utils.Trace("COM server has already been wrapped {0}.", namespaceUri); - continue; - } - - namespaceUris.Add(namespaceUri, clientConfiguration); - - ComAeClientNodeManager manager = new ComAeClientNodeManager( - server, - namespaceUri, - (ComAeClientConfiguration)clientConfiguration, - loadTypeModel); - - nodeManagers.Add(manager); - loadTypeModel = false; - continue; - } - - if (clientConfiguration is ComHdaClientConfiguration) - { - namespaceUri += "/HDA"; - - if (namespaceUris.ContainsKey(namespaceUri)) - { - Utils.Trace("COM server has already been wrapped {0}.", namespaceUri); - continue; - } - - namespaceUris.Add(namespaceUri, clientConfiguration); - - ComHdaClientNodeManager manager = new ComHdaClientNodeManager( - server, - namespaceUri, - (ComHdaClientConfiguration)clientConfiguration, - loadTypeModel); - - nodeManagers.Add(manager); - loadTypeModel = false; - continue; - } - } - } - - // create master node manager. - return new MasterNodeManager(server, configuration, null, nodeManagers.ToArray()); - } - - /// - /// Loads the non-configurable properties for the application. - /// - /// - /// These properties are exposed by the server but cannot be changed by administrators. - /// - protected override ServerProperties LoadServerProperties() - { - ServerProperties properties = new ServerProperties(); - - properties.ManufacturerName = "OPC Foundation"; - properties.ProductName = "OPC UA Quickstarts"; - properties.ProductUri = "http://opcfoundation.org/Quickstarts/ComDataAccessServer/v1.0"; - properties.SoftwareVersion = Utils.GetAssemblySoftwareVersion(); - properties.BuildNumber = Utils.GetAssemblyBuildNumber(); - properties.BuildDate = Utils.GetAssemblyTimestamp(); - - // TBD - All applications have software certificates that need to added to the properties. - - return properties; - } - - /// - /// Called after the node managers have started. - /// - protected override void OnNodeManagerStarted(IServerInternal server) - { - // check if wrapped server locales need to be added to the UA server locale list. - if (m_availableLocales != null && m_availableLocales.Count > 0) - { - lock (ServerInstance.DiagnosticsNodeManager.Lock) - { - // get the LocaleIdArray property. - BaseVariableState variable = ServerInstance.DiagnosticsNodeManager.Find(Opc.Ua.VariableIds.Server_ServerCapabilities_LocaleIdArray) as BaseVariableState; - - if (variable != null) - { - List locales = new List(); - - // preserve any existing locales. - string[] existingLocales = variable.Value as string[]; - - if (existingLocales != null) - { - locales.AddRange(existingLocales); - } - - // add locales from the wrapped servers. - foreach (string availableLocale in m_availableLocales) - { - if (!locales.Contains(availableLocale)) - { - locales.Add(availableLocale); - } - } - - // update the locale array. - variable.Value = locales.ToArray(); - } - } - } - - m_userNameValidator = new UserNameValidator(Configuration.ApplicationName); - - base.OnNodeManagerStarted(server); - } - - /// - /// Handles an error when validating the application instance certificate provided by a client. - /// - /// The client certificate. - /// The result. - protected override void OnApplicationCertificateError(byte[] clientCertificate, ServiceResult result) - { - throw new ServiceResultException(new ServiceResult(StatusCodes.BadCertificateUriInvalid)); - } - - /// - /// Called after the server has been started. - /// - /// The server. - protected override void OnServerStarted(IServerInternal server) - { - base.OnServerStarted(server); - // verify session - this.ServerInstance.SessionManager.ImpersonateUser += SessionManager_ImpersonateUser; - } - - /// - /// Check whether it is an acceptable session. - /// - /// The session. - /// IdentityToken. - void SessionManager_ImpersonateUser(Session session, ImpersonateEventArgs args) - { - switch (args.UserTokenPolicy.TokenType) - { - case UserTokenType.UserName: - - UserNameIdentityToken token = args.NewIdentity as UserNameIdentityToken; - - if (!m_userNameValidator.Validate(token)) - { // Bad user access denied. - // construct translation object with default text. - TranslationInfo info = new TranslationInfo( - "InvalidUserInformation", - "en-US", - "Specified user information are not valid. UserName='{0}'.", - token.UserName); - - // create an exception with a vendor defined sub-code. - throw new ServiceResultException(new ServiceResult( - StatusCodes.BadUserAccessDenied, - "InvalidUserInformation", - "http://opcfoundation.org", - new LocalizedText(info))); - } - break; - default: - break; - } - } - - #endregion - - #region Private Fields - private List m_availableLocales; - private UserNameValidator m_userNameValidator; - #endregion - } -} diff --git a/ComIOP/Common/Client/ComWrapperServerConfiguration.cs b/ComIOP/Common/Client/ComWrapperServerConfiguration.cs deleted file mode 100644 index d851c499f..000000000 --- a/ComIOP/Common/Client/ComWrapperServerConfiguration.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.ServiceModel; -using System.Runtime.Serialization; -using System.Collections.Generic; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the configuration for UA that wraps a COM server. - /// - [DataContract(Namespace = Namespaces.ComInterop)] - public class ComWrapperServerConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public ComWrapperServerConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - } - #endregion - - #region Public Properties - /// - /// The list of COM servers wrapped by the UA server. - /// - [DataMember(Order=1)] - public ComClientConfigurationCollection WrappedServers - { - get { return m_wrappedServers; } - set { m_wrappedServers = value; } - } - #endregion - - #region Private Members - private ComClientConfigurationCollection m_wrappedServers; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/ComDaClient.cs b/ComIOP/Common/Client/Da/ComDaClient.cs deleted file mode 100644 index 677d475e7..000000000 --- a/ComIOP/Common/Client/Da/ComDaClient.cs +++ /dev/null @@ -1,1864 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using OpcRcw.Comn; -using OpcRcw.Da; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; - -namespace Opc.Ua.Com.Client -{ - /// - /// Provides access to a COM DA server. - /// - public class ComDaClient : ComClient - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// - public ComDaClient(ComDaClientConfiguration configuration) : base(configuration) - { - m_cache = new Dictionary(); - m_configuration = configuration; - } - #endregion - - #region Public Methods - /// - /// Finds the branch or item. - /// - /// The item id. - /// The metadata for the branch. - public DaElement FindElement(string itemId) - { - if (String.IsNullOrEmpty(itemId)) - { - return null; - } - - // check the cache. - DaElement element = null; - - lock (m_cache) - { - if (m_cache.TryGetValue(itemId, out element)) - { - return element; - } - } - - // try extracting the name by parsing the item id. - string name = null; - - if (m_configuration.ItemIdParser.Parse(this, m_configuration, itemId, out name)) - { - element = CreateElement(itemId, name, null); - } - - // need to do it the hard way by searching the address space. - else - { - IDaElementBrowser browser = CreateBrowser(itemId); - element = browser.Find(itemId, false); - browser.Dispose(); - } - - // save element in the cache. - if (element != null) - { - SaveElementInCache(element); - } - - return element; - } - - /// - /// Finds the property metadata for the specified item id. - /// - /// The item id. - /// The property id. - /// The metadata for the property. - public DaProperty FindProperty(string itemId, int propertyId) - { - if (String.IsNullOrEmpty(itemId)) - { - return null; - } - - // check the cache. - DaElement element = null; - - lock (m_cache) - { - if (m_cache.TryGetValue(itemId, out element)) - { - if (element.Properties != null) - { - for (int ii = 0; ii < element.Properties.Length; ii++) - { - if (element.Properties[ii].PropertyId == propertyId) - { - return element.Properties[ii]; - } - } - } - } - } - - // check if the element has to be loaded. - if (element == null) - { - element = FindElement(itemId); - - if (element == null) - { - return null; - } - } - - // update the property list. - element.Properties = ReadAvailableProperties(itemId, false); - - if (element.Properties != null) - { - for (int ii = 0; ii < element.Properties.Length; ii++) - { - if (element.Properties[ii].PropertyId == propertyId) - { - return element.Properties[ii]; - } - } - } - - // not found. - return null; - } - - /// - /// Finds the item id for the parent of the element. - /// - /// The item id. - /// The item id for the parent of the element. - public string FindElementParentId(string itemId) - { - if (String.IsNullOrEmpty(itemId)) - { - return null; - } - - // check in cache. - DaElement element = null; - - lock (m_cache) - { - if (m_cache.TryGetValue(itemId, out element)) - { - if (element.ParentId != null) - { - return element.ParentId; - } - } - } - - // check if the element is a branch. - if (!ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_TO, itemId)) - { - return null; - } - - // need to fetch list of branches to search. - EnumString enumerator = CreateEnumerator(true); - - if (enumerator == null) - { - return null; - } - - // find the child with the same item id. - try - { - // process all branches. - string name = null; - - do - { - name = enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - break; - } - - // fetch the item id. - string targetId = GetItemId(name); - - // check if target found. - if (targetId == itemId) - { - return GetItemId(String.Empty); - } - } - while (name != null); - - } - finally - { - enumerator.Dispose(); - } - - return null; - } - - /// - /// Creates a browser. - /// - /// The item id. - /// The browser object. - public IDaElementBrowser CreateBrowser(string itemId) - { - // check if DA3 browse interface is supported. - if (SupportsInterface()) - { - return new Da20ElementBrowser(this, itemId, m_configuration.BrowseToNotSupported); - } - - return new Da20ElementBrowser(this, itemId, m_configuration.BrowseToNotSupported); - } - - /// - /// Creates a new instance of the client with the same configuration. - /// - /// The copy of the client. - public ComDaClient CloneClient() - { - ComDaClient clone = new ComDaClient(m_configuration); - clone.LocaleId = this.LocaleId; - clone.UserIdentity = this.UserIdentity; - clone.Key = this.Key; - return clone; - } - - /// - /// Reads the status from the server. - /// - public OPCSERVERSTATUS? GetStatus() - { - string methodName = "IOPCServer.GetStatus"; - - try - { - IOPCServer server = BeginComCall(methodName, true); - - IntPtr ppServerStatus; - server.GetStatus(out ppServerStatus); - - if (ppServerStatus == IntPtr.Zero) - { - return null; - } - - OpcRcw.Da.OPCSERVERSTATUS pStatus = (OpcRcw.Da.OPCSERVERSTATUS)Marshal.PtrToStructure(ppServerStatus, typeof(OpcRcw.Da.OPCSERVERSTATUS)); - - Marshal.DestroyStructure(ppServerStatus, typeof(OpcRcw.Da.OPCSERVERSTATUS)); - Marshal.FreeCoTaskMem(ppServerStatus); - - return pStatus; - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Reads the item and property values from the server. - /// - /// The requests. - public void Read(ReadRequestCollection requests) - { - if (m_supportsIOPCItemIO) - { - Da30ReadItemValues(requests); - } - else - { - Da20ReadItemValues(requests); - } - - ReadPropertyValues(requests); - } - - /// - /// Writes the item and property values to the server. - /// - /// The requests. - public void Write(WriteRequestCollection requests) - { - if (m_supportsIOPCItemIO) - { - Da30WriteItemValues(requests); - } - else - { - Da20WriteItemValues(requests); - } - } - - #region Group Management - /// - /// Creates a group. - /// - public object CreateGroup( - int groupId, - int samplingInterval, - float deadband, - out int groupHandle, - out int revisedSamplingInterval) - { - groupHandle = 0; - revisedSamplingInterval = 0; - GCHandle hDeadband = GCHandle.Alloc(deadband, GCHandleType.Pinned); - - string methodName = "IOPCServer.AddGroup"; - - try - { - IOPCServer server = BeginComCall(methodName, true); - - object group = null; - Guid iid = typeof(OpcRcw.Da.IOPCItemMgt).GUID; - - server.AddGroup( - String.Empty, - 1, - samplingInterval, - 0, - IntPtr.Zero, - hDeadband.AddrOfPinnedObject(), - LocaleId, - out groupHandle, - out revisedSamplingInterval, - ref iid, - out group); - - return group; - } - catch (Exception e) - { - ComUtils.TraceComError(e, methodName); - return null; - } - finally - { - EndComCall(methodName); - hDeadband.Free(); - } - } - - /// - /// Removes a group. - /// - public void RemoveGroup(int groupHandle) - { - string methodName = "IOPCServer.RemoveGroup"; - - try - { - IOPCServer server = BeginComCall(methodName, true); - server.RemoveGroup(groupHandle, 0); - } - catch (Exception e) - { - ComUtils.TraceComError(e, methodName); - return; - } - finally - { - EndComCall(methodName); - } - } - #endregion - - /// - /// Reads the property values and stores the results in the request objects. - /// - /// The requests. - public void ReadPropertyValues(List requests) - { - for (int ii = 0; ii < requests.Count; ii++) - { - ReadRequest request = requests[ii]; - - if (request != null && request.PropertyIds != null) - { - request.PropertyValues = ReadPropertyValues( - request.ItemId, - request.PropertyIds.ToArray()); - } - } - } - - /// - /// Read the available non-built in properties from the server. - /// - /// The item id. - /// if set to true the cache is updated. - /// The array of properties. - public DaProperty[] ReadAvailableProperties(string itemId, bool updateCache) - { - string methodName = "IOPCItemProperties.QueryAvailableProperties"; - - // query for available properties. - int count = 0; - - IntPtr pPropertyIds = IntPtr.Zero; - IntPtr pDescriptions = IntPtr.Zero; - IntPtr pDataTypes = IntPtr.Zero; - - try - { - IOPCItemProperties server = BeginComCall(methodName, true); - - server.QueryAvailableProperties( - itemId, - out count, - out pPropertyIds, - out pDescriptions, - out pDataTypes); - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_INVALIDARG, ResultIds.E_UNKNOWNITEMID, ResultIds.E_INVALIDITEMID)) - { - ComUtils.TraceComError(e, methodName); - } - - return null; - } - finally - { - EndComCall(methodName); - } - - // unmarshal results. - int[] propertyIds = ComUtils.GetInt32s(ref pPropertyIds, count, true); - string[] descriptions = ComUtils.GetUnicodeStrings(ref pDescriptions, count, true); - short[] datatype = ComUtils.GetInt16s(ref pDataTypes, count, true); - - List properties = new List(); - - for (int ii = 0; ii < count; ii++) - { - // do not return any of the built in properties. - if (propertyIds[ii] <= PropertyIds.TimeZone) - { - continue; - } - - DaProperty property = new DaProperty(); - - property.PropertyId = propertyIds[ii]; - property.Name = descriptions[ii]; - property.DataType = datatype[ii]; - - properties.Add(property); - } - - // fetch the item ids. - if (properties.Count > 0) - { - DaProperty[] array = properties.ToArray(); - - GetPropertyItemIds(itemId, array); - - // update the cache. - if (updateCache) - { - lock (m_cache) - { - DaElement element = null; - - if (m_cache.TryGetValue(itemId, out element)) - { - element.Properties = array; - } - } - } - - return array; - } - - return null; - } - #endregion - - #region Private Methods - /// - /// Saves the element in cache. - /// - /// The element. - private void SaveElementInCache(DaElement element) - { - lock (m_cache) - { - m_cache[element.ItemId] = element; - } - } - - /// - /// Creates a new element. - /// - /// The item id. - /// The name. - /// The parent id. - /// The element. - private DaElement CreateElement(string itemId, string name, string parentId) - { - DaElement element = new DaElement(); - element.ItemId = itemId; - UpdateElement(element, name, parentId); - return element; - } - - /// - /// Updates a element. - /// - /// The element. - /// The name. - /// The parent id. - private void UpdateElement(DaElement element, string name, string parentId) - { - // only update the name if specified. - if (name != null) - { - element.Name = name; - } - - // same for the parent id. - if (parentId != null) - { - element.ParentId = parentId; - } - - // read item property values. - DaValue[] values = ReadPropertyValues(element.ItemId, m_CoreProperties); - - // handle errors gracefully. - if (values == null || values.Length == 0) - { - element.ElementType = DaElementType.Branch; - return; - } - - // must be an item if the data type property exists. - if (values[0].Error >= 0) - { - element.ElementType = DaElementType.Item; - element.DataType = values[0].GetValue(); - element.AccessRights = values[1].GetValue(); - element.ScanRate = values[2].GetValue(); - element.Description = values[3].GetValue(); - element.EngineeringUnits = values[4].GetValue(); - element.EuInfo = values[5].GetValue(); - element.EuType = values[6].GetValue(); - element.HighEU = values[7].GetValue(); - element.LowEU = values[8].GetValue(); - element.OpenLabel = values[9].GetValue(); - element.CloseLabel = values[10].GetValue(); - element.HighIR = values[11].GetValue(); - element.LowIR = values[12].GetValue(); - - // check if the time zone is specified. - if (values[13].Error >= 0) - { - element.TimeZone = values[13].GetValue(); - } - - // check for analog item (checks for HighEU if EuType property not supported). - if ((values[6].Error < 0 && values[7].Error >= 0) || element.EuType == (int)OPCEUTYPE.OPC_ANALOG) - { - element.ElementType = DaElementType.AnalogItem; - } - - // check for enumerated item. - else if (element.EuType == (int)OPCEUTYPE.OPC_ENUMERATED) - { - element.ElementType = DaElementType.EnumeratedItem; - } - - // check for digital item (checks for CloseLabel property). - else if (values[10].Error >= 0) - { - element.ElementType = DaElementType.DigitalItem; - } - } - - // the element must be a branch. - else - { - element.ElementType = DaElementType.Branch; - - // branches could have description property. - element.Description = values[3].GetValue(); - } - } - - /// - /// Finds the element and updates the name if it is not already cached. - /// - /// The item id. - /// The name. - /// The parent id. - /// The element. - private DaElement FindElement(string itemId, string name, string parentId) - { - if (String.IsNullOrEmpty(itemId)) - { - return null; - } - - // look in cache for existing element. - DaElement element = null; - - lock (m_cache) - { - if (!m_cache.TryGetValue(itemId, out element)) - { - element = null; - } - } - - // create a new element. - if (element == null) - { - element = CreateElement(itemId, name, parentId); - SaveElementInCache(element); - } - - // update the element. - element.Name = name; - element.ParentId = parentId; - - return element; - } - - /// - /// The core properties used to determine an item type. - /// - private static readonly int[] m_CoreProperties = new int[] - { - PropertyIds.DataType, - PropertyIds.AccessRights, - PropertyIds.ScanRate, - PropertyIds.Description, - PropertyIds.EngineeringUnits, - PropertyIds.EuInfo, - PropertyIds.EuType, - PropertyIds.HighEU, - PropertyIds.LowEU, - PropertyIds.OpenLabel, - PropertyIds.CloseLabel, - PropertyIds.HighIR, - PropertyIds.LowIR, - PropertyIds.TimeZone - }; - - /// - /// Changes the browse position. - /// - /// The direction. - /// The name. - /// True if the operation was successful. - private bool ChangeBrowsePosition(OPCBROWSEDIRECTION direction, string name) - { - string methodName = "IOPCBrowseServerAddressSpace.ChangeBrowsePosition"; - - if (name == null) - { - name = String.Empty; - } - - try - { - IOPCBrowseServerAddressSpace server = BeginComCall(methodName, true); - server.ChangeBrowsePosition(direction, name); - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_INVALIDARG)) - { - ComCallError(methodName, e); - } - - return false; - } - finally - { - EndComCall(methodName); - } - - return true; - } - - /// - /// Creates an enumerator for the current browse position. - /// - /// if set to true then branches are enumerated. - /// The wrapped enumerator. - private EnumString CreateEnumerator(bool branches) - { - IEnumString unknown = null; - - string methodName = "IOPCBrowseServerAddressSpace.BrowseOPCItemIDs"; - - try - { - IOPCBrowseServerAddressSpace server = BeginComCall(methodName, true); - - OPCBROWSETYPE browseType = OPCBROWSETYPE.OPC_BRANCH; - - if (!branches) - { - browseType = OPCBROWSETYPE.OPC_LEAF; - } - - server.BrowseOPCItemIDs(browseType, String.Empty, 0, 0, out unknown); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - // wrapper the enumrator. hardcoding a buffer size of 256. - return new EnumString(unknown, 256); - } - - /// - /// Looks up the item id for the node relative to the current browse position. - /// - /// Name of the element to lookup. - /// The item id. Null if an error occurs. - private string GetItemId(string browseName) - { - string methodName = "IOPCBrowseServerAddressSpace.GetItemID"; - - try - { - IOPCBrowseServerAddressSpace server = BeginComCall(methodName, true); - string itemId = null; - server.GetItemID(browseName, out itemId); - return itemId; - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL)) - { - ComCallError(methodName, e); - } - - return null; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Reads the values of the properties from the server. - /// - /// The item id. - /// The list of property ids to read. All properties are read if null. - /// True if the element has properies. - private DaValue[] ReadPropertyValues(string itemId, params int[] propertyIds) - { - string methodName = "IOPCItemProperties.GetItemProperties"; - - // check for trivial case. - if (propertyIds == null) - { - return null; - } - - int count = propertyIds.Length; - DaValue[] results = new DaValue[count]; - - // check for empty list. - if (count == 0) - { - return results; - } - - // get the values from the server. - IntPtr pValues = IntPtr.Zero; - IntPtr pErrors = IntPtr.Zero; - - try - { - IOPCItemProperties server = BeginComCall(methodName, true); - - server.GetItemProperties( - itemId, - count, - propertyIds, - out pValues, - out pErrors); - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_INVALIDARG, ResultIds.E_UNKNOWNITEMID, ResultIds.E_INVALIDITEMID)) - { - ComUtils.TraceComError(e, methodName); - return null; - } - - for (int ii = 0; ii < count; ii++) - { - DaValue result = results[ii] = new DaValue(); - result.Value = null; - result.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD; - result.Timestamp = DateTime.UtcNow; - result.Error = Marshal.GetHRForException(e); - } - - return results; - } - finally - { - EndComCall(methodName); - } - - // unmarshal results. - object[] values = ComUtils.GetVARIANTs(ref pValues, count, true); - int[] errors = ComUtils.GetInt32s(ref pErrors, count, true); - - for (int ii = 0; ii < count; ii++) - { - DaValue result = results[ii] = new DaValue(); - - Variant convertedValue; - result.Error = ComDaClientNodeManager.RemoteToLocalValue(values[ii], out convertedValue); - - if (result.Error < 0) - { - continue; - } - - result.Value = convertedValue.Value; - result.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD; - result.Timestamp = DateTime.UtcNow; - result.Error = errors[ii]; - } - - return results; - } - - /// - /// Gets the property item ids. - /// - /// The item id. - /// The properties to update. - private void GetPropertyItemIds(string itemId, DaProperty[] properties) - { - string methodName = "IOPCItemProperties.LookupItemIDs"; - - int count = properties.Length; - - // get list of ids to request. - int[] propertyIds = new int[count]; - - for (int ii = 0; ii < propertyIds.Length; ii++) - { - propertyIds[ii] = properties[ii].PropertyId; - } - - // request the item ids. - IntPtr pItemIds = IntPtr.Zero; - IntPtr pErrors = IntPtr.Zero; - - try - { - IOPCItemProperties server = BeginComCall(methodName, true); - - server.LookupItemIDs( - itemId, - count, - propertyIds, - out pItemIds, - out pErrors); - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_UNKNOWNITEMID, ResultIds.E_INVALIDITEMID)) - { - ComUtils.TraceComError(e, methodName); - } - - return; - } - finally - { - EndComCall(methodName); - } - - // unmarshal results. - string[] itemIds = ComUtils.GetUnicodeStrings(ref pItemIds, count, true); - int[] errors = ComUtils.GetInt32s(ref pErrors, count, true); - - // update the objects. - for (int ii = 0; ii < count; ii++) - { - if (errors[ii] >= 0) - { - properties[ii].ItemId = itemIds[ii]; - } - else - { - properties[ii].ItemId = null; - } - } - } - - //private ComDaGroup m_group = null; - //private object m_groupLock = new object(); - - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - //lock (m_groupLock) - //{ - // if (m_group != null) - // { - // Utils.SilentDispose(m_group); - // m_group = null; - // } - //} - } - - base.Dispose(disposing); - } - - /// - /// Reads the item values and stores the results in the request object. - /// - /// The requests. - private void Da20ReadItemValues(List requests) - { - // lock (m_groupLock) - { - // if (m_group == null) - //{ - ComDaGroup m_group = new ComDaGroup(this, false); - //} - - try - { - int count1 = 0; - GroupItem[] items = new GroupItem[requests.Count]; - ReadRequest[] addItemRequests = new ReadRequest[requests.Count]; - - // create the items in the temporary group. - for (int ii = 0; ii < requests.Count; ii++) - { - ReadRequest request = requests[ii]; - - if (request == null) - { - continue; - } - - if (!request.ValueRequired) - { - continue; - } - - // add the item. - items[count1] = m_group.CreateItem(request.ItemId, 0, 0, true); - addItemRequests[count1] = request; - count1++; - } - - // create the items on the server. - m_group.ApplyChanges(); - - // build the list of values to write. - int count2 = 0; - int[] serverHandles = new int[count1]; - ReadRequest[] readRequests = new ReadRequest[count1]; - - for (int ii = 0; ii < count1; ii++) - { - // check for error on create. - GroupItem item = items[ii]; - ReadRequest request = addItemRequests[ii]; - - if (item.ErrorId < 0) - { - request.Value = new DaValue(); - request.Value.Error = item.ErrorId; - continue; - } - - serverHandles[count2] = item.ServerHandle; - readRequests[count2] = request; - count2++; - } - - if (count2 > 0) - { - // write values to the server. - DaValue[] values = m_group.SyncRead(serverHandles, count2); - - // read the values. - for (int ii = 0; ii < count2; ii++) - { - if (values != null && values.Length > ii) - { - readRequests[ii].Value = values[ii]; - } - else - { - readRequests[ii].Value = new DaValue() { Error = ResultIds.E_FAIL, Timestamp = DateTime.UtcNow }; - } - } - - // delete the items. - for (int ii = 0; ii < count1; ii++) - { - GroupItem item = items[ii]; - - if (item.ErrorId >= 0) - { - m_group.RemoveItem(item); - } - } - - m_group.ApplyChanges(); - } - } - finally - { - // delete the group and items. - m_group.Delete(); - } - } - } - - /// - /// Writes the item values to servers. - /// - /// The requests. - private void Da20WriteItemValues(List requests) - { - //lock (m_groupLock) - { - //if (m_group == null) - //{ - ComDaGroup m_group = new ComDaGroup(this, false); - //} - - try - { - int count1 = 0; - GroupItem[] items = new GroupItem[requests.Count]; - WriteRequest[] addItemRequests = new WriteRequest[requests.Count]; - object[] convertedValues = new object[requests.Count]; - - // create the items in the temporary group. - for (int ii = 0; ii < requests.Count; ii++) - { - WriteRequest request = requests[ii]; - - if (request == null) - { - continue; - } - - // status code writes not supported. - if (request.Value.StatusCode != StatusCodes.Good) - { - request.Error = ResultIds.E_NOTSUPPORTED; - continue; - } - - // timestamp writes not supported. - if (request.Value.ServerTimestamp != DateTime.MinValue) - { - request.Error = ResultIds.E_NOTSUPPORTED; - continue; - } - - // timestamp writes not supported. - if (request.Value.SourceTimestamp != DateTime.MinValue) - { - request.Error = ResultIds.E_NOTSUPPORTED; - continue; - } - - // convert to a DA compatible type. - object convertedValue = null; - request.Error = ComDaClientNodeManager.LocalToRemoteValue(request.Value.WrappedValue, out convertedValue); - - if (request.Error < 0) - { - continue; - } - - // add the item. - items[count1] = m_group.CreateItem(request.ItemId, 0, 0, true); - addItemRequests[count1] = request; - convertedValues[count1] = convertedValue; - count1++; - } - - // create the items on the server. - m_group.ApplyChanges(); - - // build the list of values to write. - int count2 = 0; - int[] serverHandles = new int[count1]; - object[] values = new object[count1]; - WriteRequest[] writeRequests = new WriteRequest[count1]; - - for (int ii = 0; ii < count1; ii++) - { - // check for error on create. - GroupItem item = items[ii]; - WriteRequest request = addItemRequests[ii]; - - if (item.ErrorId < 0) - { - request.Error = item.ErrorId; - continue; - } - - serverHandles[count2] = item.ServerHandle; - values[count2] = convertedValues[ii]; - writeRequests[count2] = request; - count2++; - } - - if (count2 > 0) - { - // write values to the server. - int[] errors = m_group.SyncWrite(serverHandles, values, count2); - - // read the errors. - for (int ii = 0; ii < count2; ii++) - { - if (errors != null && errors.Length > ii) - { - writeRequests[ii].Error = errors[ii]; - } - else - { - writeRequests[ii].Error = ResultIds.E_FAIL; - } - } - - // delete the items. - for (int ii = 0; ii < count1; ii++) - { - GroupItem item = items[ii]; - - if (item.ErrorId >= 0) - { - m_group.RemoveItem(item); - } - } - - m_group.ApplyChanges(); - } - } - finally - { - // delete the group and items. - m_group.Delete(); - } - } - } - - /// - /// Reads the values using the DA3 interfaces. - /// - /// The requests. - private void Da30ReadItemValues(List requests) - { - string[] itemIds = new string[requests.Count]; - int[] maxAge = new int[requests.Count]; - List requestIndexes = new List(); - - int count = 0; - - for (int ii = 0; ii < requests.Count; ii++) - { - if (!requests[ii].ValueRequired) - { - continue; - } - - itemIds[count] = requests[ii].ItemId; - maxAge[count] = 0; - requestIndexes.Add(ii); - count++; - } - - if (count <= 0) - { - return; - } - - IntPtr ppValues = IntPtr.Zero; - IntPtr ppQualities = IntPtr.Zero; - IntPtr ppTimeStamps = IntPtr.Zero; - IntPtr ppErrors = IntPtr.Zero; - - string methodName = "IOPCItemIO.Read"; - - try - { - IOPCItemIO server = BeginComCall(methodName, true); - - server.Read( - requestIndexes.Count, - itemIds, - maxAge, - out ppValues, - out ppQualities, - out ppTimeStamps, - out ppErrors); - } - catch (Exception e) - { - ComUtils.TraceComError(e, methodName); - return; - } - finally - { - EndComCall(methodName); - } - - System.Runtime.InteropServices.ComTypes.FILETIME[] timeStamps = ComUtils.GetFILETIMEs(ref ppTimeStamps, requestIndexes.Count); - object[] values = ComUtils.GetVARIANTs(ref ppValues, count, true); - short[] qualities = ComUtils.GetInt16s(ref ppQualities, count, true); - int[] errors = ComUtils.GetInt32s(ref ppErrors, count, true); - - DaValue[] daValues = ComDaGroup.GetItemValues(count, values, qualities, timeStamps, errors); - - for (int ii = 0; ii < requestIndexes.Count; ii++) - { - requests[requestIndexes[ii]].Value = daValues[ii]; - } - } - - /// - /// Writes the values using the DA3 interfaces. - /// - /// The requests. - private void Da30WriteItemValues(List requests) - { - int count = 0; - string[] itemIDs = new string[requests.Count]; - OpcRcw.Da.OPCITEMVQT[] values = new OpcRcw.Da.OPCITEMVQT[requests.Count]; - WriteRequest[] writeRequests = new WriteRequest[requests.Count]; - - for (int ii = 0; ii < requests.Count; ii++) - { - WriteRequest request = requests[ii]; - - if (request == null) - { - continue; - } - - // convert to a DA compatible type. - object convertedValue = null; - request.Error = ComDaClientNodeManager.LocalToRemoteValue(request.Value.WrappedValue, out convertedValue); - - if (request.Error < 0) - { - continue; - } - - itemIDs[count] = request.ItemId; - - values[count].vDataValue = convertedValue; - values[count].bQualitySpecified = 0; - values[count].bTimeStampSpecified = 0; - - // check for quality. - values[count].wQuality = ComUtils.GetQualityCode(request.Value.StatusCode); - - if (values[count].wQuality != Qualities.OPC_QUALITY_GOOD) - { - values[count].bQualitySpecified = 1; - } - - // check for server timestamp. - if (request.Value.ServerTimestamp != DateTime.MinValue) - { - values[count].ftTimeStamp = ComUtils.GetFILETIME(request.Value.ServerTimestamp); - values[count].bTimeStampSpecified = 1; - } - - // ignore server timestamp if source timestamp is provided. - if (request.Value.SourceTimestamp != DateTime.MinValue) - { - values[count].ftTimeStamp = ComUtils.GetFILETIME(request.Value.SourceTimestamp); - values[count].bTimeStampSpecified = 1; - } - - writeRequests[count] = request; - count++; - } - - IntPtr ppErrors = IntPtr.Zero; - string methodName = "IOPCItemIO.WriteVQT"; - - try - { - IOPCItemIO server = BeginComCall(methodName, true); - - server.WriteVQT( - count, - itemIDs, - values, - out ppErrors); - } - catch (Exception e) - { - ComUtils.TraceComError(e, methodName); - return; - } - finally - { - EndComCall(methodName); - } - - int[] errors = ComUtils.GetInt32s(ref ppErrors, count, true); - - for (int ii = 0; ii < count; ii++) - { - writeRequests[ii].Error = errors[ii]; - } - } - - /// - /// Called immediately after connecting to the server. - /// - protected override void OnConnected() - { - m_supportsIOPCItemIO = SupportsInterface(); - } - #endregion - - #region Da20ElementBrowser Class - /// - /// Browses for DA elements using the DA 2.0 interfaces. - /// - private class Da20ElementBrowser : IDaElementBrowser - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The client. - /// The item id. - /// if set to true BROWSE_TO not supported. - public Da20ElementBrowser( - ComDaClient client, - string itemId, - bool browseToNotSupported) - { - m_client = client; - m_itemId = itemId; - m_branches = false; - m_browseToNotSupported = browseToNotSupported; - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - Utils.SilentDispose(m_enumerator); - m_enumerator = null; - - Utils.SilentDispose(m_clone); - m_clone = null; - } - } - #endregion - - /// - /// Sets the browse position using the BROWSE_DOWN operator. - /// - /// The item id. - /// True if the item id was found. - private bool SearchAndSetBrowsePosition(string itemId) - { - EnumString enumerator = m_clone.CreateEnumerator(true); - - // a null indicates an error. - if (enumerator == null) - { - return false; - } - - // collect names. - Queue names = new Queue(); - - try - { - do - { - // fetch the next name. - string name = enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - break; - } - - // fetch the item id. - string branchId = m_clone.GetItemId(name); - - if (branchId == itemId) - { - return m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_DOWN, name); - } - - names.Enqueue(name); - } - while (true); - } - finally - { - enumerator.Dispose(); - } - - // recursively search tree. - while (names.Count > 0) - { - string name = names.Dequeue(); - - if (!m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_DOWN, name)) - { - continue; - } - - if (SearchAndSetBrowsePosition(itemId)) - { - return true; - } - - m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_UP, null); - } - - // not found anywhere. - return false; - } - - /// - /// Sets the browse position. - /// - /// The item id. - /// True if the item id was found. - private bool SetBrowsePosition(string itemId) - { - // go directly to item id. - if (m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_TO, itemId)) - { - return true; - } - - // nothing more to do isf browse to supported. - if (!m_browseToNotSupported) - { - return false; - } - - // do it the hard way. - while (m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_UP, null)) - { - // skip to root. - } - - // nothing more to do at root. - if (String.IsNullOrEmpty(itemId)) - { - return true; - } - - // find item id in tree. - return SearchAndSetBrowsePosition(itemId); - } - - #region IDaElementBrowser Members - /// - /// Returns the next DA element. - /// - /// A DA element. Null if nothing left to browse. - public DaElement Next() - { - // check if already completed. - if (m_completed) - { - return null; - } - - // create the enumerator if not already created. - if (m_enumerator == null) - { - // need to clone the client since ChangeBrowsePosition prevents multiple - // simultaneous browse operations. - m_clone = m_client.CloneClient(); - m_clone.CreateInstance(); - - // nothing to browse if change browse position failed. - if (!SetBrowsePosition(m_itemId)) - { - return null; - } - - m_enumerator = m_clone.CreateEnumerator(false); - m_branches = false; - - // a null indicates an error. - if (m_enumerator == null) - { - m_completed = true; - return null; - } - } - - // need a loop in case errors occur fetching element metadata. - DaElement element = null; - - do - { - // fetch the next name. - string name = m_enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - if (!m_branches) - { - m_branches = true; - m_enumerator.Dispose(); - m_enumerator = m_clone.CreateEnumerator(true); - continue; - } - - m_completed = true; - return null; - } - - // suppress duplicates when a item is also a branch. - if (m_branches) - { - if (m_itemNames != null) - { - if (m_itemNames.ContainsKey(name)) - { - continue; - } - } - } - - // save the item name to allow checks for duplicates. - else - { - if (m_itemNames == null) - { - m_itemNames = new Dictionary(); - } - - m_itemNames[name] = null; - } - - // fetch the item id. - string itemId = m_clone.GetItemId(name); - - // fetch the metadata. - element = m_client.FindElement(itemId, name, m_itemId); - } - while (element == null); - - // return element. - return element; - } - - /// - /// Finds the element with the specified item id. - /// - /// The target id. - /// if set to true [is item]. - /// The element if found. - public DaElement Find(string targetId, bool isItem) - { - // check for root. - if (String.IsNullOrEmpty(targetId)) - { - m_client.FindElement(targetId, String.Empty, String.Empty); - } - - // create the clone used to find the item. - if (m_clone == null) - { - m_clone = m_client.CloneClient(); - m_clone.CreateInstance(); - } - - bool recursive = false; - - // check if it is possible to browse to the item. - if (m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_TO, targetId)) - { - if (!m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_UP, String.Empty)) - { - return null; - } - } - - // need to do it the hard way from the root of the hierarchy. - else - { - while (m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_UP, String.Empty)); - recursive = true; - } - - // get the item id for the parent. - string parentId = m_clone.GetItemId(String.Empty); - - // find the target. - return Find(parentId, targetId, false, recursive); - } - - /// - /// Finds the element with the specified item id. - /// - /// The parent id. - /// The target id. - /// if set to true the element is a item. - /// if set to true [recursive]. - /// The element if found. - public DaElement Find(string parentId, string targetId, bool isItem, bool recursive) - { - // create the enumerator if not already created. - m_enumerator = m_clone.CreateEnumerator(false); - - // a null indicates an error. - if (m_enumerator == null) - { - return null; - } - - string name = null; - - // process all items. - do - { - // fetch the next name. - name = m_enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - break; - } - - // fetch the item id. - string itemId = m_clone.GetItemId(name); - - // fetch the metadata. - DaElement element = m_client.FindElement(itemId, name, parentId); - - // check if target found. - if (targetId == itemId) - { - return element; - } - } - while (true); - - m_enumerator.Dispose(); - m_enumerator = null; - - List branches = new List(); - - // fetch the branches of the target is a branch or if a recursive search is required. - if (!isItem || recursive) - { - // need to fetch list of branches to search. - m_enumerator = m_clone.CreateEnumerator(true); - - if (m_enumerator == null) - { - return null; - } - - // process all branches. - do - { - name = m_enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - break; - } - - // fetch the item id. - string itemId = m_clone.GetItemId(name); - - // fetch the metadata. - DaElement element = m_client.FindElement(itemId, name, parentId); - - // save branch for recursive search if not found at this level. - if (recursive) - { - branches.Add(element); - } - - // check if target found. - if (targetId == itemId) - { - return element; - } - } - while (name != null); - - m_enumerator.Dispose(); - m_enumerator = null; - } - - // all done if not doing a recursive search. - if (!recursive) - { - return null; - } - - // recursively search hierarchy. - for (int ii = 0; ii < branches.Count; ii++) - { - m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_DOWN, branches[ii].Name); - - DaElement element = Find(branches[ii].ItemId, targetId, isItem, recursive); - - if (element != null) - { - return element; - } - - m_clone.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_UP, String.Empty); - } - - // not found. - return null; - } - #endregion - - #region Private Fields - private ComDaClient m_client; - private ComDaClient m_clone; - private string m_itemId; - private Opc.Ua.Com.Client.EnumString m_enumerator; - private bool m_branches; - private bool m_completed; - private Dictionary m_itemNames; - private bool m_browseToNotSupported; - #endregion - } - #endregion - - #region Private Fields - private Dictionary m_cache; - private ComDaClientConfiguration m_configuration; - private bool m_supportsIOPCItemIO; - #endregion - } - - /// - /// An interface to an object that browses a DA COM server. - /// - public interface IDaElementBrowser : IDisposable - { - /// - /// Returns the next element. - /// - /// The next element. Null if nothing found or an error occurs. - DaElement Next(); - - /// - /// Finds the element with the specified item id. - /// - /// The target id. - /// if set to true the element is a branch. - /// The element if found. - DaElement Find(string targetId, bool isBranch); - } -} diff --git a/ComIOP/Common/Client/Da/ComDaClientConfiguration.cs b/ComIOP/Common/Client/Da/ComDaClientConfiguration.cs deleted file mode 100644 index 6ce1fa408..000000000 --- a/ComIOP/Common/Client/Da/ComDaClientConfiguration.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.ServiceModel; -using System.Runtime.Serialization; -using System.Collections.Generic; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the configuration the data access node manager. - /// - [DataContract(Namespace = Namespaces.ComInterop)] - public class ComDaClientConfiguration : ComClientConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public ComDaClientConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - } - #endregion - - #region Public Properties - /// - /// Get or sets a value indicating whether BROWSE_TO is supported by the COM Server. - /// - [DataMember(Order = 2)] - public bool BrowseToNotSupported - { - get { return m_browseToNotSupported; } - set { m_browseToNotSupported = value; } - } - #endregion - - #region Private Members - private bool m_browseToNotSupported; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/ComDaClientManager.cs b/ComIOP/Common/Client/Da/ComDaClientManager.cs deleted file mode 100644 index aaea5b711..000000000 --- a/ComIOP/Common/Client/Da/ComDaClientManager.cs +++ /dev/null @@ -1,141 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Da; - -namespace Opc.Ua.Com.Client -{ - /// - /// Manages the DA COM connections used by the UA server. - /// - public class ComDaClientManager : ComClientManager - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComDaClientManager() - { - } - #endregion - - #region Public Members - /// - /// Selects the DA COM client to use for the current context. - /// - /// The context. - /// True if the the default instance should be returned. - /// A DA COM client instance. - public new ComDaClient SelectClient(ServerSystemContext context, bool useDefault) - { - return (ComDaClient)base.SelectClient(context, useDefault); - } - #endregion - - #region Protected Members - /// - /// Gets or sets the default COM client instance. - /// - /// The default client. - protected new ComDaClient DefaultClient - { - get { return base.DefaultClient as ComDaClient; } - set { base.DefaultClient = value; } - } - - /// - /// Gets the configuration. - /// - /// The configuration. - protected new ComDaClientConfiguration Configuration - { - get { return base.Configuration as ComDaClientConfiguration; } - } - - /// - /// Creates a new client object. - /// - protected override ComClient CreateClient() - { - return new ComDaClient(Configuration); - } - - /// - /// Updates the status node. - /// - protected override bool UpdateStatus() - { - // get the status from the server. - ComDaClient client = DefaultClient; - OPCSERVERSTATUS? status = client.GetStatus(); - - // check the client has been abandoned. - if (!Object.ReferenceEquals(client, DefaultClient)) - { - return false; - } - - // update the server status. - lock (StatusNodeLock) - { - StatusNode.ServerUrl.Value = Configuration.ServerUrl; - - if (status != null) - { - StatusNode.SetStatusCode(DefaultSystemContext, StatusCodes.Good, DateTime.UtcNow); - - StatusNode.ServerState.Value = Utils.Format("{0}", status.Value.dwServerState); - StatusNode.CurrentTime.Value = ComUtils.GetDateTime(status.Value.ftCurrentTime); - StatusNode.LastUpdateTime.Value = ComUtils.GetDateTime(status.Value.ftLastUpdateTime); - StatusNode.StartTime.Value = ComUtils.GetDateTime(status.Value.ftStartTime); - StatusNode.VendorInfo.Value = status.Value.szVendorInfo; - StatusNode.SoftwareVersion.Value = Utils.Format("{0}.{1}.{2}", status.Value.wMajorVersion, status.Value.wMinorVersion, status.Value.wBuildNumber); - } - else - { - StatusNode.SetStatusCode(DefaultSystemContext, StatusCodes.BadOutOfService, DateTime.UtcNow); - } - - StatusNode.ClearChangeMasks(DefaultSystemContext, true); - return status != null; - } - } - #endregion - - #region Private Fields - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/ComDaClientNodeManager.cs b/ComIOP/Common/Client/Da/ComDaClientNodeManager.cs deleted file mode 100644 index 89497a1f2..000000000 --- a/ComIOP/Common/Client/Da/ComDaClientNodeManager.cs +++ /dev/null @@ -1,947 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using System.Xml; -using System.IO; -using System.Threading; -using System.Reflection; -using System.Globalization; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// A node manager for a server that exposes several variables. - /// - public class ComDaClientNodeManager : ComClientNodeManager - { - #region Constructors - /// - /// Initializes the node manager. - /// - public ComDaClientNodeManager(IServerInternal server, string namespaceUri, ComDaClientConfiguration configuration, bool ownsTypeModel) - : - base(server, namespaceUri, ownsTypeModel) - { - SystemContext.SystemHandle = m_system = new ComDaClientManager(); - SystemContext.NodeIdFactory = this; - - // save the configuration for the node manager. - m_configuration = configuration; - - // set the alias root. - AliasRoot = m_configuration.ServerName; - - if (String.IsNullOrEmpty(AliasRoot)) - { - AliasRoot = "DA"; - } - - // set the default parser if none provided. - if (configuration.ItemIdParser == null) - { - configuration.ItemIdParser = new ComItemIdParser(); - } - - // create the list of subscriptions. - m_subscriptionManagers = new Dictionary(); - m_subscriptionManagers[String.Empty] = new SubscribeRequestManager(SystemContext, null, 1000); - m_monitoredItems = new Dictionary(); - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - m_system.Dispose(); - } - - base.Dispose(disposing); - } - #endregion - - #region INodeIdFactory Members - /// - /// Creates the NodeId for the specified node. - /// - /// The context. - /// The node. - /// The new NodeId. - /// - /// This method is called by the NodeState.Create() method which initializes a Node from - /// the type model. During initialization a number of child nodes are created and need to - /// have NodeIds assigned to them. This implementation constructs NodeIds by constructing - /// strings. Other implementations could assign unique integers or Guids and save the new - /// Node in a dictionary for later lookup. - /// - public override NodeId New(ISystemContext context, NodeState node) - { - // do not assign node id to server state nodes. - if (node is ComServerStatusState) - { - return node.NodeId; - } - - return DaModelUtils.ConstructIdForComponent(node, NamespaceIndex); - } - #endregion - - #region INodeManager Members - /// - /// Does any initialization required before the address space can be used. - /// - /// - /// The externalReferences is an out parameter that allows the node manager to link to nodes - /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and - /// should have a reference to the root folder node(s) exposed by this node manager. - /// - public override void CreateAddressSpace(IDictionary> externalReferences) - { - lock (Lock) - { - // check if the type model needs to be loaded. - if (NamespaceIndexes.Length > 1) - { - LoadPredefinedNodes(SystemContext, externalReferences); - } - - // create the root node. - string serverName = m_configuration.ServerName; - - if (String.IsNullOrEmpty(serverName)) - { - serverName = "ComDaServer"; - } - - DaElement element = new DaElement(); - element.ItemId = String.Empty; - element.Name = serverName; - element.ElementType = DaElementType.Branch; - - DaBranchState root = new DaBranchState(SystemContext, element, NamespaceIndex); - root.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); - - // link root to objects folder. - IList references = null; - - if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) - { - externalReferences[ObjectIds.ObjectsFolder] = references = new List(); - } - - references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, root.NodeId)); - - // create the status node. - ComServerStatusState status = new ComServerStatusState(root); - status.ReferenceTypeId = ReferenceTypeIds.Organizes; - - // get the type namepace for the browse name. - int typeNamepaceIndex = Server.NamespaceUris.GetIndex(Namespaces.ComInterop); - - if (typeNamepaceIndex < 0) - { - typeNamepaceIndex = NamespaceIndex; - } - - status.Create( - SystemContext, - DaModelUtils.ConstructIdForInternalNode("ServerStatus", NamespaceIndex), - new QualifiedName("ServerStatus", (ushort)typeNamepaceIndex), - null, - true); - - root.AddChild(status); - - // store root folder in the pre-defined nodes. - AddPredefinedNode(SystemContext, root); - - // create the COM server. - m_system.Initialize(SystemContext, m_configuration, status, Lock, OnServerReconnected); - StartMetadataUpdates(null, null, 5000, m_configuration.MaxReconnectWait); - } - } - - /// - /// Frees any resources allocated for the address space. - /// - public override void DeleteAddressSpace() - { - lock (Lock) - { - base.DeleteAddressSpace(); - } - } - - /// - /// Called when client manager has reconnected to the COM server. - /// - public void OnServerReconnected(object state) - { - try - { - foreach (SubscribeRequestManager manager in m_subscriptionManagers.Values) - { - try - { - manager.RecreateItems(); - } - catch (Exception e) - { - Utils.Trace(e, "Could not re-create subscription after reconnect for locale {0}.", new CultureInfo(manager.LocaleId).DisplayName); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Could not re-create subscription after reconnect."); - } - } - - /// - /// Returns a unique handle for the node. - /// - protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) - { - lock (Lock) - { - // quickly exclude nodes that are not in the namespace. - if (!IsNodeIdInNamespace(nodeId)) - { - return null; - } - - // check for predefined nodes. - if (PredefinedNodes != null) - { - NodeState node = null; - - if (PredefinedNodes.TryGetValue(nodeId, out node)) - { - NodeHandle handle = new NodeHandle(); - - handle.NodeId = nodeId; - handle.Validated = true; - handle.Node = node; - - return handle; - } - } - - // parse the identifier. - DaParsedNodeId parsedNodeId = DaParsedNodeId.Parse(nodeId); - - if (parsedNodeId != null) - { - NodeHandle handle = new NodeHandle(); - - handle.NodeId = nodeId; - handle.Validated = false; - handle.Node = null; - handle.ParsedNodeId = parsedNodeId; - - return handle; - } - - return null; - } - } - - /// - /// Verifies that the specified node exists. - /// - protected override NodeState ValidateNode( - ServerSystemContext context, - NodeHandle handle, - IDictionary cache) - { - // not valid if no root. - if (handle == null) - { - return null; - } - - // check if previously validated. - if (handle.Validated) - { - return handle.Node; - } - - NodeState target = null; - - // check if already in the cache. - if (cache != null) - { - if (cache.TryGetValue(handle.NodeId, out target)) - { - // nulls mean a NodeId which was previously found to be invalid has been referenced again. - if (target == null) - { - return null; - } - - handle.Node = target; - handle.Validated = true; - return handle.Node; - } - - target = null; - } - - try - { - // check if the node id has been parsed. - DaParsedNodeId parsedNodeId = handle.ParsedNodeId as DaParsedNodeId; - - if (parsedNodeId == null) - { - return null; - } - - NodeState root = null; - DaElement element = null; - ComDaClient client = m_system.SelectClient(context, false); - - // validate a branch or item. - if (parsedNodeId.RootType == DaModelUtils.DaElement) - { - element = client.FindElement(parsedNodeId.RootId); - - // branch does not exist. - if (element == null) - { - return null; - } - - // create a temporary object to use for the operation. - root = DaModelUtils.ConstructElement(context, element, NamespaceIndex); - root.Handle = element; - - AddAdditionalElementReferences(SystemContext, root); - } - - // validate an property. - else if (parsedNodeId.RootType == DaModelUtils.DaProperty) - { - element = client.FindElement(parsedNodeId.RootId); - - // branch does not exist. - if (element == null) - { - return null; - } - - // validate the property. - DaProperty property = client.FindProperty(parsedNodeId.RootId, parsedNodeId.PropertyId); - - // property does not exist. - if (property == null) - { - return null; - } - - // create a temporary object to use for the operation. - root = DaModelUtils.ConstructProperty(context, element.ItemId, property, NamespaceIndex); - root.Handle = property; - - AddAdditionalElementReferences(SystemContext, root); - } - - // unknown root type. - else - { - return null; - } - - // all done if no components to validate. - if (String.IsNullOrEmpty(parsedNodeId.ComponentPath)) - { - handle.Validated = true; - handle.Node = target = root; - return handle.Node; - } - - // validate component. - NodeState component = root.FindChildBySymbolicName(context, parsedNodeId.ComponentPath); - - // component does not exist. - if (component == null) - { - return null; - } - - // found a valid component. - handle.Validated = true; - handle.Node = target = component; - return handle.Node; - } - finally - { - // store the node in the cache to optimize subsequent lookups. - if (cache != null) - { - cache.Add(handle.NodeId, target); - } - } - } - - /// - /// Allows sub-class to add additional references to a element node after validation. - /// - protected virtual void AddAdditionalElementReferences(ServerSystemContext context, NodeState node) - { - // TBD - } - - /// - /// Validates the nodes and reads the values from the underlying source. - /// - /// The context. - /// The nodes to read. - /// The values. - /// The errors. - /// The nodes to validate. - /// The cache. - protected override void Read( - ServerSystemContext context, - IList nodesToRead, - IList values, - IList errors, - List nodesToValidate, - IDictionary cache) - { - ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; - ComDaClient client = system.SelectClient((ServerSystemContext)SystemContext, false); - - ReadRequestCollection requests = new ReadRequestCollection(); - - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - NodeHandle handle = nodesToValidate[ii]; - - lock (Lock) - { - NodeState source = ValidateNode(context, handle, cache); - - if (source == null) - { - continue; - } - - DataValue value = values[handle.Index]; - ReadValueId nodeToRead = nodesToRead[handle.Index]; - - // determine if request can be sent to the server. - bool queued = false; - errors[handle.Index] = requests.Add(source, nodeToRead, value, out queued); - - if (queued) - { - continue; - } - - // read built-in metadata. - errors[handle.Index] = source.ReadAttribute( - context, - nodeToRead.AttributeId, - nodeToRead.ParsedIndexRange, - nodeToRead.DataEncoding, - value); - } - } - - // read the values from the server. - client.Read(requests); - - // extract the values from the results. - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - NodeHandle handle = nodesToValidate[ii]; - DataValue value = values[handle.Index]; - ReadValueId nodeToRead = nodesToRead[handle.Index]; - - lock (Lock) - { - if (!requests.HasResult(nodeToRead)) - { - continue; - } - - errors[handle.Index] = requests.GetResult(context, handle.Node, nodeToRead, value, context.DiagnosticsMask); - } - } - } - - /// - /// Validates the nodes and writes the value to the underlying system. - /// - /// The context. - /// The nodes to write. - /// The errors. - /// The nodes to validate. - /// The cache. - protected override void Write( - ServerSystemContext context, - IList nodesToWrite, - IList errors, - List nodesToValidate, - IDictionary cache) - { - ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; - ComDaClient client = system.SelectClient((ServerSystemContext)SystemContext, false); - - WriteRequestCollection requests = new WriteRequestCollection(); - - // validates the nodes and queues an write requests. - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - NodeHandle handle = nodesToValidate[ii]; - - lock (Lock) - { - // validate node. - NodeState source = ValidateNode(context, handle, cache); - - if (source == null) - { - continue; - } - - // determine if request can be sent to the server. - bool queued = false; - WriteValue nodeToWrite = nodesToWrite[handle.Index]; - errors[handle.Index] = requests.Add(source, nodeToWrite, handle.Index, out queued); - - if (queued) - { - continue; - } - - // write the attribute value. - errors[handle.Index] = source.WriteAttribute( - context, - nodeToWrite.AttributeId, - nodeToWrite.ParsedIndexRange, - nodeToWrite.Value); - - // updates to source finished - report changes to monitored items. - source.ClearChangeMasks(context, false); - } - } - - // write to the server. - client.Write(requests); - - // get the results from the requests sent to the server. - for (int ii = 0; ii < requests.Count; ii++) - { - WriteRequest request = requests[ii]; - errors[request.Index] = request.GetResult(); - } - } - #endregion - - #region Overridden Methods - /// - /// Loads a node set from a file or resource and addes them to the set of predefined nodes. - /// - protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) - { - NodeStateCollection predefinedNodes = new NodeStateCollection(); - predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.Com.Common.Opc.Ua.Com.PredefinedNodes.uanodes", Assembly.GetAssembly(this.GetType()), true); - return predefinedNodes; - } - - /// - /// Called when a batch of monitored items has been created. - /// - protected override void OnCreateMonitoredItemsComplete(ServerSystemContext context, IList monitoredItems) - { - ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; - ComDaClient client = system.SelectClient(context, false); - - // use locale for session to find a subscription manager. - SubscribeRequestManager manager = null; - - if (!m_subscriptionManagers.TryGetValue(client.Key, out manager)) - { - m_subscriptionManagers[client.Key] = manager = new SubscribeRequestManager(context, client, 1000); - } - - manager.CreateItems(context, monitoredItems); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - m_monitoredItems[monitoredItems[ii].Id] = manager; - } - } - - /// - /// Called when a batch of monitored items has been modified. - /// - protected override void OnModifyMonitoredItemsComplete(ServerSystemContext context, IList monitoredItems) - { - ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; - ComDaClient client = system.SelectClient(context, false); - - // sort monitored items by the locale id used to create them. - Dictionary> monitoredItemsByLocaleId = new Dictionary>(); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - // look up the manager that was previously used to create the monitor item. - SubscribeRequestManager manager = null; - - if (!m_monitoredItems.TryGetValue(monitoredItems[ii].Id, out manager)) - { - manager = m_subscriptionManagers[client.Key]; - } - - // add monitored item to a list of items for the locale of the manager. - List subset = null; - - if (!monitoredItemsByLocaleId.TryGetValue(manager.Key, out subset)) - { - monitoredItemsByLocaleId[manager.Key] = subset = new List(); - } - - subset.Add(monitoredItems[ii]); - } - - // modify the the item. - foreach (KeyValuePair> entry in monitoredItemsByLocaleId) - { - SubscribeRequestManager manager = null; - - if (m_subscriptionManagers.TryGetValue(entry.Key, out manager)) - { - manager.ModifyItems(context, entry.Value); - } - } - } - - /// - /// Called when a batch of monitored items has been deleted. - /// - protected override void OnDeleteMonitoredItemsComplete(ServerSystemContext context, IList monitoredItems) - { - ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; - ComDaClient client = system.SelectClient(context, false); - - // sort monitored items by the locale id used to create them. - Dictionary> monitoredItemsByLocaleId = new Dictionary>(); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - // look up the manager that was previously used to create the monitor item. - SubscribeRequestManager manager = null; - - if (!m_monitoredItems.TryGetValue(monitoredItems[ii].Id, out manager)) - { - manager = m_subscriptionManagers[client.Key]; - } - - // add monitored item to a list of items for the locale of the manager. - List subset = null; - - if (!monitoredItemsByLocaleId.TryGetValue(manager.Key, out subset)) - { - monitoredItemsByLocaleId[manager.Key] = subset = new List(); - } - - subset.Add(monitoredItems[ii]); - } - - // delete the items. - foreach (KeyValuePair> entry in monitoredItemsByLocaleId) - { - SubscribeRequestManager manager = null; - - if (m_subscriptionManagers.TryGetValue(entry.Key, out manager)) - { - manager.DeleteItems(context, entry.Value); - } - } - } - - /// - /// Called when a batch of monitored items has their monitoring mode changed. - /// - protected override void OnSetMonitoringModeComplete(ServerSystemContext context, IList monitoredItems) - { - OnModifyMonitoredItemsComplete(context, monitoredItems); - } - - /// - /// Creates a new set of monitored items for a set of variables. - /// - /// - /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. - /// - protected override ServiceResult CreateMonitoredItem(ServerSystemContext context, NodeHandle handle, uint subscriptionId, double publishingInterval, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, ref long globalIdCounter, out MonitoringFilterResult filterResult, out IMonitoredItem monitoredItem) - { - filterResult = null; - monitoredItem = null; - - // validate parameters. - MonitoringParameters parameters = itemToCreate.RequestedParameters; - - // validate attribute. - if (!Attributes.IsValid(handle.Node.NodeClass, itemToCreate.ItemToMonitor.AttributeId)) - { - return StatusCodes.BadAttributeIdInvalid; - } - - NodeState cachedNode = AddNodeToComponentCache(context, handle, handle.Node); - - // check if the node is already being monitored. - MonitoredNode2 monitoredNode = null; - - if (!MonitoredNodes.TryGetValue(handle.Node.NodeId, out monitoredNode)) - { - MonitoredNodes[handle.Node.NodeId] = monitoredNode = new MonitoredNode2(this, cachedNode); - } - - handle.Node = monitoredNode.Node; - handle.MonitoredNode = monitoredNode; - - // create a globally unique identifier. - uint monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter); - - // determine the sampling interval. - double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; - - if (samplingInterval < 0) - { - samplingInterval = publishingInterval; - } - - // ensure minimum sampling interval is not exceeded. - if (itemToCreate.ItemToMonitor.AttributeId == Attributes.Value) - { - BaseVariableState variable = handle.Node as BaseVariableState; - - if (variable != null && samplingInterval < variable.MinimumSamplingInterval) - { - samplingInterval = variable.MinimumSamplingInterval; - } - } - - // put a large upper limit on sampling. - if (samplingInterval == Double.MaxValue) - { - samplingInterval = 365 * 24 * 3600 * 1000.0; - } - - // put an upper limit on queue size. - uint queueSize = itemToCreate.RequestedParameters.QueueSize; - - if (queueSize > MaxQueueSize) - { - queueSize = MaxQueueSize; - } - - // validate the monitoring filter. - Range euRange = null; - MonitoringFilter filterToUse = null; - - ServiceResult error = ValidateMonitoringFilter( - context, - handle, - itemToCreate.ItemToMonitor.AttributeId, - samplingInterval, - queueSize, - parameters.Filter, - out filterToUse, - out euRange, - out filterResult); - - if (ServiceResult.IsBad(error)) - { - return error; - } - - // create the item. - MonitoredItem datachangeItem = new ComMonitoredItem( - Server, - this, - handle, - subscriptionId, - monitoredItemId, - context.OperationContext.Session, - itemToCreate.ItemToMonitor, - diagnosticsMasks, - timestampsToReturn, - itemToCreate.MonitoringMode, - itemToCreate.RequestedParameters.ClientHandle, - filterToUse, - filterToUse, - euRange, - samplingInterval, - queueSize, - itemToCreate.RequestedParameters.DiscardOldest, - 0); - - // report the initial value. - ReadInitialValue(context, handle, datachangeItem); - - // update monitored item list. - monitoredItem = datachangeItem; - - // save the monitored item. - monitoredNode.Add(datachangeItem); - - // report change. - OnMonitoredItemCreated(context, handle, datachangeItem); - - return error; - } - - #endregion - - #region Conversion Functions - /// - /// Converts a value to something the DA server can accept. - /// - /// The source value. - /// The converted value. - /// Any error from the conversion. - public static int LocalToRemoteValue(Variant srcValue, out object dstValue) - { - dstValue = null; - - TypeInfo srcType = srcValue.TypeInfo; - - if (srcType == null) - { - srcType = TypeInfo.Construct(srcValue.Value); - } - - if (srcType.BuiltInType <= BuiltInType.DateTime - || srcType.BuiltInType == BuiltInType.ByteString) // OPC UA specification ver 1.02 compliant. - { - dstValue = srcValue.Value; - return ResultIds.S_OK; - } - - try - { - if (srcType.BuiltInType == BuiltInType.Variant && srcType.ValueRank >= 0) - { - dstValue = TypeInfo.CastArray((Array)srcValue.Value, BuiltInType.Variant, BuiltInType.Null, LocalToRemoteValue); - return ResultIds.S_OK; - } - } - catch (Exception) - { - return ResultIds.E_BADTYPE; - } - - return ResultIds.E_BADTYPE; - } - - /// - /// Converts a DA value to a UA compatible type. - /// - /// The source value. - /// The converted value. - /// Any error from the conversion. - public static int RemoteToLocalValue(object srcValue, out Variant dstValue) - { - object value = RemoteToLocalValue(srcValue, BuiltInType.Null, BuiltInType.Null); - dstValue = new Variant(value); - return ResultIds.S_OK; - } - - /// - /// Converts a UA value to something the DA server will accept. - /// - private static object LocalToRemoteValue(object srcValue, BuiltInType srcType, BuiltInType dstType) - { - if (srcType <= BuiltInType.DateTime) - { - return srcValue; - } - - 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, LocalToRemoteValue); - } - - return LocalToRemoteValue(srcValue, srcType, dstType); - } - - throw new ServiceResultException(StatusCodes.BadTypeMismatch); - } - - /// - /// Converts a value to something the UA client can accept. - /// - private static object RemoteToLocalValue(object srcValue, BuiltInType srcType, BuiltInType dstType) - { - if (typeof(decimal).IsInstanceOfType(srcValue)) - { - return ((decimal)srcValue).ToString(); - } - - if (typeof(decimal[]).IsInstanceOfType(srcValue)) - { - return TypeInfo.CastArray((Array)srcValue, BuiltInType.Null, BuiltInType.String, RemoteToLocalValue); - } - - return srcValue; - } - #endregion - - #region Private Methods - #endregion - - #region Private Fields - private ComDaClientManager m_system; - private ComDaClientConfiguration m_configuration; - private Dictionary m_subscriptionManagers; - private Dictionary m_monitoredItems; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/ComDaDataCallback.cs b/ComIOP/Common/Client/Da/ComDaDataCallback.cs deleted file mode 100644 index a84e33c40..000000000 --- a/ComIOP/Common/Client/Da/ComDaDataCallback.cs +++ /dev/null @@ -1,205 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; -using OpcRcw.Da; - -namespace Opc.Ua.Com.Client -{ - /// - /// A class that implements the IOPCDataCallback interface. - /// - internal class ComDaDataCallback : OpcRcw.Da.IOPCDataCallback, IDisposable - { - #region Constructors - /// - /// Initializes the object with the containing subscription object. - /// - public ComDaDataCallback(ComDaGroup group) - { - // save group. - m_group = group; - - // create connection point. - m_connectionPoint = new ConnectionPoint(group.Unknown, typeof(OpcRcw.Da.IOPCDataCallback).GUID); - - // advise. - m_connectionPoint.Advise(this); - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (m_connectionPoint != null) - { - if (disposing) - { - m_connectionPoint.Dispose(); - m_connectionPoint = null; - } - } - } - #endregion - - #region Public Properties - /// - /// Whether the callback is connected. - /// - public bool Connected - { - get - { - return m_connectionPoint != null; - } - } - #endregion - - #region IOPCDataCallback Members - /// - /// Called when a data changed event is received. - /// - public void OnDataChange( - int dwTransid, - int hGroup, - int hrMasterquality, - int hrMastererror, - int dwCount, - int[] phClientItems, - object[] pvValues, - short[] pwQualities, - System.Runtime.InteropServices.ComTypes.FILETIME[] pftTimeStamps, - int[] pErrors) - { - try - { - // unmarshal item values. - DaValue[] values = ComDaGroup.GetItemValues( - dwCount, - pvValues, - pwQualities, - pftTimeStamps, - pErrors); - - // invoke the callback. - m_group.OnDataChange(phClientItems, values); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnDataChange callback."); - } - } - - /// - /// Called when an asynchronous read operation completes. - /// - public void OnReadComplete( - int dwTransid, - int hGroup, - int hrMasterquality, - int hrMastererror, - int dwCount, - int[] phClientItems, - object[] pvValues, - short[] pwQualities, - System.Runtime.InteropServices.ComTypes.FILETIME[] pftTimeStamps, - int[] pErrors) - { - try - { - // unmarshal item values. - DaValue[] values = ComDaGroup.GetItemValues( - dwCount, - pvValues, - pwQualities, - pftTimeStamps, - pErrors); - - // invoke the callback. - m_group.OnReadComplete(dwTransid, phClientItems, values); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnReadComplete callback."); - } - } - - /// - /// Called when an asynchronous write operation completes. - /// - public void OnWriteComplete( - int dwTransid, - int hGroup, - int hrMastererror, - int dwCount, - int[] phClientItems, - int[] pErrors) - { - try - { - m_group.OnWriteComplete(dwTransid, phClientItems, pErrors); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnWriteComplete callback."); - } - } - - /// - /// Called when an asynchronous operation is cancelled. - /// - public void OnCancelComplete( - int dwTransid, - int hGroup) - { - } - #endregion - - #region Private Members - private ComDaGroup m_group; - private ConnectionPoint m_connectionPoint; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/ComDaGroup.cs b/ComIOP/Common/Client/Da/ComDaGroup.cs deleted file mode 100644 index 43e3a8874..000000000 --- a/ComIOP/Common/Client/Da/ComDaGroup.cs +++ /dev/null @@ -1,1079 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Globalization; -using System.Security.Principal; -using System.Threading; -using System.Runtime.InteropServices; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Da; - -namespace Opc.Ua.Com.Client -{ - /// - /// A wrapper for COM-DA group. - /// - internal class ComDaGroup : ComObject - { - #region Constructor - /// - /// Creates an empty group. - /// - /// The server that the group belongs to. - /// if set to true if the group will received callbacks. - public ComDaGroup(ComDaClient server, bool callbacksRequired) - { - m_server = server; - m_clientHandle = Utils.IncrementIdentifier(ref m_groupCounter); - m_serverHandle = 0; - m_items = new List(); - - if (callbacksRequired) - { - m_monitoredItems = new Dictionary(); - } - - // Utils.Trace("GROUP {0}", m_clientHandle); - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - Utils.SilentDispose(m_callback); - m_callback = null; - } - - base.Dispose(disposing); - } - - /// - /// Releases all references to the server. - /// - protected override void ReleaseServer() - { - Utils.SilentDispose(m_callback); - m_callback = null; - base.ReleaseServer(); - } - #endregion - - #region Public Properties - /// - /// Gets the group's client handle. - /// - /// The client handle. - public int ClientHandle - { - get { return m_clientHandle; } - } - - /// - /// Gets the group's server handle. - /// - /// The server handle. - public int ServerHandle - { - get { return m_serverHandle; } - } - - /// - /// The requested sampling interval for the group. - /// - public int SamplingInterval - { - get { return m_samplingInterval; } - } - - /// - /// The actual sampling interval for the group. - /// - public int ActualSamplingInterval - { - get { return m_actualSamplingInterval; } - } - - /// - /// The deadband applied to the group. - /// - public float Deadband - { - get { return m_deadband; } - } - #endregion - - /// - /// Sets the monitored items associated with the item. - /// - /// The item. - /// The monitored items. - public void SetMonitoredItems(GroupItem item, MonitoredItem[] monitoredItems) - { - // check if callbacks are enabled. - if (item == null || m_monitoredItems == null) - { - return; - } - - // save the monitored items. - lock (m_monitoredItems) - { - DataChangeInfo info = null; - - if (!m_monitoredItems.TryGetValue(item.ClientHandle, out info)) - { - m_monitoredItems[item.ClientHandle] = info = new DataChangeInfo(); - } - - info.MonitoredItems = monitoredItems; - - // resend the last cached value. - if (info.LastError != null || info.LastValue != null) - { - for (int ii = 0; ii < monitoredItems.Length; ii++) - { - monitoredItems[ii].QueueValue(info.LastValue, info.LastError); - } - } - } - } - - /// - /// Stores the information used to report data changes. - /// - private class DataChangeInfo - { - public MonitoredItem[] MonitoredItems; - public DataValue LastValue; - public ServiceResult LastError; - } - - /// - /// Called when a data change event arrives. - /// - /// The client handles. - /// The values. - internal void OnDataChange(int[] clientHandles, DaValue[] values) - { - // check if callbacks are enabled. - if (m_monitoredItems == null) - { - return; - } - - // lookup client handle a report change directly to monitored item. - lock (m_monitoredItems) - { - for (int ii = 0; ii < clientHandles.Length; ii++) - { - DataChangeInfo info = null; - - if (!m_monitoredItems.TryGetValue(clientHandles[ii], out info)) - { - continue; - } - - MonitoredItem[] monitoredItems = info.MonitoredItems; - - // convert the value to a UA value. - info.LastValue = new DataValue(); - info.LastError = ReadRequest.GetItemValue(values[ii], info.LastValue, DiagnosticsMasks.All); - info.LastValue.ServerTimestamp = DateTime.UtcNow; - - // queue the values. - for (int jj = 0; jj < monitoredItems.Length; jj++) - { - - if (info.LastValue.Value != null - && info.LastValue.Value.GetType().IsArray - && monitoredItems[jj].IndexRange.Count != info.LastValue.Value.GetType().GetArrayRank() - && StatusCode.IsBad(info.LastValue.StatusCode)) - { - info.LastValue.StatusCode = StatusCodes.BadIndexRangeNoData; - } - - monitoredItems[jj].QueueValue(info.LastValue, info.LastError); - } - } - } - } - - /// - /// Called when a asynchronous read completes. - /// - /// The request id. - /// The client handles. - /// The values. - internal void OnReadComplete(int requestId, int[] clientHandles, DaValue[] values) - { - } - - /// - /// Called when a asynchronous write completes. - /// - /// The request id. - /// The client handles. - /// The errors. - internal void OnWriteComplete(int requestId, int[] clientHandles, int[] errors) - { - } - - /// - /// Creates the group on the server if not already created. - /// - public void Create() - { - // Utils.Trace("CREATE"); - - if (Unknown != null) - { - return; - } - - int serverHandle = 0; - int actualSamplingInterval = 0; - - object unknown = m_server.CreateGroup( - m_clientHandle, - m_samplingInterval, - m_deadband, - out serverHandle, - out actualSamplingInterval); - - Unknown = unknown; - m_serverHandle = serverHandle; - m_actualSamplingInterval = actualSamplingInterval; - - // Utils.Trace( - // "Group {0}/{1} Created({5}) {2}/{3}ms {4}%", - // m_clientHandle, - // m_serverHandle, - // m_samplingInterval, - // m_actualSamplingInterval, - // m_deadband, - // m_items.Count); - - // set up data change callback. - if (m_monitoredItems != null) - { - try - { - m_callback = new ComDaDataCallback(this); - } - catch (Exception e) - { - Utils.Trace("Could not establish IOPCDataCallback.", e); - } - } - } - - /// - /// Deletes the group on the server if it has been created. - /// - public void Delete() - { - // Utils.Trace("DELETE"); - - if (Unknown == null) - { - return; - } - - // Utils.Trace( - // "Group {0}/{1} Deleted({5}) {2}/{3}ms {4}%", - // m_clientHandle, - // m_serverHandle, - // m_samplingInterval, - // m_actualSamplingInterval, - // m_deadband, - // m_items.Count); - - m_server.RemoveGroup(m_serverHandle); - ReleaseServer(); - } - - /// - /// Modifies the group. - /// - /// The error. S_OK on success. - public int ModifyGroup() - { - m_actualSamplingInterval = 0; - - int localeId = m_server.LocaleId; - - GCHandle hSamplingInterval = GCHandle.Alloc(m_samplingInterval, GCHandleType.Pinned); - GCHandle hDeadband = GCHandle.Alloc(m_deadband, GCHandleType.Pinned); - - string methodName = "IOPCGroupStateMgt.SetState"; - - try - { - IOPCGroupStateMgt server = BeginComCall(methodName, true); - - server.SetState( - hSamplingInterval.AddrOfPinnedObject(), - out m_actualSamplingInterval, - IntPtr.Zero, - IntPtr.Zero, - hDeadband.AddrOfPinnedObject(), - IntPtr.Zero, - IntPtr.Zero); - - /* - Utils.Trace( - "Group {0} Modified({4}) {1}/{2}ms {3}%", - m_clientHandle, - m_samplingInterval, - m_actualSamplingInterval, - m_deadband, - m_items.Count); - */ - - return ResultIds.S_OK; - } - catch (Exception e) - { - ComUtils.TraceComError(e, methodName); - return Marshal.GetHRForException(e); - } - finally - { - EndComCall(methodName); - hSamplingInterval.Free(); - hDeadband.Free(); - } - } - - /// - /// Creates the item. - /// - /// The item id. - /// The sampling interval. - /// The deadband. - /// if set to true [active]. - /// - /// The item that was added to the group. Null if the item could not be added. - /// - public GroupItem CreateItem(string itemId, int samplingInterval, float deadband, bool active) - { - // set the group parameters if this is the first item. - if (m_items.Count == 0) - { - m_samplingInterval = samplingInterval; - m_deadband = deadband; - } - - // check if the item can be added to the group. - if (m_samplingInterval != samplingInterval || m_deadband != deadband) - { - return null; - } - - // create the item. - GroupItem item = new GroupItem(); - - item.ItemId = itemId; - item.ClientHandle = Utils.IncrementIdentifier(ref m_itemCounter); - item.ServerHandle = 0; - item.Active = active; - item.ActiveChanged = false; - item.Deleted = false; - item.Created = false; - item.ErrorId = 0; - - lock (Lock) - { - m_items.Add(item); - } - - return item; - } - - /// - /// Modifies the item. - /// - /// The item. - /// The sampling interval. - /// The deadband. - /// if set to true [active]. - /// True if the item is in the group. - public bool ModifyItem(GroupItem item, int samplingInterval, float deadband, bool active) - { - // check if the item can be added to the group. - if (m_samplingInterval != samplingInterval || m_deadband != deadband) - { - // check if the item needs to be removed from the group. - if (m_items.Count > 1) - { - item.Deleted = true; - return false; - } - - // update active state. - item.ActiveChanged = active != item.Active; - item.Active = active; - - // update the group parameters. - m_samplingInterval = samplingInterval; - m_deadband = deadband; - m_updateRequired = true; - - return true; - } - - // undelete the item. - item.Deleted = false; - - // update active state. - item.ActiveChanged = active != item.Active; - item.Active = active; - - // nothing to do - the group matches the item. - return true; - } - - /// - /// Removes the item from the group. - /// - /// The item. - /// True if the item exists. - public bool RemoveItem(GroupItem item) - { - // add the item if it does not exist. - if (item == null) - { - return false; - } - - // flag the item as deleted. - item.Deleted = true; - return true; - } - - /// - /// Adds all items to the group that have not already been added. - /// - public void AddItems() - { - // count the number of items to add. - List itemsToAdd = new List(); - - 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(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); - */ - } - - /// - /// Sets the active state for a set of items in a group. - /// - public void ActivateItems(bool active) - { - // count the number of items to activate. - List itemsToActivate = new List(); - - 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(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); - */ - } - - /// - /// Removes the items from the group that have been marked as deleted. - /// - public void RemoveItems() - { - // count the number of items to remove. - List itemsToRemove = new List(); - - lock (Lock) - { - List itemsToKeep = new List(); - - 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(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); - */ - } - - /// - /// Reads the values for a set of items. - /// - public DaValue[] SyncRead(int[] serverHandles, int count) - { - // initialize output parameters. - IntPtr pValues = IntPtr.Zero; - IntPtr pErrors = IntPtr.Zero; - - if (count > 0) - { - string methodName = "IOPCSyncIO.Read"; - - try - { - IOPCSyncIO server = BeginComCall(methodName, true); - - server.Read( - OPCDATASOURCE.OPC_DS_DEVICE, - count, - serverHandles, - out pValues, - out pErrors); - } - catch (Exception e) - { - ComUtils.TraceComError(e, methodName); - return null; - } - finally - { - EndComCall(methodName); - } - } - - // unmarshal output parameters. - DaValue[] values = GetItemValues(ref pValues, count, true); - - int[] errors = ComUtils.GetInt32s(ref pErrors, count, true); - - // save error codes. - for (int ii = 0; ii < count; ii++) - { - values[ii].Error = errors[ii]; - } - - return values; - } - - /// - /// Writes the values for a set of items. - /// - public int[] SyncWrite(int[] serverHandles, object[] values, int count) - { - // initialize output parameters. - IntPtr pErrors = IntPtr.Zero; - - string methodName = "IOPCSyncIO.Write"; - - try - { - IOPCSyncIO server = BeginComCall(methodName, true); - - server.Write( - count, - serverHandles, - values, - out pErrors); - } - catch (Exception e) - { - ComUtils.TraceComError(e, methodName); - return null; - } - finally - { - EndComCall(methodName); - } - - // unmarshal output parameters. - return ComUtils.GetInt32s(ref pErrors, count, true); - } - - #region Public Members - /// - /// Applys any changes to the group. - /// - /// True if the group contains a valid item. - public bool ApplyChanges() - { - // create the group if it does not already exist. - if (Unknown == null) - { - Create(); - } - - if (m_updateRequired) - { - ModifyGroup(); - m_updateRequired = false; - } - - RemoveItems(); - AddItems(); - ActivateItems(true); - ActivateItems(false); - - // check if at least one valid item. - lock (Lock) - { - List clientHandles = new List(); - List values = new List(); - - bool result = false; - - for (int ii = 0; ii < m_items.Count; ii++) - { - if (m_items[ii].Created) - { - result = true; - } - - if (m_items[ii].ErrorId < 0) - { - if (clientHandles == null) - { - clientHandles = new List(); - values = new List(); - } - - clientHandles.Add(m_items[ii].ClientHandle); - values.Add(new DaValue() { Error = m_items[ii].ErrorId, Timestamp = DateTime.UtcNow }); - } - - if (clientHandles != null) - { - OnDataChange(clientHandles.ToArray(), values.ToArray()); - } - } - - return result; - } - } - #endregion - - #region Private Methods - /// - /// Unmarshals and deallocates a OPCITEMRESULT structures. - /// - internal static int[] GetItemResults(ref IntPtr pInput, int count, bool deallocate) - { - int[] output = null; - - if (pInput != IntPtr.Zero && count > 0) - { - output = new int[count]; - - IntPtr pos = pInput; - - for (int ii = 0; ii < count; ii++) - { - OpcRcw.Da.OPCITEMRESULT result = (OpcRcw.Da.OPCITEMRESULT)Marshal.PtrToStructure(pos, typeof(OpcRcw.Da.OPCITEMRESULT)); - - output[ii] = result.hServer; - - if (deallocate) - { - if (result.pBlob != IntPtr.Zero) - { - Marshal.FreeCoTaskMem(result.pBlob); - result.pBlob = IntPtr.Zero; - result.dwBlobSize = 0; - } - - Marshal.DestroyStructure(pos, typeof(OpcRcw.Da.OPCITEMRESULT)); - } - - pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMRESULT))); - } - - if (deallocate) - { - Marshal.FreeCoTaskMem(pInput); - pInput = IntPtr.Zero; - } - } - - return output; - } - - /// - /// Unmarshals and deallocates a OPCITEMSTATE structures. - /// - internal static DaValue[] GetItemValues(ref IntPtr pInput, int count, bool deallocate) - { - DaValue[] output = null; - - if (pInput != IntPtr.Zero && count > 0) - { - output = new DaValue[count]; - - IntPtr pos = pInput; - - for (int ii = 0; ii < count; ii++) - { - OpcRcw.Da.OPCITEMSTATE result = (OpcRcw.Da.OPCITEMSTATE)Marshal.PtrToStructure(pos, typeof(OpcRcw.Da.OPCITEMSTATE)); - - DaValue value = new DaValue(); - - value.Value = ComUtils.ProcessComValue(result.vDataValue); - value.Quality = result.wQuality; - value.Timestamp = ComUtils.GetDateTime(result.ftTimeStamp); - - output[ii] = value; - - if (deallocate) - { - Marshal.DestroyStructure(pos, typeof(OpcRcw.Da.OPCITEMSTATE)); - } - - pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMSTATE))); - } - - if (deallocate) - { - Marshal.FreeCoTaskMem(pInput); - pInput = IntPtr.Zero; - } - } - - return output; - } - - /// - /// Creates an array of item value result objects from the callback data. - /// - internal static DaValue[] GetItemValues( - int dwCount, - object[] pvValues, - short[] pwQualities, - System.Runtime.InteropServices.ComTypes.FILETIME[] pftTimeStamps, - int[] pErrors) - { - // contruct the item value results. - DaValue[] values = new DaValue[dwCount]; - - for (int ii = 0; ii < dwCount; ii++) - { - DaValue value = values[ii] = new DaValue(); - - value.Error = pErrors[ii]; - - if (pErrors[ii] >= 0) - { - value.Value = ComUtils.ProcessComValue(pvValues[ii]); - value.Quality = pwQualities[ii]; - value.Timestamp = ComUtils.GetDateTime(pftTimeStamps[ii]); - } - } - - // return results - return values; - } - #endregion - - #region Private Fields - private static int m_groupCounter = 0; - private static int m_itemCounter = 0; - private ComDaClient m_server; - private int m_clientHandle; - private int m_serverHandle; - private int m_samplingInterval; - private int m_actualSamplingInterval; - private float m_deadband; - private bool m_updateRequired; - private List m_items; - private ComDaDataCallback m_callback; - private Dictionary m_monitoredItems; - #endregion - } - - #region GroupItem Class - /// - /// An item that belongs to group. - /// - internal class GroupItem - { - public string ItemId; - public int ServerHandle; - public int ClientHandle; - public int ErrorId; - public bool Created; - public bool Deleted; - public bool Active; - public bool ActiveChanged; - } - #endregion -} diff --git a/ComIOP/Common/Client/Da/ComMonitoredItem.cs b/ComIOP/Common/Client/Da/ComMonitoredItem.cs deleted file mode 100644 index 3e77a4794..000000000 --- a/ComIOP/Common/Client/Da/ComMonitoredItem.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Opc.Ua.Server; - - -namespace Opc.Ua.Com.Client -{ - /// - /// A handle that describes how to access a node/attribute via an i/o manager. - /// - public class ComMonitoredItem : MonitoredItem - { - #region Constructors - /// - /// Initializes the object with its node type. - /// - public ComMonitoredItem( - IServerInternal server, - INodeManager nodeManager, - object mangerHandle, - uint subscriptionId, - uint id, - Session session, - ReadValueId itemToMonitor, - DiagnosticsMasks diagnosticsMasks, - TimestampsToReturn timestampsToReturn, - MonitoringMode monitoringMode, - uint clientHandle, - MonitoringFilter originalFilter, - MonitoringFilter filterToUse, - Range range, - double samplingInterval, - uint queueSize, - bool discardOldest, - double sourceSamplingInterval) - : base(server, - nodeManager, - mangerHandle, - subscriptionId, - id, - itemToMonitor, - diagnosticsMasks, - timestampsToReturn, - monitoringMode, - clientHandle, - originalFilter, - filterToUse, - range, - samplingInterval, - queueSize, - discardOldest, - sourceSamplingInterval) - { - } - #endregion - - #region Private Methods - /// - /// Publishes a single data change notifications. - /// - protected override bool Publish(OperationContext context, - Queue notifications, - Queue diagnostics, - DataValue value, - ServiceResult error) - { - bool result = base.Publish(context, notifications, diagnostics, value, error); - return result; - } - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/DaBranchState.cs b/ComIOP/Common/Client/Da/DaBranchState.cs deleted file mode 100644 index 9d1967757..000000000 --- a/ComIOP/Common/Client/Da/DaBranchState.cs +++ /dev/null @@ -1,164 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// A object which maps a segment to a UA object. - /// - public partial class DaBranchState : FolderState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The element. - /// Index of the namespace. - public DaBranchState( - ISystemContext context, - DaElement element, - ushort namespaceIndex) - : - base(null) - { - this.TypeDefinitionId = Opc.Ua.ObjectTypeIds.FolderType; - this.Description = null; - this.WriteMask = 0; - this.UserWriteMask = 0; - this.EventNotifier = EventNotifiers.None; - - if (element != null) - { - Initialize(context, element, namespaceIndex); - } - } - #endregion - - #region Public Interface - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get - { - if (m_element != null) - { - return m_element.ItemId; - } - - return null; - } - } - - /// - /// Gets the element. - /// - /// The element. - public DaElement Element - { - get { return m_element; } - } - - /// - /// Initializes the node from the element. - /// - /// The context. - /// The element. - /// Index of the namespace. - public void Initialize(ISystemContext context, DaElement element, ushort namespaceIndex) - { - m_element = element; - - if (element == null) - { - return; - } - - this.NodeId = DaModelUtils.ConstructIdForDaElement(element.ItemId, -1, namespaceIndex); - this.BrowseName = new QualifiedName(element.Name, namespaceIndex); - this.DisplayName = new LocalizedText(element.Name); - } - - /// - /// Creates a browser that finds the references to the branch. - /// - /// The system context to use. - /// The view which may restrict the set of references/nodes found. - /// The type of references being followed. - /// Whether subtypes of the reference type are followed. - /// Which way the references are being followed. - /// The browse name of a specific target (used when translating browse paths). - /// Any additional references that should be included. - /// If true the browser should not making blocking calls to external systems. - /// The browse object (must be disposed). - public override INodeBrowser CreateBrowser( - ISystemContext context, - ViewDescription view, - NodeId referenceType, - bool includeSubtypes, - BrowseDirection browseDirection, - QualifiedName browseName, - IEnumerable additionalReferences, - bool internalOnly) - { - NodeBrowser browser = new DaElementBrowser( - context, - view, - referenceType, - includeSubtypes, - browseDirection, - browseName, - additionalReferences, - internalOnly, - this.ItemId, - this.NodeId.NamespaceIndex); - - PopulateBrowser(context, browser); - - return browser; - } - #endregion - - #region Private Fields - private DaElement m_element; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/DaElement.cs b/ComIOP/Common/Client/Da/DaElement.cs deleted file mode 100644 index abdd89cdf..000000000 --- a/ComIOP/Common/Client/Da/DaElement.cs +++ /dev/null @@ -1,324 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores information an element in the DA server address space. - /// - public class DaElement - { - #region Public Members - /// - /// Initializes a new instance of the class. - /// - public DaElement() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Gets or sets the parent item id. - /// - /// The parent item id. - public string ParentId - { - get { return m_parentId; } - set { m_parentId = value; } - } - - /// - /// Gets or sets the type of the element. - /// - /// The type of the element. - public DaElementType ElementType - { - get { return m_elementType; } - set { m_elementType = value; } - } - - /// - /// Gets or sets the properties available for the element. - /// - /// The available properties. - public DaProperty[] Properties - { - get { return m_properties; } - set { m_properties = value; } - } - - /// - /// Gets or sets the COM data type for the value. - /// - /// The COM data type for the value. - public short DataType - { - get { return m_dataType; } - set { m_dataType = value; } - } - - /// - /// Gets or sets the access rights for the item. - /// - /// The access rights. - public int AccessRights - { - get { return m_accessRights; } - set { m_accessRights = value; } - } - - /// - /// Gets or sets the scan rate. - /// - /// The scan rate. - public float ScanRate - { - get { return m_scanRate; } - set { m_scanRate = value; } - } - - /// - /// Gets or sets the description. - /// - /// The description. - public string Description - { - get { return m_description; } - set { m_description = value; } - } - - /// - /// Gets or sets the engineering units. - /// - /// The engineering units. - public string EngineeringUnits - { - get { return m_engineeringUnits; } - set { m_engineeringUnits = value; } - } - - /// - /// Gets or sets EUType forthe item. - /// - /// The EUType for the item. - public int EuType - { - get { return m_euType; } - set { m_euType = value; } - } - - /// - /// Gets or sets the EU information for the item. - /// - /// The EU information for the item. - public string[] EuInfo - { - get { return m_euInfo; } - set { m_euInfo = value; } - } - - /// - /// Gets or sets the high EU value. - /// - /// The high EU value. - public double HighEU - { - get { return m_highEU; } - set { m_highEU = value; } - } - - /// - /// Gets or sets the low EU value. - /// - /// The low EU value. - public double LowEU - { - get { return m_lowEU; } - set { m_lowEU = value; } - } - - /// - /// Gets or sets the high IR value. - /// - /// The high IR value. - public double HighIR - { - get { return m_highIR; } - set { m_highIR = value; } - } - - /// - /// Gets or sets the low IR value. - /// - /// The low IR value. - public double LowIR - { - get { return m_lowIR; } - set { m_lowIR = value; } - } - - /// - /// Gets or sets the open label. - /// - /// The open label. - public string OpenLabel - { - get { return m_openLabel; } - set { m_openLabel = value; } - } - - /// - /// Gets or sets the close label. - /// - /// The close label. - public string CloseLabel - { - get { return m_closeLabel; } - set { m_closeLabel = value; } - } - - /// - /// Gets or sets the time zone for the item. - /// - /// The time zone. - public int? TimeZone - { - get { return m_timeZone; } - set { m_timeZone = value; } - } - - /// - /// Returns true if the element supports the specified property. - /// - /// The property id. - /// Rrue if the element supports the specified property. - public bool SupportsProperty(int propertyId) - { - if (m_properties != null) - { - for (int ii = 0; ii < m_properties.Length; ii++) - { - if (propertyId == m_properties[ii].PropertyId) - { - return true; - } - } - } - - return false; - } - #endregion - - #region Private Methods - #endregion - - #region Private Fields - private string m_itemId; - private string m_name; - private string m_parentId; - private DaElementType m_elementType; - private DaProperty[] m_properties; - private short m_dataType; - private int m_accessRights; - private float m_scanRate; - private string m_description; - private string m_engineeringUnits; - private int m_euType; - private string[] m_euInfo; - private double m_highEU; - private double m_lowEU; - private double m_highIR; - private double m_lowIR; - private string m_openLabel; - private string m_closeLabel; - private int? m_timeZone; - #endregion - } - - /// - /// The possible type of elements. - /// - public enum DaElementType - { - /// - /// Unknown element type. - /// - Undefined = 0, - - /// - /// A branch - /// - Branch = 1, - - /// - /// An item. - /// - Item = 2, - - /// - /// An analog item. - /// - AnalogItem = 3, - - /// - /// An enumerated item. - /// - EnumeratedItem = 4, - - /// - /// An digital item. - /// - DigitalItem = 5 - } -} diff --git a/ComIOP/Common/Client/Da/DaElementBrowser.cs b/ComIOP/Common/Client/Da/DaElementBrowser.cs deleted file mode 100644 index f499f4da2..000000000 --- a/ComIOP/Common/Client/Da/DaElementBrowser.cs +++ /dev/null @@ -1,361 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// Browses the children of a segment. - /// - public class DaElementBrowser : NodeBrowser - { - #region Constructors - /// - /// Creates a new browser object with a set of filters. - /// - /// The system context to use. - /// The view which may restrict the set of references/nodes found. - /// The type of references being followed. - /// Whether subtypes of the reference type are followed. - /// Which way the references are being followed. - /// The browse name of a specific target (used when translating browse paths). - /// Any additional references that should be included. - /// If true the browser should not making blocking calls to external systems. - /// The item id. - /// Index of the namespace. - public DaElementBrowser( - ISystemContext context, - ViewDescription view, - NodeId referenceType, - bool includeSubtypes, - BrowseDirection browseDirection, - QualifiedName browseName, - IEnumerable additionalReferences, - bool internalOnly, - string itemId, - ushort namespaceIndex) - : - base( - context, - view, - referenceType, - includeSubtypes, - browseDirection, - browseName, - additionalReferences, - internalOnly) - { - m_itemId = itemId; - m_namespaceIndex = namespaceIndex; - m_stage = Stage.Begin; - } - #endregion - - #region Overridden Methods - /// - /// An overrideable version of the Dispose. - /// - /// True if being called explicitly - protected override void Dispose(bool disposing) - { - if (disposing) - { - Utils.SilentDispose(m_browser); - m_browser = null; - } - - base.Dispose(disposing); - } - - /// - /// Returns the next reference. - /// - /// The next reference that meets the browse criteria. - public override IReference Next() - { - lock (DataLock) - { - IReference reference = null; - - // enumerate pre-defined references. - // always call first to ensure any pushed-back references are returned first. - reference = base.Next(); - - if (reference != null) - { - return reference; - } - - // don't start browsing huge number of references when only internal references are requested. - if (InternalOnly) - { - return null; - } - - // fetch references from the server. - do - { - // fetch next reference. - reference = NextChild(); - - if (reference != null) - { - return reference; - } - - // go to the next stage. - NextStage(); - } - while (m_stage != Stage.Done); - - // all done. - return null; - } - } - #endregion - - #region Private Methods - /// - /// Returns the next child. - /// - private IReference NextChild() - { - // check if a specific browse name is requested. - if (QualifiedName.IsNull(base.BrowseName)) - { - return NextChild(m_stage); - } - - // keep fetching references until a matching browse name if found. - NodeStateReference reference = null; - - do - { - reference = NextChild(m_stage); - - if (reference != null) - { - // need to let the caller look up the browse name. - if (reference.Target == null) - { - return reference; - } - - // check for browse name match. - if (reference.Target.BrowseName == base.BrowseName) - { - return reference; - } - } - } - while (reference != null); - - // no match - need to go onto the next stage. - return null; - } - - /// - /// Returns the next child. - /// - private NodeStateReference NextChild(Stage stage) - { - ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; - ComDaClient client = system.SelectClient((ServerSystemContext)SystemContext, false); - - DaElement element = null; - - if (stage == Stage.Children) - { - if (m_browser == null) - { - return null; - } - - element = m_browser.Next(); - - if (element == null) - { - return null; - } - - // construct the node. - NodeState node = DaModelUtils.ConstructElement(SystemContext, element, m_namespaceIndex); - - // return the reference. - return new NodeStateReference(ReferenceTypeIds.Organizes, false, node); - } - - if (stage == Stage.Properties) - { - if (m_properties == null) - { - return null; - } - - for (int ii = m_position; ii < m_properties.Length; ii++) - { - if (m_properties[ii].PropertyId <= PropertyIds.TimeZone) - { - continue; - } - - m_position = ii+1; - - // construct the node. - NodeState node = DaModelUtils.ConstructProperty(SystemContext, m_itemId, m_properties[ii], m_namespaceIndex); - - // return the reference. - return new NodeStateReference(ReferenceTypeIds.HasProperty, false, node); - } - - // all done. - return null; - } - - if (stage == Stage.Parents) - { - if (m_parentId != null) - { - NodeId parentId = DaModelUtils.ConstructIdForDaElement(m_parentId, -1, m_namespaceIndex); - m_parentId = null; - return new NodeStateReference(ReferenceTypeIds.Organizes, true, parentId); - } - } - - return null; - } - - /// - /// Initializes the next stage of browsing. - /// - private void NextStage() - { - ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; - ComDaClient client = system.SelectClient((ServerSystemContext)SystemContext, false); - - // determine which stage is next based on the reference types requested. - for (Stage next = m_stage+1; next <= Stage.Done; next++) - { - if (next == Stage.Children) - { - if (IsRequired(ReferenceTypeIds.Organizes, false)) - { - m_stage = next; - break; - } - } - - else if (next == Stage.Properties) - { - if (IsRequired(ReferenceTypeIds.HasProperty, false)) - { - m_stage = next; - break; - } - } - - else if (next == Stage.Parents) - { - if (IsRequired(ReferenceTypeIds.Organizes, true)) - { - m_stage = next; - break; - } - } - - else if (next == Stage.Done) - { - m_stage = next; - break; - } - } - - m_position = 0; - - // start enumerating branches. - if (m_stage == Stage.Children) - { - m_browser = client.CreateBrowser(m_itemId); - return; - } - - // start enumerating properties. - if (m_stage == Stage.Properties) - { - m_properties = client.ReadAvailableProperties(m_itemId, true); - m_position = 0; - return; - } - - // start enumerating parents. - if (m_stage == Stage.Parents) - { - m_parentId = client.FindElementParentId(m_itemId); - return; - } - - // all done. - } - - #endregion - - #region Stage Enumeration - /// - /// The stages available in a browse operation. - /// - private enum Stage - { - Begin, - Children, - Properties, - Parents, - Done - } - #endregion - - #region Private Fields - private Stage m_stage; - private string m_itemId; - private ushort m_namespaceIndex; - private DaProperty[] m_properties; - private int m_position; - private string m_parentId; - private IDaElementBrowser m_browser; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/DaItemState.cs b/ComIOP/Common/Client/Da/DaItemState.cs deleted file mode 100644 index b91bf7e8e..000000000 --- a/ComIOP/Common/Client/Da/DaItemState.cs +++ /dev/null @@ -1,281 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// A object which maps a COM DA item to a UA variable. - /// - public partial class DaItemState : BaseDataVariableState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The element. - /// Index of the namespace. - public DaItemState( - ISystemContext context, - DaElement element, - ushort namespaceIndex) - : - base(null) - { - this.TypeDefinitionId = Opc.Ua.VariableTypeIds.DataItemType; - this.Description = null; - this.WriteMask = 0; - this.UserWriteMask = 0; - - if (element != null) - { - Initialize(context, element, namespaceIndex); - } - } - #endregion - - #region Public Interface - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get - { - if (m_element != null) - { - return m_element.ItemId; - } - - return null; - } - } - - /// - /// Gets the element. - /// - /// The element. - public DaElement Element - { - get { return m_element; } - } - - /// - /// Initializes the node from the element. - /// - /// The context. - /// The element. - /// Index of the namespace. - public void Initialize(ISystemContext context, DaElement element, ushort namespaceIndex) - { - m_element = element; - - if (element == null) - { - return; - } - - this.NodeId = DaModelUtils.ConstructIdForDaElement(element.ItemId, -1, namespaceIndex); - this.BrowseName = new QualifiedName(element.Name, namespaceIndex); - this.DisplayName = new LocalizedText(element.Name); - - // check if TimeZone is supported. - if (element.TimeZone != null) - { - PropertyState property = this.AddProperty(Opc.Ua.BrowseNames.LocalTime, DataTypeIds.TimeZoneDataType, ValueRanks.Scalar); - property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); - property.Value = new Range(element.HighIR, element.LowIR); - } - - // set the TypeDefinition based on the ElementType. - switch (element.ElementType) - { - case DaElementType.AnalogItem: - { - this.TypeDefinitionId = Opc.Ua.VariableTypeIds.AnalogItemType; - - // EURange is always present. - PropertyState property = this.AddProperty(Opc.Ua.BrowseNames.EURange, DataTypeIds.Range, ValueRanks.Scalar); - property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); - property.Value = new Range(element.HighEU, element.LowEU); - - // check if InstrumentRange is supported. - if (element.HighIR != 0 || element.LowIR != 0) - { - property = this.AddProperty(Opc.Ua.BrowseNames.InstrumentRange, DataTypeIds.Range, ValueRanks.Scalar); - property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); - property.Value = new Range(element.HighIR, element.LowIR); - } - - // check if EngineeringUnits is supported. - if (element.EngineeringUnits != null) - { - property = this.AddProperty(Opc.Ua.BrowseNames.EngineeringUnits, DataTypeIds.EUInformation, ValueRanks.Scalar); - property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); - - // use the server's namespace uri to qualify the engineering units. - string namespaceUri = context.NamespaceUris.GetString(namespaceIndex); - property.Value = new EUInformation(element.EngineeringUnits, namespaceUri); - } - - break; - } - - case DaElementType.DigitalItem: - { - this.TypeDefinitionId = Opc.Ua.VariableTypeIds.TwoStateDiscreteType; - - // check if CloseLabel is supported. - if (element.CloseLabel != null) - { - PropertyState property = this.AddProperty(Opc.Ua.BrowseNames.TrueState, DataTypeIds.LocalizedText, ValueRanks.Scalar); - property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); - property.Value = element.CloseLabel; - } - - // check if OpenLabel is supported. - if (element.OpenLabel != null) - { - PropertyState property = this.AddProperty(Opc.Ua.BrowseNames.FalseState, DataTypeIds.LocalizedText, ValueRanks.Scalar); - property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); - property.Value = element.OpenLabel; - } - - break; - } - - case DaElementType.EnumeratedItem: - { - this.TypeDefinitionId = Opc.Ua.VariableTypeIds.MultiStateDiscreteType; - - // check if EuInfo is supported. - if (element.EuInfo != null) - { - PropertyState property = this.AddProperty(Opc.Ua.BrowseNames.EnumStrings, DataTypeIds.LocalizedText, ValueRanks.OneDimension); - property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); - - LocalizedText[] strings = new LocalizedText[element.EuInfo.Length]; - - for (int ii = 0; ii < strings.Length; ii++) - { - strings[ii] = element.EuInfo[ii]; - } - - property.Value = strings; - } - - break; - } - } - - if (element.Description != null) - { - this.Description = element.Description; - } - - this.Value = null; - this.StatusCode = StatusCodes.BadWaitingForInitialData; - this.Timestamp = DateTime.UtcNow; - - bool isArray = false; - this.DataType = ComUtils.GetDataTypeId(element.DataType, out isArray); - this.ValueRank = (isArray)?ValueRanks.OneOrMoreDimensions:ValueRanks.Scalar; - - this.AccessLevel = AccessLevels.None; - - if ((element.AccessRights & OpcRcw.Da.Constants.OPC_READABLE) != 0) - { - this.AccessLevel |= AccessLevels.CurrentRead; - } - - if ((element.AccessRights & OpcRcw.Da.Constants.OPC_WRITEABLE) != 0) - { - this.AccessLevel |= AccessLevels.CurrentWrite; - } - - this.UserAccessLevel = this.AccessLevel; - this.MinimumSamplingInterval = element.ScanRate; - } - - /// - /// Creates a browser that finds the references to the branch. - /// - /// The system context to use. - /// The view which may restrict the set of references/nodes found. - /// The type of references being followed. - /// Whether subtypes of the reference type are followed. - /// Which way the references are being followed. - /// The browse name of a specific target (used when translating browse paths). - /// Any additional references that should be included. - /// If true the browser should not making blocking calls to external systems. - /// The browse object (must be disposed). - public override INodeBrowser CreateBrowser( - ISystemContext context, - ViewDescription view, - NodeId referenceType, - bool includeSubtypes, - BrowseDirection browseDirection, - QualifiedName browseName, - IEnumerable additionalReferences, - bool internalOnly) - { - NodeBrowser browser = new DaElementBrowser( - context, - view, - referenceType, - includeSubtypes, - browseDirection, - browseName, - additionalReferences, - internalOnly, - this.ItemId, - this.NodeId.NamespaceIndex); - - PopulateBrowser(context, browser); - - return browser; - } - #endregion - - #region Private Fields - private DaElement m_element; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/DaModelUtils.cs b/ComIOP/Common/Client/Da/DaModelUtils.cs deleted file mode 100644 index 248af068f..000000000 --- a/ComIOP/Common/Client/Da/DaModelUtils.cs +++ /dev/null @@ -1,141 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// A class that builds NodeIds used by the DataAccess NodeManager - /// - public static class DaModelUtils - { - /// - /// The RootType for a DA Branch or Item. - /// - public const int DaElement = 0; - - /// - /// The RootType for a DA Property identified by its property id. - /// - public const int DaProperty = 2; - - /// - /// The RootType for a node defined by the UA server. - /// - public const int InternalNode = 3; - - /// - /// Constructs a NodeId from the BrowseName of an internal node. - /// - /// The browse name. - /// Index of the namespace. - /// The node id. - public static NodeId ConstructIdForInternalNode(QualifiedName browseName, ushort namespaceIndex) - { - ParsedNodeId parsedNodeId = new ParsedNodeId(); - - parsedNodeId.RootId = browseName.Name; - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.RootType = InternalNode; - - return parsedNodeId.Construct(); - } - - /// - /// Constructs a NodeId from the ItemId for a DA branch. - /// - /// The item id. - /// The property id. - /// Index of the namespace. - /// The node id. - public static NodeId ConstructIdForDaElement(string itemId, int propertyId, ushort namespaceIndex) - { - DaParsedNodeId parsedNodeId = new DaParsedNodeId(); - - parsedNodeId.RootId = itemId; - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.RootType = DaElement; - - if (propertyId >= 0) - { - parsedNodeId.PropertyId = propertyId; - parsedNodeId.RootType = DaProperty; - } - - return parsedNodeId.Construct(); - } - - /// - /// Constructs the node identifier for a component. - /// - /// The component. - /// Index of the namespace. - /// The node identifier for a component. - public static NodeId ConstructIdForComponent(NodeState component, ushort namespaceIndex) - { - return ParsedNodeId.ConstructIdForComponent(component, namespaceIndex); - } - - /// - /// Constructs a branch or item node from a DaElement returned from the COM server. - /// - /// The context. - /// The element. - /// Index of the namespace for the NodeId. - /// The node. - public static NodeState ConstructElement(ISystemContext context, DaElement element, ushort namespaceIndex) - { - if (element.ElementType == DaElementType.Branch) - { - return new DaBranchState(context, element, namespaceIndex); - } - - return new DaItemState(context, element, namespaceIndex); - } - - /// - /// Constructs a property node for a DA property. - /// - /// The context. - /// The parent id. - /// The property. - /// Index of the namespace. - /// The property node. - public static PropertyState ConstructProperty(ISystemContext context, string parentId, DaProperty property, ushort namespaceIndex) - { - return new DaPropertyState(context, parentId, property, namespaceIndex); - } - } -} diff --git a/ComIOP/Common/Client/Da/DaParseNodeId.cs b/ComIOP/Common/Client/Da/DaParseNodeId.cs deleted file mode 100644 index 1a36c9650..000000000 --- a/ComIOP/Common/Client/Da/DaParseNodeId.cs +++ /dev/null @@ -1,239 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Collections.Generic; -using System.Reflection; -using Opc.Ua; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - #region DaParsedNodeId Class - /// - /// Stores the elements of a NodeId after it is parsed. - /// - /// - /// The NodeIds used by the samples are strings with an optional path appended. - /// The RootType identifies the type of Root Node. The RootId is the unique identifier - /// for the Root Node. The ComponentPath is constructed from the SymbolicNames - /// of one or more children of the Root Node. - /// - public class DaParsedNodeId : ParsedNodeId - { - #region Public Interface - /// - /// The identifier for the property identifier. - /// - public int PropertyId - { - get { return m_propertyId; } - set { m_propertyId = value; } - } - - /// - /// Parses the specified node identifier. - /// - /// The node identifier. - /// The parsed node identifier. Null if the identifier cannot be parsed. - public static new DaParsedNodeId Parse(NodeId nodeId) - { - // can only parse non-null string node identifiers. - if (NodeId.IsNull(nodeId)) - { - return null; - } - - string identifier = nodeId.Identifier as string; - - if (String.IsNullOrEmpty(identifier)) - { - return null; - } - - DaParsedNodeId parsedNodeId = new DaParsedNodeId(); - parsedNodeId.NamespaceIndex = nodeId.NamespaceIndex; - - // extract the type of identifier. - parsedNodeId.RootType = 0; - - int start = 0; - - for (int ii = 0; ii < identifier.Length; ii++) - { - if (!Char.IsDigit(identifier[ii])) - { - start = ii; - break; - } - - parsedNodeId.RootType *= 10; - parsedNodeId.RootType += (byte)(identifier[ii] - '0'); - } - - if (start >= identifier.Length || identifier[start] != ':') - { - return null; - } - - // extract any component path. - StringBuilder buffer = new StringBuilder(); - - int index = start+1; - int end = identifier.Length; - - bool escaped = false; - - while (index < end) - { - char ch = identifier[index++]; - - // skip any escape character but keep the one after it. - if (ch == '&') - { - escaped = true; - continue; - } - - if (!escaped && ch == '?') - { - end = index; - break; - } - - buffer.Append(ch); - escaped = false; - } - - // extract any component. - parsedNodeId.RootId = buffer.ToString(); - parsedNodeId.ComponentPath = null; - - if (parsedNodeId.RootType == DaModelUtils.DaProperty) - { - // must have the property id. - if (end >= identifier.Length) - { - return null; - } - - // extract the property id. - for (int ii = end; ii < identifier.Length; ii++) - { - end++; - - if (!Char.IsDigit(identifier[ii])) - { - // check for terminator. - if (identifier[ii] != ':') - { - return null; - } - - break; - } - - parsedNodeId.PropertyId *= 10; - parsedNodeId.PropertyId += (byte)(identifier[ii] - '0'); - } - } - - // extract the component path. - if (end < identifier.Length) - { - parsedNodeId.ComponentPath = identifier.Substring(end); - } - - return parsedNodeId; - } - - /// - /// Constructs a node identifier. - /// - /// The node identifier. - public new NodeId Construct() - { - StringBuilder buffer = new StringBuilder(); - - // add the root type. - buffer.Append(RootType); - buffer.Append(':'); - - // add the root identifier. - if (this.RootId != null) - { - for (int ii = 0; ii < this.RootId.Length; ii++) - { - char ch = this.RootId[ii]; - - // escape any special characters. - if (ch == '&' || ch == '?') - { - buffer.Append('&'); - } - - buffer.Append(ch); - } - } - - // add property id. - if (this.RootType == DaModelUtils.DaProperty) - { - buffer.Append('?'); - buffer.Append(this.PropertyId); - - // add the component path. - if (!String.IsNullOrEmpty(this.ComponentPath)) - { - buffer.Append(':'); - buffer.Append(this.ComponentPath); - } - } - else - { - // add the component path. - if (!String.IsNullOrEmpty(this.ComponentPath)) - { - buffer.Append('?'); - buffer.Append(this.ComponentPath); - } - } - - // construct the node id with the namespace index provided. - return new NodeId(buffer.ToString(), this.NamespaceIndex); - } - #endregion - - #region Private Fields - private int m_propertyId; - #endregion - } - #endregion -} diff --git a/ComIOP/Common/Client/Da/DaProperty.cs b/ComIOP/Common/Client/Da/DaProperty.cs deleted file mode 100644 index a83ae7539..000000000 --- a/ComIOP/Common/Client/Da/DaProperty.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores information an element in the DA server address space. - /// - public class DaProperty - { - #region Public Members - /// - /// Initializes a new instance of the class. - /// - public DaProperty() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the property id. - /// - /// The property id. - public int PropertyId - { - get { return m_propertyId; } - set { m_propertyId = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the COM data type. - /// - /// The COM data type for the property. - public short DataType - { - get { return m_dataType; } - set { m_dataType = value; } - } - #endregion - - #region Private Fields - private int m_propertyId; - private string m_name; - private string m_itemId; - private short m_dataType; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/DaPropertyState.cs b/ComIOP/Common/Client/Da/DaPropertyState.cs deleted file mode 100644 index 1fe3c3016..000000000 --- a/ComIOP/Common/Client/Da/DaPropertyState.cs +++ /dev/null @@ -1,169 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// A object which maps a COM DA item to a UA variable. - /// - public partial class DaPropertyState : PropertyState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The item id. - /// The property. - /// Index of the namespace. - public DaPropertyState( - ISystemContext context, - string itemId, - DaProperty property, - ushort namespaceIndex) - : - base(null) - { - this.TypeDefinitionId = Opc.Ua.VariableTypeIds.DataItemType; - this.Description = null; - this.WriteMask = 0; - this.UserWriteMask = 0; - - if (property != null) - { - Initialize(context, itemId, property, namespaceIndex); - } - } - #endregion - - #region Public Interface - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get - { - return m_itemId; - } - } - - /// - /// Gets the property id. - /// - /// The property id. - public int PropertyId - { - get - { - if (m_property != null) - { - return m_property.PropertyId; - } - - return -1; - } - } - - /// - /// Gets the property description. - /// - /// The property description. - public DaProperty Property - { - get { return m_property; } - } - - /// - /// Initializes the node from the element. - /// - /// The context. - /// The item id. - /// The property. - /// Index of the namespace. - public void Initialize(ISystemContext context, string itemId, DaProperty property, ushort namespaceIndex) - { - m_itemId = itemId; - m_property = property; - - if (property == null) - { - return; - } - - this.NodeId = DaModelUtils.ConstructIdForDaElement(m_itemId, property.PropertyId, namespaceIndex); - this.BrowseName = new QualifiedName(property.Name, namespaceIndex); - this.DisplayName = new LocalizedText(property.Name); - this.TypeDefinitionId = Opc.Ua.VariableTypeIds.PropertyType; - this.Value = null; - this.StatusCode = StatusCodes.BadWaitingForInitialData; - this.Timestamp = DateTime.UtcNow; - - bool isArray = false; - this.DataType = ComUtils.GetDataTypeId(property.DataType, out isArray); - this.ValueRank = (isArray)?ValueRanks.OneOrMoreDimensions:ValueRanks.Scalar; - this.ArrayDimensions = null; - - // assume that properties with item ids are writeable. the server may still reject the write. - if (String.IsNullOrEmpty(property.ItemId)) - { - this.AccessLevel = AccessLevels.CurrentRead; - } - else - { - this.AccessLevel = AccessLevels.CurrentReadOrWrite; - } - - this.UserAccessLevel = this.AccessLevel; - this.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; - this.Historizing = false; - - // add a reference to the parent node. - NodeId parentNodeId = DaModelUtils.ConstructIdForDaElement(itemId, -1, namespaceIndex); - this.AddReference(ReferenceTypeIds.HasProperty, true, parentNodeId); - } - #endregion - - #region Private Fields - private string m_itemId; - private DaProperty m_property; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/DaValue.cs b/ComIOP/Common/Client/Da/DaValue.cs deleted file mode 100644 index 3d7e7d457..000000000 --- a/ComIOP/Common/Client/Da/DaValue.cs +++ /dev/null @@ -1,119 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores information an element in the DA server address space. - /// - public class DaValue - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public DaValue() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the value. - /// - /// The value. - public object Value - { - get { return m_value; } - set { m_value = value; } - } - - /// - /// Gets or sets the timestamp. - /// - /// The timestamp. - public DateTime Timestamp - { - get { return m_timestamp; } - set { m_timestamp = value; } - } - - /// - /// Gets or sets the quality. - /// - /// The quality. - public short Quality - { - get { return m_quality; } - set { m_quality = value; } - } - - /// - /// Gets or sets the COM error. - /// - /// The COM error. - public int Error - { - get { return m_error; } - set { m_error = value; } - } - - /// - /// Gets the value. - /// - /// The type of value to return. - /// The value if no error and a valid value exists. The default value for the type otherwise. - public T GetValue() - { - if (m_error < 0) - { - return default(T); - } - - if (typeof(T).IsInstanceOfType(m_value)) - { - return (T)m_value; - } - - return default(T); - } - #endregion - - #region Private Fields - private object m_value; - private short m_quality; - private DateTime m_timestamp; - private int m_error; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/ReadRequest.cs b/ComIOP/Common/Client/Da/ReadRequest.cs deleted file mode 100644 index b475c98a3..000000000 --- a/ComIOP/Common/Client/Da/ReadRequest.cs +++ /dev/null @@ -1,1016 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using OpcRcw.Comn; -using OpcRcw.Da; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the parameters and results for a COM DA read operation. - /// - public class ReadRequest - { - #region Private Feilds - - /// - /// The BrowseName for the DefaultBinary component. - /// - private const string DefaultBinary = "Default Binary"; - - /// - /// The BrowseName for the DefaultXml component. - /// - private const string DefaultXml = "Default XML"; - - #endregion - - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - public ReadRequest(string itemId) - { - m_itemId = itemId; - } - #endregion - - #region Public Properties - /// - /// Gets the item id to read. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - } - - /// - /// Gets the property ids to read. - /// - /// The property ids. - public List PropertyIds - { - get { return m_propertyIds; } - } - - /// - /// Gets or sets a value indicating whether the item value must be read. - /// - /// true if the item value must be read; otherwise, false. - public bool ValueRequired - { - get { return m_valueRequired; } - set { m_valueRequired = value; } - } - - /// - /// Gets or sets the item value returned from the server. - /// - /// The value. - public DaValue Value - { - get { return m_value; } - set { m_value = value; } - } - - /// - /// Gets or sets the property values returned from the server. - /// - /// The property values. - public DaValue[] PropertyValues - { - get { return m_propertyValues; } - set { m_propertyValues = value; } - } - #endregion - - #region Public Methods - /// - /// Adds the property to the request. - /// - /// The property ids. - public void AddProperty(params int[] propertyIds) - { - if (m_propertyIds == null) - { - m_propertyIds = new List(); - } - - if (propertyIds != null) - { - for (int ii = 0; ii < propertyIds.Length; ii++) - { - bool found = false; - - for (int jj = 0; jj < PropertyIds.Count; jj++) - { - if (PropertyIds[jj] == propertyIds[ii]) - { - found = true; - break; - } - } - - if (!found) - { - PropertyIds.Add(propertyIds[ii]); - } - } - } - } - - /// - /// Gets the item value. - /// - /// The da value. - /// The ua value. - /// The diagnostics masks. - /// - public static ServiceResult GetItemValue(DaValue daValue, DataValue uaValue, DiagnosticsMasks diagnosticsMasks) - { - ServiceResult result = null; - - uaValue.Value = null; - - if (daValue == null) - { - result = uaValue.StatusCode = StatusCodes.BadOutOfService; - return result; - } - - uaValue.SourceTimestamp = daValue.Timestamp; - - if (daValue.Error < 0) - { - result = MapReadErrorToServiceResult(daValue.Error, diagnosticsMasks); - uaValue.StatusCode = result.StatusCode; - return result; - } - - if (daValue.Quality != OpcRcw.Da.Qualities.OPC_QUALITY_GOOD) - { - uaValue.StatusCode = ComUtils.GetQualityCode(daValue.Quality); - } - - if (StatusCode.IsBad(uaValue.StatusCode)) - { - result = uaValue.StatusCode; - return result; - } - - uaValue.Value = daValue.Value; - - return result; - } - - /// - /// Gets the property value. - /// - /// The expected type for the property value. - /// The property id. - /// The value to update. - /// if set to true if the property is required for the value attribute of a node. - /// The value cast to the type T. - /// - /// This method sets the StatusCode in the DataValue if an error occurs and returns default(T). - /// The DataValue.Value property is set to the value cast to type T. - /// - public T GetPropertyValue(int propertyId, DataValue value, bool isValue) - { - value.Value = null; - - // find the property value. - DaValue result = null; - - if (PropertyIds != null && PropertyValues != null) - { - for (int ii = 0; ii < PropertyIds.Count; ii++) - { - if (PropertyIds[ii] == propertyId) - { - if (PropertyValues != null && PropertyValues.Length > ii) - { - result = PropertyValues[ii]; - } - - break; - } - } - } - - // set the appropriate error code if no value found. - if (result == null || result.Error < 0) - { - value.StatusCode = StatusCodes.BadNotFound; - return default(T); - } - - // update the source timestamp if a value is being read. - if (isValue) - { - value.SourceTimestamp = result.Timestamp; - } - - // save the value and return the result. - value.Value = (T)result.Value; - return (T)result.Value; - } - - /// - /// Gets the result for the read operayoin. - /// - /// The context. - /// The item. - /// The node to read. - /// The value. - /// The diagnostics masks. - /// - 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(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(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(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(Opc.Ua.Com.PropertyIds.AccessRights, value, false); - - if (StatusCode.IsGood(value.StatusCode)) - { - value.Value = (byte)accessRights; - } - - break; - } - - case Attributes.MinimumSamplingInterval: - { - float scanRate = this.GetPropertyValue(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); - } - - private ServiceResult ApplyIndexRangeAndDataEncoding( - ISystemContext context, - ReadValueId nodeToRead, - DataValue value) - { - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - if (nodeToRead.ParsedIndexRange != NumericRange.Empty || !QualifiedName.IsNull(nodeToRead.DataEncoding)) - { - if (nodeToRead.AttributeId != Attributes.Value && !QualifiedName.IsNull(nodeToRead.DataEncoding)) - { - return StatusCodes.BadDataEncodingInvalid; - } - - object valueToUpdate = value.Value; - - ServiceResult result = BaseVariableState.ApplyIndexRangeAndDataEncoding( - context, - nodeToRead.ParsedIndexRange, - nodeToRead.DataEncoding, - ref valueToUpdate); - - if (ServiceResult.IsBad(result)) - { - bool useXml = nodeToRead.DataEncoding.Name == DefaultXml; - - if (!useXml - && !string.IsNullOrEmpty(nodeToRead.DataEncoding.Name) - && nodeToRead.DataEncoding.Name != DefaultBinary) - { - result = StatusCodes.BadDataEncodingInvalid; - } - - value.Value = null; - value.StatusCode = result.StatusCode; - return result; - } - - value.Value = valueToUpdate; - } - - return value.StatusCode; - } - - /// - /// Gets the result for the read operation. - /// - /// The context. - /// The property. - /// The node to read. - /// The value. - /// The diagnostics masks. - /// - public ServiceResult GetResult( - ISystemContext context, - DaPropertyState property, - ReadValueId nodeToRead, - DataValue value, - DiagnosticsMasks diagnosticsMasks) - { - ServiceResult result = null; - - switch (nodeToRead.AttributeId) - { - case Attributes.Value: - { - if (!String.IsNullOrEmpty(property.Property.ItemId)) - { - result = GetItemValue(m_value, value, diagnosticsMasks); - } - else - { - this.GetPropertyValue(property.PropertyId, value, true); - result = value.StatusCode; - } - - // check if the property value is missing. - if (value.StatusCode == StatusCodes.BadNotFound) - { - return StatusCodes.BadAttributeIdInvalid; - } - - if (ServiceResult.IsBad(result)) - { - return result; - } - - return ApplyIndexRangeAndDataEncoding(context, nodeToRead, value); - } - } - - return StatusCodes.BadAttributeIdInvalid; - } - - /// - /// Gets the result for the read operation. - /// - /// The context. - /// The property. - /// The node to read. - /// The value. - /// The diagnostics masks. - /// - public ServiceResult GetResult( - ISystemContext context, - PropertyState property, - ReadValueId nodeToRead, - DataValue value, - DiagnosticsMasks diagnosticsMasks) - { - DaItemState item = property.Parent as DaItemState; - - if (item == null) - { - return StatusCodes.BadNodeIdUnknown; - } - - if (nodeToRead.AttributeId != Attributes.Value) - { - return StatusCodes.BadAttributeIdInvalid; - } - - switch (property.SymbolicName) - { - case Opc.Ua.BrowseNames.EURange: - { - double high = this.GetPropertyValue(Opc.Ua.Com.PropertyIds.HighEU, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - double low = this.GetPropertyValue(Opc.Ua.Com.PropertyIds.LowEU, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = new Range(high, low); - break; - } - - case Opc.Ua.BrowseNames.InstrumentRange: - { - double high = this.GetPropertyValue(Opc.Ua.Com.PropertyIds.HighIR, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - double low = this.GetPropertyValue(Opc.Ua.Com.PropertyIds.LowIR, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = new Range(high, low); - break; - } - - case Opc.Ua.BrowseNames.EngineeringUnits: - { - string units = this.GetPropertyValue(Opc.Ua.Com.PropertyIds.EngineeringUnits, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = new EUInformation(units, Namespaces.ComInterop); - break; - } - - case Opc.Ua.BrowseNames.EnumStrings: - { - string[] strings = this.GetPropertyValue(Opc.Ua.Com.PropertyIds.EuInfo, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - if (strings != null) - { - LocalizedText[] texts = new LocalizedText[strings.Length]; - - for (int ii = 0; ii < texts.Length; ii++) - { - texts[ii] = new LocalizedText(strings[ii]); - } - - value.Value = texts; - } - - break; - } - - case Opc.Ua.BrowseNames.LocalTime: - { - int timebias = this.GetPropertyValue(Opc.Ua.Com.PropertyIds.TimeZone, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - TimeZoneDataType timeZone = new TimeZoneDataType(); - timeZone.Offset = (short)timebias; - timeZone.DaylightSavingInOffset = false; - - value.Value = timeZone; - break; - } - - case Opc.Ua.BrowseNames.TrueState: - { - string description = this.GetPropertyValue(Opc.Ua.Com.PropertyIds.CloseLabel, value, false); - - if (StatusCode.IsGood(value.StatusCode)) - { - value.Value = new LocalizedText(description); - } - - break; - } - - case Opc.Ua.BrowseNames.FalseState: - { - string description = this.GetPropertyValue(Opc.Ua.Com.PropertyIds.OpenLabel, value, false); - - if (StatusCode.IsGood(value.StatusCode)) - { - value.Value = new LocalizedText(description); - } - - break; - } - - default: - { - return StatusCodes.BadAttributeIdInvalid; - } - } - - // check if the property value is missing. - if (value.StatusCode == StatusCodes.BadNotFound) - { - return StatusCodes.BadNodeIdUnknown; - } - - return ApplyIndexRangeAndDataEncoding(context, nodeToRead, value); - } - #endregion - - #region Private Methods - /// - /// Maps a DA error code onto a service result. - /// - private static ServiceResult MapReadErrorToServiceResult( - int error, - DiagnosticsMasks diagnosticsMasks) - { - if (error == 0) - { - return ServiceResult.Good; - } - - switch (error) - { - case ResultIds.E_OUTOFMEMORY: { return StatusCodes.BadOutOfMemory; } - case ResultIds.E_INVALIDHANDLE: { return StatusCodes.BadNodeIdUnknown; } - case ResultIds.E_BADRIGHTS: { return StatusCodes.BadNotReadable; } - case ResultIds.E_UNKNOWNITEMID: { return StatusCodes.BadNodeIdUnknown; } - case ResultIds.E_INVALIDITEMID: { return StatusCodes.BadNodeIdInvalid; } - case ResultIds.E_INVALID_PID: { return StatusCodes.BadNodeIdInvalid; } - case ResultIds.E_ACCESSDENIED: { return StatusCodes.BadOutOfService; } - } - - return StatusCodes.BadUnexpectedError; - } - #endregion - - #region Private Fields - private string m_itemId; - private List m_propertyIds; - private bool m_valueRequired; - private DaValue m_value; - private DaValue[] m_propertyValues; - #endregion - } - - /// - /// A collection of read requests. - /// - public class ReadRequestCollection : List - { - #region Public Methods - /// - /// Determines whether the specified operation has a read request result. - /// - /// The read operation parameters. - /// - /// true if the specified operation has a read request result; otherwise, false. - /// - public bool HasResult(ReadValueId nodeToRead) - { - return nodeToRead.Handle is ReadRequest; - } - - /// - /// Gets the result. - /// - /// The context. - /// The source. - /// The node to read. - /// The value. - /// The diagnostics masks. - /// - public ServiceResult GetResult( - ISystemContext context, - NodeState source, - ReadValueId nodeToRead, - DataValue value, - DiagnosticsMasks diagnosticsMasks) - { - ReadRequest request = nodeToRead.Handle as ReadRequest; - - if (request == null) - { - return StatusCodes.Good; - } - - // read item value. - DaItemState item = source as DaItemState; - - if (item != null) - { - return request.GetResult(context, item, nodeToRead, value, diagnosticsMasks); - } - - // read vendor defined property value. - DaPropertyState daProperty = source as DaPropertyState; - - if (daProperty != null) - { - return request.GetResult(context, daProperty, nodeToRead, value, diagnosticsMasks); - } - - // read UA defined property value. - PropertyState uaProperty = source as PropertyState; - - if (uaProperty != null) - { - return request.GetResult(context, uaProperty, nodeToRead, value, diagnosticsMasks); - } - - return StatusCodes.Good; - } - - /// - /// Adds a request for the specified source. - /// - /// The source. - /// The node to read. - /// The value. - /// if set to true [queued]. - /// - public StatusCode Add(NodeState source, ReadValueId nodeToRead, DataValue value, out bool queued) - { - queued = true; - - // read item value. - DaItemState item = source as DaItemState; - - if (item != null) - { - return Add(item, nodeToRead, out queued); - } - - // read vendor defined property value. - DaPropertyState daProperty = source as DaPropertyState; - - if (daProperty != null) - { - return Add(daProperty, nodeToRead, out queued); - } - - // read UA defined property value. - PropertyState uaProperty = source as PropertyState; - - if (uaProperty != null) - { - return Add(uaProperty, nodeToRead, out queued); - } - - queued = false; - return StatusCodes.Good; - } - #endregion - - #region Private Methods - /// - /// Adds a request for the specified item id. - /// - /// The item id. - /// The new request. - private ReadRequest Add(string itemId) - { - if (itemId == null) - { - this.Add((ReadRequest)null); - return null; - } - - if (m_index == null) - { - m_index = new Dictionary(); - } - - ReadRequest request = null; - - if (!m_index.TryGetValue(itemId, out request)) - { - request = new ReadRequest(itemId); - m_index.Add(itemId, request); - } - - request.ValueRequired = true; - this.Add(request); - return request; - } - - /// - /// Adds a read request for the specified properties. - /// - /// The item id. - /// The property ids. - /// The new request. - private ReadRequest Add(string itemId, params int[] propertyIds) - { - if (m_index == null) - { - m_index = new Dictionary(); - } - - ReadRequest request = null; - - if (!m_index.TryGetValue(itemId, out request)) - { - request = new ReadRequest(itemId); - m_index.Add(itemId, request); - Add(request); - } - - request.AddProperty(propertyIds); - - return request; - } - - /// - /// Adds a read request for the specified property. - /// - /// The item id. - /// The property. - /// The new request. - private ReadRequest Add(string itemId, DaProperty property) - { - if (m_index == null) - { - m_index = new Dictionary(); - } - - if (!String.IsNullOrEmpty(property.ItemId)) - { - return Add(property.ItemId); - } - - return Add(itemId, property.PropertyId); - } - - /// - /// Adds a read request for the specified item. - /// - /// The item. - /// The node to read. - /// if set to true if a request was created. - /// Any error. - private StatusCode Add(DaItemState item, ReadValueId nodeToRead, out bool queued) - { - queued = true; - - switch (nodeToRead.AttributeId) - { - case Attributes.Value: - { - nodeToRead.Handle = Add(item.ItemId); - break; - } - - case Attributes.Description: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.Description); - break; - } - - case Attributes.DataType: - case Attributes.ValueRank: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.DataType); - break; - } - - case Attributes.AccessLevel: - case Attributes.UserAccessLevel: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.AccessRights); - break; - } - - case Attributes.MinimumSamplingInterval: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.ScanRate); - break; - } - - default: - { - queued = false; - break; - } - } - - return StatusCodes.Good; - } - - /// - /// Adds the specified property. - /// - /// The property. - /// The node to read. - /// if set to true [queued]. - /// Any error. - private StatusCode Add(DaPropertyState property, ReadValueId nodeToRead, out bool queued) - { - queued = true; - - switch (nodeToRead.AttributeId) - { - case Attributes.Value: - { - nodeToRead.Handle = Add(property.ItemId, property.Property); - break; - } - - default: - { - queued = false; - break; - } - } - - return StatusCodes.Good; - } - - /// - /// Adds the specified property read to the request list. - /// - /// The property. - /// The node to read. - /// if set to true [queued]. - /// - private StatusCode Add(PropertyState property, ReadValueId nodeToRead, out bool queued) - { - queued = false; - - DaItemState item = property.Parent as DaItemState; - - if (item == null) - { - return StatusCodes.Good; - } - - if (nodeToRead.AttributeId != Attributes.Value) - { - return StatusCodes.Good; - } - - queued = true; - - switch (property.SymbolicName) - { - case Opc.Ua.BrowseNames.EURange: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.HighEU, PropertyIds.LowEU); - break; - } - - case Opc.Ua.BrowseNames.InstrumentRange: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.HighIR, PropertyIds.LowIR); - break; - } - - case Opc.Ua.BrowseNames.EngineeringUnits: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.EngineeringUnits); - break; - } - - case Opc.Ua.BrowseNames.EnumStrings: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.EuInfo); - break; - } - - case Opc.Ua.BrowseNames.LocalTime: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.TimeZone); - break; - } - - case Opc.Ua.BrowseNames.TrueState: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.CloseLabel); - break; - } - - case Opc.Ua.BrowseNames.FalseState: - { - nodeToRead.Handle = Add(item.ItemId, PropertyIds.OpenLabel); - break; - } - - default: - { - queued = false; - break; - } - } - - return StatusCodes.Good; - } - #endregion - - #region Private Fields - Dictionary m_index; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/SubscribeRequest.cs b/ComIOP/Common/Client/Da/SubscribeRequest.cs deleted file mode 100644 index db258ad1e..000000000 --- a/ComIOP/Common/Client/Da/SubscribeRequest.cs +++ /dev/null @@ -1,1720 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Runtime.InteropServices; -using OpcRcw.Comn; -using OpcRcw.Da; -using Opc.Ua; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores a request to subscribe to a COM DA item. - /// - internal class SubscribeItemRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - public SubscribeItemRequest(string itemId) - { - m_itemId = itemId; - } - #endregion - - #region Public Properties - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - } - - /// - /// Gets or sets the group used to subscribe to the item. - /// - /// The group. - public ComDaGroup Group - { - get { return m_group; } - set { m_group = value; } - } - - /// - /// Gets or sets the item within the DA group. - /// - /// The group item. - public GroupItem GroupItem - { - get { return m_groupItem; } - set { m_groupItem = value; } - } - - /// - /// Gets the monitored items. - /// - /// The monitored items. - public List MonitoredItems - { - get { return m_monitoredItems; } - } - - /// - /// Gets the sampling interval. - /// - /// The sampling interval. - public int SamplingInterval - { - get { return m_samplingInterval; } - } - - /// - /// Gets the deadband. - /// - /// The deadband. - public float Deadband - { - get { return m_deadband; } - } - - /// - /// Gets a value indicating whether this is active. - /// - /// true if active; otherwise, false. - public bool Active - { - get { return m_active; } - } - - /// - /// Gets a value indicating whether this has changed. - /// - /// true if changed; otherwise, false. - public bool Changed - { - get { return m_changed; } - } - #endregion - - #region Public Methods - /// - /// Adds the specified monitored item. - /// - /// The monitored item. - public void Add(MonitoredItem monitoredItem) - { - if (m_monitoredItems == null) - { - m_monitoredItems = new List(); - } - - m_monitoredItems.Add(monitoredItem); - m_changed = true; - } - - /// - /// Modifies request after the specified monitored item changed. - /// - /// The monitored item. - public void Modify(MonitoredItem monitoredItem) - { - m_changed = true; - } - - /// - /// Removes the specified monitored item. - /// - /// The monitored item. - public void Remove(MonitoredItem monitoredItem) - { - if (monitoredItem != null && m_monitoredItems != null) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - if (Object.ReferenceEquals(m_monitoredItems[ii], monitoredItem)) - { - m_monitoredItems.RemoveAt(ii); - m_changed = true; - break; - } - } - } - } - - /// - /// Marks the groups changes as complete and updates the sampling interval. - /// - public void ChangesComplete() - { - if (m_group != null && m_monitoredItems != null) - { - this.m_changed = false; - - int actualSamplingInterval = m_group.ActualSamplingInterval; - - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - int samplingInterval = (int)m_monitoredItems[ii].SamplingInterval; - - if (actualSamplingInterval > samplingInterval) - { - m_monitoredItems[ii].SetSamplingInterval(actualSamplingInterval); - continue; - } - - if (samplingInterval%actualSamplingInterval != 0) - { - int muliple = samplingInterval/actualSamplingInterval + 1; - m_monitoredItems[ii].SetSamplingInterval(actualSamplingInterval*muliple); - } - } - } - } - - /// - /// Updates this request after monitored items have been added/removed. - /// - public void Update() - { - double samplingInterval = Double.MaxValue; - double deadband = Double.MaxValue; - bool active = false; - - for (int ii = 0; ii < MonitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = MonitoredItems[ii]; - - // check if the item needs to be active. - if (monitoredItem.MonitoringMode != MonitoringMode.Disabled) - { - active = true; - } - - // find the fastest sampling interval. - if (samplingInterval > monitoredItem.SamplingInterval) - { - samplingInterval = monitoredItem.SamplingInterval; - } - - // find the lowest deadband. - DataChangeFilter filter = monitoredItem.Filter as DataChangeFilter; - - // no deadband means no deadband set on the OPC server. - if (filter == null || filter.DeadbandType != (uint)DeadbandType.Percent) - { - deadband = 0; - continue; - } - - // must process deadbands locally if different deadbands requested. - if (deadband != Double.MaxValue && deadband != filter.DeadbandValue) - { - deadband = 0; - continue; - } - - // set the deadband. - if (deadband > filter.DeadbandValue) - { - deadband = filter.DeadbandValue; - } - } - - // update values. - m_samplingInterval = (int)samplingInterval; - m_deadband = 0; - - if (deadband < Double.MaxValue) - { - m_deadband = (float)deadband; - } - - // set a flag indicating that something has changed. - m_changed = (samplingInterval != m_samplingInterval || deadband != m_deadband || active != m_active); - m_active = active; - } - #endregion - - #region Private Fields - private string m_itemId; - private ComDaGroup m_group; - private GroupItem m_groupItem; - private List m_monitoredItems; - private int m_samplingInterval; - private float m_deadband; - private bool m_changed; - private bool m_active; - #endregion - } - - /// - /// Stores a request to subscribe to the properties of a COM DA item. - /// - public class SubscribePropertyRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - public SubscribePropertyRequest(string itemId) - { - m_itemId = itemId; - } - #endregion - - #region Public Properties - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - } - - /// - /// Gets the property ids. - /// - /// The property ids. - public int[] PropertyIds - { - get { return m_propertyIds; } - } - - /// - /// Gets the monitored items. - /// - /// The monitored items. - public List MonitoredItems - { - get { return m_monitoredItems; } - } - - /// - /// Gets the sampling interval. - /// - /// The sampling interval. - public int SamplingInterval - { - get { return m_samplingInterval; } - } - - /// - /// Gets the next update time. - /// - /// The next update time. - public DateTime NextUpdateTime - { - get { return m_nextUpdateTime; } - } - #endregion - - #region Public Methods - /// - /// Updates the request after changes are completed. - /// - /// The property sampling interval. - public void ChangesComplete(int propertySamplingInterval) - { - // adjust the sampling interval on the monitored items. - if (m_monitoredItems != null) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - int samplingInterval = (int)m_monitoredItems[ii].SamplingInterval; - - if (propertySamplingInterval > samplingInterval) - { - m_monitoredItems[ii].SetSamplingInterval(propertySamplingInterval); - continue; - } - - if (samplingInterval%propertySamplingInterval != 0) - { - int muliple = samplingInterval/propertySamplingInterval + 1; - m_monitoredItems[ii].SetSamplingInterval(propertySamplingInterval*muliple); - } - } - } - - Update(); - } - - /// - /// Queues the value to the monitored item. - /// - /// The context. - /// The request. - public void QueueValues(ServerSystemContext context, ReadRequest request) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - QueueValue(context, request, m_monitoredItems[ii]); - } - - m_lastRequest = request; - IncrementSampleTime(); - } - - /// - /// Increments the sample time to the next interval. - /// - private void IncrementSampleTime() - { - // update next sample time. - long now = DateTime.UtcNow.Ticks; - long samplingInterval = (long)(m_samplingInterval*TimeSpan.TicksPerMillisecond); - - long nextSampleTime = 0; - - if (nextSampleTime > 0) - { - long delta = now - nextSampleTime; - - if (samplingInterval > 0 && delta >= 0) - { - nextSampleTime += ((delta/samplingInterval)+1)*samplingInterval; - } - } - - // set sampling time based on current time. - else - { - nextSampleTime = now + samplingInterval; - } - - m_nextUpdateTime = new DateTime(nextSampleTime); - } - - /// - /// Queues the value to the monitored item. - /// - /// The context. - /// The request. - /// The monitored item. - public void QueueValue(ServerSystemContext context, ReadRequest request, MonitoredItem monitoredItem) - { - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - return; - } - - ReadValueId nodeToRead = monitoredItem.GetReadValueId(); - DataValue value = new DataValue(); - ServiceResult error = null; - - // read item value. - DaItemState item = handle.Node as DaItemState; - DaPropertyState daProperty = handle.Node as DaPropertyState; - PropertyState uaProperty = handle.Node as PropertyState; - - if (item != null) - { - error = request.GetResult(context, item, nodeToRead, value, monitoredItem.DiagnosticsMasks); - } - - // read vendor defined property value. - else if (daProperty != null) - { - error = request.GetResult(context, daProperty, nodeToRead, value, monitoredItem.DiagnosticsMasks); - } - - // read UA defined property value. - else if (uaProperty != null) - { - error = request.GetResult(context, uaProperty, nodeToRead, value, monitoredItem.DiagnosticsMasks); - } - - value.ServerTimestamp = DateTime.UtcNow; - - if (value.StatusCode != StatusCodes.BadNotFound) - { - monitoredItem.QueueValue(value, error); - } - else - { - monitoredItem.QueueValue(value, StatusCodes.BadNodeIdUnknown); - } - } - - /// - /// Adds the specified monitored item. - /// - /// The context. - /// The monitored item. - public void Add(ServerSystemContext context, MonitoredItem monitoredItem) - { - if (monitoredItem == null) - { - return; - } - - // save the monitored item. - if (m_monitoredItems == null) - { - m_monitoredItems = new List(); - } - - m_monitoredItems.Add(monitoredItem); - - // queue the initial value. - if (m_lastRequest != null) - { - QueueValue(context, m_lastRequest, monitoredItem); - } - } - - /// - /// Modifies the request after the specified item changes. - /// - /// The context. - /// The monitored item. - public void Modify(ServerSystemContext context, MonitoredItem monitoredItem) - { - // re-queue the last value. - if (m_lastRequest != null) - { - QueueValue(context, m_lastRequest, monitoredItem); - } - } - - /// - /// Removes the specified monitored item. - /// - /// The context. - /// The monitored item. - public void Remove(ServerSystemContext context, MonitoredItem monitoredItem) - { - // remove the monitored item. - if (monitoredItem != null && m_monitoredItems != null) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - if (Object.ReferenceEquals(m_monitoredItems[ii], monitoredItem)) - { - m_monitoredItems.RemoveAt(ii); - break; - } - } - } - } - - /// - /// Updates the request after adding/removing items. - /// - public void Update() - { - double samplingInterval = Double.MaxValue; - List propertyIds = new List(); - - for (int ii = 0; ii < MonitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = MonitoredItems[ii]; - - // find the handle associated with the item. - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - continue; - } - - // ignore disabled items. - if (monitoredItem.MonitoringMode == MonitoringMode.Disabled) - { - continue; - } - - // find the fastest sampling interval. - if (samplingInterval > monitoredItem.SamplingInterval) - { - samplingInterval = monitoredItem.SamplingInterval; - } - - // check for DA item. - DaItemState item = handle.Node as DaItemState; - - if (item != null) - { - int propertyId = DaItemAttributeToDaProperty(monitoredItem.AttributeId); - - if (propertyId != -1 && !propertyIds.Contains(propertyId)) - { - propertyIds.Add(propertyId); - } - - continue; - } - - // check for DA property. - DaPropertyState daProperty = handle.Node as DaPropertyState; - - if (daProperty != null) - { - if (!propertyIds.Contains(daProperty.PropertyId)) - { - propertyIds.Add(daProperty.PropertyId); - } - - continue; - } - - // check for UA property. - PropertyState uaProperty = handle.Node as PropertyState; - - if (uaProperty != null) - { - int[] ids = UaPropertyToDaProperty(uaProperty.SymbolicName); - - if (ids != null) - { - for (int jj = 0; jj < ids.Length; jj++) - { - if (!propertyIds.Contains(ids[jj])) - { - propertyIds.Add(ids[jj]); - } - } - } - - continue; - } - } - - // update values. - m_propertyIds = propertyIds.ToArray(); - m_samplingInterval = (int)samplingInterval; - m_nextUpdateTime = DateTime.UtcNow; - } - #endregion - - #region Private Methods - /// - /// Maps a UA attribute id to a DA property id. - /// - /// The attribute id. - /// The DA property id. -1 if no mapping exists - internal static int DaItemAttributeToDaProperty(uint attributeId) - { - switch (attributeId) - { - case Attributes.Value: - { - return Opc.Ua.Com.PropertyIds.Value; - } - - case Attributes.Description: - { - return Opc.Ua.Com.PropertyIds.Description; - } - - case Attributes.DataType: - case Attributes.ValueRank: - { - return Opc.Ua.Com.PropertyIds.DataType; - } - - case Attributes.AccessLevel: - case Attributes.UserAccessLevel: - { - return Opc.Ua.Com.PropertyIds.AccessRights; - } - - case Attributes.MinimumSamplingInterval: - { - return Opc.Ua.Com.PropertyIds.ScanRate; - } - } - - return -1; - } - - /// - /// Maps a UA property name to a set of DA property ids. - /// - /// The symbolic name for the property. - /// The list of matching DA property ids. - internal static int[] UaPropertyToDaProperty(string symbolicName) - { - switch (symbolicName) - { - case Opc.Ua.BrowseNames.EURange: { return s_PropertyMapping_EURange; } - case Opc.Ua.BrowseNames.InstrumentRange: { return s_PropertyMapping_InstrumentRange; } - case Opc.Ua.BrowseNames.EngineeringUnits: { return s_PropertyMapping_EngineeringUnits; } - case Opc.Ua.BrowseNames.EnumStrings: { return s_PropertyMapping_EnumStrings; } - case Opc.Ua.BrowseNames.LocalTime: { return s_PropertyMapping_TimeZone; } - case Opc.Ua.BrowseNames.TrueState: { return s_PropertyMapping_TrueState; } - case Opc.Ua.BrowseNames.FalseState: { return s_PropertyMapping_FalseState; } - } - - return null; - } - - private static int[] s_PropertyMapping_EURange = new int[] { Opc.Ua.Com.PropertyIds.HighEU, Opc.Ua.Com.PropertyIds.LowEU }; - private static int[] s_PropertyMapping_InstrumentRange = new int[] { Opc.Ua.Com.PropertyIds.HighIR, Opc.Ua.Com.PropertyIds.LowIR }; - private static int[] s_PropertyMapping_EngineeringUnits = new int[] { Opc.Ua.Com.PropertyIds.EngineeringUnits }; - private static int[] s_PropertyMapping_EnumStrings = new int[] { Opc.Ua.Com.PropertyIds.EuInfo }; - private static int[] s_PropertyMapping_TimeZone = new int[] { Opc.Ua.Com.PropertyIds.TimeZone }; - private static int[] s_PropertyMapping_TrueState = new int[] { Opc.Ua.Com.PropertyIds.CloseLabel }; - private static int[] s_PropertyMapping_FalseState = new int[] { Opc.Ua.Com.PropertyIds.OpenLabel }; - #endregion - - #region Private Fields - private string m_itemId; - private List m_monitoredItems; - private int m_samplingInterval; - private int[] m_propertyIds; - private ReadRequest m_lastRequest; - private DateTime m_nextUpdateTime; - #endregion - } - - /// - /// Stores a collection of write requests. - /// - internal class SubscribeRequestManager : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The COKM client wrapper. - /// The property sampling interval. - public SubscribeRequestManager(ServerSystemContext context, ComClient client, int propertySamplingInterval) - { - m_context = context; - - m_propertySamplingInterval = propertySamplingInterval; - m_subscribedItems = new Dictionary(); - m_subscribedProperties = new Dictionary(); - m_groups = new List(); - m_monitoredItems = new Dictionary(); - - if (client == null) - { - LocaleId = ComUtils.LOCALE_SYSTEM_DEFAULT; - UserIdentity = null; - Key = String.Empty; - } - else - { - LocaleId = client.LocaleId; - UserIdentity = client.UserIdentity; - Key = client.Key; - } - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - lock (m_lock) - { - Utils.SilentDispose(m_propertyScanTimer); - m_propertyScanTimer = null; - - for (int ii = 0; ii < m_groups.Count; ii++) - { - Utils.SilentDispose(m_groups[ii]); - } - - m_groups.Clear(); - } - } - } - #endregion - - #region Public Properties - /// - /// The locale to use when creating the subscriptions. - /// - public int LocaleId { get; private set; } - - /// - /// The user identity to use. - /// - public IUserIdentity UserIdentity { get; private set; } - - /// - /// A key that combines the user identity and the locale. - /// - public string Key { get; private set; } - - /// - /// Gets the item requests. - /// - /// The item requests. - public List ItemRequests - { - get - { - lock (m_lock) - { - return new List(m_subscribedItems.Values); - } - } - } - - /// - /// Gets the item property requests. - /// - /// The item property requests. - public List PropertyRequests - { - get - { - lock (m_lock) - { - return new List(m_subscribedProperties.Values); - } - } - } - #endregion - - #region Public Methods - /// - /// Finds the item value request for the specifed item. - /// - /// The item id. - /// if set to true a new request is created if it does not exist. - /// The subscribe item request. - public SubscribeItemRequest FindItemRequest(string itemId, bool create) - { - lock (m_lock) - { - SubscribeItemRequest subscribedItem = null; - - if (!m_subscribedItems.TryGetValue(itemId, out subscribedItem)) - { - if (!create) - { - return null; - } - - subscribedItem = new SubscribeItemRequest(itemId); - m_subscribedItems.Add(itemId, subscribedItem); - } - - return subscribedItem; - } - } - - /// - /// Finds the item properties request for the specifed item. - /// - /// The item id. - /// if set to true a new request is created if it does not exist. - /// The subscribe property request. - public SubscribePropertyRequest FindPropertyRequest(string itemId, bool create) - { - lock (m_lock) - { - SubscribePropertyRequest subscribedProperty = null; - - if (!m_subscribedProperties.TryGetValue(itemId, out subscribedProperty)) - { - if (!create) - { - return null; - } - - subscribedProperty = new SubscribePropertyRequest(itemId); - m_subscribedProperties.Add(itemId, subscribedProperty); - } - - return subscribedProperty; - } - } - - /// - /// Recreates the items after a disconnect. - /// - public void RecreateItems() - { - lock (m_lock) - { - m_subscribedItems.Clear(); - m_subscribedProperties.Clear(); - - Utils.SilentDispose(m_propertyScanTimer); - m_propertyScanTimer = null; - - for (int ii = 0; ii < m_groups.Count; ii++) - { - Utils.SilentDispose(m_groups[ii]); - } - - m_groups.Clear(); - - IList monitoredItems = new List(m_monitoredItems.Values); - m_monitoredItems.Clear(); - - CreateItems(m_context, monitoredItems); - } - } - - /// - /// Creates subscription requests for monitored items. - /// - /// The context. - /// The monitored items. - public void CreateItems(ServerSystemContext context, IList monitoredItems) - { - ComDaClientManager system = (ComDaClientManager)context.SystemHandle; - ComDaClient client = (ComDaClient)system.GetLocalizedClient(this.UserIdentity, this.LocaleId); - - lock (m_lock) - { - if (monitoredItems != null) - { - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem; - - if (monitoredItem == null) - { - continue; - } - - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - continue; - } - - Add(handle.Node, monitoredItem); - } - - ApplyGroupChanges(client); - } - } - } - - /// - /// Modifies subscription requests for monitored items. - /// - /// The context. - /// The monitored items. - public void ModifyItems(ServerSystemContext context, IList monitoredItems) - { - ComDaClientManager system = (ComDaClientManager)context.SystemHandle; - ComDaClient client = (ComDaClient)system.GetLocalizedClient(this.UserIdentity, this.LocaleId); - - lock (m_lock) - { - if (monitoredItems != null) - { - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem; - - if (monitoredItem == null) - { - continue; - } - - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - continue; - } - - Modify(handle.Node, monitoredItem); - } - - ApplyGroupChanges(client); - } - } - } - - /// - /// Deletes subscription requests for monitored items. - /// - /// The context. - /// The monitored items. - public void DeleteItems(ServerSystemContext context, IList monitoredItems) - { - ComDaClientManager system = (ComDaClientManager)context.SystemHandle; - ComDaClient client = (ComDaClient)system.GetLocalizedClient(this.UserIdentity, this.LocaleId); - - lock (m_lock) - { - if (monitoredItems != null) - { - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem; - - if (monitoredItem == null) - { - continue; - } - - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - continue; - } - - Remove(handle.Node, monitoredItem); - } - - ApplyGroupChanges(client); - } - } - } - - /// - /// Adds the monitored item to the collection. - /// - /// The source. - /// The monitored item. - public void Add(NodeState source, MonitoredItem monitoredItem) - { - lock (m_lock) - { - m_monitoredItems.Add(monitoredItem.Id, monitoredItem); - - DaItemState item = source as DaItemState; - - if (item != null) - { - Add(item, monitoredItem); - return; - } - - DaPropertyState daProperty = source as DaPropertyState; - - if (daProperty != null) - { - Add(daProperty, monitoredItem); - return; - } - - PropertyState uaProperty = source as PropertyState; - - if (uaProperty != null) - { - Add(uaProperty, monitoredItem); - return; - } - } - } - - /// - /// Modifies the monitored item to the collection. - /// - /// The source. - /// The monitored item. - public void Modify(NodeState source, MonitoredItem monitoredItem) - { - lock (m_lock) - { - DaItemState item = source as DaItemState; - - if (item != null) - { - Modify(item, monitoredItem); - return; - } - - DaPropertyState daProperty = source as DaPropertyState; - - if (daProperty != null) - { - Modify(daProperty, monitoredItem); - return; - } - - PropertyState uaProperty = source as PropertyState; - - if (uaProperty != null) - { - Modify(uaProperty, monitoredItem); - return; - } - } - } - - /// - /// Removes the monitored item from the collection. - /// - /// The source. - /// The monitored item. - public void Remove(NodeState source, MonitoredItem monitoredItem) - { - lock (m_lock) - { - m_monitoredItems.Remove(monitoredItem.Id); - - DaItemState item = source as DaItemState; - - if (item != null) - { - Remove(item, monitoredItem); - return; - } - - DaPropertyState daProperty = source as DaPropertyState; - - if (daProperty != null) - { - Remove(daProperty, monitoredItem); - return; - } - - PropertyState uaProperty = source as PropertyState; - - if (uaProperty != null) - { - Remove(uaProperty, monitoredItem); - return; - } - } - } - - /// - /// Removes the specified item request. - /// - /// The request. - /// True of the request was removed. - public bool Remove(SubscribeItemRequest request) - { - lock (m_lock) - { - if (request != null && request.ItemId != null) - { - return m_subscribedItems.Remove(request.ItemId); - } - - return false; - } - } - - /// - /// Removes the specified property request. - /// - /// The request. - /// True of the request was removed. - public bool Remove(SubscribePropertyRequest request) - { - lock (m_lock) - { - if (request != null && request.ItemId != null) - { - return m_subscribedProperties.Remove(request.ItemId); - } - - return false; - } - } - - /// - /// Assigns a request to a group. - /// - /// The client. - /// The request. - public void UpdateGroup(ComDaClient client, SubscribeItemRequest request) - { - lock (m_lock) - { - // check for empty request. - if (request.MonitoredItems.Count == 0) - { - return; - } - - request.Update(); - - // check if existing group can be used. - if (request.Group != null) - { - if (request.Group.ModifyItem(request.GroupItem, request.SamplingInterval, request.Deadband, request.Active)) - { - if (request.GroupItem.Active != request.Active) - { - request.GroupItem.Active = request.Active; - request.GroupItem.ActiveChanged = true; - } - - request.Group.SetMonitoredItems(request.GroupItem, request.MonitoredItems.ToArray()); - return; - } - } - - // clear link to existing group. - request.Group = null; - request.GroupItem = null; - - // assign to an existing group. - for (int ii = 0; ii < m_groups.Count; ii++) - { - ComDaGroup group = m_groups[ii]; - - request.GroupItem = group.CreateItem(request.ItemId, request.SamplingInterval, request.Deadband, request.Active); - - if (request.GroupItem != null) - { - request.Group = group; - request.Group.SetMonitoredItems(request.GroupItem, request.MonitoredItems.ToArray()); - return; - } - } - - // create a new group. - request.Group = new ComDaGroup(client, true); - request.GroupItem = request.Group.CreateItem(request.ItemId, request.SamplingInterval, request.Deadband, request.Active); - request.Group.SetMonitoredItems(request.GroupItem, request.MonitoredItems.ToArray()); - m_groups.Add(request.Group); - } - } - - /// - /// Applies any changes to the groups. - /// - public void ApplyGroupChanges(ComDaClient client) - { - List groups = null; - List items = null; - - lock (m_lock) - { - items = new List(m_subscribedItems.Values); - - // modify or remove items. - for (int ii = 0; ii < items.Count; ii++) - { - SubscribeItemRequest request = items[ii]; - - // remove unused requests. - if (request.MonitoredItems.Count == 0) - { - if (request.Group != null && request.GroupItem != null) - { - request.Group.RemoveItem(request.GroupItem); - } - - Remove(request); - continue; - } - } - - // add any new items to groups. - for (int ii = 0; ii < items.Count; ii++) - { - SubscribeItemRequest request = items[ii]; - - if (!request.Changed) - { - continue; - } - - UpdateGroup(client, request); - } - - groups = new List(m_groups.Count); - - // update group on the server. - for (int ii = 0; ii < m_groups.Count; ii++) - { - if (m_groups[ii].ApplyChanges()) - { - groups.Add(m_groups[ii]); - } - else - { - m_groups[ii].Delete(); - } - } - - m_groups = groups; - - // update request. - for (int ii = 0; ii < items.Count; ii++) - { - if (items[ii].Changed) - { - items[ii].ChangesComplete(); - } - } - - // modify or remove items. - List properties = new List(m_subscribedProperties.Values); - - for (int ii = 0; ii < properties.Count; ii++) - { - SubscribePropertyRequest request = properties[ii]; - - // remove unused requests. - if (request.MonitoredItems == null || request.MonitoredItems.Count == 0) - { - Remove(request); - continue; - } - - request.ChangesComplete(m_propertySamplingInterval); - } - - // check if the property scanner needs to be stopped/started. - if (m_propertyScanTimer == null) - { - if (m_subscribedProperties.Count > 0) - { - m_propertyScanTimer = new Timer(OnScanProperties, null, 0, m_propertySamplingInterval); - } - } - else - { - if (m_subscribedProperties.Count == 0) - { - m_propertyScanTimer.Dispose(); - m_propertyScanTimer = null; - } - } - } - } - #endregion - - #region Private Methods - /// - /// Called when the scan properties timer expires. - /// - private void OnScanProperties(object state) - { - try - { - ComDaClientManager system = (ComDaClientManager)m_context.SystemHandle; - ComDaClient client = (ComDaClient)system.GetLocalizedClient(this.UserIdentity, this.LocaleId); - - // collect the list of properties that need reading. - List requests1 = new List(); - List requests2 = new List(); - - lock (m_lock) - { - DateTime now = DateTime.UtcNow; - - foreach (SubscribePropertyRequest request1 in m_subscribedProperties.Values) - { - if (request1.NextUpdateTime <= now) - { - requests1.Add(request1); - ReadRequest request2 = new ReadRequest(request1.ItemId); - request2.AddProperty(request1.PropertyIds); - requests2.Add(request2); - } - } - } - - // read the properties from teh server. - client.ReadPropertyValues(requests2); - - // update the monitored items. - lock (m_lock) - { - for (int ii = 0; ii < requests1.Count; ii++) - { - requests1[ii].QueueValues(m_context, requests2[ii]); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error scanning properties in DA COM server."); - } - } - - /// - /// Adds a request for the specified item. - /// - /// The item. - /// The monitored item. - private void Add(DaItemState item, MonitoredItem monitoredItem) - { - if (monitoredItem.AttributeId == Attributes.Value) - { - SubscribeItemRequest request = FindItemRequest(item.ItemId, true); - - if (request != null) - { - request.Add(monitoredItem); - } - } - else - { - int propertyId = SubscribePropertyRequest.DaItemAttributeToDaProperty(monitoredItem.AttributeId); - - if (propertyId < 0) - { - return; - } - - SubscribePropertyRequest request = FindPropertyRequest(item.ItemId, true); - - if (request != null) - { - request.Add(m_context, monitoredItem); - } - } - } - - /// - /// Adds the specified item property. - /// - /// The item property. - /// The monitored item. - private void Add(DaPropertyState item, MonitoredItem monitoredItem) - { - if (monitoredItem.AttributeId != Attributes.Value) - { - return; - } - - // check if the server supports access by item id for the property. - if (!String.IsNullOrEmpty(item.Property.ItemId)) - { - SubscribeItemRequest request = FindItemRequest(item.Property.ItemId, true); - - if (request != null) - { - request.Add(monitoredItem); - } - } - - // must access with the property id. - else - { - SubscribePropertyRequest request = FindPropertyRequest(item.ItemId, true); - - if (request != null) - { - request.Add(m_context, monitoredItem); - } - } - } - - /// - /// Adds the specified UA property. - /// - /// The property. - /// The monitored item. - private void Add(PropertyState property, MonitoredItem monitoredItem) - { - if (monitoredItem.AttributeId != Attributes.Value) - { - return; - } - - DaItemState item = property.Parent as DaItemState; - - if (item == null) - { - return; - } - - int[] propertyIds = SubscribePropertyRequest.UaPropertyToDaProperty(property.SymbolicName); - - if (propertyIds == null) - { - return; - } - - SubscribePropertyRequest request = FindPropertyRequest(item.ItemId, true); - - if (request != null) - { - request.Add(m_context, monitoredItem); - } - } - - /// - /// Modifies a request for the specified item. - /// - /// The item. - /// The monitored item. - private void Modify(DaItemState item, MonitoredItem monitoredItem) - { - if (monitoredItem.AttributeId == Attributes.Value) - { - SubscribeItemRequest request = FindItemRequest(item.ItemId, false); - - if (request != null) - { - request.Modify(monitoredItem); - } - } - else - { - int propertyId = SubscribePropertyRequest.DaItemAttributeToDaProperty(monitoredItem.AttributeId); - - if (propertyId < 0) - { - return; - } - - SubscribePropertyRequest request = FindPropertyRequest(item.ItemId, false); - - if (request != null) - { - request.Modify(m_context, monitoredItem); - } - } - } - - /// - /// Modifies the specified item property. - /// - /// The item property. - /// The monitored item. - private void Modify(DaPropertyState item, MonitoredItem monitoredItem) - { - if (monitoredItem.AttributeId != Attributes.Value) - { - return; - } - - // check if the server supports access by item id for the property. - if (!String.IsNullOrEmpty(item.Property.ItemId)) - { - SubscribeItemRequest request = FindItemRequest(item.Property.ItemId, false); - - if (request != null) - { - request.Modify(monitoredItem); - } - } - - // must access with the property id. - else - { - SubscribePropertyRequest request = FindPropertyRequest(item.ItemId, false); - - if (request != null) - { - request.Modify(m_context, monitoredItem); - } - } - } - - /// - /// Modifies the specified UA property. - /// - /// The property. - /// The monitored item. - private void Modify(PropertyState property, MonitoredItem monitoredItem) - { - if (monitoredItem.AttributeId != Attributes.Value) - { - return; - } - - DaItemState item = property.Parent as DaItemState; - - if (item == null) - { - return; - } - - int[] propertyIds = SubscribePropertyRequest.UaPropertyToDaProperty(property.SymbolicName); - - if (propertyIds == null) - { - return; - } - - SubscribePropertyRequest request = FindPropertyRequest(item.ItemId, false); - - if (request != null) - { - request.Modify(m_context, monitoredItem); - } - } - - /// - /// Removes a request for the specified item. - /// - /// The item. - /// The monitored item. - private void Remove(DaItemState item, MonitoredItem monitoredItem) - { - if (monitoredItem.AttributeId == Attributes.Value) - { - SubscribeItemRequest request = FindItemRequest(item.ItemId, false); - - if (request != null) - { - request.Remove(monitoredItem); - } - } - else - { - int propertyId = SubscribePropertyRequest.DaItemAttributeToDaProperty(monitoredItem.AttributeId); - - if (propertyId < 0) - { - return; - } - - SubscribePropertyRequest request = FindPropertyRequest(item.ItemId, false); - - if (request != null) - { - request.Remove(m_context, monitoredItem); - - if (request.MonitoredItems.Count == 0) - { - m_subscribedProperties.Remove(item.ItemId); - } - } - } - } - - /// - /// Removes a request for the specified item property. - /// - /// The item property. - /// The monitored item. - private void Remove(DaPropertyState item, MonitoredItem monitoredItem) - { - if (monitoredItem.AttributeId != Attributes.Value) - { - return; - } - - // check if the server supports access by item id for the property. - if (!String.IsNullOrEmpty(item.Property.ItemId)) - { - SubscribeItemRequest request = FindItemRequest(item.Property.ItemId, false); - - if (request != null) - { - request.Remove(monitoredItem); - } - } - - // must access with the property id. - else - { - SubscribePropertyRequest request = FindPropertyRequest(item.ItemId, false); - - if (request != null) - { - request.Remove(m_context, monitoredItem); - - if (request.MonitoredItems.Count == 0) - { - m_subscribedProperties.Remove(item.ItemId); - } - } - } - } - - /// - /// Removes a request for the specified UA property. - /// - /// The property. - /// The monitored item. - private void Remove(PropertyState property, MonitoredItem monitoredItem) - { - if (monitoredItem.AttributeId != Attributes.Value) - { - return; - } - - DaItemState item = property.Parent as DaItemState; - - if (item == null) - { - return; - } - - int[] propertyIds = SubscribePropertyRequest.UaPropertyToDaProperty(property.SymbolicName); - - if (propertyIds == null) - { - return; - } - - SubscribePropertyRequest request = FindPropertyRequest(item.ItemId, false); - - if (request != null) - { - request.Remove(m_context, monitoredItem); - - if (request.MonitoredItems.Count == 0) - { - m_subscribedProperties.Remove(item.ItemId); - } - } - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private Dictionary m_subscribedItems; - private Dictionary m_subscribedProperties; - private List m_groups; - private Timer m_propertyScanTimer; - private int m_propertySamplingInterval; - private ServerSystemContext m_context; - private Dictionary m_monitoredItems; - #endregion - } -} diff --git a/ComIOP/Common/Client/Da/WriteRequest.cs b/ComIOP/Common/Client/Da/WriteRequest.cs deleted file mode 100644 index 6232aaf3f..000000000 --- a/ComIOP/Common/Client/Da/WriteRequest.cs +++ /dev/null @@ -1,346 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Runtime.InteropServices; -using OpcRcw.Comn; -using OpcRcw.Da; -using Opc.Ua; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the parameters and results for a COM DA write operation. - /// - public class WriteRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - /// The value to write. - /// The index associated with the request. - public WriteRequest(string itemId, DataValue value, int index) - { - m_itemId = itemId; - m_value = value; - m_index = index; - } - #endregion - - #region Public Methods - /// - /// Gets the result fo the write opeartion. - /// - /// The result code. - public StatusCode GetResult() - { - return MapWriteErrorToServiceResult(Error); - } - #endregion - - #region Public Properties - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - } - - /// - /// Gets the value to write. - /// - /// The value to write. - public DataValue Value - { - get { return m_value; } - } - - /// - /// Gets or sets the COM error. - /// - /// The COM error. - public int Error - { - get { return m_error; } - set { m_error = value; } - } - - /// - /// Gets or sets the index. - /// - /// The index. - public int Index - { - get { return m_index; } - set { m_index = value; } - } - #endregion - - #region Private Methods - /// - /// Maps a DA error code onto a service result. - /// - private StatusCode MapWriteErrorToServiceResult(int error) - { - if (error == 0) - { - return StatusCodes.Good; - } - - switch (error) - { - case ResultIds.E_BADRIGHTS: { return StatusCodes.BadUserAccessDenied; } - case ResultIds.DISP_E_TYPEMISMATCH: { return StatusCodes.BadTypeMismatch; } - case ResultIds.E_BADTYPE: { return StatusCodes.BadTypeMismatch; } - case ResultIds.E_RANGE: { return StatusCodes.BadOutOfRange; } - case ResultIds.DISP_E_OVERFLOW: { return StatusCodes.BadOutOfRange; } - case ResultIds.E_OUTOFMEMORY: { return StatusCodes.BadOutOfMemory; } - case ResultIds.E_INVALIDHANDLE: { return StatusCodes.BadNodeIdUnknown; } - case ResultIds.E_UNKNOWNITEMID: { return StatusCodes.BadNodeIdUnknown; } - case ResultIds.E_INVALIDITEMID: { return StatusCodes.BadNodeIdInvalid; } - case ResultIds.E_INVALID_PID: { return StatusCodes.BadNodeIdInvalid; } - case ResultIds.E_NOTSUPPORTED: { return StatusCodes.BadWriteNotSupported; } - case ResultIds.S_CLAMP: { return StatusCodes.GoodClamped; } - case ResultIds.E_FILTER_DUPLICATE: { return StatusCodes.BadTypeMismatch; } - case ResultIds.E_FILTER_INVALID: { return StatusCodes.BadTypeMismatch; } - case ResultIds.E_FILTER_ERROR: { return StatusCodes.BadTypeMismatch; } - } - - return StatusCodes.BadUnexpectedError; - } - #endregion - - #region Private Fields - private string m_itemId; - private DataValue m_value; - private int m_error; - private int m_index; - #endregion - } - - /// - /// Stores a collection of write requests. - /// - public class WriteRequestCollection : List - { - #region Public Methods - /// - /// Adds a write request for a DA item. - /// - /// The source. - /// The node to write. - /// The index associated with the value. - /// If set to true then the a request was added. - /// - /// StatusCode.Good if the write is allowed. An error code otherwise. - /// - public StatusCode Add(NodeState source, WriteValue nodeToWrite, int index, out bool queued) - { - queued = true; - - DaItemState item = source as DaItemState; - - if (item != null) - { - return Add(item, nodeToWrite, index); - } - - DaPropertyState property = source as DaPropertyState; - - if (property != null) - { - return Add(property, nodeToWrite, index); - } - - queued = false; - return StatusCodes.Good; - } - #endregion - - #region Private Methods - /// - /// Adds a write request for a DA item. - /// - /// The item. - /// The node to write. - /// The index associated with the value. - /// StatusCode.Good if the write is allowed. An error code otherwise. - private StatusCode Add(DaItemState item, WriteValue nodeToWrite, int index) - { - if (nodeToWrite.AttributeId != Attributes.Value) - { - return StatusCodes.BadNotWritable; - } - - //if (nodeToWrite.ParsedIndexRange != NumericRange.Empty) - //{ - // return StatusCodes.BadIndexRangeInvalid; - //} - - if (nodeToWrite.Value.ServerTimestamp != DateTime.MinValue) - { - return StatusCodes.BadWriteNotSupported; - } - - if (item.Element.DataType != 0) - { - if (!CheckDataType(item.Element.DataType, nodeToWrite.Value.WrappedValue)) - { - return StatusCodes.BadTypeMismatch; - } - } - - WriteRequest request = new WriteRequest(item.ItemId, nodeToWrite.Value, index); - Add(request); - return StatusCodes.Good; - } - - /// - /// Adds a write request for a DA property value. - /// - /// The item. - /// The node to write. - /// The index associated with the value. - /// - /// StatusCode.Good if the write is allowed. An error code otherwise. - /// - private StatusCode Add(DaPropertyState item, WriteValue nodeToWrite, int index) - { - if (nodeToWrite.AttributeId != Attributes.Value) - { - return StatusCodes.BadNotWritable; - } - - if (String.IsNullOrEmpty(item.Property.ItemId)) - { - return StatusCodes.BadNotWritable; - } - - if (nodeToWrite.ParsedIndexRange != NumericRange.Empty) - { - return StatusCodes.BadIndexRangeInvalid; - } - - if (nodeToWrite.Value.ServerTimestamp != DateTime.MinValue) - { - return StatusCodes.BadWriteNotSupported; - } - - if (item.Property.DataType != 0) - { - if (!CheckDataType(item.Property.DataType, nodeToWrite.Value.WrappedValue)) - { - return StatusCodes.BadTypeMismatch; - } - } - - WriteRequest request = new WriteRequest(item.Property.ItemId, nodeToWrite.Value, index); - Add(request); - nodeToWrite.Handle = request; - return StatusCodes.Good; - } - - /// - /// Checks the type of the data. - /// - /// The expected type. - /// The value. - /// True if the value can be written to the server. - private bool CheckDataType(short expectedType, Variant value) - { - if (value.Value == null) - { - return true; - } - - if (expectedType == (short)VarEnum.VT_CY) - { - expectedType = (short)VarEnum.VT_BSTR; - } - - if (expectedType == (short)(VarEnum.VT_ARRAY | VarEnum.VT_CY)) - { - expectedType = (short)(VarEnum.VT_ARRAY | VarEnum.VT_BSTR); - } - - TypeInfo typeInfo = value.TypeInfo; - VarEnum vtType = ComUtils.GetVarType(typeInfo); - - if (vtType == VarEnum.VT_EMPTY) - { - return false; - } - - if (expectedType == (short)(VarEnum.VT_ARRAY | VarEnum.VT_VARIANT)) - { - // must be an array. - Array array = value.Value as Array; - - if (array == null || (typeInfo.BuiltInType == BuiltInType.ByteString && typeInfo.ValueRank == ValueRanks.Scalar)) - { - return false; - } - - // nothing more to for fixed type arrays. - if (typeInfo.BuiltInType != BuiltInType.Variant) - { - return true; - } - - // must check each element. - for (int ii = 0; ii < array.GetLength(0); ii++) - { - object element = array.GetValue(ii); - - if (!CheckDataType((short)VarEnum.VT_VARIANT, new Variant(element))) - { - return false; - } - } - } - - if (expectedType == (short)vtType || expectedType == (short)VarEnum.VT_VARIANT) - { - return true; - } - - return false; - } - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/ComHdaBrowserClient.cs b/ComIOP/Common/Client/Hda/ComHdaBrowserClient.cs deleted file mode 100644 index a1de92258..000000000 --- a/ComIOP/Common/Client/Hda/ComHdaBrowserClient.cs +++ /dev/null @@ -1,415 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Hda; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Client -{ - /// - /// Browses areas and sources in the AE server. - /// - public class ComHdaBrowserClient : ComObject - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The client. - /// The qualified area name. - public ComHdaBrowserClient( - ComHdaClient client, - string itemId) - { - m_client = client; - m_itemId = itemId; - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - Utils.SilentDispose(m_enumerator); - m_enumerator = null; - } - - base.Dispose(disposing); - } - #endregion - - #region Public Methods - /// - /// Returns the next AE area or source. - /// - /// A DA element. Null if nothing left to browse. - public BaseInstanceState Next(ISystemContext context, ushort namespaceIndex) - { - // check if already completed. - if (m_completed) - { - return null; - } - - // create the browser. - if (base.Unknown == null) - { - base.Unknown = m_client.CreateBrowser(); - - if (base.Unknown == null) - { - return null; - } - - if (!String.IsNullOrEmpty(m_itemId)) - { - if (!ChangeBrowsePosition(OPCHDA_BROWSEDIRECTION.OPCHDA_BROWSE_DIRECT, m_itemId)) - { - return null; - } - } - } - - // create the enumerator if not already created. - if (m_enumerator == null) - { - m_enumerator = CreateEnumerator(true); - m_branches = true; - - // a null indicates an error. - if (m_enumerator == null) - { - m_completed = true; - return null; - } - } - - // need a loop in case errors occur fetching element metadata. - BaseInstanceState node = null; - - do - { - // fetch the next name. - string name = m_enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - if (m_branches) - { - m_enumerator.Dispose(); - m_enumerator = CreateEnumerator(false); - m_branches = false; - - // a null indicates an error. - if (m_enumerator != null) - { - continue; - } - } - - m_completed = true; - return null; - } - - // create the node. - if (m_branches) - { - string itemId = GetBranchPosition(m_itemId, name); - node = new HdaBranchState(itemId, name, namespaceIndex); - - } - else - { - string itemId = GetItemId(name); - node = new HdaItemState(itemId, name, namespaceIndex); - } - - break; - } - while (node == null); - - // return node. - return node; - } - - /// - /// Finds the branch. - /// - public BaseObjectState FindBranch(ISystemContext context, string itemId, ushort namespaceIndex) - { - // create the browser. - if (base.Unknown == null) - { - base.Unknown = m_client.CreateBrowser(); - - if (base.Unknown == null) - { - return null; - } - } - - // goto branch. - if (!ChangeBrowsePosition(OPCHDA_BROWSEDIRECTION.OPCHDA_BROWSE_DIRECT, itemId)) - { - return null; - } - - // find browse name via parent. - if (!ChangeBrowsePosition(OPCHDA_BROWSEDIRECTION.OPCHDA_BROWSE_UP, String.Empty)) - { - return null; - } - - // find the branch. - return FindBranch(context, GetBranchPosition(null, null), itemId, namespaceIndex); - } - - /// - /// Recusively finds the branch. - /// - private BaseObjectState FindBranch(ISystemContext context, string parentId, string itemId, ushort namespaceIndex) - { - // remove the enumerator. - if (m_enumerator != null) - { - m_enumerator.Dispose(); - m_enumerator = null; - } - - // find item at current level. - m_enumerator = CreateEnumerator(true); - List children = new List(); - - do - { - // fetch the next name. - string name = m_enumerator.Next(); - - // a null indicates the end of list. - if (name == null) - { - break; - } - - // create the node. - string targetId = GetBranchPosition(parentId, name); - - if (itemId == targetId) - { - return new HdaBranchState(itemId, name, namespaceIndex); - } - - children.Add(targetId); - } - while (true); - - // recursively search for item ids. - for (int ii = 0; ii < children.Count; ii++) - { - if (!ChangeBrowsePosition(OPCHDA_BROWSEDIRECTION.OPCHDA_BROWSE_DIRECT, children[ii])) - { - continue; - } - - BaseObjectState node = FindBranch(context, children[ii], itemId, namespaceIndex); - - if (node != null) - { - return node; - } - } - - m_completed = true; - return null; - } - #endregion - - #region Private Methods - /// - /// Changes the browse position. - /// - /// The direction. - /// The target. - private bool ChangeBrowsePosition(OPCHDA_BROWSEDIRECTION direction, string itemId) - { - string methodName = "IOPCHDA_Browser.ChangeBrowsePosition"; - - try - { - IOPCHDA_Browser server = BeginComCall(methodName, true); - server.ChangeBrowsePosition(direction, itemId); - return true; - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL)) - { - ComCallError(methodName, e); - } - - return false; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Gets the branch position. - /// - private string GetBranchPosition(string parentId, string name) - { - string methodName = "IOPCHDA_Browser.GetBranchPosition"; - - // need to move down to get the browse position. - if (!String.IsNullOrEmpty(name)) - { - if (!ChangeBrowsePosition(OPCHDA_BROWSEDIRECTION.OPCHDA_BROWSE_DOWN, name)) - { - return null; - } - } - - string itemId = null; - - try - { - IOPCHDA_Browser server = BeginComCall(methodName, true); - server.GetBranchPosition(out itemId); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - - // restore browse position. - if (!String.IsNullOrEmpty(name)) - { - ChangeBrowsePosition(OPCHDA_BROWSEDIRECTION.OPCHDA_BROWSE_DIRECT, parentId); - } - } - - return itemId; - } - - /// - /// Gets the item id. - /// - /// The name of the item. - private string GetItemId(string name) - { - string methodName = "IOPCHDA_Browser.GetItemID"; - - string itemId = null; - - try - { - IOPCHDA_Browser server = BeginComCall(methodName, true); - server.GetItemID(name, out itemId); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - return itemId; - } - - /// - /// Creates an enumerator for the current browse position. - /// - /// if set to true then browse branches. - /// The wrapped enumerator. - private EnumString CreateEnumerator(bool branches) - { - IEnumString unknown = null; - - string methodName = "IOPCHDA_Browser.GetEnum"; - - try - { - IOPCHDA_Browser server = BeginComCall(methodName, true); - - OPCHDA_BROWSETYPE browseType = OPCHDA_BROWSETYPE.OPCHDA_ITEMS; - - if (branches) - { - browseType = OPCHDA_BROWSETYPE.OPCHDA_BRANCH; - } - - server.GetEnum(browseType, out unknown); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - // wrapper the enumrator. hardcoding a buffer size of 256. - return new EnumString(unknown, 256); - } - #endregion - - #region Private Fields - private ComHdaClient m_client; - private string m_itemId; - private Opc.Ua.Com.Client.EnumString m_enumerator; - private bool m_completed; - private bool m_branches; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/ComHdaClient.cs b/ComIOP/Common/Client/Hda/ComHdaClient.cs deleted file mode 100644 index da00b15f8..000000000 --- a/ComIOP/Common/Client/Hda/ComHdaClient.cs +++ /dev/null @@ -1,2281 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using OpcRcw.Comn; -using OpcRcw.Hda; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; - -namespace Opc.Ua.Com.Client -{ - /// - /// Provides access to a COM DA server. - /// - public class ComHdaClient : ComClient - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// - public ComHdaClient(ComHdaClientConfiguration configuration) : base(configuration) - { - m_configuration = configuration; - } - #endregion - - #region ServerStatus Structure - /// - /// Stores the status of the server. - /// - public struct ServerStatus - { - /// - /// The server status. - /// - public OPCHDA_SERVERSTATUS wStatus; - - /// - /// The current server time. - /// - public DateTime ftCurrentTime; - - /// - /// The current server time. - /// - public DateTime ftStartTime; - - /// - /// The server major version. - /// - public short wMajorVersion; - - /// - /// The server minor version. - /// - public short wMinorVersion; - - /// - /// The server build number. - /// - public short wBuildNumber; - - /// - /// The maximum number of values returned. - /// - public int dwMaxReturnValues; - - /// - /// The server status information. - /// - public string szStatusString; - - /// - /// The server vendor information. - /// - public string szVendorInfo; - } - #endregion - - #region Public Methods - /// - /// Reads the status from the server. - /// - public ServerStatus? GetStatus() - { - string methodName = "IOPCHDA_Server.GetStatus"; - - try - { - - IOPCHDA_Server server = BeginComCall(methodName, true); - - ServerStatus pStatus; - IntPtr pftCurrentTime; - IntPtr pftStartTime; - - server.GetHistorianStatus( - out pStatus.wStatus, - out pftCurrentTime, - out pftStartTime, - out pStatus.wMajorVersion, - out pStatus.wMinorVersion, - out pStatus.wBuildNumber, - out pStatus.dwMaxReturnValues, - out pStatus.szStatusString, - out pStatus.szVendorInfo); - - pStatus.ftCurrentTime = ComUtils.GetDateTime(pftCurrentTime); - pStatus.ftStartTime = ComUtils.GetDateTime(pftStartTime); - - Marshal.FreeCoTaskMem(pftCurrentTime); - Marshal.FreeCoTaskMem(pftStartTime); - - // cache the capabilities. - m_maxReturnValues = pStatus.dwMaxReturnValues; - - return pStatus; - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - } - - /// - /// Updates the server metadata. - /// - public void UpdateServerMetadata() - { - HdaAttribute[] supportedAttributes = m_supportedAttributes; - - if (supportedAttributes == null) - { - lock (m_lock) - { - m_supportedAttributes = GetSupportedAttributes(); - m_annotationAccessLevel = GetAnnotationAccessLevel(); - m_updateCapabilities = GetUpdateCapabilities(); - } - } - } - - /// - /// Gets the history access level for the HDA server. - /// - public byte GetHistoryAccessLevel() - { - if (m_supportedAttributes == null) - { - UpdateServerMetadata(); - } - - if (m_updateCapabilities != 0) - { - return AccessLevels.HistoryReadOrWrite; - } - - return AccessLevels.HistoryRead; - } - - /// - /// Gets the server capabilities. - /// - /// The property id. - /// The default value. - /// - public object GetServerCapabilities(uint propertyId, object defaultValue) - { - if (m_supportedAttributes == null) - { - UpdateServerMetadata(); - } - - switch (propertyId) - { - case Opc.Ua.Variables.HistoryServerCapabilitiesType_MaxReturnDataValues: - { - return (uint)m_maxReturnValues; - } - - case Opc.Ua.Variables.HistoryServerCapabilitiesType_InsertDataCapability: - { - return (m_updateCapabilities & OPCHDA_UPDATECAPABILITIES.OPCHDA_INSERTCAP) != 0; - } - - case Opc.Ua.Variables.HistoryServerCapabilitiesType_ReplaceDataCapability: - { - return (m_updateCapabilities & OPCHDA_UPDATECAPABILITIES.OPCHDA_REPLACECAP) != 0; - } - - case Opc.Ua.Variables.HistoryServerCapabilitiesType_UpdateDataCapability: - { - return (m_updateCapabilities & OPCHDA_UPDATECAPABILITIES.OPCHDA_INSERTREPLACECAP) != 0; - } - - case Opc.Ua.Variables.HistoryServerCapabilitiesType_DeleteAtTimeCapability: - { - return (m_updateCapabilities & OPCHDA_UPDATECAPABILITIES.OPCHDA_DELETEATTIMECAP) != 0; - } - - case Opc.Ua.Variables.HistoryServerCapabilitiesType_DeleteRawCapability: - { - return (m_updateCapabilities & OPCHDA_UPDATECAPABILITIES.OPCHDA_DELETERAWCAP) != 0; - } - } - - return defaultValue; - } - - /// - /// Creates the browser. - /// - /// An object which browses branches and items. - public IOPCHDA_Browser CreateBrowser() - { - IOPCHDA_Browser browser = null; - - string methodName = "IOPCHDA_Server.CreateBrowser"; - - try - { - IOPCHDA_Server server = BeginComCall(methodName, true); - - IntPtr ppErrors; - - server.CreateBrowse( - 0, - new int[0], - new OPCHDA_OPERATORCODES[0], - new object[0], - out browser, - out ppErrors); - - Marshal.FreeCoTaskMem(ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - return browser; - } - - /// - /// Gets the supported attributes. - /// - public HdaAttribute[] GetSupportedAttributes() - { - string methodName = "IOPCHDA_Server.GetItemAttributes"; - - int pdwCount; - IntPtr ppdwAttrID; - IntPtr ppszAttrName; - IntPtr ppszAttrDesc; - IntPtr ppvtAttrDataType; - - try - { - IOPCHDA_Server server = BeginComCall(methodName, true); - - server.GetItemAttributes( - out pdwCount, - out ppdwAttrID, - out ppszAttrName, - out ppszAttrDesc, - out ppvtAttrDataType); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - int[] attributeIds = ComUtils.GetInt32s(ref ppdwAttrID, pdwCount, true); - string[] names = ComUtils.GetUnicodeStrings(ref ppszAttrName, pdwCount, true); - string[] descriptions = ComUtils.GetUnicodeStrings(ref ppszAttrDesc, pdwCount, true); - short[] datatypes = ComUtils.GetInt16s(ref ppvtAttrDataType, pdwCount, true); - - HdaAttribute[] results = new HdaAttribute[pdwCount]; - - for (int ii = 0; ii < results.Length; ii++) - { - HdaAttribute result = results[ii] = new HdaAttribute(); - - result.Id = Utils.ToUInt32(attributeIds[ii]); - result.Name = names[ii]; - result.Description = descriptions[ii]; - result.DataType = datatypes[ii]; - } - - return results; - } - - /// - /// Finds the specified aggregate. - /// - public BaseObjectState FindAggregate(uint aggregateId, ushort namespaceIndex) - { - BaseObjectState[] aggregates = GetSupportedAggregates(namespaceIndex); - - for (int ii = 0; ii < aggregates.Length; ii++) - { - if ((uint)aggregates[ii].Handle == aggregateId) - { - return aggregates[ii]; - } - } - - return null; - } - - /// - /// Gets the supported aggregates. - /// - public BaseObjectState[] GetSupportedAggregates(ushort namespaceIndex) - { - string methodName = "IOPCHDA_Server.GetAggregates"; - - int pdwCount; - IntPtr ppdwAggrID; - IntPtr ppszAggrName; - IntPtr ppszAggrDesc; - - try - { - IOPCHDA_Server server = BeginComCall(methodName, true); - - server.GetAggregates( - out pdwCount, - out ppdwAggrID, - out ppszAggrName, - out ppszAggrDesc); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - int[] aggregateIds = ComUtils.GetInt32s(ref ppdwAggrID, pdwCount, true); - string[] names = ComUtils.GetUnicodeStrings(ref ppszAggrName, pdwCount, true); - string[] descriptions = ComUtils.GetUnicodeStrings(ref ppszAggrDesc, pdwCount, true); - - BaseObjectState[] results = new BaseObjectState[pdwCount]; - - for (int ii = 0; ii < results.Length; ii++) - { - BaseObjectState aggregate = results[ii] = new BaseObjectState(null); - - aggregate.NodeId = HdaModelUtils.ConstructIdForHdaAggregate(Utils.ToUInt32(aggregateIds[ii]), namespaceIndex); - aggregate.SymbolicName = aggregateIds[ii].ToString(); - aggregate.BrowseName = new QualifiedName(aggregate.SymbolicName, namespaceIndex); - aggregate.DisplayName = names[ii]; - aggregate.Description = descriptions[ii]; - aggregate.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasComponent; - aggregate.TypeDefinitionId = Opc.Ua.ObjectTypeIds.AggregateFunctionType; - aggregate.Handle = (uint)aggregateIds[ii]; - } - - return results; - } - - /// - /// Get handles for the specified items. - /// - public HdaItem[] GetItems(params string[] itemIds) - { - string methodName = "IOPCHDA_Server.GetItemHandles"; - - if (itemIds == null) - { - return null; - } - - IntPtr pphServer; - IntPtr ppErrors; - - try - { - IOPCHDA_Server server = BeginComCall(methodName, true); - - server.GetItemHandles( - itemIds.Length, - itemIds, - new int[itemIds.Length], - out pphServer, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - int[] serverHandles = ComUtils.GetInt32s(ref pphServer, itemIds.Length, true); - int[] errors = ComUtils.GetInt32s(ref ppErrors, itemIds.Length, true); - - HdaItem[] results = new HdaItem[itemIds.Length]; - - for (int ii = 0; ii < results.Length; ii++) - { - HdaItem result = results[ii] = new HdaItem(); - - result.ItemId = itemIds[ii]; - result.ServerHandle = serverHandles[ii]; - result.Error = errors[ii]; - } - - return results; - } - - /// - /// Validates the item ids. - /// - public bool[] ValidateItemIds(params string[] itemIds) - { - string methodName = "IOPCHDA_Server.ValidateItemIDs"; - - if (itemIds == null) - { - return null; - } - - IntPtr ppErrors; - - try - { - IOPCHDA_Server server = BeginComCall(methodName, true); - - server.ValidateItemIDs( - itemIds.Length, - itemIds, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - int[] errors = ComUtils.GetInt32s(ref ppErrors, itemIds.Length, true); - - bool[] results = new bool[itemIds.Length]; - - for (int ii = 0; ii < results.Length; ii++) - { - results[ii] = errors[ii] >= 0; - } - - return results; - } - - /// - /// Releases the handles for the items. - /// - public void ReleaseItemHandles(HdaItem[] items) - { - if (items == null) - { - return; - } - - int[] serverHandles = new int[items.Length]; - - for (int ii = 0; ii < items.Length; ii++) - { - serverHandles[ii] = items[ii].ServerHandle; - } - - int[] errors = ReleaseItemHandles(serverHandles); - - for (int ii = 0; ii < items.Length; ii++) - { - items[ii].ServerHandle = 0; - items[ii].Error = ResultIds.E_FAIL; - - if (errors != null) - { - items[ii].Error = errors[ii]; - } - } - } - - /// - /// Releases the handles for the items. - /// - public int[] ReleaseItemHandles(params int[] serverHandles) - { - string methodName = "IOPCHDA_Server.GetItemHandles"; - - IntPtr ppErrors; - - try - { - IOPCHDA_Server server = BeginComCall(methodName, true); - - server.ReleaseItemHandles( - serverHandles.Length, - serverHandles, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - return ComUtils.GetInt32s(ref ppErrors, serverHandles.Length, true); - } - - /// - /// Updates the attributes for the items. - /// - public HdaAttributeValue[] ReadAttributeValues(int serverHandle, params int[] attributeIds) - { - string methodName = "IOPCHDA_SyncRead.ReadAttribute"; - - OPCHDA_TIME htStartTime; - htStartTime.bString = 1; - htStartTime.szTime = "NOW"; - htStartTime.ftTime.dwHighDateTime = 0; - htStartTime.ftTime.dwLowDateTime = 0; - - OPCHDA_TIME htEndTime; - htEndTime.bString = 1; - htEndTime.szTime = String.Empty; - htEndTime.ftTime.dwHighDateTime = 0; - htEndTime.ftTime.dwLowDateTime = 0; - - IntPtr ppAttributeValues; - IntPtr ppErrors; - - try - { - IOPCHDA_SyncRead server = BeginComCall(methodName, true); - - server.ReadAttribute( - ref htStartTime, - ref htEndTime, - serverHandle, - attributeIds.Length, - attributeIds, - out ppAttributeValues, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return null; - } - finally - { - EndComCall(methodName); - } - - int[] errors = ComUtils.GetInt32s(ref ppErrors, attributeIds.Length, true); - - HdaAttributeValue[] results = new HdaAttributeValue[attributeIds.Length]; - IntPtr pos = ppAttributeValues; - - for (int ii = 0; ii < attributeIds.Length; ii++) - { - HdaAttributeValue result = results[ii] = new HdaAttributeValue(); - - result.AttributeId = Utils.ToUInt32(attributeIds[ii]); - result.Error = errors[ii]; - - OPCHDA_ATTRIBUTE attributes = (OPCHDA_ATTRIBUTE)Marshal.PtrToStructure(pos, typeof(OPCHDA_ATTRIBUTE)); - - if (attributes.dwNumValues > 0) - { - object[] values = ComUtils.GetVARIANTs(ref attributes.vAttributeValues, attributes.dwNumValues, true); - DateTime[] timestamps = ComUtils.GetDateTimes(ref attributes.ftTimeStamps, attributes.dwNumValues, true); - - result.Value = ComUtils.ProcessComValue(values[0]); - result.Timestamp = timestamps[0]; - } - - pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(OPCHDA_ATTRIBUTE))); - } - - Marshal.FreeCoTaskMem(ppAttributeValues); - - return results; - } - - /// - /// Reads the values for all available attributes. - /// - /// The item. - /// The list of attribute values for the item. - public HdaAttributeValue[] ReadAvailableAttributes(HdaItem item) - { - if (item == null) - { - return null; - } - - // get the supported attributes. - if (m_supportedAttributes == null) - { - UpdateServerMetadata(); - } - - HdaAttribute[] supportedAttributes = m_supportedAttributes; - - if (supportedAttributes == null || supportedAttributes.Length == 0) - { - return null; - } - - // read the attribute values. - int[] attributeIds = new int[supportedAttributes.Length]; - - for (int ii = 0; ii < supportedAttributes.Length; ii++) - { - attributeIds[ii] = Utils.ToInt32(supportedAttributes[ii].Id); - } - - return ReadAttributeValues(item.ServerHandle, attributeIds); - } - - /// - /// Finds the UA defined component of the item. - /// - /// The item id. - /// The attribute id. - /// Index of the namespace. - /// - public PropertyState FindItemAttribute(string itemId, uint attributeId, ushort namespaceIndex) - { - if (itemId == null) - { - return null; - } - - // get the supported attributes. - if (m_supportedAttributes == null) - { - UpdateServerMetadata(); - } - - HdaAttribute[] supportedAttributes = m_supportedAttributes; - - if (supportedAttributes == null || supportedAttributes.Length == 0) - { - return null; - } - - // validate the attribute. - HdaAttribute attribute = null; - - for (int ii = 0; ii < supportedAttributes.Length; ii++) - { - if (attributeId == supportedAttributes[ii].Id) - { - attribute = supportedAttributes[ii]; - break; - } - } - - if (attribute == null) - { - return null; - } - - // check for attributes which are not exposed. - switch (attributeId) - { - case Constants.OPCHDA_ITEMID: - case Constants.OPCHDA_DATA_TYPE: - case Constants.OPCHDA_DESCRIPTION: - case Constants.OPCHDA_ARCHIVING: - case Constants.OPCHDA_NORMAL_MINIMUM: - case Constants.OPCHDA_LOW_ENTRY_LIMIT: - { - return null; - } - } - - // create the property. - HdaAttributeState property = new HdaAttributeState( - m_configuration, - itemId, - attribute, - namespaceIndex); - - return property; - } - - /// - /// Finds the item annotations. - /// - /// The item id. - /// Index of the namespace. - /// - public PropertyState FindItemAnnotations(string itemId, ushort namespaceIndex) - { - if (itemId == null) - { - return null; - } - - // check if the server supports annotations. - if (m_supportedAttributes == null) - { - UpdateServerMetadata(); - } - - if (m_annotationAccessLevel == 0) - { - return null; - } - - - // create the property. - PropertyState property = HdaModelUtils.GetItemAnnotationsNode(itemId, namespaceIndex); - - property.AccessLevel = m_annotationAccessLevel; - property.UserAccessLevel = m_annotationAccessLevel; - - return property; - } - - /// - /// Reads the specified requests. - /// - /// The requests. - /// if set to true use the handles specified in the request objects. - public void Read(HdaReadRequestCollection requests, bool useExistingHandles) - { - // check if nothing to do. - if (requests == null || requests.Count == 0) - { - return; - } - - int[] serverHandles = new int[requests.Count]; - int[] itemErrors = null; - HdaItem[] items = null; - - // check if using existing handles. - if (useExistingHandles) - { - for (int ii = 0; ii < requests.Count; ii++) - { - serverHandles[ii] = requests[ii].ServerHandle; - } - } - - // create new handles to use for the request. - else - { - string[] itemIds = new string[requests.Count]; - itemErrors = new int[requests.Count]; - - for (int ii = 0; ii < requests.Count; ii++) - { - itemIds[ii] = requests[ii].ItemId; - } - - items = GetItems(itemIds); - - for (int ii = 0; ii < requests.Count; ii++) - { - serverHandles[ii] = items[ii].ServerHandle; - itemErrors[ii] = items[ii].Error; - } - } - - // read attributes. - try - { - for (int ii = 0; ii < serverHandles.Length; ii++) - { - HdaReadRequest request = requests[ii]; - - if (itemErrors != null && itemErrors[ii] < 0) - { - request.SetError(request.AttributeIds.Count); - continue; - } - - try - { - int[] attributeIds = new int[request.AttributeIds.Count]; - - for (int jj = 0; jj < attributeIds.Length; jj++) - { - attributeIds[jj] = Utils.ToInt32(request.AttributeIds[jj]); - } - - request.AttributeValues = ReadAttributeValues(serverHandles[ii], attributeIds); - } - catch (Exception e) - { - request.SetError(Marshal.GetHRForException(e)); - } - } - } - finally - { - if (items != null) - { - ReleaseItemHandles(items); - } - } - } - - /// - /// Reads the raw data history. - /// - /// The request. - public StatusCode ReadHistory(HdaHistoryReadRawModifiedRequest request) - { - // check if nothing to do. - if (request == null) - { - return StatusCodes.BadNothingToDo; - } - - HdaItem[] items = GetItems(request.ItemId); - - if (items == null || items[0].Error < 0) - { - return StatusCodes.BadNodeIdUnknown; - } - - request.ServerHandle = items[0].ServerHandle; - - try - { - if (request.IsReadModified) - { - return ReadModified(request); - } - - return ReadRaw(request); - } - catch (Exception) - { - return StatusCodes.BadUnexpectedError; - } - finally - { - ReleaseItemHandles(request.ServerHandle); - request.ServerHandle = 0; - } - } - - /// - /// Reads the data history at specified times. - /// - public StatusCode ReadHistory(HdaHistoryReadAtTimeRequest request) - { - if (request == null) - { - return StatusCodes.BadNothingToDo; - } - - HdaItem[] items = GetItems(request.ItemId); - - if (items == null || items[0].Error < 0) - { - return StatusCodes.BadNodeIdUnknown; - } - - request.ServerHandle = items[0].ServerHandle; - - try - { - return ReadAtTime(request); - } - catch (Exception) - { - return StatusCodes.BadUnexpectedError; - } - finally - { - ReleaseItemHandles(request.ServerHandle); - request.ServerHandle = 0; - } - } - - /// - /// Updates the history of an item. - /// - public StatusCode UpdateData(string itemId, UpdateDataDetails details, HistoryUpdateResult result) - { - // create handles. - HdaItem[] items = GetItems(itemId); - - if (items == null || items[0].Error < 0) - { - result.StatusCode = StatusCodes.BadNodeIdUnknown; - return result.StatusCode; - } - - int[] errors = null; - - try - { - // update data. - result.StatusCode = UpdateData( - items[0], - details.PerformInsertReplace, - details.UpdateValues, - out errors); - - // update error codes. - for (int ii = 0; ii < errors.Length; ii++) - { - StatusCode statusCode = MapErrorCodeToUpdateStatus(errors[ii]); - result.OperationResults.Add(statusCode); - } - } - catch (Exception) - { - result.StatusCode = StatusCodes.BadUnexpectedError; - } - finally - { - // reelase handles. - ReleaseItemHandles(items); - } - - return result.StatusCode; - } - - /// - /// Updates the history of an item. - /// - public StatusCode DeleteRaw(string itemId, DeleteRawModifiedDetails details, HistoryUpdateResult result) - { - // create handles. - HdaItem[] items = GetItems(itemId); - - if (items == null || items[0].Error < 0) - { - result.StatusCode = StatusCodes.BadNodeIdUnknown; - return result.StatusCode; - } - - try - { - // update data. - result.StatusCode = DeleteRaw( - items[0], - details.StartTime, - details.EndTime); - } - catch (Exception) - { - result.StatusCode = StatusCodes.BadUnexpectedError; - } - finally - { - // release handles. - ReleaseItemHandles(items); - } - - return result.StatusCode; - } - - /// - /// Updates the history of an item. - /// - public StatusCode DeleteAtTime(string itemId, DeleteAtTimeDetails details, HistoryUpdateResult result) - { - // create handles. - HdaItem[] items = GetItems(itemId); - - if (items == null || items[0].Error < 0) - { - result.StatusCode = StatusCodes.BadNodeIdUnknown; - return result.StatusCode; - } - - try - { - int[] errors = DeleteAtTime(items[0], details.ReqTimes); - - // update error codes. - for (int ii = 0; ii < errors.Length; ii++) - { - StatusCode statusCode = MapErrorCodeToUpdateStatus(errors[ii]); - result.OperationResults.Add(statusCode); - } - } - catch (Exception) - { - result.StatusCode = StatusCodes.BadUnexpectedError; - } - finally - { - // release handles. - ReleaseItemHandles(items); - } - - return result.StatusCode; - } - - /// - /// Inserts annotations for item. - /// - /// The item id. - /// The details. - /// The result. - /// - public StatusCode InsertAnnotations(string itemId, UpdateDataDetails details, HistoryUpdateResult result) - { - // only insert supported. - if (details.PerformInsertReplace != PerformUpdateType.Insert) - { - result.StatusCode = StatusCodes.BadHistoryOperationUnsupported; - return result.StatusCode; - } - - // create handles. - HdaItem[] items = GetItems(itemId); - - if (items == null || items[0].Error < 0) - { - result.StatusCode = StatusCodes.BadNodeIdUnknown; - return result.StatusCode; - } - - int[] errors = null; - - try - { - // update data. - result.StatusCode = InsertAnnotations( - items[0], - details.UpdateValues, - out errors); - - // update error codes. - for (int ii = 0; ii < errors.Length; ii++) - { - StatusCode statusCode = MapErrorCodeToUpdateStatus(errors[ii]); - result.OperationResults.Add(statusCode); - } - } - catch (Exception) - { - result.StatusCode = StatusCodes.BadUnexpectedError; - } - finally - { - // reelase handles. - ReleaseItemHandles(items); - } - - return result.StatusCode; - } - - /// - /// Converts a HRESULT returned during a HistoryUpdate to an StatusCode. - /// - internal static StatusCode MapErrorCodeToUpdateStatus(int error) - { - // map bad status codes. - if (error < 0) - { - switch (error) - { - case ResultIds.E_OUTOFMEMORY: { return StatusCodes.BadOutOfMemory; } - case ResultIds.E_BADRIGHTS: { return StatusCodes.BadNotWritable; } - case ResultIds.E_ACCESSDENIED: { return StatusCodes.BadUserAccessDenied; } - case ResultIds.E_RANGE: { return StatusCodes.BadOutOfRange; } - case ResultIds.E_BADTYPE: { return StatusCodes.BadTypeMismatch; } - case ResultIds.DISP_E_OVERFLOW: { return StatusCodes.BadOutOfRange; } - case ResultIds.DISP_E_TYPEMISMATCH: { return StatusCodes.BadTypeMismatch; } - case ResultIds.E_DATAEXISTS: { return StatusCodes.BadEntryExists; } - case ResultIds.E_NODATAEXISTS: { return StatusCodes.BadNoEntryExists; } - } - - return StatusCodes.BadUnexpectedError; - } - - // ignore uncertain and success codes. - return ResultIds.S_OK; - } - - /// - /// Update data - /// - private StatusCode UpdateData( - HdaItem item, - PerformUpdateType updateType, - DataValueCollection values, - out int[] errors) - { - errors = null; - string methodName = "IOPCHDA_SyncUpdate.Insert"; - - int dwNumItems = values.Count; - int[] phServer = new int[dwNumItems]; - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps = new System.Runtime.InteropServices.ComTypes.FILETIME[dwNumItems]; - object[] vDataValues = new object[dwNumItems]; - int[] pdwQualities = new int[dwNumItems]; - - for (int ii = 0; ii < dwNumItems; ii++) - { - DataValue value = values[ii]; - - phServer[ii] = item.ServerHandle; - vDataValues[ii] = ComUtils.GetVARIANT(value.WrappedValue); - pdwQualities[ii] = Utils.ToInt32(ComUtils.GetHdaQualityCode(value.StatusCode)); - ftTimeStamps[ii] = ComUtils.GetFILETIME(value.SourceTimestamp); - } - - IntPtr ppErrors = IntPtr.Zero; - - try - { - IOPCHDA_SyncUpdate server = BeginComCall(methodName, true); - - switch (updateType) - { - case PerformUpdateType.Insert: - { - server.Insert( - dwNumItems, - phServer, - ftTimeStamps, - vDataValues, - pdwQualities, - out ppErrors); - - break; - } - - case PerformUpdateType.Update: - { - server.InsertReplace( - dwNumItems, - phServer, - ftTimeStamps, - vDataValues, - pdwQualities, - out ppErrors); - - break; - } - - case PerformUpdateType.Replace: - { - server.Replace( - dwNumItems, - phServer, - ftTimeStamps, - vDataValues, - pdwQualities, - out ppErrors); - - break; - } - } - - // check for error. - errors = ComUtils.GetInt32s(ref ppErrors, dwNumItems, true); - } - catch (Exception e) - { - ComCallError(methodName, e); - return StatusCodes.BadUnexpectedError; - } - finally - { - EndComCall(methodName); - } - - return StatusCodes.Good; - } - - /// - /// Insert annotations. - /// - private StatusCode InsertAnnotations( - HdaItem item, - DataValueCollection values, - out int[] errors) - { - errors = null; - string methodName = "IOPCHDA_SyncAnnotations.Insert"; - - int dwNumItems = values.Count; - int[] phServer = new int[dwNumItems]; - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps = new System.Runtime.InteropServices.ComTypes.FILETIME[dwNumItems]; - OPCHDA_ANNOTATION[] pAnnotationValues = new OPCHDA_ANNOTATION[dwNumItems]; - - IntPtr ppErrors; - - try - { - for (int ii = 0; ii < dwNumItems; ii++) - { - DataValue value = values[ii]; - - phServer[ii] = item.ServerHandle; - ftTimeStamps[ii] = ComUtils.GetFILETIME(value.SourceTimestamp); - pAnnotationValues[ii] = new OPCHDA_ANNOTATION(); - - // pass an empty structure if the annotation is not valid. - pAnnotationValues[ii].dwNumValues = 0; - - Annotation annotation = value.GetValue(null); - - if (annotation != null && !String.IsNullOrEmpty(annotation.Message)) - { - pAnnotationValues[ii].dwNumValues = 1; - pAnnotationValues[ii].ftAnnotationTime = ComUtils.GetFILETIMEs(new DateTime[] { annotation.AnnotationTime }); - pAnnotationValues[ii].ftTimeStamps = ComUtils.GetFILETIMEs(new DateTime[] { value.SourceTimestamp }); - pAnnotationValues[ii].szAnnotation = ComUtils.GetUnicodeStrings(new string[] { annotation.Message }); - pAnnotationValues[ii].szUser = ComUtils.GetUnicodeStrings(new string[] { annotation.UserName }); - } - } - - IOPCHDA_SyncAnnotations server = BeginComCall(methodName, true); - - server.Insert( - dwNumItems, - phServer, - ftTimeStamps, - pAnnotationValues, - out ppErrors); - - // check for error. - errors = ComUtils.GetInt32s(ref ppErrors, dwNumItems, true); - - // set bad type error for invalid annotations. - for (int ii = 0; ii < dwNumItems; ii++) - { - if (pAnnotationValues[ii].dwNumValues == 0) - { - errors[ii] = ResultIds.E_BADTYPE; - } - } - } - catch (Exception e) - { - ComCallError(methodName, e); - return StatusCodes.BadUnexpectedError; - } - finally - { - EndComCall(methodName); - - // free allocated memory. - for (int ii = 0; ii < dwNumItems; ii++) - { - if (pAnnotationValues[ii].dwNumValues == 0) - { - continue; - } - - IntPtr[] pointers = new IntPtr[1]; - Marshal.Copy(pAnnotationValues[ii].szUser, pointers, 0, 1); - Marshal.FreeCoTaskMem(pointers[0]); - - Marshal.Copy(pAnnotationValues[ii].szAnnotation, pointers, 0, 1); - Marshal.FreeCoTaskMem(pointers[0]); - - Marshal.FreeCoTaskMem(pAnnotationValues[ii].ftAnnotationTime); - Marshal.FreeCoTaskMem(pAnnotationValues[ii].ftTimeStamps); - Marshal.FreeCoTaskMem(pAnnotationValues[ii].szUser); - Marshal.FreeCoTaskMem(pAnnotationValues[ii].szAnnotation); - } - } - - return StatusCodes.Good; - } - - /// - /// Reads the processed data history. - /// - public StatusCode ReadHistory(HdaHistoryReadProcessedRequest request) - { - if (request == null) - { - return StatusCodes.BadNothingToDo; - } - - HdaItem[] items = GetItems(request.ItemId); - - if (items == null || items[0].Error < 0) - { - return StatusCodes.BadNodeIdUnknown; - } - - request.ServerHandle = items[0].ServerHandle; - - try - { - return ReadProcessed(request); - } - catch (Exception) - { - return StatusCodes.BadUnexpectedError; - } - finally - { - ReleaseItemHandles(request.ServerHandle); - request.ServerHandle = 0; - } - } - - /// - /// Reads the raw data history. - /// - /// The request. - public StatusCode ReadAttributeHistory(HdaHistoryReadAttributeRequest request) - { - // check if nothing to do. - if (request == null) - { - return StatusCodes.BadNothingToDo; - } - - // create the handle. - HdaItem[] items = GetItems(request.ItemId); - - if (items == null || items[0].Error < 0) - { - return StatusCodes.BadNodeIdUnknown; - } - - request.ServerHandle = items[0].ServerHandle; - - try - { - // read modified not supported for attributes. - if (request.IsReadModified) - { - return StatusCodes.BadNoData; - } - - // convert the requested attribute to a list of attributes to read. - int[] attributeIds = null; - - switch (request.AttributeId) - { - case Constants.OPCHDA_NORMAL_MAXIMUM: - { - attributeIds = new int[] { Constants.OPCHDA_NORMAL_MAXIMUM, Constants.OPCHDA_NORMAL_MINIMUM }; - break; - } - - case Constants.OPCHDA_HIGH_ENTRY_LIMIT: - { - attributeIds = new int[] { Constants.OPCHDA_HIGH_ENTRY_LIMIT, Constants.OPCHDA_LOW_ENTRY_LIMIT }; - break; - } - - default: - { - attributeIds = new int[] { Utils.ToInt32(request.AttributeId) }; - break; - } - } - - // read the values and them in the request object. - return ReadAttributes(request, attributeIds); - } - catch (Exception) - { - return StatusCodes.BadUnexpectedError; - } - finally - { - ReleaseItemHandles(request.ServerHandle); - request.ServerHandle = 0; - } - } - - /// - /// Reads the raw data history. - /// - /// The request. - public StatusCode ReadAnnotationHistory(HdaHistoryReadAnnotationRequest request) - { - // check if nothing to do. - if (request == null) - { - return StatusCodes.BadNothingToDo; - } - - // create the handle. - HdaItem[] items = GetItems(request.ItemId); - - if (items == null || items[0].Error < 0) - { - return StatusCodes.BadNodeIdUnknown; - } - - request.ServerHandle = items[0].ServerHandle; - - try - { - // read modified not supported for annotations. - if (request.IsReadModified) - { - return StatusCodes.BadNoData; - } - - // read the values and them in the request object. - return ReadAnnotations(request); - } - catch (Exception) - { - return StatusCodes.BadUnexpectedError; - } - finally - { - ReleaseItemHandles(request.ServerHandle); - request.ServerHandle = 0; - } - } - #endregion - - #region Private Methods - /// - /// Gets the access level for annotations provided by the server. - /// - private byte GetAnnotationAccessLevel() - { - string methodName = "IOPCHDA_SyncAnnotations.QueryCapabilities"; - - OPCHDA_ANNOTATIONCAPABILITIES pCapabilities = 0; - - try - { - IOPCHDA_SyncAnnotations server = BeginComCall(methodName, false); - - if (server == null) - { - return 0; - } - - server.QueryCapabilities(out pCapabilities); - } - catch (Exception e) - { - ComCallError(methodName, e); - return 0; - } - finally - { - EndComCall(methodName); - } - - byte accessLevel = AccessLevels.None; - - if ((pCapabilities & OPCHDA_ANNOTATIONCAPABILITIES.OPCHDA_READANNOTATIONCAP) != 0) - { - accessLevel |= AccessLevels.HistoryRead; - } - - if ((pCapabilities & OPCHDA_ANNOTATIONCAPABILITIES.OPCHDA_INSERTANNOTATIONCAP) != 0) - { - accessLevel |= AccessLevels.HistoryWrite; - } - - return accessLevel; - } - - /// - /// Gets the update capabilities for the server. - /// - private OPCHDA_UPDATECAPABILITIES GetUpdateCapabilities() - { - string methodName = "IOPCHDA_SyncUpdate.QueryCapabilities"; - - OPCHDA_UPDATECAPABILITIES pCapabilities = 0; - - try - { - IOPCHDA_SyncUpdate server = BeginComCall(methodName, false); - - if (server == null) - { - return 0; - } - - server.QueryCapabilities(out pCapabilities); - } - catch (Exception e) - { - ComCallError(methodName, e); - return 0; - } - finally - { - EndComCall(methodName); - } - - return pCapabilities; - } - - /// - /// Converts the DateTime to an OPCHDA_TIME. - /// - /// The time. - private OPCHDA_TIME ConvertTime(DateTime time) - { - OPCHDA_TIME htTime = new OPCHDA_TIME(); - - if (time != DateTime.MinValue) - { - htTime.bString = 0; - htTime.ftTime = ComUtils.GetFILETIME(time); - } - else - { - htTime.bString = 1; - htTime.szTime = String.Empty; - } - - return htTime; - } - - /// - /// Deletes the raw data for an item. - /// - private StatusCode DeleteRaw(HdaItem item, DateTime startTime, DateTime endTime) - { - string methodName = "IOPCHDA_SyncUpdate.DeleteRaw"; - - OPCHDA_TIME htStartTime = ConvertTime(startTime); - OPCHDA_TIME htEndTime = ConvertTime(endTime); - - IntPtr ppErrors; - - try - { - IOPCHDA_SyncUpdate server = BeginComCall(methodName, true); - - server.DeleteRaw( - ref htStartTime, - ref htEndTime, - 1, - new int[] { item.ServerHandle }, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return StatusCodes.BadUnexpectedError; - } - finally - { - EndComCall(methodName); - } - - int[] errors = ComUtils.GetInt32s(ref ppErrors, 1, true); - return MapErrorCodeToUpdateStatus(errors[0]); - } - - /// - /// Deletes the raw data for an item. - /// - private int[] DeleteAtTime(HdaItem item, DateTimeCollection timestamps) - { - string methodName = "IOPCHDA_SyncUpdate.DeleteAtTime"; - - int count = timestamps.Count; - int[] serverHandles = new int[count]; - System.Runtime.InteropServices.ComTypes.FILETIME[] pTimestamps = new System.Runtime.InteropServices.ComTypes.FILETIME[count]; - - for (int ii = 0; ii < count; ii++) - { - serverHandles[ii] = item.ServerHandle; - pTimestamps[ii] = ComUtils.GetFILETIME(timestamps[ii]); - } - - IntPtr ppErrors; - - try - { - IOPCHDA_SyncUpdate server = BeginComCall(methodName, true); - - server.DeleteAtTime( - count, - serverHandles, - pTimestamps, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - - int[] errors = new int[count]; - - for (int ii = 0; ii < count; ii++) - { - errors[ii] = ResultIds.E_FAIL; - } - - return errors; - } - finally - { - EndComCall(methodName); - } - - return ComUtils.GetInt32s(ref ppErrors, count, true); - } - - /// - /// Reads the raw data for an item. - /// - private StatusCode ReadRaw(HdaHistoryReadRawModifiedRequest request) - { - string methodName = "IOPCHDA_SyncRead.ReadRaw"; - - OPCHDA_TIME htStartTime = ConvertTime(request.StartTime); - OPCHDA_TIME htEndTime = ConvertTime(request.EndTime); - - int maxReturnValues = request.MaxReturnValues; - - if (m_maxReturnValues > 0 && maxReturnValues > m_maxReturnValues) - { - maxReturnValues = m_maxReturnValues; - } - - // must have a least two values. - if (request.MaxReturnValues == 1 && request.TotalValuesReturned > 0) - { - maxReturnValues = 2; - } - - IntPtr ppItemValues; - IntPtr ppErrors; - - try - { - IOPCHDA_SyncRead server = BeginComCall(methodName, true); - - server.ReadRaw( - ref htStartTime, - ref htEndTime, - maxReturnValues, - (request.ReturnBounds)?1:0, - 1, - new int[] { request.ServerHandle }, - out ppItemValues, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return StatusCodes.BadUnexpectedError; - } - finally - { - EndComCall(methodName); - } - - // check for error. - int[] errors = ComUtils.GetInt32s(ref ppErrors, 1, true); - - if (errors[0] < 0) - { - return StatusCodes.BadNodeIdUnknown; - } - - // check if operation halted. - request.Completed = errors[0] != ResultIds.S_MOREDATA; - - // unmarshal the results. - OPCHDA_ITEM result = (OPCHDA_ITEM)Marshal.PtrToStructure(ppItemValues, typeof(OPCHDA_ITEM)); - - if (result.dwCount > 0) - { - object[] values = ComUtils.GetVARIANTs(ref result.pvDataValues, result.dwCount, true); - int[] qualities = ComUtils.GetInt32s(ref result.pdwQualities, result.dwCount, true); - DateTime[] timestamps = ComUtils.GetDateTimes(ref result.pftTimeStamps, result.dwCount, true); - - request.Results = new DataValueCollection(result.dwCount); - - for (int ii = 0; ii < result.dwCount; ii++) - { - // suppress previously returned values. - if (ii == 0 && request.TotalValuesReturned > 0) - { - if (request.StartTime < request.EndTime && timestamps[ii] <= request.StartTime) - { - continue; - } - - if (request.StartTime > request.EndTime && timestamps[ii] >= request.StartTime) - { - continue; - } - } - - DataValue value = new DataValue(); - value.Value = ComUtils.ProcessComValue(values[ii]); - value.StatusCode = ComUtils.GetHdaQualityCode(Utils.ToUInt32(qualities[ii])); - value.SourceTimestamp = timestamps[ii]; - request.Results.Add(value); - } - - request.TotalValuesReturned += request.Results.Count; - - if (!request.Completed) - { - request.StartTime = request.Results[request.Results.Count-1].SourceTimestamp; - } - } - - Marshal.FreeCoTaskMem(ppItemValues); - - if (result.dwCount == 0) - { - return StatusCodes.GoodNoData; - } - - if (maxReturnValues > 0 && !request.Completed) - { - return StatusCodes.GoodMoreData; - } - - return StatusCodes.Good; - } - - /// - /// Reads the raw modified data for an item. - /// - private StatusCode ReadModified(HdaHistoryReadRawModifiedRequest request) - { - string methodName = "IOPCHDA_SyncRead.ReadModified"; - - OPCHDA_TIME htStartTime = ConvertTime(request.StartTime); - OPCHDA_TIME htEndTime = ConvertTime(request.EndTime); - - int maxReturnValues = request.MaxReturnValues; - - if (m_maxReturnValues > 0 && maxReturnValues > m_maxReturnValues) - { - maxReturnValues = m_maxReturnValues; - } - - IntPtr ppItemValues; - IntPtr ppErrors; - - try - { - IOPCHDA_SyncRead server = BeginComCall(methodName, true); - - server.ReadModified( - ref htStartTime, - ref htEndTime, - maxReturnValues, - 1, - new int[] { request.ServerHandle }, - out ppItemValues, - out ppErrors); - } - catch (Exception e) - { - if (ComUtils.IsUnknownError(e, ResultIds.E_NOTIMPL)) - { - ComCallError(methodName, e); - } - - return StatusCodes.BadNoData; - } - finally - { - EndComCall(methodName); - } - - // check for error. - int[] errors = ComUtils.GetInt32s(ref ppErrors, 1, true); - - if (errors[0] < 0) - { - return StatusCodes.BadNodeIdUnknown; - } - - // check if operation halted. - request.Completed = errors[0] != ResultIds.S_MOREDATA; - - // unmarshal the results. - OPCHDA_MODIFIEDITEM result = (OPCHDA_MODIFIEDITEM)Marshal.PtrToStructure(ppItemValues, typeof(OPCHDA_MODIFIEDITEM)); - - if (result.dwCount > 0) - { - object[] values = ComUtils.GetVARIANTs(ref result.pvDataValues, result.dwCount, true); - int[] qualities = ComUtils.GetInt32s(ref result.pdwQualities, result.dwCount, true); - DateTime[] timestamps = ComUtils.GetDateTimes(ref result.pftTimeStamps, result.dwCount, true); - DateTime[] modificationTimes = ComUtils.GetDateTimes(ref result.pftModificationTime, result.dwCount, true); - string[] userNames = ComUtils.GetUnicodeStrings(ref result.szUser, result.dwCount, true); - int[] editTypes = ComUtils.GetInt32s(ref result.pEditType, result.dwCount, true); - - request.Results = new DataValueCollection(result.dwCount); - request.ModificationInfos = new ModificationInfoCollection(result.dwCount); - - for (int ii = 0; ii < result.dwCount; ii++) - { - DataValue value = new DataValue(); - value.Value = ComUtils.ProcessComValue(values[ii]); - value.StatusCode = ComUtils.GetHdaQualityCode(Utils.ToUInt32(qualities[ii])); - value.SourceTimestamp = timestamps[ii]; - request.Results.Add(value); - - ModificationInfo modification = new ModificationInfo(); - modification.ModificationTime = modificationTimes[ii]; - modification.UpdateType = (HistoryUpdateType)editTypes[ii]; - modification.UserName = userNames[ii]; - request.ModificationInfos.Add(modification); - } - - if (!request.Completed) - { - request.StartTime = request.Results[request.Results.Count-1].SourceTimestamp; - } - } - - Marshal.FreeCoTaskMem(ppItemValues); - - if (result.dwCount == 0) - { - return StatusCodes.GoodNoData; - } - - if (maxReturnValues > 0 && !request.Completed) - { - return StatusCodes.GoodMoreData; - } - - return StatusCodes.Good; - } - - /// - /// Reads the raw data for an item. - /// - private StatusCode ReadProcessed(HdaHistoryReadProcessedRequest request) - { - string methodName = "IOPCHDA_SyncRead.ReadProcessed"; - - DateTime startTime = request.StartTime; - DateTime endTime = request.EndTime; - - // adjust the resample interval. - if (m_maxReturnValues > 0 && request.ResampleInterval > 0) - { - double range = (startTime - endTime).TotalMilliseconds; - double resampleInterval = request.ResampleInterval; - - if (Math.Abs(range/resampleInterval) > m_maxReturnValues) - { - range = resampleInterval*m_maxReturnValues; - - if (startTime > endTime) - { - range = -range; - } - - endTime = startTime.AddMilliseconds(range); - } - } - - OPCHDA_TIME htStartTime = ConvertTime(startTime); - OPCHDA_TIME htEndTime = ConvertTime(endTime); - - System.Runtime.InteropServices.ComTypes.FILETIME ftResampleInterval; - - ulong ticks = (ulong)request.ResampleInterval*TimeSpan.TicksPerMillisecond; - ftResampleInterval.dwHighDateTime = (int)((0xFFFFFFFF00000000 & ticks) >> 32); - ftResampleInterval.dwLowDateTime = (int)(ticks & 0x00000000FFFFFFFF); - - IntPtr ppItemValues; - IntPtr ppErrors; - - try - { - IOPCHDA_SyncRead server = BeginComCall(methodName, true); - - server.ReadProcessed( - ref htStartTime, - ref htEndTime, - ftResampleInterval, - 1, - new int[] { request.ServerHandle }, - new int[] { Utils.ToInt32(request.AggregateId) }, - out ppItemValues, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return StatusCodes.BadUnexpectedError; - } - finally - { - EndComCall(methodName); - } - - // check for error. - int[] errors = ComUtils.GetInt32s(ref ppErrors, 1, true); - - if (errors[0] < 0) - { - if (errors[0] == ResultIds.E_NOT_AVAIL) - { - return StatusCodes.BadAggregateNotSupported; - } - - return StatusCodes.BadNodeIdUnknown; - } - - // check if operation halted. - request.Completed = endTime == request.EndTime; - - // unmarshal the results. - OPCHDA_ITEM result = (OPCHDA_ITEM)Marshal.PtrToStructure(ppItemValues, typeof(OPCHDA_ITEM)); - - if (result.dwCount > 0) - { - object[] values = ComUtils.GetVARIANTs(ref result.pvDataValues, result.dwCount, true); - int[] qualities = ComUtils.GetInt32s(ref result.pdwQualities, result.dwCount, true); - DateTime[] timestamps = ComUtils.GetDateTimes(ref result.pftTimeStamps, result.dwCount, true); - - request.Results = new DataValueCollection(result.dwCount); - - for (int ii = 0; ii < result.dwCount; ii++) - { - DataValue value = new DataValue(); - value.Value = ComUtils.ProcessComValue(values[ii]); - value.StatusCode = ComUtils.GetHdaQualityCode(Utils.ToUInt32(qualities[ii])); - value.SourceTimestamp = timestamps[ii]; - request.Results.Add(value); - } - - if (!request.Completed) - { - request.StartTime = endTime; - } - } - - Marshal.FreeCoTaskMem(ppItemValues); - - if (result.dwCount == 0) - { - return StatusCodes.GoodNoData; - } - - if (!request.Completed) - { - return StatusCodes.GoodMoreData; - } - - return StatusCodes.Good; - } - - /// - /// Reads the data for an item at the specified times. - /// - private StatusCode ReadAtTime(HdaHistoryReadAtTimeRequest request) - { - string methodName = "IOPCHDA_SyncRead.ReadAtTime"; - - IntPtr ppItemValues; - IntPtr ppErrors; - - System.Runtime.InteropServices.ComTypes.FILETIME[] pTimestamps = new System.Runtime.InteropServices.ComTypes.FILETIME[request.ReqTimes.Count]; - - for (int ii = 0; ii < pTimestamps.Length; ii++) - { - pTimestamps[ii] = ComUtils.GetFILETIME(request.ReqTimes[ii]); - } - - try - { - IOPCHDA_SyncRead server = BeginComCall(methodName, true); - - server.ReadAtTime( - pTimestamps.Length, - pTimestamps, - 1, - new int[] { request.ServerHandle }, - out ppItemValues, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return StatusCodes.BadUnexpectedError; - } - finally - { - EndComCall(methodName); - } - - // check for error. - int[] errors = ComUtils.GetInt32s(ref ppErrors, 1, true); - - if (errors[0] < 0) - { - return StatusCodes.BadNodeIdUnknown; - } - - // check if operation halted. - request.Completed = true; - - // unmarshal the results. - OPCHDA_ITEM result = (OPCHDA_ITEM)Marshal.PtrToStructure(ppItemValues, typeof(OPCHDA_ITEM)); - - if (result.dwCount > 0) - { - object[] values = ComUtils.GetVARIANTs(ref result.pvDataValues, result.dwCount, true); - int[] qualities = ComUtils.GetInt32s(ref result.pdwQualities, result.dwCount, true); - DateTime[] timestamps = ComUtils.GetDateTimes(ref result.pftTimeStamps, result.dwCount, true); - - request.Results = new DataValueCollection(result.dwCount); - - for (int ii = 0; ii < result.dwCount; ii++) - { - DataValue value = new DataValue(); - value.Value = ComUtils.ProcessComValue(values[ii]); - value.StatusCode = ComUtils.GetHdaQualityCode(Utils.ToUInt32(qualities[ii])); - value.SourceTimestamp = timestamps[ii]; - request.Results.Add(value); - } - } - - Marshal.FreeCoTaskMem(ppItemValues); - - if (result.dwCount == 0) - { - return StatusCodes.GoodNoData; - } - - return StatusCodes.Good; - } - - /// - /// Reads the raw modified data for an item. - /// - private StatusCode ReadAttributes(HdaHistoryReadAttributeRequest request, params int[] attributeIds) - { - string methodName = "IOPCHDA_SyncRead.ReadAttribute"; - - OPCHDA_TIME htStartTime = ConvertTime(request.StartTime); - OPCHDA_TIME htEndTime = ConvertTime(request.EndTime); - - IntPtr ppAttributeValues; - IntPtr ppErrors; - - try - { - IOPCHDA_SyncRead server = BeginComCall(methodName, true); - - server.ReadAttribute( - ref htStartTime, - ref htEndTime, - request.ServerHandle, - attributeIds.Length, - attributeIds, - out ppAttributeValues, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return StatusCodes.BadUnexpectedError; - } - finally - { - EndComCall(methodName); - } - - StatusCode status = StatusCodes.Good; - - // error in one attribute means operation failed. - int[] errors = ComUtils.GetInt32s(ref ppErrors, attributeIds.Length, true); - - for (int ii = 0; ii < errors.Length; ii++) - { - if (errors[ii] < 0) - { - status = StatusCodes.BadNodeIdUnknown; - break; - } - } - - // unmarshal results. - HdaAttributeValue[][] results = new HdaAttributeValue[attributeIds.Length][]; - IntPtr pos = ppAttributeValues; - - for (int ii = 0; ii < attributeIds.Length; ii++) - { - OPCHDA_ATTRIBUTE attributes = (OPCHDA_ATTRIBUTE)Marshal.PtrToStructure(pos, typeof(OPCHDA_ATTRIBUTE)); - - if (attributes.dwNumValues > 0) - { - results[ii] = new HdaAttributeValue[attributes.dwNumValues]; - - object[] values = ComUtils.GetVARIANTs(ref attributes.vAttributeValues, attributes.dwNumValues, true); - DateTime[] timestamps = ComUtils.GetDateTimes(ref attributes.ftTimeStamps, attributes.dwNumValues, true); - - for (int jj = 0; jj < values.Length; jj++) - { - HdaAttributeValue result = results[ii][jj] = new HdaAttributeValue(); - result.AttributeId = Utils.ToUInt32(attributeIds[ii]); - result.Value = ComUtils.ProcessComValue(values[jj]); - result.Timestamp = timestamps[jj]; - result.Error = ResultIds.S_OK; - } - } - else - { - results[ii] = new HdaAttributeValue[1]; - HdaAttributeValue result = results[ii][0] = new HdaAttributeValue(); - result.AttributeId = Utils.ToUInt32(attributeIds[ii]); - result.Value = null; - result.Timestamp = request.StartTime; - result.Error = ResultIds.S_NODATA; - } - - pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(OPCHDA_ATTRIBUTE))); - } - - Marshal.FreeCoTaskMem(ppAttributeValues); - - // save the results. - request.SetHistoryResults(attributeIds, results); - - return StatusCodes.Good; - } - - /// - /// Reads the annotation data for an item. - /// - private StatusCode ReadAnnotations(HdaHistoryReadAnnotationRequest request) - { - string methodName = "IOPCHDA_SyncAnnotations.Read"; - - OPCHDA_TIME htStartTime = ConvertTime(request.StartTime); - OPCHDA_TIME htEndTime = ConvertTime(request.EndTime); - - IntPtr ppAnnotationValues; - IntPtr ppErrors; - - try - { - IOPCHDA_SyncAnnotations server = BeginComCall(methodName, true); - - server.Read( - ref htStartTime, - ref htEndTime, - 1, - new int[] { request.ServerHandle }, - out ppAnnotationValues, - out ppErrors); - } - catch (Exception e) - { - ComCallError(methodName, e); - return StatusCodes.BadUnexpectedError; - } - finally - { - EndComCall(methodName); - } - - // check for error. - int[] errors = ComUtils.GetInt32s(ref ppErrors, 1, true); - - if (errors[0] < 0) - { - return StatusCodes.BadNodeIdUnknown; - } - - // unmarshal the results. - OPCHDA_ANNOTATION result = (OPCHDA_ANNOTATION)Marshal.PtrToStructure(ppAnnotationValues, typeof(OPCHDA_ANNOTATION)); - - if (result.dwNumValues > 0) - { - DateTime[] timestamps = ComUtils.GetDateTimes(ref result.ftTimeStamps, result.dwNumValues, true); - string[] annotations = ComUtils.GetUnicodeStrings(ref result.szAnnotation, result.dwNumValues, true); - DateTime[] annotationTimes = ComUtils.GetDateTimes(ref result.ftAnnotationTime, result.dwNumValues, true); - string[] userNames = ComUtils.GetUnicodeStrings(ref result.szUser, result.dwNumValues, true); - - request.Annotations = new List(result.dwNumValues); - - for (int ii = 0; ii < result.dwNumValues; ii++) - { - Annotation annotation = new Annotation(); - annotation.AnnotationTime = annotationTimes[ii]; - annotation.Message = annotations[ii]; - annotation.UserName = userNames[ii]; - - DataValue value = new DataValue(new Variant(new ExtensionObject(annotation))); - value.SourceTimestamp = timestamps[ii]; - request.Annotations.Add(value); - } - } - - Marshal.FreeCoTaskMem(ppAnnotationValues); - - return StatusCodes.Good; - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private ComHdaClientConfiguration m_configuration; - private HdaAttribute[] m_supportedAttributes; - private byte m_annotationAccessLevel; - private OPCHDA_UPDATECAPABILITIES m_updateCapabilities; - private int m_maxReturnValues; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/ComHdaClientConfiguration.cs b/ComIOP/Common/Client/Hda/ComHdaClientConfiguration.cs deleted file mode 100644 index 4f6eabca1..000000000 --- a/ComIOP/Common/Client/Hda/ComHdaClientConfiguration.cs +++ /dev/null @@ -1,158 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.ServiceModel; -using System.Runtime.Serialization; -using System.Collections.Generic; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the configuration the data access node manager. - /// - [DataContract(Namespace = Namespaces.ComInterop)] - public class ComHdaClientConfiguration : ComClientConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public ComHdaClientConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - m_addCapabilitiesToServerObject = false; - m_attributeSamplingInterval = 1000; - m_treatUncertainAsBad = true; - m_percentDataBad = 0; - m_percentDataGood = 100; - m_steppedSlopedExtrapolation = false; - } - #endregion - - #region Public Properties - /// - /// Gets or sets a value indicating whether the history server capabilities should be added to the server object. - /// - /// - /// true if the history server capabilities should be added to the server object; otherwise, false. - /// - [DataMember(Order = 1)] - public bool AddCapabilitiesToServerObject - { - get { return m_addCapabilitiesToServerObject; } - set { m_addCapabilitiesToServerObject = value; } - } - - /// - /// Gets or sets the attribute sampling interval. - /// - /// The attribute sampling interval. - [DataMember(Order=2)] - public int AttributeSamplingInterval - { - get { return m_attributeSamplingInterval; } - set { m_attributeSamplingInterval = value; } - } - - /// - /// Gets or sets a value indicating whether the HDA server treats uncertain values as bad. - /// - /// - /// true if the HDA server treats uncertain values as bad; otherwise, false. - /// - [DataMember(Order=3)] - public bool TreatUncertainAsBad - { - get { return m_treatUncertainAsBad; } - set { m_treatUncertainAsBad = value; } - } - - /// - /// Gets or sets the percent data that is bad before the HDA server treats the entire interval as bad. - /// - /// The percent data bad. - [DataMember(Order=4)] - public byte PercentDataBad - { - get { return m_percentDataBad; } - set { m_percentDataBad = value; } - } - /// - /// Gets or sets the percent data after which the HDA server treats the entire interval as dood. - /// - /// The percent data good. - [DataMember(Order=5)] - public byte PercentDataGood - { - get { return m_percentDataGood; } - set { m_percentDataGood = value; } - } - - /// - /// Gets or sets a value indicating whether the HDA server sloped extrapolation to calculate end bounds. - /// - /// - /// true if the HDA server sloped extrapolation; otherwise, false. - /// - [DataMember(Order=6)] - public bool SteppedSlopedExtrapolation - { - get { return m_steppedSlopedExtrapolation; } - set { m_steppedSlopedExtrapolation = value; } - } - #endregion - - #region Private Members - private bool m_addCapabilitiesToServerObject; - private int m_attributeSamplingInterval; - private bool m_treatUncertainAsBad; - private byte m_percentDataBad; - private byte m_percentDataGood; - private bool m_steppedSlopedExtrapolation; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/ComHdaClientManager.cs b/ComIOP/Common/Client/Hda/ComHdaClientManager.cs deleted file mode 100644 index 4d309a2fd..000000000 --- a/ComIOP/Common/Client/Hda/ComHdaClientManager.cs +++ /dev/null @@ -1,139 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Da; - -namespace Opc.Ua.Com.Client -{ - /// - /// Manages the DA COM connections used by the UA server. - /// - public class ComHdaClientManager : ComClientManager - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComHdaClientManager() - { - } - #endregion - - #region Public Members - #endregion - - #region Protected Members - /// - /// Gets or sets the default COM client instance. - /// - /// The default client. - protected new ComHdaClient DefaultClient - { - get { return base.DefaultClient as ComHdaClient; } - set { base.DefaultClient = value; } - } - - /// - /// Gets the configuration. - /// - /// The configuration. - protected new ComHdaClientConfiguration Configuration - { - get { return base.Configuration as ComHdaClientConfiguration; } - } - - /// - /// Creates a new client object. - /// - protected override ComClient CreateClient() - { - return new ComHdaClient(Configuration); - } - - /// - /// Updates the status node. - /// - protected override bool UpdateStatus() - { - // get the status from the server. - ComHdaClient client = DefaultClient; - ComHdaClient.ServerStatus? status = client.GetStatus(); - - // check the client has been abandoned. - if (!Object.ReferenceEquals(client, DefaultClient)) - { - return false; - } - - // update the server status. - lock (StatusNodeLock) - { - StatusNode.ServerUrl.Value = Configuration.ServerUrl; - - if (status != null) - { - StatusNode.SetStatusCode(DefaultSystemContext, StatusCodes.Good, DateTime.UtcNow); - - if (String.IsNullOrEmpty(status.Value.szStatusString)) - { - StatusNode.ServerState.Value = Utils.Format("{0}", status.Value.wStatus); - } - else - { - StatusNode.ServerState.Value = Utils.Format("{0} '{1}'", status.Value.wStatus, status.Value.szStatusString); - } - - StatusNode.CurrentTime.Value = status.Value.ftCurrentTime; - StatusNode.LastUpdateTime.Value = DateTime.MinValue; - StatusNode.StartTime.Value = status.Value.ftStartTime; - StatusNode.VendorInfo.Value = status.Value.szVendorInfo; - StatusNode.SoftwareVersion.Value = Utils.Format("{0}.{1}.{2}", status.Value.wMajorVersion, status.Value.wMinorVersion, status.Value.wBuildNumber); - } - else - { - StatusNode.SetStatusCode(DefaultSystemContext, StatusCodes.BadOutOfService, DateTime.UtcNow); - } - - StatusNode.ClearChangeMasks(DefaultSystemContext, true); - return status != null; - } - } - #endregion - - #region Private Fields - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/ComHdaClientNodeManager.cs b/ComIOP/Common/Client/Hda/ComHdaClientNodeManager.cs deleted file mode 100644 index 1c9f0587d..000000000 --- a/ComIOP/Common/Client/Hda/ComHdaClientNodeManager.cs +++ /dev/null @@ -1,1550 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using System.Xml; -using System.IO; -using System.Threading; -using System.Reflection; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// A node manager for a server that exposes several variables. - /// - public class ComHdaClientNodeManager : ComClientNodeManager - { - #region Constructors - /// - /// Initializes the node manager. - /// - public ComHdaClientNodeManager(IServerInternal server, string namespaceUri, ComHdaClientConfiguration configuration, bool ownsTypeModel) - : - base(server, namespaceUri, ownsTypeModel) - { - SystemContext.SystemHandle = m_system = new ComHdaClientManager(); - SystemContext.NodeIdFactory = this; - - // save the configuration for the node manager. - m_configuration = configuration; - - // set the alias root. - AliasRoot = m_configuration.ServerName; - - if (String.IsNullOrEmpty(AliasRoot)) - { - AliasRoot = "HDA"; - } - - // set the default parser if none provided. - if (configuration.ItemIdParser == null) - { - configuration.ItemIdParser = new ComItemIdParser(); - } - - // set default parameters. - if (m_configuration.AttributeSamplingInterval == 0) - { - m_configuration.AttributeSamplingInterval = 1000; - } - - // create the list of subscriptions. - m_subscriptionManagers = new Dictionary(); - m_subscriptionManagers[ComUtils.LOCALE_SYSTEM_DEFAULT] = new HdaSubscribeRequestManager(SystemContext, ComUtils.LOCALE_SYSTEM_DEFAULT, m_configuration); - m_monitoredItems = new Dictionary(); - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - m_system.Dispose(); - } - - base.Dispose(disposing); - } - #endregion - - #region INodeIdFactory Members - /// - /// Creates the NodeId for the specified node. - /// - /// The context. - /// The node. - /// The new NodeId. - /// - /// This method is called by the NodeState.Create() method which initializes a Node from - /// the type model. During initialization a number of child nodes are created and need to - /// have NodeIds assigned to them. This implementation constructs NodeIds by constructing - /// strings. Other implementations could assign unique integers or Guids and save the new - /// Node in a dictionary for later lookup. - /// - public override NodeId New(ISystemContext context, NodeState node) - { - BaseInstanceState instance = node as BaseInstanceState; - - if (instance != null && instance.Parent == null) - { - return instance.NodeId; - } - - return HdaModelUtils.ConstructIdForComponent(node, NamespaceIndex); - } - #endregion - - #region INodeManager Members - /// - /// Does any initialization required before the address space can be used. - /// - /// - /// The externalReferences is an out parameter that allows the node manager to link to nodes - /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and - /// should have a reference to the root folder node(s) exposed by this node manager. - /// - public override void CreateAddressSpace(IDictionary> externalReferences) - { - lock (Lock) - { - // check if the type model needs to be loaded. - if (NamespaceIndexes.Length > 1) - { - LoadPredefinedNodes(SystemContext, externalReferences); - } - - // create the root node. - string serverName = m_configuration.ServerName; - - if (String.IsNullOrEmpty(serverName)) - { - serverName = "ComHdaServer"; - } - - HdaBranchState root = new HdaBranchState(String.Empty, serverName, NamespaceIndex); - root.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); - - // link root to objects folder. - IList references = null; - - if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) - { - externalReferences[ObjectIds.ObjectsFolder] = references = new List(); - } - - references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, root.NodeId)); - - // create the status node. - ComServerStatusState status = new ComServerStatusState(root); - status.ReferenceTypeId = ReferenceTypeIds.Organizes; - - // get the type namepace for the browse name. - int typeNamepaceIndex = Server.NamespaceUris.GetIndex(Namespaces.ComInterop); - - if (typeNamepaceIndex < 0) - { - typeNamepaceIndex = NamespaceIndex; - } - - status.Create( - SystemContext, - HdaModelUtils.ConstructIdForInternalNode("ServerStatus", NamespaceIndex), - new QualifiedName("ServerStatus", (ushort)typeNamepaceIndex), - null, - true); - - root.AddChild(status); - - // store root folder in the pre-defined nodes. - AddPredefinedNode(SystemContext, root); - - // create the server capabilities object. - HistoryServerCapabilitiesState capabilities = m_capabilities = new HistoryServerCapabilitiesState(null); - - CreateNode( - SystemContext, - root.NodeId, - ReferenceTypeIds.Organizes, - new QualifiedName(Opc.Ua.BrowseNames.HistoryServerCapabilities), - capabilities); - - capabilities.AccessHistoryDataCapability.Value = true; - capabilities.AccessHistoryEventsCapability.Value = false; - capabilities.MaxReturnDataValues.Value = 0; - capabilities.MaxReturnEventValues.Value = 0; - capabilities.ReplaceDataCapability.Value = false; - capabilities.UpdateDataCapability.Value = false; - capabilities.InsertEventCapability.Value = false; - capabilities.ReplaceEventCapability.Value = false; - capabilities.UpdateEventCapability.Value = false; - capabilities.InsertAnnotationCapability.Value = false; - capabilities.InsertDataCapability.Value = false; - capabilities.DeleteRawCapability.Value = false; - capabilities.DeleteAtTimeCapability.Value = false; - - AddPredefinedNode(SystemContext, capabilities); - - // create the default aggregate configuration object. - AggregateConfigurationState aggregateConfiguration = new AggregateConfigurationState(null); - aggregateConfiguration.ReferenceTypeId = ReferenceTypeIds.Organizes; - - aggregateConfiguration.Create( - SystemContext, - HdaModelUtils.ConstructIdForInternalNode(Opc.Ua.BrowseNames.AggregateConfiguration, NamespaceIndex), - Opc.Ua.BrowseNames.AggregateConfiguration, - null, - true); - - aggregateConfiguration.TreatUncertainAsBad.Value = m_configuration.TreatUncertainAsBad; - aggregateConfiguration.PercentDataBad.Value = m_configuration.PercentDataBad; - aggregateConfiguration.PercentDataGood.Value = m_configuration.PercentDataGood; - aggregateConfiguration.UseSlopedExtrapolation.Value = m_configuration.SteppedSlopedExtrapolation; - - AddPredefinedNode(SystemContext, aggregateConfiguration); - - // create the COM server. - m_system.Initialize(SystemContext, m_configuration, status, Lock, OnServerReconnected); - StartMetadataUpdates(DoMetadataUpdate, null, 5000, m_configuration.MaxReconnectWait); - } - } - - /// - /// Frees any resources allocated for the address space. - /// - public override void DeleteAddressSpace() - { - lock (Lock) - { - base.DeleteAddressSpace(); - } - } - - /// - /// Called to create the browser for the item configuration. - /// - private NodeBrowser OnCreateItemConfigurationBrowser( - ISystemContext context, - NodeState node, - ViewDescription view, - NodeId referenceType, - bool includeSubtypes, - BrowseDirection browseDirection, - QualifiedName browseName, - IEnumerable additionalReferences, - bool internalOnly) - { - HdaParsedNodeId nodeId = HdaParsedNodeId.Parse(node.NodeId); - - if (nodeId == null) - { - return null; - } - - return new HdaElementBrower( - context, - view, - referenceType, - includeSubtypes, - browseDirection, - browseName, - additionalReferences, - internalOnly, - nodeId.RootId, - Opc.Ua.ObjectTypeIds.HistoricalDataConfigurationType, - Opc.Ua.BrowseNames.HAConfiguration, - NamespaceIndex); - } - - /// - /// Called when client manager has reconnected to the COM server. - /// - public void OnServerReconnected(object state) - { - try - { - foreach (HdaSubscribeRequestManager manager in m_subscriptionManagers.Values) - { - try - { - manager.RecreateItems(); - } - catch (Exception e) - { - Utils.Trace(e, "Could not re-create subscription after reconnect for locale {0}.", new System.Globalization.CultureInfo(manager.LocaleId).DisplayName); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Could not re-create subscriptions after reconnect."); - } - } - - /// - /// Returns a unique handle for the node. - /// - protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) - { - lock (Lock) - { - // quickly exclude nodes that are not in the namespace. - if (!IsNodeIdInNamespace(nodeId)) - { - return null; - } - - // check cache. - if (cache != null) - { - NodeState node = null; - - if (cache.TryGetValue(nodeId, out node)) - { - return new NodeHandle(nodeId, node); - } - } - - NodeHandle handle = null; - - try - { - // check for predefined nodes. - if (PredefinedNodes != null) - { - NodeState node = null; - - if (PredefinedNodes.TryGetValue(nodeId, out node)) - { - return handle = new NodeHandle(nodeId, node); - } - } - - // parse the identifier. - HdaParsedNodeId parsedNodeId = HdaParsedNodeId.Parse(nodeId); - - if (parsedNodeId != null) - { - handle = new NodeHandle(); - - handle.NodeId = nodeId; - handle.Validated = false; - handle.Node = null; - handle.ParsedNodeId = parsedNodeId; - - return handle; - } - } - finally - { - if (handle != null && handle.Node != null && cache != null) - { - cache.Add(nodeId, handle.Node); - } - } - - return null; - } - } - - /// - /// Verifies that the specified node exists. - /// - protected override NodeState ValidateNode( - ServerSystemContext context, - NodeHandle handle, - IDictionary cache) - { - // not valid if no root. - if (handle == null) - { - return null; - } - - // check if previously validated. - if (handle.Validated) - { - return handle.Node; - } - - NodeState target = null; - - // check if already in the cache. - if (cache != null) - { - if (cache.TryGetValue(handle.NodeId, out target)) - { - // nulls mean a NodeId which was previously found to be invalid has been referenced again. - if (target == null) - { - return null; - } - - handle.Node = target; - handle.Validated = true; - return handle.Node; - } - - target = null; - } - - try - { - // check if the node id has been parsed. - HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; - - if (parsedNodeId == null) - { - return null; - } - - ComHdaClient client = (ComHdaClient)m_system.SelectClient(context, false); - - switch (parsedNodeId.RootType) - { - case HdaModelUtils.HdaBranch: - { - ComHdaBrowserClient browser = new ComHdaBrowserClient(client, null); - target = browser.FindBranch(context, parsedNodeId.RootId, NamespaceIndex); - browser.Dispose(); - break; - } - - case HdaModelUtils.HdaItem: - { - HdaItem[] items = client.GetItems(parsedNodeId.RootId); - - if (items[0].Error < 0) - { - return null; - } - - try - { - string browseName = null; - - if (!m_configuration.ItemIdParser.Parse(client, m_configuration, parsedNodeId.RootId, out browseName)) - { - HdaAttributeValue[] attributes = client.ReadAttributeValues(items[0].ServerHandle, OpcRcw.Hda.Constants.OPCHDA_ITEMID); - browseName = attributes[0].Value as string; - } - - target = new HdaItemState(items[0].ItemId, browseName, NamespaceIndex); - } - finally - { - client.ReleaseItemHandles(items); - } - - break; - } - - case HdaModelUtils.HdaItemAttribute: - { - bool[] results = client.ValidateItemIds(parsedNodeId.RootId); - - if (!results[0]) - { - return null; - } - - target = client.FindItemAttribute(parsedNodeId.RootId, parsedNodeId.AttributeId, NamespaceIndex); - break; - } - - case HdaModelUtils.HdaItemAnnotations: - { - bool[] results = client.ValidateItemIds(parsedNodeId.RootId); - - if (!results[0]) - { - return null; - } - - target = client.FindItemAnnotations(parsedNodeId.RootId, NamespaceIndex); - break; - } - - case HdaModelUtils.HdaItemConfiguration: - { - bool[] results = client.ValidateItemIds(parsedNodeId.RootId); - - if (results == null || !results[0]) - { - return null; - } - - target = HdaModelUtils.GetItemConfigurationNode(parsedNodeId.RootId, NamespaceIndex); - target.OnCreateBrowser = OnCreateItemConfigurationBrowser; - break; - } - - case HdaModelUtils.HdaAggregate: - { - target = client.FindAggregate(parsedNodeId.AggregateId, NamespaceIndex); - break; - } - } - - // check if found. - if (target == null) - { - return null; - } - - // found a valid component. - handle.Validated = true; - handle.Node = target; - - return handle.Node; - } - finally - { - // store the node in the cache to optimize subsequent lookups. - if (cache != null) - { - cache.Add(handle.NodeId, target); - } - } - } - #endregion - - #region Overridden Methods - /// - /// Updates the data history for one or more nodes. - /// - protected override void HistoryUpdateData( - ServerSystemContext context, - IList nodesToUpdate, - IList results, - IList errors, - List nodesToProcess, - IDictionary cache) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); - - for (int ii = 0; ii < nodesToProcess.Count; ii++) - { - NodeHandle handle = nodesToProcess[ii]; - UpdateDataDetails nodeToUpdate = nodesToUpdate[handle.Index]; - HistoryUpdateResult result = results[handle.Index]; - - // check if the node id has been parsed. - HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; - - if (parsedNodeId == null) - { - errors[handle.Index] = StatusCodes.BadNodeIdInvalid; - continue; - } - - // read the history of an item. - if (parsedNodeId.RootType == HdaModelUtils.HdaItem) - { - errors[handle.Index] = client.UpdateData(parsedNodeId.RootId, nodeToUpdate, results[handle.Index]); - continue; - } - - // read the annotations of an item. - if (parsedNodeId.RootType == HdaModelUtils.HdaItemAnnotations) - { - errors[handle.Index] = client.InsertAnnotations(parsedNodeId.RootId, nodeToUpdate, results[handle.Index]); - continue; - } - - errors[handle.Index] = StatusCodes.BadHistoryOperationUnsupported; - } - } - - /// - /// Deletes the data history for one or more nodes. - /// - protected override void HistoryDeleteRawModified( - ServerSystemContext context, - IList nodesToUpdate, - IList results, - IList errors, - List nodesToProcess, - IDictionary cache) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); - - for (int ii = 0; ii < nodesToProcess.Count; ii++) - { - NodeHandle handle = nodesToProcess[ii]; - DeleteRawModifiedDetails nodeToUpdate = nodesToUpdate[handle.Index]; - HistoryUpdateResult result = results[handle.Index]; - - // check if the node id has been parsed. - HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; - - if (parsedNodeId == null) - { - errors[handle.Index] = StatusCodes.BadNodeIdInvalid; - continue; - } - - if (nodeToUpdate.IsDeleteModified) - { - errors[handle.Index] = StatusCodes.BadHistoryOperationUnsupported; - continue; - } - - if (parsedNodeId.RootType == HdaModelUtils.HdaItem) - { - errors[handle.Index] = client.DeleteRaw(parsedNodeId.RootId, nodeToUpdate, results[handle.Index]); - continue; - } - - errors[handle.Index] = StatusCodes.BadHistoryOperationUnsupported; - } - } - - /// - /// Deletes the data history for one or more nodes. - /// - protected override void HistoryDeleteAtTime( - ServerSystemContext context, - IList nodesToUpdate, - IList results, - IList errors, - List nodesToProcess, - IDictionary cache) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); - - for (int ii = 0; ii < nodesToProcess.Count; ii++) - { - NodeHandle handle = nodesToProcess[ii]; - DeleteAtTimeDetails nodeToUpdate = nodesToUpdate[handle.Index]; - HistoryUpdateResult result = results[handle.Index]; - - // check if the node id has been parsed. - HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; - - if (parsedNodeId == null) - { - errors[handle.Index] = StatusCodes.BadNodeIdInvalid; - continue; - } - - if (parsedNodeId.RootType == HdaModelUtils.HdaItem) - { - errors[handle.Index] = client.DeleteAtTime(parsedNodeId.RootId, nodeToUpdate, results[handle.Index]); - continue; - } - - errors[handle.Index] = StatusCodes.BadHistoryOperationUnsupported; - } - } - - /// - /// Validates the nodes and reads the values from the underlying source. - /// - /// The context. - /// The nodes to read. - /// The values. - /// The errors. - /// The nodes to validate. - /// The cache. - protected override void Read( - ServerSystemContext context, - IList nodesToRead, - IList values, - IList errors, - List nodesToValidate, - IDictionary cache) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); - - HdaReadRequestCollection requests = new HdaReadRequestCollection(); - - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - NodeHandle handle = nodesToValidate[ii]; - - lock (Lock) - { - NodeState source = ValidateNode(context, handle, cache); - - if (source == null) - { - continue; - } - - DataValue value = values[handle.Index]; - ReadValueId nodeToRead = nodesToRead[handle.Index]; - - // determine if request can be sent to the server. - bool queued = false; - errors[handle.Index] = requests.Add(source, nodeToRead, out queued); - - if (queued) - { - continue; - } - - // read built-in metadata. - errors[handle.Index] = source.ReadAttribute( - context, - nodeToRead.AttributeId, - nodeToRead.ParsedIndexRange, - nodeToRead.DataEncoding, - value); - } - } - - // read the attributes. - if (requests.Count > 0) - { - client.Read(requests, false); - } - - // extract the values from the results. - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - NodeHandle handle = nodesToValidate[ii]; - DataValue value = values[handle.Index]; - ReadValueId nodeToRead = nodesToRead[handle.Index]; - - lock (Lock) - { - if (!requests.HasResult(nodeToRead)) - { - continue; - } - - errors[handle.Index] = requests.GetResult(context, handle.Node, nodeToRead, value, context.DiagnosticsMask); - } - } - } - - /// - /// Releases the history continuation point. - /// - protected override void HistoryReleaseContinuationPoints( - ServerSystemContext context, - IList nodesToRead, - IList errors, - List nodesToProcess, - IDictionary cache) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); - - for (int ii = 0; ii < nodesToProcess.Count; ii++) - { - NodeHandle handle = nodesToProcess[ii]; - HistoryReadValueId nodeToRead = nodesToRead[handle.Index]; - - // check if the node id has been parsed. - HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; - - if (parsedNodeId == null) - { - errors[handle.Index] = StatusCodes.BadNodeIdInvalid; - continue; - } - - // find the continuation point. - HdaHistoryReadRequest request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint); - - if (request == null) - { - errors[handle.Index] = StatusCodes.BadContinuationPointInvalid; - continue; - } - - // all done. - errors[handle.Index] = StatusCodes.Good; - } - } - - /// - /// Reads the history of an HDA item. - /// - private ServiceResult HistoryReadItem( - ServerSystemContext context, - ComHdaClient client, - ReadRawModifiedDetails details, - TimestampsToReturn timestampsToReturn, - HistoryReadValueId nodeToRead, - HdaParsedNodeId parsedNodeId, - HistoryReadResult result) - { - // create the request or load it from a continuation point. - HdaHistoryReadRawModifiedRequest request = null; - - if (nodeToRead.ContinuationPoint == null) - { - request = new HdaHistoryReadRawModifiedRequest(parsedNodeId.RootId, details, nodeToRead); - } - else - { - request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadRawModifiedRequest; - - if (request == null) - { - return StatusCodes.BadContinuationPointInvalid; - } - } - - // fetch the data. - result.StatusCode = client.ReadHistory(request); - - // fill in the results. - if (request.Results != null) - { - HistoryData data = (request.IsReadModified)?new HistoryModifiedData():new HistoryData(); - - if (request.IsReadModified) - { - ((HistoryModifiedData)data).ModificationInfos = request.ModificationInfos; - } - - data.DataValues = request.Results; - result.HistoryData = new ExtensionObject(data); - } - - // create a new continuation point. - if (!request.Completed) - { - result.ContinuationPoint = SaveContinuationPoint(context, request); - } - - return result.StatusCode; - } - - /// - /// Reads the history of an HDA attribute. - /// - private ServiceResult HistoryReadAttribute( - ServerSystemContext context, - ComHdaClient client, - ReadRawModifiedDetails details, - TimestampsToReturn timestampsToReturn, - HistoryReadValueId nodeToRead, - HdaParsedNodeId parsedNodeId, - HistoryReadResult result) - { - // create the request or load it from a continuation point. - HdaHistoryReadAttributeRequest request = null; - - if (nodeToRead.ContinuationPoint == null) - { - // create a new request. - request = new HdaHistoryReadAttributeRequest(parsedNodeId.RootId, parsedNodeId.AttributeId, details, nodeToRead); - - // fetch all of the data at once. - result.StatusCode = client.ReadAttributeHistory(request); - } - else - { - request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadAttributeRequest; - - if (request == null) - { - return StatusCodes.BadContinuationPointInvalid; - } - } - - // select a subset of the results. - if (StatusCode.IsGood(result.StatusCode)) - { - request.Results = new DataValueCollection(); - request.GetHistoryResults(context, nodeToRead, request.Results); - } - - // fill in the results. - if (request.Results != null) - { - HistoryData data = new HistoryData(); - data.DataValues = request.Results; - result.HistoryData = new ExtensionObject(data); - } - - // create a new continuation point. - if (!request.Completed) - { - result.ContinuationPoint = SaveContinuationPoint(context, request); - } - - return result.StatusCode; - } - - /// - /// Reads the history of an HDA item annotations. - /// - private ServiceResult HistoryReadAnnotations( - ServerSystemContext context, - ComHdaClient client, - ReadRawModifiedDetails details, - TimestampsToReturn timestampsToReturn, - HistoryReadValueId nodeToRead, - HdaParsedNodeId parsedNodeId, - HistoryReadResult result) - { - // create the request or load it from a continuation point. - HdaHistoryReadAnnotationRequest request = null; - - if (nodeToRead.ContinuationPoint == null) - { - // create a new request. - request = new HdaHistoryReadAnnotationRequest(parsedNodeId.RootId, details, nodeToRead); - - // fetch all of the data at once. - result.StatusCode = client.ReadAnnotationHistory(request); - } - else - { - request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadAnnotationRequest; - - if (request == null) - { - return StatusCodes.BadContinuationPointInvalid; - } - } - - // select a subset of the results. - if (StatusCode.IsGood(result.StatusCode)) - { - request.Results = new DataValueCollection(); - request.GetHistoryResults(context, nodeToRead, request.Results); - } - - // fill in the results. - if (request.Results != null) - { - HistoryData data = new HistoryData(); - data.DataValues = request.Results; - result.HistoryData = new ExtensionObject(data); - } - - // create a new continuation point. - if (!request.Completed) - { - result.ContinuationPoint = SaveContinuationPoint(context, request); - } - - return result.StatusCode; - } - - /// - /// Reads raw history data. - /// - protected override void HistoryReadRawModified( - ServerSystemContext context, - ReadRawModifiedDetails details, - TimestampsToReturn timestampsToReturn, - IList nodesToRead, - IList results, - IList errors, - List nodesToProcess, - IDictionary cache) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); - - for (int ii = 0; ii < nodesToProcess.Count; ii++) - { - NodeHandle handle = nodesToProcess[ii]; - HistoryReadValueId nodeToRead = nodesToRead[handle.Index]; - HistoryReadResult result = results[handle.Index]; - - // check if the node id has been parsed. - HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; - - if (parsedNodeId == null) - { - errors[handle.Index] = StatusCodes.BadNodeIdInvalid; - continue; - } - - // read the history of an item. - if (parsedNodeId.RootType == HdaModelUtils.HdaItem) - { - errors[handle.Index] = HistoryReadItem( - context, - client, - details, - timestampsToReturn, - nodeToRead, - parsedNodeId, - result); - - continue; - } - - // read the history of an attribute. - if (parsedNodeId.RootType == HdaModelUtils.HdaItemAttribute) - { - errors[handle.Index] = HistoryReadAttribute( - context, - client, - details, - timestampsToReturn, - nodeToRead, - parsedNodeId, - result); - - continue; - } - - // read the annotations of an item. - if (parsedNodeId.RootType == HdaModelUtils.HdaItemAnnotations) - { - errors[handle.Index] = HistoryReadAnnotations( - context, - client, - details, - timestampsToReturn, - nodeToRead, - parsedNodeId, - result); - - continue; - } - - errors[handle.Index] = StatusCodes.BadHistoryOperationUnsupported; - } - } - - /// - /// Reads processed history data. - /// - protected override void HistoryReadAtTime( - ServerSystemContext context, - ReadAtTimeDetails details, - TimestampsToReturn timestampsToReturn, - IList nodesToRead, - IList results, - IList errors, - List nodesToProcess, - IDictionary cache) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); - - for (int ii = 0; ii < nodesToProcess.Count; ii++) - { - NodeHandle handle = nodesToProcess[ii]; - HistoryReadValueId nodeToRead = nodesToRead[handle.Index]; - HistoryReadResult result = results[handle.Index]; - - // check if the node id has been parsed. - HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; - - if (parsedNodeId == null) - { - errors[handle.Index] = StatusCodes.BadNodeIdInvalid; - continue; - } - - // read the history of an item. - if (parsedNodeId.RootType == HdaModelUtils.HdaItem) - { - errors[handle.Index] = HistoryReadAtTime( - context, - client, - details, - timestampsToReturn, - nodeToRead, - parsedNodeId, - result); - - continue; - } - - errors[handle.Index] = StatusCodes.BadHistoryOperationUnsupported; - } - } - - /// - /// Reads the history of an HDA item. - /// - private ServiceResult HistoryReadAtTime( - ServerSystemContext context, - ComHdaClient client, - ReadAtTimeDetails details, - TimestampsToReturn timestampsToReturn, - HistoryReadValueId nodeToRead, - HdaParsedNodeId parsedNodeId, - HistoryReadResult result) - { - // create the request or load it from a continuation point. - HdaHistoryReadAtTimeRequest request = null; - - if (nodeToRead.ContinuationPoint == null) - { - request = new HdaHistoryReadAtTimeRequest(parsedNodeId.RootId, details, nodeToRead); - } - else - { - request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadAtTimeRequest; - - if (request == null) - { - return StatusCodes.BadContinuationPointInvalid; - } - } - - // fetch the data. - result.StatusCode = client.ReadHistory(request); - - // fill in the results. - if (request.Results != null) - { - HistoryData data = new HistoryData(); - data.DataValues = request.Results; - result.HistoryData = new ExtensionObject(data); - } - - // create a new continuation point. - if (!request.Completed) - { - result.ContinuationPoint = SaveContinuationPoint(context, request); - } - - return result.StatusCode; - } - - /// - /// Reads processed history data. - /// - protected override void HistoryReadProcessed( - ServerSystemContext context, - ReadProcessedDetails details, - TimestampsToReturn timestampsToReturn, - IList nodesToRead, - IList results, - IList errors, - List nodesToProcess, - IDictionary cache) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); - - for (int ii = 0; ii < nodesToProcess.Count; ii++) - { - NodeHandle handle = nodesToProcess[ii]; - HistoryReadValueId nodeToRead = nodesToRead[handle.Index]; - HistoryReadResult result = results[handle.Index]; - NodeId aggregateId = details.AggregateType[handle.Index]; - - // check if the node id has been parsed. - HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; - - if (parsedNodeId == null) - { - errors[handle.Index] = StatusCodes.BadNodeIdInvalid; - continue; - } - - // validate the aggregate. - uint hdaAggregateId = HdaModelUtils.HdaAggregateToUaAggregate(aggregateId, NamespaceIndex); - - if (hdaAggregateId == 0) - { - errors[handle.Index] = StatusCodes.BadAggregateNotSupported; - continue; - } - - // read the history of an item. - if (parsedNodeId.RootType == HdaModelUtils.HdaItem) - { - errors[handle.Index] = HistoryReadProcessedItem( - context, - client, - details, - timestampsToReturn, - hdaAggregateId, - nodeToRead, - parsedNodeId, - result); - - continue; - } - - errors[handle.Index] = StatusCodes.BadHistoryOperationUnsupported; - } - } - - /// - /// Reads the history of an HDA item. - /// - private ServiceResult HistoryReadProcessedItem( - ServerSystemContext context, - ComHdaClient client, - ReadProcessedDetails details, - TimestampsToReturn timestampsToReturn, - uint aggregateId, - HistoryReadValueId nodeToRead, - HdaParsedNodeId parsedNodeId, - HistoryReadResult result) - { - // create the request or load it from a continuation point. - HdaHistoryReadProcessedRequest request = null; - - if (nodeToRead.ContinuationPoint == null) - { - request = new HdaHistoryReadProcessedRequest(parsedNodeId.RootId, aggregateId, details, nodeToRead); - } - else - { - request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadProcessedRequest; - - if (request == null) - { - return StatusCodes.BadContinuationPointInvalid; - } - } - - // fetch the data. - result.StatusCode = client.ReadHistory(request); - - // fill in the results. - if (request.Results != null) - { - HistoryData data = new HistoryData(); - data.DataValues = request.Results; - result.HistoryData = new ExtensionObject(data); - } - - // create a new continuation point. - if (!request.Completed) - { - result.ContinuationPoint = SaveContinuationPoint(context, request); - } - - return result.StatusCode; - } - - /// - /// Loads a node set from a file or resource and addes them to the set of predefined nodes. - /// - protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) - { - NodeStateCollection predefinedNodes = new NodeStateCollection(); - predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.Com.Common.Opc.Ua.Com.PredefinedNodes.uanodes", Assembly.GetAssembly(this.GetType()), true); - return predefinedNodes; - } - - /// - /// Called when a batch of monitored items has been created. - /// - protected override void OnCreateMonitoredItemsComplete(ServerSystemContext context, IList monitoredItems) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient(context, false); - - // use locale for session to find a subscription manager. - HdaSubscribeRequestManager manager = null; - - if (!m_subscriptionManagers.TryGetValue(client.LocaleId, out manager)) - { - m_subscriptionManagers[client.LocaleId] = manager = new HdaSubscribeRequestManager(context, client.LocaleId, m_configuration); - } - - manager.CreateItems(context, monitoredItems); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - m_monitoredItems[monitoredItems[ii].Id] = manager; - } - } - - /// - /// Called when a batch of monitored items has been modified. - /// - protected override void OnModifyMonitoredItemsComplete(ServerSystemContext context, IList monitoredItems) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient(context, false); - - // sort monitored items by the locale id used to create them. - Dictionary> monitoredItemsByLocaleId = new Dictionary>(); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - // look up the manager that was previously used to create the monitor item. - HdaSubscribeRequestManager manager = null; - - if (!m_monitoredItems.TryGetValue(monitoredItems[ii].Id, out manager)) - { - manager = m_subscriptionManagers[client.LocaleId]; - } - - // add monitored item to a list of items for the locale of the manager. - List subset = null; - - if (!monitoredItemsByLocaleId.TryGetValue(manager.LocaleId, out subset)) - { - monitoredItemsByLocaleId[manager.LocaleId] = subset = new List(); - } - - subset.Add(monitoredItems[ii]); - } - - // modify the the item. - foreach (KeyValuePair> entry in monitoredItemsByLocaleId) - { - HdaSubscribeRequestManager manager = null; - - if (m_subscriptionManagers.TryGetValue(entry.Key, out manager)) - { - manager.ModifyItems(context, entry.Value); - } - } - } - - /// - /// Called when a batch of monitored items has been deleted. - /// - protected override void OnDeleteMonitoredItemsComplete(ServerSystemContext context, IList monitoredItems) - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient(context, false); - - // sort monitored items by the locale id used to create them. - Dictionary> monitoredItemsByLocaleId = new Dictionary>(); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - // look up the manager that was previously used to create the monitor item. - HdaSubscribeRequestManager manager = null; - - if (!m_monitoredItems.TryGetValue(monitoredItems[ii].Id, out manager)) - { - manager = m_subscriptionManagers[client.LocaleId]; - } - - // add monitored item to a list of items for the locale of the manager. - List subset = null; - - if (!monitoredItemsByLocaleId.TryGetValue(manager.LocaleId, out subset)) - { - monitoredItemsByLocaleId[manager.LocaleId] = subset = new List(); - } - - subset.Add(monitoredItems[ii]); - } - - // delete the items. - foreach (KeyValuePair> entry in monitoredItemsByLocaleId) - { - HdaSubscribeRequestManager manager = null; - - if (m_subscriptionManagers.TryGetValue(entry.Key, out manager)) - { - manager.DeleteItems(context, entry.Value); - } - } - } - - /// - /// Called when a batch of monitored items has their monitoring mode changed. - /// - protected override void OnSetMonitoringModeComplete(ServerSystemContext context, IList monitoredItems) - { - OnModifyMonitoredItemsComplete(context, monitoredItems); - } - #endregion - - #region Private Methods - /// - /// Loads a history continuation point. - /// - private HdaHistoryReadRequest LoadContinuationPoint( - ServerSystemContext context, - byte[] continuationPoint) - { - Session session = context.OperationContext.Session; - - if (session == null) - { - return null; - } - - HdaHistoryReadRequest request = session.RestoreHistoryContinuationPoint(continuationPoint) as HdaHistoryReadRequest; - - if (request == null) - { - return null; - } - - return request; - } - - /// - /// Saves a history continuation point. - /// - private byte[] SaveContinuationPoint( - ServerSystemContext context, - HdaHistoryReadRequest request) - { - Session session = context.OperationContext.Session; - - if (session == null) - { - return null; - } - - Guid id = Guid.NewGuid(); - session.SaveHistoryContinuationPoint(id, request); - request.ContinuationPoint = id.ToByteArray(); - return request.ContinuationPoint; - } - - /// - /// Updates the type cache. - /// - private void DoMetadataUpdate(object state) - { - try - { - if (!Server.IsRunning) - { - return; - } - - ComHdaClientManager system = (ComHdaClientManager)SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient(SystemContext, true); - - client.UpdateServerMetadata(); - BaseObjectState[] aggregates = client.GetSupportedAggregates(NamespaceIndex); - - lock (Lock) - { - m_capabilities.MaxReturnDataValues.Value = (uint)client.GetServerCapabilities(Opc.Ua.Variables.HistoryServerCapabilitiesType_MaxReturnDataValues, 0); - m_capabilities.InsertDataCapability.Value = (bool)client.GetServerCapabilities(Opc.Ua.Variables.HistoryServerCapabilitiesType_InsertDataCapability, false); - m_capabilities.ReplaceDataCapability.Value = (bool)client.GetServerCapabilities(Opc.Ua.Variables.HistoryServerCapabilitiesType_ReplaceDataCapability, false); - m_capabilities.UpdateDataCapability.Value = (bool)client.GetServerCapabilities(Opc.Ua.Variables.HistoryServerCapabilitiesType_UpdateDataCapability, false); - m_capabilities.InsertAnnotationCapability.Value = (bool)client.GetServerCapabilities(Opc.Ua.Variables.HistoryServerCapabilitiesType_ReplaceDataCapability, false); - m_capabilities.DeleteRawCapability.Value = (bool)client.GetServerCapabilities(Opc.Ua.Variables.HistoryServerCapabilitiesType_DeleteRawCapability, false); - m_capabilities.DeleteAtTimeCapability.Value = (bool)client.GetServerCapabilities(Opc.Ua.Variables.HistoryServerCapabilitiesType_DeleteAtTimeCapability, false); - - if (m_aggregates == null) - { - m_aggregates = aggregates; - m_capabilities.AggregateFunctions.RemoveReferences(Opc.Ua.ReferenceTypeIds.Organizes, false); - - if (m_aggregates != null) - { - for (int ii = 0; ii < m_aggregates.Length; ii++) - { - AddPredefinedNode(SystemContext, m_aggregates[ii]); - m_capabilities.AggregateFunctions.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, m_aggregates[ii].NodeId); - m_aggregates[ii].AddReference(Opc.Ua.ReferenceTypeIds.Organizes, true, m_capabilities.AggregateFunctions.NodeId); - } - } - } - } - - lock (Server.DiagnosticsLock) - { - HistoryServerCapabilitiesState capabilities = Server.DiagnosticsNodeManager.GetDefaultHistoryCapabilities(); - - capabilities.AccessHistoryDataCapability.Value = true; - - if (capabilities.MaxReturnDataValues.Value < m_capabilities.MaxReturnDataValues.Value) - { - capabilities.MaxReturnDataValues.Value = m_capabilities.MaxReturnDataValues.Value; - } - - if (m_capabilities.InsertDataCapability.Value) - { - capabilities.InsertDataCapability.Value = true; - } - - if (m_capabilities.ReplaceDataCapability.Value) - { - capabilities.ReplaceDataCapability.Value = true; - } - - if (m_capabilities.UpdateDataCapability.Value) - { - capabilities.UpdateDataCapability.Value = true; - } - - if (m_capabilities.InsertAnnotationCapability.Value) - { - capabilities.InsertAnnotationCapability.Value = true; - } - - if (m_capabilities.DeleteRawCapability.Value) - { - capabilities.DeleteRawCapability.Value = true; - } - - if (m_capabilities.DeleteAtTimeCapability.Value) - { - capabilities.DeleteAtTimeCapability.Value = true; - } - - if (m_aggregates != null) - { - for (int ii = 0; ii < m_aggregates.Length; ii++) - { - if (!capabilities.AggregateFunctions.ReferenceExists(Opc.Ua.ReferenceTypeIds.Organizes, false, aggregates[ii].NodeId)) - { - capabilities.AggregateFunctions.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, aggregates[ii].NodeId); - } - } - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error updating HDA server metadata."); - } - } - #endregion - - #region Private Fields - private ComHdaClientManager m_system; - private ComHdaClientConfiguration m_configuration; - private HistoryServerCapabilitiesState m_capabilities; - private BaseObjectState[] m_aggregates; - private Dictionary m_subscriptionManagers; - private Dictionary m_monitoredItems; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/ComHdaServerCallback.cs b/ComIOP/Common/Client/Hda/ComHdaServerCallback.cs deleted file mode 100644 index 1ac034379..000000000 --- a/ComIOP/Common/Client/Hda/ComHdaServerCallback.cs +++ /dev/null @@ -1,284 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Client -{ - /// - /// A class that implements the IOPCHDA_DataCallback interface. - /// - internal class ComHdaDataCallback : OpcRcw.Hda.IOPCHDA_DataCallback, IDisposable - { - #region Constructors - /// - /// Initializes the object with the containing subscription object. - /// - public ComHdaDataCallback(ComHdaClient server) - { - // save group. - m_server = server; - - // create connection point. - m_connectionPoint = new ConnectionPoint(server.Unknown, typeof(OpcRcw.Hda.IOPCHDA_DataCallback).GUID); - - // advise. - m_connectionPoint.Advise(this); - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (m_connectionPoint != null) - { - if (disposing) - { - m_connectionPoint.Dispose(); - m_connectionPoint = null; - } - } - } - #endregion - - #region Public Properties - /// - /// Whether the callback is connected. - /// - public bool Connected - { - get - { - return m_connectionPoint != null; - } - } - #endregion - - #region IOPCDataCallback Members - /// - /// Called when a data change arrives. - /// - public void OnDataChange( - int dwTransactionID, - int hrStatus, - int dwNumItems, - OPCHDA_ITEM[] pItemValues, - int[] phrErrors) - { - try - { - // TBD - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnDataChange callback."); - } - } - - /// - /// Called when an async read completes. - /// - public void OnReadComplete( - int dwTransactionID, - int hrStatus, - int dwNumItems, - OPCHDA_ITEM[] pItemValues, - int[] phrErrors) - { - try - { - // TBD - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnReadComplete callback."); - } - } - - /// - /// Called when an async read modified completes. - /// - public void OnReadModifiedComplete( - int dwTransactionID, - int hrStatus, - int dwNumItems, - OPCHDA_MODIFIEDITEM[] pItemValues, - int[] phrErrors) - { - try - { - // TBD - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnReadModifiedComplete callback."); - } - } - - /// - /// Called when an async read attributes completes. - /// - public void OnReadAttributeComplete( - int dwTransactionID, - int hrStatus, - int hClient, - int dwNumItems, - OPCHDA_ATTRIBUTE[] pAttributeValues, - int[] phrErrors) - { - try - { - // TBD - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnReadAttributeComplete callback."); - } - } - - /// - /// Called when an async read annotations completes. - /// - public void OnReadAnnotations( - int dwTransactionID, - int hrStatus, - int dwNumItems, - OPCHDA_ANNOTATION[] pAnnotationValues, - int[] phrErrors) - { - try - { - // TBD - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnReadAnnotations callback."); - } - } - - /// - /// Called when an async insert annotations completes. - /// - public void OnInsertAnnotations ( - int dwTransactionID, - int hrStatus, - int dwCount, - int[] phClients, - int[] phrErrors) - { - try - { - // TBD - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnInsertAnnotations callback."); - } - } - - /// - /// Called when a playback result arrives. - /// - public void OnPlayback ( - int dwTransactionID, - int hrStatus, - int dwNumItems, - IntPtr ppItemValues, - int[] phrErrors) - { - try - { - // TBD - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnPlayback callback."); - } - } - - /// - /// Called when a async update completes. - /// - public void OnUpdateComplete ( - int dwTransactionID, - int hrStatus, - int dwCount, - int[] phClients, - int[] phrErrors) - { - try - { - // TBD - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnUpdateComplete callback."); - } - } - - /// - /// Called when a async opeartion cancel completes. - /// - public void OnCancelComplete( - int dwCancelID) - { - try - { - // TBD - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing OnCancelComplete callback."); - } - } - #endregion - - #region Private Members - private ComHdaClient m_server; - private ConnectionPoint m_connectionPoint; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaAttribute.cs b/ComIOP/Common/Client/Hda/HdaAttribute.cs deleted file mode 100644 index 701947c66..000000000 --- a/ComIOP/Common/Client/Hda/HdaAttribute.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores information about an HDA attribute. - /// - public class HdaAttribute - { - #region Public Members - /// - /// Initializes a new instance of the class. - /// - public HdaAttribute() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the id. - /// - /// The id. - public uint Id - { - get { return m_id; } - set { m_id = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Gets or sets the description. - /// - /// The description. - public string Description - { - get { return m_description; } - set { m_description = value; } - } - - /// - /// Gets or sets the type of the data. - /// - /// The type of the data. - public short DataType - { - get { return m_dataType; } - set { m_dataType = value; } - } - #endregion - - #region Private Fields - private uint m_id; - private string m_name; - private string m_description; - private short m_dataType; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaAttributeState.cs b/ComIOP/Common/Client/Hda/HdaAttributeState.cs deleted file mode 100644 index c230a8204..000000000 --- a/ComIOP/Common/Client/Hda/HdaAttributeState.cs +++ /dev/null @@ -1,229 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Client -{ - /// - /// A object which maps a COM DA item to a UA variable. - /// - public partial class HdaAttributeState : PropertyState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The configuration. - /// The item id. - /// The attribute. - /// Index of the namespace. - 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); - } - #endregion - - #region Public Interface - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get - { - return m_itemId; - } - } - - /// - /// Gets the attribute. - /// - /// The attribute. - public HdaAttribute Attribute - { - get - { - return m_attribute; - } - } - #endregion - - #region Private Fields - private string m_itemId; - private HdaAttribute m_attribute; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaAttributeValue.cs b/ComIOP/Common/Client/Hda/HdaAttributeValue.cs deleted file mode 100644 index a77765ffd..000000000 --- a/ComIOP/Common/Client/Hda/HdaAttributeValue.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the value of an HDA attribute. - /// - public class HdaAttributeValue - { - #region Public Members - /// - /// Initializes a new instance of the class. - /// - public HdaAttributeValue() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the attribute id. - /// - /// The attribute id. - public uint AttributeId - { - get { return m_attributeId; } - set { m_attributeId = value; } - } - - /// - /// Gets or sets the value. - /// - /// The value. - public object Value - { - get { return m_value; } - set { m_value = value; } - } - - /// - /// Gets or sets the timestamp. - /// - /// The timestamp. - public DateTime Timestamp - { - get { return m_timestamp; } - set { m_timestamp = value; } - } - - /// - /// Gets or sets the error. - /// - /// The error. - public int Error - { - get { return m_error; } - set { m_error = value; } - } - #endregion - - #region Private Fields - private uint m_attributeId; - private object m_value; - private DateTime m_timestamp; - private int m_error; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaBranchState.cs b/ComIOP/Common/Client/Hda/HdaBranchState.cs deleted file mode 100644 index 7c1725289..000000000 --- a/ComIOP/Common/Client/Hda/HdaBranchState.cs +++ /dev/null @@ -1,132 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// A object which maps a segment to a UA object. - /// - public partial class HdaBranchState : FolderState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The qualified name for the area. - /// The name of the area. - /// Index of the namespace. - public HdaBranchState( - string itemId, - string name, - ushort namespaceIndex) - : - base(null) - { - m_itemId = itemId; - - this.SymbolicName = name; - this.TypeDefinitionId = Opc.Ua.ObjectTypeIds.FolderType; - this.NodeId = HdaModelUtils.ConstructIdForHdaBranch(itemId, namespaceIndex); - this.BrowseName = new QualifiedName(name, namespaceIndex); - this.DisplayName = this.BrowseName.Name; - this.Description = null; - this.WriteMask = 0; - this.UserWriteMask = 0; - this.EventNotifier = EventNotifiers.None; - } - #endregion - - #region Public Properties - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - } - #endregion - - #region Overridden Methods - /// - /// Creates a browser that finds the references to the branch. - /// - /// The system context to use. - /// The view which may restrict the set of references/nodes found. - /// The type of references being followed. - /// Whether subtypes of the reference type are followed. - /// Which way the references are being followed. - /// The browse name of a specific target (used when translating browse paths). - /// Any additional references that should be included. - /// If true the browser should not making blocking calls to external systems. - /// The browse object (must be disposed). - public override INodeBrowser CreateBrowser( - ISystemContext context, - ViewDescription view, - NodeId referenceType, - bool includeSubtypes, - BrowseDirection browseDirection, - QualifiedName browseName, - IEnumerable additionalReferences, - bool internalOnly) - { - NodeBrowser browser = new HdaElementBrower( - context, - view, - referenceType, - includeSubtypes, - browseDirection, - browseName, - additionalReferences, - internalOnly, - m_itemId, - TypeDefinitionId, - BrowseName, - this.NodeId.NamespaceIndex); - - PopulateBrowser(context, browser); - - return browser; - } - #endregion - - #region Private Fields - private string m_itemId; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaElementBrowser.cs b/ComIOP/Common/Client/Hda/HdaElementBrowser.cs deleted file mode 100644 index 4316afb50..000000000 --- a/ComIOP/Common/Client/Hda/HdaElementBrowser.cs +++ /dev/null @@ -1,514 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Hda; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Client -{ - /// - /// Browses the children of a segment. - /// - public class HdaElementBrower : NodeBrowser - { - #region Constructors - /// - /// Creates a new browser object with a set of filters. - /// - /// The system context to use. - /// The view which may restrict the set of references/nodes found. - /// The type of references being followed. - /// Whether subtypes of the reference type are followed. - /// Which way the references are being followed. - /// The browse name of a specific target (used when translating browse paths). - /// Any additional references that should be included. - /// If true the browser should not making blocking calls to external systems. - /// Name of the qualified. - /// The type definition id. - /// Index of the namespace. - public HdaElementBrower( - ISystemContext context, - ViewDescription view, - NodeId referenceType, - bool includeSubtypes, - BrowseDirection browseDirection, - QualifiedName browseName, - IEnumerable additionalReferences, - bool internalOnly, - string itemId, - NodeId sourceTypeDefinitionId, - QualifiedName sourceBrowseName, - ushort namespaceIndex) - : - base( - context, - view, - referenceType, - includeSubtypes, - browseDirection, - browseName, - additionalReferences, - internalOnly) - { - m_namespaceIndex = namespaceIndex; - m_itemId = itemId; - m_sourceTypeDefinitionId = sourceTypeDefinitionId; - m_sourceBrowseName = sourceBrowseName; - m_stage = Stage.Begin; - } - #endregion - - #region Overridden Methods - /// - /// Returns the next reference. - /// - /// The next reference that meets the browse criteria. - public override IReference Next() - { - lock (DataLock) - { - IReference reference = null; - - // enumerate pre-defined references. - // always call first to ensure any pushed-back references are returned first. - reference = base.Next(); - - if (reference != null) - { - return reference; - } - - // don't start browsing huge number of references when only internal references are requested. - if (InternalOnly) - { - return null; - } - - // fetch references from the server. - do - { - // fetch next reference. - reference = NextChild(); - - if (reference != null) - { - return reference; - } - - // go to the next stage. - NextStage(); - } - while (m_stage != Stage.Done); - - // all done. - return null; - } - } - #endregion - - #region Private Methods - /// - /// Returns the next child. - /// - private IReference NextChild() - { - // check if a specific browse name is requested. - if (QualifiedName.IsNull(base.BrowseName)) - { - return NextChild(m_stage); - } - - // keep fetching references until a matching browse name if found. - NodeStateReference reference = null; - - do - { - reference = NextChild(m_stage); - - if (reference != null) - { - // need to let the caller look up the browse name. - if (reference.Target == null) - { - return reference; - } - - // check for browse name match. - if (reference.Target.BrowseName == base.BrowseName) - { - return reference; - } - } - } - while (reference != null); - - // no match - need to go onto the next stage. - return null; - } - - /// - /// Returns the next child. - /// - private NodeStateReference NextChild(Stage stage) - { - // fetch children. - if (stage == Stage.Browse) - { - if (m_browser == null) - { - return null; - } - - BaseInstanceState node = m_browser.Next(SystemContext, m_namespaceIndex); - - if (node != null) - { - return new NodeStateReference(ReferenceTypeIds.Organizes, false, node); - } - - // all done. - return null; - } - - // fetch attributes. - if (stage == Stage.Children) - { - if (m_children == null) - { - return null; - } - - for (int ii = m_position; ii < m_children.Length;) - { - m_position = ii+1; - return new NodeStateReference(m_children[ii].ReferenceTypeId, false, m_children[ii]); - } - - // all done. - return null; - } - - // fetch child parents. - if (stage == Stage.Parents) - { - return null; - } - - return null; - } - - /// - /// Initializes the next stage of browsing. - /// - private void NextStage() - { - ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); - - // determine which stage is next based on the reference types requested. - for (Stage next = m_stage+1; next <= Stage.Done; next++) - { - if (next == Stage.Browse) - { - if (IsRequired(ReferenceTypeIds.Organizes, false)) - { - m_stage = next; - break; - } - } - - else if (next == Stage.Children) - { - if (IsRequired(ReferenceTypeIds.HasProperty, false) || IsRequired(ReferenceTypeIds.HasHistoricalConfiguration, false)) - { - m_stage = next; - break; - } - } - - else if (next == Stage.Parents) - { - if (IsRequired(ReferenceTypeIds.Organizes, true) || IsRequired(ReferenceTypeIds.HasHistoricalConfiguration, true)) - { - m_stage = next; - break; - } - } - - else if (next == Stage.Done) - { - m_stage = next; - break; - } - } - - // start enumerating areas. - if (m_stage == Stage.Browse) - { - m_browser = null; - - if (m_sourceTypeDefinitionId == Opc.Ua.ObjectTypeIds.FolderType) - { - m_browser = new ComHdaBrowserClient(client, m_itemId); - } - - return; - } - - // start enumerating attributes. - if (m_stage == Stage.Children) - { - m_position = 0; - m_children = null; - - if (m_sourceTypeDefinitionId == Opc.Ua.ObjectTypeIds.FolderType) - { - return; - } - - List children = new List(); - - // check if browsing aggregate functions. - if (m_sourceBrowseName == Opc.Ua.BrowseNames.AggregateFunctions) - { - if (IsRequired(ReferenceTypeIds.HasComponent, false)) - { - BaseObjectState[] aggregates = client.GetSupportedAggregates(m_namespaceIndex); - - if (aggregates != null) - { - children.AddRange(aggregates); - } - - m_children = children.ToArray(); - } - - return; - } - - // must be browsing children of an item. - HdaItem[] items = client.GetItems(m_itemId); - - if (items[0].Error < 0) - { - return; - } - - try - { - HdaAttributeValue[] attributes = client.ReadAvailableAttributes(items[0]); - - if (m_sourceTypeDefinitionId == Opc.Ua.VariableTypeIds.DataItemType) - { - FindChildrenForHdaItem(client, children, attributes); - } - - if (m_sourceTypeDefinitionId == Opc.Ua.ObjectTypeIds.HistoricalDataConfigurationType) - { - FindChildrenForHdaItemConfiguration(client, children, attributes); - } - } - finally - { - client.ReleaseItemHandles(items); - } - - m_children = children.ToArray(); - return; - } - - // start enumerating parents. - if (m_stage == Stage.Parents) - { - return; - } - - // all done. - } - - /// - /// Finds the children for hda item. - /// - /// The client. - /// The children. - /// The attribute values. - private void FindChildrenForHdaItem(ComHdaClient client, List children, HdaAttributeValue[] attributes) - { - BaseInstanceState child = null; - - if (IsRequired(ReferenceTypeIds.HasHistoricalConfiguration, false)) - { - child = HdaModelUtils.GetItemConfigurationNode(m_itemId, m_namespaceIndex); - - if (child != null) - { - children.Add(child); - } - } - - if (IsRequired(ReferenceTypeIds.HasProperty, false)) - { - child = client.FindItemAnnotations(m_itemId, m_namespaceIndex); - - if (child != null) - { - children.Add(child); - } - - if (attributes != null) - { - for (int ii = 0; ii < attributes.Length; ii++) - { - if (attributes[ii].Error < 0 || attributes[ii].Error == ResultIds.S_NODATA) - { - continue; - } - - bool skip = false; - - switch (attributes[ii].AttributeId) - { - case Constants.OPCHDA_DATA_TYPE: - case Constants.OPCHDA_DESCRIPTION: - case Constants.OPCHDA_ITEMID: - case Constants.OPCHDA_ARCHIVING: - case Constants.OPCHDA_DERIVE_EQUATION: - case Constants.OPCHDA_STEPPED: - case Constants.OPCHDA_MAX_TIME_INT: - case Constants.OPCHDA_MIN_TIME_INT: - case Constants.OPCHDA_EXCEPTION_DEV: - case Constants.OPCHDA_EXCEPTION_DEV_TYPE: - { - skip = true; - break; - } - } - - if (skip) - { - continue; - } - - child = client.FindItemAttribute(m_itemId, attributes[ii].AttributeId, m_namespaceIndex); - - if (child != null) - { - children.Add(child); - } - } - } - } - } - - /// - /// Finds the children for hda item configuration. - /// - /// The client. - /// The children. - /// The attribute values. - private void FindChildrenForHdaItemConfiguration(ComHdaClient client, List children, HdaAttributeValue[] attributes) - { - BaseInstanceState child = null; - - if (IsRequired(ReferenceTypeIds.HasProperty, false)) - { - for (int ii = 0; ii < attributes.Length; ii++) - { - if (attributes[ii].Error < 0 || attributes[ii].Error == ResultIds.S_NODATA) - { - continue; - } - - bool skip = true; - - switch (attributes[ii].AttributeId) - { - case Constants.OPCHDA_DERIVE_EQUATION: - case Constants.OPCHDA_STEPPED: - case Constants.OPCHDA_MAX_TIME_INT: - case Constants.OPCHDA_MIN_TIME_INT: - case Constants.OPCHDA_EXCEPTION_DEV: - case Constants.OPCHDA_EXCEPTION_DEV_TYPE: - { - skip = false; - break; - } - } - - if (skip) - { - continue; - } - - child = client.FindItemAttribute(m_itemId, attributes[ii].AttributeId, m_namespaceIndex); - - if (child != null) - { - children.Add(child); - } - } - } - } - #endregion - - #region Stage Enumeration - /// - /// The stages available in a browse operation. - /// - private enum Stage - { - Begin, - Browse, - Children, - Parents, - Done - } - #endregion - - #region Private Fields - private Stage m_stage; - private string m_itemId; - private NodeId m_sourceTypeDefinitionId; - private QualifiedName m_sourceBrowseName; - private ushort m_namespaceIndex; - private ComHdaBrowserClient m_browser; - private BaseInstanceState[] m_children; - private int m_position; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaHistoryReadRequest.cs b/ComIOP/Common/Client/Hda/HdaHistoryReadRequest.cs deleted file mode 100644 index 2afac637a..000000000 --- a/ComIOP/Common/Client/Hda/HdaHistoryReadRequest.cs +++ /dev/null @@ -1,929 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using OpcRcw.Comn; -using OpcRcw.Hda; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores a read history request. - /// - public class HdaHistoryBaseRequest - { - /// - /// Gets the attribute value. - /// - protected ServiceResult GetAttributeValue( - ISystemContext context, - NumericRange indexRange, - QualifiedName dataEncoding, - uint attributeId, - DataValue value, - params HdaAttributeValue[] sources) - { - if (sources == null || sources.Length <= 0) - { - value.StatusCode = StatusCodes.BadNoData; - return value.StatusCode; - } - - switch (attributeId) - { - case Constants.OPCHDA_NORMAL_MAXIMUM: - { - double high = this.GetAttributeValue(value, sources[0]); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - if (sources.Length <= 1) - { - value.StatusCode = StatusCodes.BadNoData; - return value.StatusCode; - } - - double low = this.GetAttributeValue(value, sources[1]); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - // take the latest timestamp. - if (sources[0].Timestamp > sources[1].Timestamp) - { - value.SourceTimestamp = sources[0].Timestamp; - } - - value.Value = new Range(high, low); - break; - } - - case Constants.OPCHDA_HIGH_ENTRY_LIMIT: - { - double high = this.GetAttributeValue(value, sources[0]); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - if (sources.Length <= 1) - { - value.StatusCode = StatusCodes.BadNoData; - return value.StatusCode; - } - - double low = this.GetAttributeValue(value, sources[1]); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - // take the latest timestamp. - if (sources[0].Timestamp > sources[1].Timestamp) - { - value.SourceTimestamp = sources[0].Timestamp; - } - - value.Value = new Range(high, low); - break; - } - - case Constants.OPCHDA_ENG_UNITS: - { - string units = this.GetAttributeValue(value, sources[0]); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = new EUInformation(units, Namespaces.ComInterop); - break; - } - - case Constants.OPCHDA_MAX_TIME_INT: - case Constants.OPCHDA_MIN_TIME_INT: - { - string number = this.GetAttributeValue(value, sources[0]); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - try - { - value.Value = Convert.ToDouble(number); - } - catch (Exception) - { - value.StatusCode = StatusCodes.BadTypeMismatch; - return value.StatusCode; - } - - break; - } - - case Constants.OPCHDA_EXCEPTION_DEV_TYPE: - { - short number = this.GetAttributeValue(value, sources[0]); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = (int)number; - break; - } - - default: - { - value.Value = this.GetAttributeValue(value, sources[0]); - break; - } - } - - return ApplyIndexRangeAndDataEncoding(context, indexRange, dataEncoding, value); - } - - /// - /// Converts the attribute value to the specified type. - /// - protected T GetAttributeValue(DataValue value, HdaAttributeValue source) - { - value.Value = null; - - // find the attribute value. - if (source == null) - { - value.StatusCode = StatusCodes.BadOutOfService; - return default(T); - } - - // set the appropriate error code if no value found. - if (source == null || source.Error < 0 || source.Error == ResultIds.S_NODATA) - { - value.StatusCode = StatusCodes.BadNoData; - return default(T); - } - - // update the source timestamp if a value is being read. - value.SourceTimestamp = source.Timestamp; - - // check type conversion error. - if (!typeof(T).IsInstanceOfType(source.Value)) - { - value.StatusCode = StatusCodes.BadTypeMismatch; - return default(T); - } - - // save the value and return the result. - value.Value = (T)source.Value; - return (T)source.Value; - } - - /// - /// Applies the index range and data encoding to the value. - /// - /// The context. - /// The index range. - /// The data encoding. - /// The value. - /// - protected ServiceResult ApplyIndexRangeAndDataEncoding( - ISystemContext context, - NumericRange indexRange, - QualifiedName dataEncoding, - DataValue value) - { - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - if (indexRange != NumericRange.Empty || !QualifiedName.IsNull(dataEncoding)) - { - object valueToUpdate = value.Value; - - ServiceResult result = BaseVariableState.ApplyIndexRangeAndDataEncoding( - context, - indexRange, - dataEncoding, - ref valueToUpdate); - - if (ServiceResult.IsBad(result)) - { - value.Value = null; - value.StatusCode = result.StatusCode; - return result; - } - - value.Value = valueToUpdate; - } - - return value.StatusCode; - } - } - - /// - /// Stores a read history request. - /// - public class HdaHistoryReadRequest : HdaHistoryBaseRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - /// The details. - /// The node to read. - public HdaHistoryReadRequest(string itemId, HistoryReadDetails details, HistoryReadValueId nodeToRead) - { - ItemId = itemId; - IndexRange = nodeToRead.ParsedIndexRange; - DataEncoding = nodeToRead.DataEncoding; - } - #endregion - - #region Public Properties - /// - /// Gets or sets the continuation point. - /// - /// The continuation point. - public byte[] ContinuationPoint - { - get { return m_continuationPoint; } - set { m_continuationPoint = value; } - } - - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the server handle. - /// - /// The server handle. - public int ServerHandle - { - get { return m_serverHandle; } - set { m_serverHandle = value; } - } - - /// - /// Gets or sets the index range. - /// - /// The index range. - public NumericRange IndexRange - { - get { return m_indexRange; } - set { m_indexRange = value; } - } - - /// - /// Gets or sets the data encoding. - /// - /// The data encoding. - public QualifiedName DataEncoding - { - get { return m_dataEncoding; } - set { m_dataEncoding = value; } - } - - /// - /// Gets or sets the start time. - /// - /// The start time. - public DateTime StartTime - { - get { return m_startTime; } - set { m_startTime = value; } - } - - /// - /// Gets or sets the end time. - /// - /// The end time. - public DateTime EndTime - { - get { return m_endTime; } - set { m_endTime = value; } - } - - /// - /// Gets or sets the max return values. - /// - /// The max return values. - public int MaxReturnValues - { - get { return m_maxReturnValues; } - set { m_maxReturnValues = value; } - } - - /// - /// Gets or sets the error. - /// - /// The error. - public StatusCode Error - { - get { return m_error; } - set { m_error = value; } - } - - /// - /// Gets or sets the results. - /// - /// The results. - public DataValueCollection Results - { - get { return m_results; } - set { m_results = value; } - } - - /// - /// Gets or sets a value indicating whether this is completed. - /// - /// true if completed; otherwise, false. - public bool Completed - { - get { return m_completed; } - set { m_completed = value; } - } - - /// - /// Gets or sets the total values returned. - /// - /// The total values returned. - public int TotalValuesReturned - { - get { return m_totalValuesReturned; } - set { m_totalValuesReturned = value; } - } - #endregion - - #region Private Fields - private byte[] m_continuationPoint; - private string m_itemId; - private int m_serverHandle; - private NumericRange m_indexRange; - private QualifiedName m_dataEncoding; - private DateTime m_startTime; - private DateTime m_endTime; - private int m_maxReturnValues; - private StatusCode m_error; - private DataValueCollection m_results; - private bool m_completed; - private int m_totalValuesReturned; - #endregion - } - - /// - /// A request to read raw or modified history data. - /// - public class HdaHistoryReadRawModifiedRequest : HdaHistoryReadRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - /// The details. - /// The node to read. - public HdaHistoryReadRawModifiedRequest(string itemId, ReadRawModifiedDetails details, HistoryReadValueId nodeToRead) - : - base(itemId, details, nodeToRead) - { - StartTime = details.StartTime; - EndTime = details.EndTime; - MaxReturnValues = (int)details.NumValuesPerNode; - ReturnBounds = details.ReturnBounds; - IsReadModified = details.IsReadModified; - } - #endregion - - #region Public Members - /// - /// Gets or sets a value indicating whether [return bounds]. - /// - /// true if the bounds should be returned; otherwise, false. - public bool ReturnBounds - { - get { return m_returnBounds; } - set { m_returnBounds = value; } - } - - /// - /// Gets or sets a value indicating whether this instance is read modified. - /// - /// - /// true if this instance is read modified; otherwise, false. - /// - public bool IsReadModified - { - get { return m_isReadModified; } - set { m_isReadModified = value; } - } - - /// - /// Gets or sets the modification infos. - /// - /// The modification infos. - public ModificationInfoCollection ModificationInfos - { - get { return m_modificationInfos; } - set { m_modificationInfos = value; } - } - #endregion - - #region Private Fields - private bool m_returnBounds; - private bool m_isReadModified; - private ModificationInfoCollection m_modificationInfos; - #endregion - } - - /// - /// A request to read raw history data at specific times. - /// - public class HdaHistoryReadAtTimeRequest : HdaHistoryReadRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - /// The details. - /// The node to read. - public HdaHistoryReadAtTimeRequest(string itemId, ReadAtTimeDetails details, HistoryReadValueId nodeToRead) - : - base(itemId, details, nodeToRead) - { - ReqTimes = details.ReqTimes; - } - #endregion - - #region Private Fields - /// - /// Gets or sets the requested times. - /// - /// The req times. - public DateTimeCollection ReqTimes - { - get { return m_reqTimes; } - set { m_reqTimes = value; } - } - #endregion - - #region Private Fields - private DateTimeCollection m_reqTimes; - #endregion - } - - /// - /// A request to read raw history data at specific times. - /// - public class HdaHistoryReadAttributeRequest : HdaHistoryReadRawModifiedRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - /// The attribute id. - /// The details. - /// The node to read. - public HdaHistoryReadAttributeRequest(string itemId, uint attributeId, ReadRawModifiedDetails details, HistoryReadValueId nodeToRead) - : - base(itemId, details, nodeToRead) - { - MaxReturnValues = (int)details.NumValuesPerNode; - m_attributeId = attributeId; - } - #endregion - - #region Public Members - /// - /// Gets or sets the attribute id. - /// - /// The attribute id. - public uint AttributeId - { - get { return m_attributeId; } - set { m_attributeId = value; } - } - - /// - /// Gets the history for the attribute. - /// - public void GetHistoryResults( - ISystemContext context, - HistoryReadValueId nodeToRead, - DataValueCollection values) - { - DataValue value = null; - - do - { - value = NextValue( - context, - nodeToRead.ParsedIndexRange, - nodeToRead.DataEncoding); - - if (value != null) - { - values.Add(value); - - if (MaxReturnValues > 0 && values.Count == MaxReturnValues) - { - break; - } - } - } - while (value != null); - - Completed = value == null; - } - - /// - /// Sets the history for the attribute. - /// - public void SetHistoryResults( - int[] attributeIds, - HdaAttributeValue[][] results) - { - m_historyData = null; - - // save the primary series. - if (results.Length > 0) - { - m_historyData = results[0]; - } - - // create a merged series from multiple streams. - if (results.Length > 1) - { - m_mergedSeries = new List(); - - // find the first set. - HdaAttributeValue[] tuple = new HdaAttributeValue[attributeIds.Length]; - - for (int ii = 0; ii < tuple.Length; ii++) - { - if (results[ii] != null) - { - tuple[ii] = results[ii][0]; - } - } - - m_mergedSeries.Add(tuple); - - // add in additional sets. - int[] indexes = new int[attributeIds.Length]; - - while (tuple != null) - { - tuple = NextTuple(results, indexes); - - if (tuple != null) - { - m_mergedSeries.Add(tuple); - } - } - } - } - - private HdaAttributeValue[] NextTuple(HdaAttributeValue[][] results, int[] indexes) - { - int soonest = -1; - DateTime timestamp = DateTime.MaxValue; - - for (int ii = 0; ii < indexes.Length; ii++) - { - // get the next index for the series. - int index = indexes[ii]+1; - - // check if at the end of the series. - if (index >= results[ii].Length) - { - continue; - } - - // check the timestamp. - HdaAttributeValue value = results[ii][index]; - - if (value.Timestamp < timestamp) - { - timestamp = value.Timestamp; - soonest = ii; - } - } - - // check if at end. - if (soonest == -1) - { - return null; - } - - // increment all series with a matching timestamp. - for (int ii = 0; ii < indexes.Length; ii++) - { - // get the next index for the series. - int index = indexes[ii]+1; - - // check if at the end of the series. - if (index >= results[ii].Length) - { - continue; - } - - // check the timestamp. - HdaAttributeValue value = results[ii][index]; - - if (value.Timestamp == timestamp) - { - indexes[ii]++; - } - } - - // build the tuple. - HdaAttributeValue[] tuple = new HdaAttributeValue[indexes.Length]; - - for (int ii = 0; ii < indexes.Length; ii++) - { - tuple[ii] = results[ii][indexes[ii]]; - } - - return tuple; - } - #endregion - - #region Private Methods - /// - /// Nexts the value in the time series. - /// - private DataValue NextValue( - ISystemContext context, - NumericRange indexRange, - QualifiedName dataEncoding) - { - DataValue value = new DataValue(); - - if (m_mergedSeries == null) - { - // check for end of series. - if (m_historyData == null || m_position >= m_historyData.Length) - { - return GetLastBound(context, indexRange, dataEncoding); - } - - // process next value. - HdaAttributeValue source = m_historyData[m_position++]; - GetAttributeValue(context, indexRange, dataEncoding, m_attributeId, value, source); - - return value; - } - - // check for end of series. - if (m_mergedSeries == null || m_position >= m_mergedSeries.Count) - { - return GetLastBound(context, indexRange, dataEncoding); - } - - // process next value. - HdaAttributeValue[] sources = m_mergedSeries[m_position++]; - GetAttributeValue(context, indexRange, dataEncoding, m_attributeId, value, sources); - return value; - } - - /// - /// Gets the last bound if requested. - /// - private DataValue GetLastBound( - ISystemContext context, - NumericRange indexRange, - QualifiedName dataEncoding) - { - if (m_lastBoundReturned) - { - return null; - } - - m_lastBoundReturned = true; - - if (!ReturnBounds) - { - return null; - } - - if (m_mergedSeries == null && m_historyData == null) - { - return null; - } - - if (EndTime == DateTime.MinValue) - { - return null; - } - - m_position = ((m_mergedSeries != null)?m_mergedSeries.Count:m_historyData.Length)-1; - - DataValue lastValue = NextValue(context, indexRange, dataEncoding); - - if (lastValue == null) - { - return null; - } - - if (lastValue.SourceTimestamp == EndTime) - { - return null; - } - - return new DataValue(Variant.Null, StatusCodes.BadBoundNotSupported, EndTime, EndTime); - } - #endregion - - #region Private Fields - private uint m_attributeId; - private HdaAttributeValue[] m_historyData; - private List m_mergedSeries; - private int m_position; - private bool m_lastBoundReturned; - #endregion - } - - /// - /// A request to read raw history data at specific times. - /// - public class HdaHistoryReadAnnotationRequest : HdaHistoryReadRawModifiedRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - /// The details. - /// The node to read. - public HdaHistoryReadAnnotationRequest(string itemId, ReadRawModifiedDetails details, HistoryReadValueId nodeToRead) - : - base(itemId, details, nodeToRead) - { - MaxReturnValues = (int)details.NumValuesPerNode; - } - #endregion - - #region Public Members - /// - /// Gets or sets the annotations. - /// - /// The annotations. - public List Annotations - { - get { return m_annotations; } - set { m_annotations = value; } - } - - /// - /// Gets the history for the attribute. - /// - public void GetHistoryResults( - ISystemContext context, - HistoryReadValueId nodeToRead, - DataValueCollection values) - { - DataValue value = null; - - do - { - if (m_annotations == null || m_position >= m_annotations.Count) - { - break; - } - - value = m_annotations[m_position++]; - ApplyIndexRangeAndDataEncoding(context, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, value); - values.Add(value); - - if (values.Count == MaxReturnValues) - { - break; - } - } - while (value != null); - - Completed = m_annotations == null || m_position >= m_annotations.Count; - - if (m_annotations != null && m_position > 0) - { - m_annotations.RemoveRange(0, m_position); - m_position = 0; - } - } - #endregion - - #region Private Fields - private List m_annotations; - private int m_position; - #endregion - } - - /// - /// A request to read raw or modified history data. - /// - public class HdaHistoryReadProcessedRequest : HdaHistoryReadRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - /// The aggregate id. - /// The details. - /// The node to read. - public HdaHistoryReadProcessedRequest(string itemId, uint aggregateId, ReadProcessedDetails details, HistoryReadValueId nodeToRead) - : - base(itemId, details, nodeToRead) - { - StartTime = details.StartTime; - EndTime = details.EndTime; - ResampleInterval = (long)details.ProcessingInterval; - - m_aggregateId = aggregateId; - } - #endregion - - #region Public Members - /// - /// Gets or sets the resample interval. - /// - /// The resample interval. - public long ResampleInterval - { - get { return m_resampleInterval; } - set { m_resampleInterval = value; } - } - - /// - /// Gets or sets the resample interval. - /// - /// The resample interval. - public uint AggregateId - { - get { return m_aggregateId; } - set { m_aggregateId = value; } - } - #endregion - - #region Private Fields - private long m_resampleInterval; - private uint m_aggregateId; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaItem.cs b/ComIOP/Common/Client/Hda/HdaItem.cs deleted file mode 100644 index c71c801de..000000000 --- a/ComIOP/Common/Client/Hda/HdaItem.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores information about an HDA item. - /// - public class HdaItem - { - #region Public Members - /// - /// Initializes a new instance of the class. - /// - public HdaItem() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Gets or sets the server handle. - /// - /// The server handle. - public int ServerHandle - { - get { return m_serverHandle; } - set { m_serverHandle = value; } - } - - /// - /// Gets or sets the error. - /// - /// The error. - public int Error - { - get { return m_error; } - set { m_error = value; } - } - #endregion - - #region Private Fields - private string m_itemId; - private string m_name; - private int m_serverHandle; - private int m_error; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaItemHistoryData.cs b/ComIOP/Common/Client/Hda/HdaItemHistoryData.cs deleted file mode 100644 index 3d98936bb..000000000 --- a/ComIOP/Common/Client/Hda/HdaItemHistoryData.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the history of an HDA item. - /// - public class HdaItemHistoryData - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public HdaItemHistoryData() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the server handle. - /// - /// The server handle. - public int ServerHandle - { - get { return m_serverHandle; } - set { m_serverHandle = value; } - } - - /// - /// Gets or sets the error. - /// - /// The error. - public int Error - { - get { return m_error; } - set { m_error = value; } - } - - /// - /// Gets or sets the value. - /// - /// The value. - public object[] Values - { - get { return m_values; } - set { m_values = value; } - } - - /// - /// Gets or sets the qualities. - /// - /// The qualities. - public int[] Qualities - { - get { return m_qualities; } - set { m_qualities = value; } - } - - /// - /// Gets or sets the timestamp. - /// - /// The timestamp. - public DateTime[] Timestamps - { - get { return m_timestamps; } - set { m_timestamps = value; } - } - - /// - /// Gets or sets the modifications. - /// - /// The modifications. - public ModificationInfo[] Modifications - { - get { return m_modifications; } - set { m_modifications = value; } - } - #endregion - - #region Private Fields - private int m_serverHandle; - private object[] m_values; - private int[] m_qualities; - private DateTime[] m_timestamps; - private ModificationInfo[] m_modifications; - private int m_error; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaItemState.cs b/ComIOP/Common/Client/Hda/HdaItemState.cs deleted file mode 100644 index b15c6c09d..000000000 --- a/ComIOP/Common/Client/Hda/HdaItemState.cs +++ /dev/null @@ -1,145 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.IO; -using System.Reflection; -using System.Threading; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; - -namespace Opc.Ua.Com.Client -{ - /// - /// A object which maps a COM DA item to a UA variable. - /// - public partial class HdaItemState : BaseDataVariableState - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - /// The name. - /// Index of the namespace. - public HdaItemState( - string itemId, - string name, - ushort namespaceIndex) - : - base(null) - { - m_itemId = itemId; - - if (String.IsNullOrEmpty(name)) - { - name = itemId; - } - - this.NodeId = HdaModelUtils.ConstructIdForHdaItem(itemId, namespaceIndex); - this.BrowseName = new QualifiedName(name, namespaceIndex); - this.DisplayName = new LocalizedText(name); - this.TypeDefinitionId = Opc.Ua.VariableTypeIds.DataItemType; - this.Description = null; - this.WriteMask = 0; - this.UserWriteMask = 0; - this.DataType = DataTypeIds.BaseDataType; - this.ValueRank = ValueRanks.Any; - this.Historizing = false; - this.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; - this.AccessLevel = AccessLevels.HistoryRead; - this.UserAccessLevel = AccessLevels.HistoryRead; - } - #endregion - - #region Public Interface - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get - { - return m_itemId; - } - } - #endregion - - #region Overridden Methods - /// - /// Creates a browser that finds the references to the branch. - /// - /// The system context to use. - /// The view which may restrict the set of references/nodes found. - /// The type of references being followed. - /// Whether subtypes of the reference type are followed. - /// Which way the references are being followed. - /// The browse name of a specific target (used when translating browse paths). - /// Any additional references that should be included. - /// If true the browser should not making blocking calls to external systems. - /// The browse object (must be disposed). - public override INodeBrowser CreateBrowser( - ISystemContext context, - ViewDescription view, - NodeId referenceType, - bool includeSubtypes, - BrowseDirection browseDirection, - QualifiedName browseName, - IEnumerable additionalReferences, - bool internalOnly) - { - NodeBrowser browser = new HdaElementBrower( - context, - view, - referenceType, - includeSubtypes, - browseDirection, - browseName, - additionalReferences, - internalOnly, - m_itemId, - TypeDefinitionId, - BrowseName, - this.NodeId.NamespaceIndex); - - PopulateBrowser(context, browser); - - return browser; - } - #endregion - - #region Private Fields - private string m_itemId; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaModelUtils.cs b/ComIOP/Common/Client/Hda/HdaModelUtils.cs deleted file mode 100644 index 878c297f3..000000000 --- a/ComIOP/Common/Client/Hda/HdaModelUtils.cs +++ /dev/null @@ -1,298 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Client -{ - /// - /// A class that builds NodeIds used by the DataAccess NodeManager - /// - public static class HdaModelUtils - { - /// - /// The RootType for a branch. - /// - public const int HdaBranch = 1; - - /// - /// The RootType for an item. - /// - public const int HdaItem = 2; - - /// - /// The RootType for an item attribute. - /// - public const int HdaItemAttribute = 3; - - /// - /// The RootType for a HA configuration belonging to an item. - /// - public const int HdaItemConfiguration = 4; - - /// - /// The RootType for a HA annotations belonging to an item. - /// - public const int HdaItemAnnotations = 5; - - /// - /// The RootType for a node defined by the UA server. - /// - public const int InternalNode = 6; - - /// - /// The RootType for a aggregate function node. - /// - public const int HdaAggregate = 7; - - /// - /// Constructs the node id for a branch. - /// - /// The item id. - /// Index of the namespace. - public static NodeId ConstructIdForHdaBranch(string itemId, ushort namespaceIndex) - { - ParsedNodeId parsedNodeId = new ParsedNodeId(); - - parsedNodeId.RootId = itemId; - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.RootType = HdaBranch; - - return parsedNodeId.Construct(); - } - - /// - /// Constructs the node id for an item. - /// - /// The item id. - /// Index of the namespace. - public static NodeId ConstructIdForHdaItem(string itemId, ushort namespaceIndex) - { - ParsedNodeId parsedNodeId = new ParsedNodeId(); - - parsedNodeId.RootId = itemId; - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.RootType = HdaItem; - - return parsedNodeId.Construct(); - } - - /// - /// Converts a HDA Aggregate ID to a UA aggregate ID - /// - /// The aggregate id. - /// Index of the namespace. - /// - public static NodeId HdaAggregateToUaAggregate(uint aggregateId, ushort namespaceIndex) - { - NodeId nodeId = ComUtils.GetHdaAggregateId(aggregateId); - - if (nodeId != null) - { - return nodeId; - } - - return HdaParsedNodeId.Construct(HdaAggregate, aggregateId.ToString(), null, namespaceIndex); - } - - /// - /// Converts a UA Aggregate ID to a HDA aggregate ID - /// - /// The node id. - /// Index of the namespace. - /// - public static uint HdaAggregateToUaAggregate(NodeId nodeId, ushort namespaceIndex) - { - // check for valid node. - if (nodeId == null) - { - return 0; - } - - // check for built in aggregate. - uint aggregateId = ComUtils.GetHdaAggregateId(nodeId); - - if (aggregateId != 0) - { - return aggregateId; - } - - // parse the node id. - HdaParsedNodeId parsedNodeId = HdaParsedNodeId.Parse(nodeId); - - if (parsedNodeId == null || namespaceIndex != parsedNodeId.NamespaceIndex || parsedNodeId.RootType != HdaModelUtils.HdaAggregate) - { - return 0; - } - - return parsedNodeId.AggregateId; - } - - /// - /// Constructs the node id for an aggregate function. - /// - /// The aggregate id. - /// Index of the namespace. - /// - public static NodeId ConstructIdForHdaAggregate(uint aggregateId, ushort namespaceIndex) - { - // check for built in aggregates. - NodeId nodeId = ComUtils.GetHdaAggregateId(aggregateId); - - if (nodeId != null) - { - return nodeId; - } - - // server specific aggregates. - ParsedNodeId parsedNodeId = new ParsedNodeId(); - - parsedNodeId.RootId = aggregateId.ToString(); - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.RootType = HdaAggregate; - - return parsedNodeId.Construct(); - } - - /// - /// Constructs the node id for an item attribute. - /// - /// The item id. - /// The attribute id. - /// Index of the namespace. - /// - public static NodeId ConstructIdForHdaItemAttribute(string itemId, uint attributeId, ushort namespaceIndex) - { - ParsedNodeId parsedNodeId = new ParsedNodeId(); - - parsedNodeId.RootId = itemId; - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.RootType = HdaItemAttribute; - parsedNodeId.ComponentPath = attributeId.ToString(); - - return parsedNodeId.Construct(); - } - - /// - /// Constructs a NodeId from the BrowseName of an internal node. - /// - /// The browse name. - /// Index of the namespace. - /// The node id. - public static NodeId ConstructIdForInternalNode(QualifiedName browseName, ushort namespaceIndex) - { - ParsedNodeId parsedNodeId = new ParsedNodeId(); - - parsedNodeId.RootId = browseName.Name; - parsedNodeId.NamespaceIndex = namespaceIndex; - parsedNodeId.RootType = InternalNode; - - return parsedNodeId.Construct(); - } - - /// - /// Constructs the node identifier for a component. - /// - /// The component. - /// Index of the namespace. - /// The node identifier for a component. - public static NodeId ConstructIdForComponent(NodeState component, ushort namespaceIndex) - { - return ParsedNodeId.ConstructIdForComponent(component, namespaceIndex); - } - - /// - /// Gets the item configuration node. - /// - /// The item id. - /// Index of the namespace. - /// - public static BaseInstanceState GetItemConfigurationNode(string itemId, ushort namespaceIndex) - { - if (itemId == null) - { - return null; - } - - FolderState component = new FolderState(null); - - component.NodeId = HdaParsedNodeId.Construct(HdaModelUtils.HdaItemConfiguration, itemId, null, namespaceIndex); - component.SymbolicName = Opc.Ua.BrowseNames.HAConfiguration; - component.BrowseName = new QualifiedName(component.SymbolicName); - component.DisplayName = component.BrowseName.Name; - component.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasComponent; - component.TypeDefinitionId = Opc.Ua.ObjectTypeIds.HistoricalDataConfigurationType; - component.EventNotifier = EventNotifiers.None; - - component.AddReference(ReferenceTypeIds.HasHistoricalConfiguration, true, HdaModelUtils.ConstructIdForHdaItem(itemId, namespaceIndex)); - component.AddReference(ReferenceTypeIds.HasComponent, false, HdaModelUtils.ConstructIdForInternalNode(Opc.Ua.BrowseNames.AggregateConfiguration, namespaceIndex)); - - return component; - } - - /// - /// Gets the item annotations node. - /// - /// The item id. - /// Index of the namespace. - /// - public static PropertyState GetItemAnnotationsNode(string itemId, ushort namespaceIndex) - { - if (itemId == null) - { - return null; - } - - PropertyState component = new PropertyState(null); - - component.NodeId = HdaParsedNodeId.Construct(HdaModelUtils.HdaItemAnnotations, itemId, null, namespaceIndex); - component.SymbolicName = Opc.Ua.BrowseNames.Annotations; - component.BrowseName = new QualifiedName(component.SymbolicName); - component.DisplayName = component.BrowseName.Name; - component.DataType = DataTypeIds.Annotation; - component.ValueRank = ValueRanks.Scalar; - component.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; - component.Historizing = false; - component.AccessLevel = AccessLevels.HistoryRead; - component.UserAccessLevel = AccessLevels.HistoryRead; - component.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasProperty; - component.TypeDefinitionId = Opc.Ua.VariableTypeIds.PropertyType; - - component.AddReference(ReferenceTypeIds.HasProperty, true, HdaModelUtils.ConstructIdForHdaItem(itemId, namespaceIndex)); - - return component; - } - } -} diff --git a/ComIOP/Common/Client/Hda/HdaParsedNodeId.cs b/ComIOP/Common/Client/Hda/HdaParsedNodeId.cs deleted file mode 100644 index 93ee60dc6..000000000 --- a/ComIOP/Common/Client/Hda/HdaParsedNodeId.cs +++ /dev/null @@ -1,208 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Collections.Generic; -using System.Reflection; -using Opc.Ua; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - #region HdaParsedNodeId Class - /// - /// Stores the elements of a NodeId after it is parsed. - /// - /// - /// The NodeIds used by the samples are strings with an optional path appended. - /// The RootType identifies the type of Root Node. The RootId is the unique identifier - /// for the Root Node. The ComponentPath is constructed from the SymbolicNames - /// of one or more children of the Root Node. - /// - public class HdaParsedNodeId : ParsedNodeId - { - #region Public Interface - /// - /// Gets or sets the aggregate id. - /// - /// The aggregate id. - public uint AggregateId - { - get { return m_aggregateId; } - set { m_aggregateId = value; } - } - - /// - /// Gets or sets the attribute id. - /// - /// The attribute id. - public uint AttributeId - { - get { return m_attributeId; } - set { m_attributeId = value; } - } - - /// - /// Parses the specified node identifier. - /// - /// The node identifier. - /// The parsed node identifier. Null if the identifier cannot be parsed. - public static new HdaParsedNodeId Parse(NodeId nodeId) - { - // can only parse non-null string node identifiers. - if (NodeId.IsNull(nodeId)) - { - return null; - } - - string identifier = nodeId.Identifier as string; - - if (String.IsNullOrEmpty(identifier)) - { - return null; - } - - HdaParsedNodeId parsedNodeId = new HdaParsedNodeId(); - parsedNodeId.NamespaceIndex = nodeId.NamespaceIndex; - - int start = 0; - - // extract the type of identifier. - parsedNodeId.RootType = (int)ExtractNumber(identifier, ref start); - - if (start >= identifier.Length || identifier[start] != ':') - { - return null; - } - - // extract any component path. - StringBuilder buffer = new StringBuilder(); - - int index = start+1; - - parsedNodeId.RootId = ExtractAndUnescapeString(identifier, ref index, '&', '?'); - - // extract any component. - int end = index+1; - parsedNodeId.ComponentPath = null; - - // extract the component path. - if (end < identifier.Length) - { - parsedNodeId.ComponentPath = identifier.Substring(end); - } - - // extract the category and condition name. - start = 0; - identifier = parsedNodeId.RootId; - - switch (parsedNodeId.RootType) - { - case HdaModelUtils.HdaAggregate: - { - parsedNodeId.AggregateId = ExtractNumber(identifier, ref start); - - if (start < identifier.Length) - { - return null; - } - - break; - } - } - - // extract the attribute id. - if (!String.IsNullOrEmpty(parsedNodeId.ComponentPath)) - { - start = 0; - identifier = parsedNodeId.ComponentPath; - - switch (parsedNodeId.RootType) - { - case HdaModelUtils.HdaItemAttribute: - { - parsedNodeId.AttributeId = ExtractNumber(identifier, ref start); - - if (start < identifier.Length) - { - return null; - } - - break; - } - } - } - - return parsedNodeId; - } - - /// - /// Constructs a node identifier. - /// - /// The node identifier. - public new NodeId Construct() - { - return Construct(this.RootType, this.RootId, this.ComponentPath, this.NamespaceIndex); - } - - /// - /// Constructs a node identifier. - /// - /// The node identifier. - public static NodeId Construct(int rootType, string rootId, string componentPath, ushort namespaceIndex) - { - StringBuilder buffer = new StringBuilder(); - - // add the root type. - buffer.Append(rootType); - buffer.Append(':'); - - // add the root identifier. - EscapeAndAppendString(buffer, rootId, '&', '?'); - - // add the component path. - if (!String.IsNullOrEmpty(componentPath)) - { - buffer.Append('?'); - buffer.Append(componentPath); - } - - // construct the node id with the namespace index provided. - return new NodeId(buffer.ToString(), namespaceIndex); - } - #endregion - - #region Private Fields - private uint m_aggregateId; - private uint m_attributeId; - #endregion - } - #endregion -} diff --git a/ComIOP/Common/Client/Hda/HdaReadRequest.cs b/ComIOP/Common/Client/Hda/HdaReadRequest.cs deleted file mode 100644 index 387fa6ad5..000000000 --- a/ComIOP/Common/Client/Hda/HdaReadRequest.cs +++ /dev/null @@ -1,770 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using OpcRcw.Comn; -using OpcRcw.Hda; -using Opc.Ua; -using Opc.Ua.Server; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the parameters and results for a COM DA read operation. - /// - public class HdaReadRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - public HdaReadRequest(string itemId) - { - m_itemId = itemId; - } - #endregion - - #region Public Properties - /// - /// Gets the item id to read. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - } - - /// - /// Gets or sets the server handle. - /// - /// The server handle. - public int ServerHandle - { - get { return m_serverHandle; } - set { m_serverHandle = value; } - } - - /// - /// Gets the attribute ids to read. - /// - /// The attribute ids. - public List AttributeIds - { - get { return m_attributeIds; } - } - - /// - /// Gets or sets the attribute values returned from the server. - /// - /// The attribute values. - public HdaAttributeValue[] AttributeValues - { - get { return m_attributeValues; } - set { m_attributeValues = value; } - } - #endregion - - #region Public Methods - /// - /// Sets the error for all attributes. - /// - /// The error. - public void SetError(int error) - { - if (m_attributeIds != null) - { - m_attributeValues = new HdaAttributeValue[m_attributeIds.Count]; - - for (int ii = 0; ii < m_attributeValues.Length; ii++) - { - m_attributeValues[ii] = new HdaAttributeValue(); - m_attributeValues[ii].AttributeId = m_attributeIds[ii]; - m_attributeValues[ii].Error = error; - } - } - } - - /// - /// Adds the attribute to the request. - /// - /// The attribute ids. - public void AddAttribute(params uint[] attributeIds) - { - if (m_attributeIds == null) - { - m_attributeIds = new List(); - } - - if (attributeIds != null) - { - for (int ii = 0; ii < attributeIds.Length; ii++) - { - bool found = false; - - for (int jj = 0; jj < AttributeIds.Count; jj++) - { - if (AttributeIds[jj] == attributeIds[ii]) - { - found = true; - break; - } - } - - if (!found) - { - AttributeIds.Add(attributeIds[ii]); - } - } - } - } - - /// - /// Gets the attribute value. - /// - /// The expected type for the attribute value. - /// The attribute id. - /// The value to update. - /// if set to true if the attribute is required for the value attribute of a node. - /// The value cast to the type T. - /// - /// This method sets the StatusCode in the DataValue if an error occurs and returns default(T). - /// The DataValue.Value attribute is set to the value cast to type T. - /// - public T GetAttributeValue(uint attributeId, DataValue value, bool isValue) - { - value.Value = null; - - // find the attribute value. - HdaAttributeValue result = GetAttributeValue(attributeId); - - if (result == null) - { - value.StatusCode = StatusCodes.BadOutOfService; - return default(T); - } - - // set the appropriate error code if no value found. - if (result == null || result.Error < 0 || result.Error == ResultIds.S_NODATA) - { - value.StatusCode = StatusCodes.BadNotFound; - return default(T); - } - - // update the source timestamp if a value is being read. - if (isValue) - { - value.SourceTimestamp = result.Timestamp; - } - - // check type conversion error. - if (!typeof(T).IsInstanceOfType(result.Value)) - { - value.StatusCode = StatusCodes.BadTypeMismatch; - return default(T); - } - - // save the value and return the result. - value.Value = (T)result.Value; - return (T)result.Value; - } - - /// - /// Gets the result for the read operayoin. - /// - /// The context. - /// The item. - /// The node to read. - /// The value. - /// The diagnostics masks. - /// - public ServiceResult GetResult( - ISystemContext context, - HdaItemState item, - ReadValueId nodeToRead, - DataValue value, - DiagnosticsMasks diagnosticsMasks) - { - switch (nodeToRead.AttributeId) - { - case Attributes.Description: - { - string description = this.GetAttributeValue(Constants.OPCHDA_DESCRIPTION, value, false); - - if (StatusCode.IsGood(value.StatusCode)) - { - value.Value = new LocalizedText(description); - } - - break; - } - - case Attributes.DataType: - { - short datatype = this.GetAttributeValue(Constants.OPCHDA_DATA_TYPE, value, false); - - if (StatusCode.IsGood(value.StatusCode)) - { - value.Value = ComUtils.GetDataTypeId(datatype); - } - else - { - value.Value = DataTypeIds.BaseDataType; - value.StatusCode = StatusCodes.GoodLocalOverride; - } - - break; - } - - case Attributes.ValueRank: - { - short datatype = this.GetAttributeValue(Constants.OPCHDA_DATA_TYPE, value, false); - - if (StatusCode.IsGood(value.StatusCode)) - { - value.Value = ComUtils.GetValueRank(datatype); - } - else - { - value.Value = ValueRanks.Any; - value.StatusCode = StatusCodes.GoodLocalOverride; - } - - break; - } - - case Attributes.Historizing: - { - bool archiving = this.GetAttributeValue(Constants.OPCHDA_ARCHIVING, value, false); - - if (StatusCode.IsGood(value.StatusCode)) - { - value.Value = archiving; - } - else - { - value.Value = false; - value.StatusCode = StatusCodes.GoodLocalOverride; - } - - break; - } - - default: - { - return StatusCodes.BadAttributeIdInvalid; - } - } - - // check if the attribute value is missing. - if (value.StatusCode == StatusCodes.BadNotFound) - { - return StatusCodes.BadAttributeIdInvalid; - } - - return ApplyIndexRangeAndDataEncoding(context, nodeToRead, value); - } - - /// - /// Gets the result for the read operation. - /// - /// The context. - /// The attribute. - /// The node to read. - /// The value. - /// The diagnostics masks. - /// - public ServiceResult GetResult( - ISystemContext context, - HdaAttributeState attribute, - ReadValueId nodeToRead, - DataValue value, - DiagnosticsMasks diagnosticsMasks) - { - if (nodeToRead.AttributeId != Attributes.Value) - { - // check if reading access level. - if (nodeToRead.AttributeId == Attributes.AccessLevel || nodeToRead.AttributeId == Attributes.UserAccessLevel) - { - HdaAttributeValue result = GetAttributeValue(attribute.Attribute.Id); - - if (result == null || result.Error < 0 || result.Error == ResultIds.S_NODATA) - { - value.StatusCode = StatusCodes.BadNotFound; - return value.StatusCode; - } - - value.Value = AccessLevels.CurrentRead; - - if (result.Error != ResultIds.S_CURRENTVALUE) - { - value.Value = (byte)(AccessLevels.CurrentRead | AccessLevels.HistoryRead); - } - - return value.StatusCode; - } - - return StatusCodes.BadAttributeIdInvalid; - } - - // convert values when required. - switch (attribute.Attribute.Id) - { - case Constants.OPCHDA_NORMAL_MAXIMUM: - { - double high = this.GetAttributeValue(Constants.OPCHDA_NORMAL_MAXIMUM, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - double low = this.GetAttributeValue(Constants.OPCHDA_NORMAL_MINIMUM, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = new Range(high, low); - break; - } - - case Constants.OPCHDA_HIGH_ENTRY_LIMIT: - { - double high = this.GetAttributeValue(Constants.OPCHDA_HIGH_ENTRY_LIMIT, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - double low = this.GetAttributeValue(Constants.OPCHDA_LOW_ENTRY_LIMIT, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = new Range(high, low); - break; - } - - case Constants.OPCHDA_ENG_UNITS: - { - string units = this.GetAttributeValue(Constants.OPCHDA_ENG_UNITS, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = new EUInformation(units, Namespaces.ComInterop); - break; - } - - case Constants.OPCHDA_MAX_TIME_INT: - case Constants.OPCHDA_MIN_TIME_INT: - { - string number = this.GetAttributeValue(attribute.Attribute.Id, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - try - { - value.Value = Convert.ToDouble(number); - } - catch (Exception) - { - value.StatusCode = StatusCodes.BadTypeMismatch; - return value.StatusCode; - } - - break; - } - - case Constants.OPCHDA_EXCEPTION_DEV_TYPE: - { - short number = this.GetAttributeValue(attribute.Attribute.Id, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = (int)number; - break; - } - - default: - { - object result = this.GetAttributeValue(attribute.Attribute.Id, value, true); - - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - value.Value = result; - break; - } - - } - - // check if the attribute value is missing. - if (value.StatusCode == StatusCodes.BadNotFound) - { - return StatusCodes.BadNodeIdUnknown; - } - - return ApplyIndexRangeAndDataEncoding(context, nodeToRead, value); - } - #endregion - - #region Private Methods - /// - /// Gets the attribute value. - /// - /// The attribute id. - private HdaAttributeValue GetAttributeValue(uint attributeId) - { - if (m_attributeIds != null) - { - for (int ii = 0; ii < m_attributeIds.Count; ii++) - { - if (m_attributeIds[ii] == attributeId) - { - if (m_attributeValues != null && ii < m_attributeValues.Length) - { - return m_attributeValues[ii]; - } - - break; - } - } - } - - return null; - } - - /// - /// Applies the index range and data encoding to the value. - /// - /// The context. - /// The node to read. - /// The value. - /// - private ServiceResult ApplyIndexRangeAndDataEncoding( - ISystemContext context, - ReadValueId nodeToRead, - DataValue value) - { - if (StatusCode.IsBad(value.StatusCode)) - { - return value.StatusCode; - } - - if (nodeToRead.ParsedIndexRange != NumericRange.Empty || !QualifiedName.IsNull(nodeToRead.DataEncoding)) - { - if (nodeToRead.AttributeId != Attributes.Value && !QualifiedName.IsNull(nodeToRead.DataEncoding)) - { - return StatusCodes.BadDataEncodingInvalid; - } - - object valueToUpdate = value.Value; - - ServiceResult result = BaseVariableState.ApplyIndexRangeAndDataEncoding( - context, - nodeToRead.ParsedIndexRange, - nodeToRead.DataEncoding, - ref valueToUpdate); - - if (ServiceResult.IsBad(result)) - { - value.Value = null; - value.StatusCode = result.StatusCode; - return result; - } - - value.Value = valueToUpdate; - } - - return value.StatusCode; - } - #endregion - - #region Private Fields - private string m_itemId; - private int m_serverHandle; - private List m_attributeIds; - private HdaAttributeValue[] m_attributeValues; - #endregion - } - - /// - /// A collection of read requests. - /// - public class HdaReadRequestCollection : List - { - #region Public Methods - /// - /// Determines whether the specified operation has a read request result. - /// - /// The read operation parameters. - /// - /// true if the specified operation has a read request result; otherwise, false. - /// - public bool HasResult(ReadValueId nodeToRead) - { - return nodeToRead.Handle is HdaReadRequest; - } - - /// - /// Gets the result. - /// - /// The context. - /// The source. - /// The node to read. - /// The value. - /// The diagnostics masks. - /// - public ServiceResult GetResult( - ISystemContext context, - NodeState source, - ReadValueId nodeToRead, - DataValue value, - DiagnosticsMasks diagnosticsMasks) - { - HdaReadRequest request = nodeToRead.Handle as HdaReadRequest; - - if (request == null) - { - return StatusCodes.Good; - } - - // read item value. - HdaItemState item = source as HdaItemState; - - if (item != null) - { - return request.GetResult(context, item, nodeToRead, value, diagnosticsMasks); - } - - // read vendor defined attribute value. - HdaAttributeState attribute = source as HdaAttributeState; - - if (attribute != null) - { - return request.GetResult(context, attribute, nodeToRead, value, diagnosticsMasks); - } - - return StatusCodes.Good; - } - - /// - /// Adds a request for the specified source. - /// - /// The source. - /// The node to read. - /// if set to true [queued]. - /// - public StatusCode Add(NodeState source, ReadValueId nodeToRead, out bool queued) - { - queued = true; - - // read item attributes. - HdaItemState item = source as HdaItemState; - - if (item != null) - { - return Add(item, nodeToRead, out queued); - } - - // read HDA attribute value. - HdaAttributeState attribute = source as HdaAttributeState; - - if (attribute != null) - { - return Add(attribute, nodeToRead, out queued); - } - - queued = false; - return StatusCodes.Good; - } - #endregion - - #region Private Methods - /// - /// Adds a request for the specified item id. - /// - /// The item id. - /// The new request. - private HdaReadRequest Add(string itemId) - { - if (m_index == null) - { - m_index = new Dictionary(); - } - - HdaReadRequest request = null; - - if (!m_index.TryGetValue(itemId, out request)) - { - request = new HdaReadRequest(itemId); - m_index.Add(itemId, request); - } - - this.Add(request); - return request; - } - - /// - /// Adds a read request for the specified properties. - /// - /// The item id. - /// The attribute ids. - /// The new request. - private HdaReadRequest Add(string itemId, params uint[] attributeIds) - { - if (m_index == null) - { - m_index = new Dictionary(); - } - - HdaReadRequest request = null; - - if (!m_index.TryGetValue(itemId, out request)) - { - request = new HdaReadRequest(itemId); - m_index.Add(itemId, request); - this.Add(request); - } - - request.AddAttribute(attributeIds); - return request; - } - - /// - /// Adds a read request for the specified item. - /// - /// The item. - /// The node to read. - /// if set to true if a request was created. - /// Any error. - private StatusCode Add(HdaItemState item, ReadValueId nodeToRead, out bool queued) - { - queued = true; - - switch (nodeToRead.AttributeId) - { - case Attributes.Description: - { - nodeToRead.Handle = Add(item.ItemId, Constants.OPCHDA_DESCRIPTION); - break; - } - - case Attributes.DataType: - case Attributes.ValueRank: - { - nodeToRead.Handle = Add(item.ItemId, Constants.OPCHDA_DATA_TYPE); - break; - } - - case Attributes.Historizing: - { - nodeToRead.Handle = Add(item.ItemId, Constants.OPCHDA_ARCHIVING); - break; - } - - default: - { - queued = false; - break; - } - } - - return StatusCodes.Good; - } - - /// - /// Adds the specified attribute read to the request list. - /// - /// The attribute. - /// The node to read. - /// if set to true [queued]. - /// - private StatusCode Add(HdaAttributeState attribute, ReadValueId nodeToRead, out bool queued) - { - queued = false; - - if (nodeToRead.AttributeId != Attributes.Value && nodeToRead.AttributeId != Attributes.AccessLevel && nodeToRead.AttributeId != Attributes.UserAccessLevel) - { - return StatusCodes.Good; - } - - queued = true; - - switch (attribute.Attribute.Id) - { - case Constants.OPCHDA_NORMAL_MAXIMUM: - { - nodeToRead.Handle = Add(attribute.ItemId, Constants.OPCHDA_NORMAL_MAXIMUM, Constants.OPCHDA_NORMAL_MINIMUM); - break; - } - - case Constants.OPCHDA_HIGH_ENTRY_LIMIT: - { - nodeToRead.Handle = Add(attribute.ItemId, Constants.OPCHDA_HIGH_ENTRY_LIMIT, Constants.OPCHDA_LOW_ENTRY_LIMIT); - break; - } - - default: - { - nodeToRead.Handle = Add(attribute.ItemId, attribute.Attribute.Id); - break; - } - } - - return StatusCodes.Good; - } - #endregion - - #region Private Fields - Dictionary m_index; - #endregion - } -} diff --git a/ComIOP/Common/Client/Hda/HdaSubscribeRequestManager.cs b/ComIOP/Common/Client/Hda/HdaSubscribeRequestManager.cs deleted file mode 100644 index ffb84438e..000000000 --- a/ComIOP/Common/Client/Hda/HdaSubscribeRequestManager.cs +++ /dev/null @@ -1,1009 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Runtime.InteropServices; -using OpcRcw.Comn; -using OpcRcw.Da; -using Opc.Ua; -using Opc.Ua.Com; -using Opc.Ua.Com.Client; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores a request to subscribe to the attributes of an HDA item. - /// - public class HdaSubscribeAttributeRequest - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The item id. - public HdaSubscribeAttributeRequest(string itemId) - { - m_itemId = itemId; - } - #endregion - - #region Public Attributes - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - } - - /// - /// Gets or sets the server handle. - /// - /// The server handle. - public int? ServerHandle - { - get { return m_serverHandle; } - set { m_serverHandle = value; } - } - - /// - /// Gets the monitored items. - /// - /// The monitored items. - public List MonitoredItems - { - get { return m_monitoredItems; } - } - - /// - /// Gets the sampling interval. - /// - /// The sampling interval. - public int SamplingInterval - { - get { return m_samplingInterval; } - } - - /// - /// Gets the next update time. - /// - /// The next update time. - public DateTime NextUpdateTime - { - get { return m_nextUpdateTime; } - } - #endregion - - #region Public Methods - /// - /// Adds the specified monitored item. - /// - /// The context. - /// The monitored item. - public void Add(ServerSystemContext context, MonitoredItem monitoredItem) - { - if (monitoredItem == null) - { - return; - } - - // save the monitored item. - if (m_monitoredItems == null) - { - m_monitoredItems = new List(); - } - - m_monitoredItems.Add(monitoredItem); - } - - /// - /// Modifies the request after the specified item changes. - /// - /// The context. - /// The monitored item. - public void Modify(ServerSystemContext context, MonitoredItem monitoredItem) - { - // nothing to do. - } - - /// - /// Removes the specified monitored item. - /// - /// The context. - /// The monitored item. - public void Remove(ServerSystemContext context, MonitoredItem monitoredItem) - { - // remove the monitored item. - if (monitoredItem != null && m_monitoredItems != null) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - if (Object.ReferenceEquals(m_monitoredItems[ii], monitoredItem)) - { - m_monitoredItems.RemoveAt(ii); - break; - } - } - } - } - - /// - /// Queues the value to the monitored item. - /// - /// The context. - /// The request. - /// if set to true [initial update]. - public void QueueValues(ServerSystemContext context, HdaReadRequest request, bool initialUpdate) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - QueueValue(context, request, m_monitoredItems[ii]); - } - - if (!initialUpdate) - { - IncrementSampleTime(); - } - } - - /// - /// Updates the request after changes are completed. - /// - /// The attribute sampling interval. - public void ChangesComplete(int attributeSamplingInterval) - { - // adjust the sampling interval on the monitored items. - if (m_monitoredItems != null) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - int samplingInterval = (int)m_monitoredItems[ii].SamplingInterval; - - if (attributeSamplingInterval > samplingInterval) - { - m_monitoredItems[ii].SetSamplingInterval(attributeSamplingInterval); - continue; - } - - if (samplingInterval%attributeSamplingInterval != 0) - { - int muliple = samplingInterval/attributeSamplingInterval + 1; - m_monitoredItems[ii].SetSamplingInterval(attributeSamplingInterval*muliple); - } - } - } - - UpdateSamplingInterval(); - } - #endregion - - #region Private Methods - /// - /// Updates the request after adding/removing items. - /// - private void UpdateSamplingInterval() - { - double samplingInterval = Double.MaxValue; - - for (int ii = 0; ii < MonitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = MonitoredItems[ii]; - - // find the handle associated with the item. - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - continue; - } - - // ignore disabled items. - if (monitoredItem.MonitoringMode == MonitoringMode.Disabled) - { - continue; - } - - // find the fastest sampling interval. - if (samplingInterval > monitoredItem.SamplingInterval) - { - samplingInterval = monitoredItem.SamplingInterval; - } - } - - // update values. - if (samplingInterval != m_samplingInterval) - { - m_samplingInterval = (int)samplingInterval; - m_nextUpdateTime = DateTime.UtcNow; - } - } - - /// - /// Increments the sample time to the next interval. - /// - private void IncrementSampleTime() - { - // update next sample time. - long now = DateTime.UtcNow.Ticks; - long samplingInterval = (long)(m_samplingInterval*TimeSpan.TicksPerMillisecond); - - long nextSampleTime = 0; - - if (nextSampleTime > 0) - { - long delta = now - nextSampleTime; - - if (samplingInterval > 0 && delta >= 0) - { - nextSampleTime += ((delta/samplingInterval)+1)*samplingInterval; - } - } - - // set sampling time based on current time. - else - { - nextSampleTime = now + samplingInterval; - } - - m_nextUpdateTime = new DateTime(nextSampleTime); - } - - /// - /// Queues the value to the monitored item. - /// - /// The context. - /// The request. - /// The monitored item. - private void QueueValue(ServerSystemContext context, HdaReadRequest request, MonitoredItem monitoredItem) - { - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - return; - } - - ReadValueId nodeToRead = monitoredItem.GetReadValueId(); - DataValue value = new DataValue(); - ServiceResult error = null; - - HdaItemState item = handle.Node as HdaItemState; - HdaAttributeState attribute = handle.Node as HdaAttributeState; - - if (item != null) - { - error = request.GetResult(context, item, nodeToRead, value, monitoredItem.DiagnosticsMasks); - } - else if (attribute != null) - { - error = request.GetResult(context, attribute, nodeToRead, value, monitoredItem.DiagnosticsMasks); - } - - value.ServerTimestamp = DateTime.UtcNow; - - if (value.StatusCode != StatusCodes.BadNotFound) - { - monitoredItem.QueueValue(value, error); - } - } - #endregion - - #region Private Fields - private string m_itemId; - private int? m_serverHandle; - private List m_monitoredItems; - private int m_samplingInterval; - private DateTime m_nextUpdateTime; - #endregion - } - - /// - /// Manages the subscribe requests. - /// - internal class HdaSubscribeRequestManager : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The context. - /// The locale to use. - /// The configuration. - public HdaSubscribeRequestManager(ServerSystemContext context, int localeId, ComHdaClientConfiguration configuration) - { - m_context = context; - m_localeId = localeId; - m_configuration = configuration; - m_requests = new Dictionary(); - m_monitoredItems = new Dictionary(); - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - lock (m_lock) - { - Utils.SilentDispose(m_attributeScanTimer); - m_attributeScanTimer = null; - } - } - } - #endregion - - #region Public Methods - /// - /// The local used by the request manager. - /// - public int LocaleId - { - get { return m_localeId; } - } - - /// - /// Recreates the items after a disconnect. - /// - public void RecreateItems() - { - lock (m_lock) - { - m_requests.Clear(); - - Utils.SilentDispose(m_attributeScanTimer); - m_attributeScanTimer = null; - - IList monitoredItems = new List(m_monitoredItems.Values); - m_monitoredItems.Clear(); - - CreateItems(m_context, monitoredItems); - } - } - - /// - /// Creates subscription requests for monitored items. - /// - /// The context. - /// The monitored items. - public void CreateItems(ServerSystemContext context, IList monitoredItems) - { - lock (m_lock) - { - if (monitoredItems != null) - { - Dictionary requests = new Dictionary(); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem; - - if (monitoredItem == null) - { - continue; - } - - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - continue; - } - - if (!HasExternalSource(handle.Node, monitoredItem.AttributeId)) - { - continue; - } - - HdaSubscribeAttributeRequest request = Add(handle.Node, monitoredItem); - - if (request != null) - { - requests[request.ItemId] = request; - } - } - - ApplyChanges(requests, true); - } - } - } - - /// - /// Modifies subscription requests for monitored items. - /// - /// The context. - /// The monitored items. - public void ModifyItems(ServerSystemContext context, IList monitoredItems) - { - lock (m_lock) - { - if (monitoredItems != null) - { - Dictionary requests = new Dictionary(); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem; - - if (monitoredItem == null) - { - continue; - } - - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - continue; - } - - if (!HasExternalSource(handle.Node, monitoredItem.AttributeId)) - { - continue; - } - - HdaSubscribeAttributeRequest request = Modify(handle.Node, monitoredItem); - - if (request != null) - { - requests[request.ItemId] = request; - } - } - - ApplyChanges(requests, true); - } - } - } - - /// - /// Deletes subscription requests for monitored items. - /// - /// The context. - /// The monitored items. - public void DeleteItems(ServerSystemContext context, IList monitoredItems) - { - lock (m_lock) - { - if (monitoredItems != null) - { - Dictionary requests = new Dictionary(); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem; - - if (monitoredItem == null) - { - continue; - } - - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - continue; - } - - if (!HasExternalSource(handle.Node, monitoredItem.AttributeId)) - { - continue; - } - - HdaSubscribeAttributeRequest request = Remove(handle.Node, monitoredItem); - - if (request != null) - { - requests[request.ItemId] = request; - } - } - - ApplyChanges(requests, false); - } - } - } - #endregion - - #region Private Methods - /// - /// Finds the item attributes request for the specifed item. - /// - /// The item id. - /// if set to true a new request is created if it does not exist. - /// The subscribe attribute request. - private HdaSubscribeAttributeRequest FindAttributeRequest(string itemId, bool create) - { - lock (m_lock) - { - HdaSubscribeAttributeRequest requests = null; - - if (!m_requests.TryGetValue(itemId, out requests)) - { - if (!create) - { - return null; - } - - requests = new HdaSubscribeAttributeRequest(itemId); - m_requests.Add(itemId, requests); - } - - return requests; - } - } - - /// - /// Determines whether the attribute has an external source. - /// - private bool HasExternalSource(NodeState node, uint attributeId) - { - HdaItemState item = node as HdaItemState; - - if (item != null) - { - switch (attributeId) - { - case Attributes.DataType: - case Attributes.ValueRank: - case Attributes.Description: - case Attributes.Historizing: - { - return true; - } - } - - return false; - } - - HdaAttributeState attribute = node as HdaAttributeState; - - if (attribute != null) - { - switch (attributeId) - { - case Attributes.Value: - case Attributes.AccessLevel: - case Attributes.UserAccessLevel: - { - return true; - } - } - - return false; - } - - return false; - } - - /// - /// Adds the monitored item to the collection. - /// - /// The source. - /// The monitored item. - private HdaSubscribeAttributeRequest Add(NodeState source, MonitoredItem monitoredItem) - { - lock (m_lock) - { - m_monitoredItems.Add(monitoredItem.Id, monitoredItem); - - // get the HDA item id. - string itemId = GetItemId(source); - - // create/update the subscribe request for the HDA item. - if (itemId != null) - { - HdaSubscribeAttributeRequest request = FindAttributeRequest(itemId, true); - - if (request != null) - { - request.Add(m_context, monitoredItem); - return request; - } - } - - return null; - } - } - - /// - /// Modifies the monitored item to the collection. - /// - /// The source. - /// The monitored item. - private HdaSubscribeAttributeRequest Modify(NodeState source, MonitoredItem monitoredItem) - { - lock (m_lock) - { - // get the HDA item id. - string itemId = GetItemId(source); - - // update the subscribe request for the HDA item. - if (itemId != null) - { - HdaSubscribeAttributeRequest request = FindAttributeRequest(itemId, false); - - if (request != null) - { - request.Modify(m_context, monitoredItem); - return request; - } - } - - return null; - } - } - - /// - /// Removes the monitored item from the collection. - /// - /// The source. - /// The monitored item. - private HdaSubscribeAttributeRequest Remove(NodeState source, MonitoredItem monitoredItem) - { - lock (m_lock) - { - m_monitoredItems.Remove(monitoredItem.Id); - - // get the HDA item id. - string itemId = GetItemId(source); - - // delete the subscribe request for the HDA item. - if (itemId != null) - { - HdaSubscribeAttributeRequest request = FindAttributeRequest(itemId, false); - - if (request != null) - { - request.Remove(m_context, monitoredItem); - return request; - } - } - - return null; - } - } - - /// - /// Gets the HDA item id associated with the source. - /// - /// The source. - private string GetItemId(NodeState source) - { - HdaItemState item = source as HdaItemState; - - if (item != null) - { - return item.ItemId; - } - - HdaAttributeState attribute = source as HdaAttributeState; - - if (attribute != null) - { - return attribute.ItemId; - } - - return null; - } - - /// - /// Applies any changes to the subscriptions. - /// - private void ApplyChanges(Dictionary requests, bool initialUpdateRequired) - { - List requestsToRemove = null; - - lock (m_lock) - { - // update existing requests. - foreach (KeyValuePair entry in requests) - { - HdaSubscribeAttributeRequest request = entry.Value; - - // remove unused requests. - if (request.MonitoredItems == null || request.MonitoredItems.Count == 0) - { - if (requestsToRemove == null) - { - requestsToRemove = new List(); - } - - requestsToRemove.Add(entry.Value); - continue; - } - - request.ChangesComplete(m_configuration.AttributeSamplingInterval); - } - - // remove deleted requests from dictionary. - if (requestsToRemove != null) - { - for (int ii = 0; ii < requestsToRemove.Count; ii++) - { - m_requests.Remove(requestsToRemove[ii].ItemId); - } - } - - // check if the attribute scanner needs to be stopped/started. - if (m_attributeScanTimer == null) - { - if (m_requests.Count > 0) - { - m_attributeScanTimer = new Timer(OnScanAttributes, null, m_configuration.AttributeSamplingInterval, m_configuration.AttributeSamplingInterval); - } - } - else - { - if (m_requests.Count == 0) - { - m_attributeScanTimer.Dispose(); - m_attributeScanTimer = null; - } - } - } - - // release any unused handles. - if (requestsToRemove != null) - { - ComHdaClientManager system = (ComHdaClientManager)m_context.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient(m_context, false); - ReleaseHandles(client, requestsToRemove); - } - - // send initial update. - if (initialUpdateRequired) - { - DoScan(requests, true); - } - } - - /// - /// Assigns the handles to the requests. - /// - /// The client. - /// The requests. - private void AssignHandles(ComHdaClient client, Dictionary requests) - { - List itemIds = null; - - lock (m_lock) - { - foreach (KeyValuePair entry in requests) - { - if (entry.Value.ServerHandle == null) - { - if (itemIds == null) - { - itemIds = new List(); - } - - itemIds.Add(entry.Key); - } - } - } - - if (itemIds == null) - { - return; - } - - HdaItem[] items = client.GetItems(itemIds.ToArray()); - - lock (m_lock) - { - for (int ii = 0; ii < items.Length; ii++) - { - HdaSubscribeAttributeRequest request = null; - - if (!requests.TryGetValue(itemIds[ii], out request)) - { - continue; - } - - if (items[ii].Error < 0) - { - request.ServerHandle = null; - continue; - } - - request.ServerHandle = items[ii].ServerHandle; - } - } - } - - /// - /// Releases the handles. - /// - /// The client. - /// The requests. - private void ReleaseHandles(ComHdaClient client, List requests) - { - List serverHandles = null; - - lock (m_lock) - { - for (int ii = 0; ii < requests.Count; ii++) - { - if (requests[ii].ServerHandle != null) - { - if (serverHandles == null) - { - serverHandles = new List(); - } - - serverHandles.Add(requests[ii].ServerHandle.Value); - requests[ii].ServerHandle = null; - } - } - } - - if (serverHandles == null) - { - return; - } - - client.ReleaseItemHandles(serverHandles.ToArray()); - } - - /// - /// Called when the scan attributes timer expires. - /// - private void DoScan(Dictionary requests, bool initialUpdate) - { - try - { - ComHdaClientManager system = (ComHdaClientManager)m_context.SystemHandle; - ComHdaClient client = (ComHdaClient)system.SelectClient(m_context, false); - - // ensure all requests have valid handles. - AssignHandles(client, requests); - - // collect the list of attributes that need reading. - HdaReadRequestCollection itemsToRead = new HdaReadRequestCollection(); - List subscribeRequests = new List(); - List readRequestsForSubscribeRequests = new List(); - - lock (m_lock) - { - DateTime now = DateTime.UtcNow; - - foreach (KeyValuePair entry in requests) - { - // check if it is time for an update. - if (!initialUpdate && entry.Value.NextUpdateTime > now) - { - continue; - } - - // create a read request for each monitored item. - bool somethingToDo = false; - - for (int ii = 0; ii < entry.Value.MonitoredItems.Count; ii++) - { - MonitoredItem monitoredItem = entry.Value.MonitoredItems[ii]; - - NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; - - if (handle == null) - { - continue; - } - - // check if item is not valid. - if (entry.Value.ServerHandle == null) - { - monitoredItem.QueueValue(null, StatusCodes.BadNodeIdUnknown); - continue; - } - - ReadValueId valueToRead = monitoredItem.GetReadValueId(); - - bool queued = false; - StatusCode error = itemsToRead.Add(handle.Node, valueToRead, out queued); - - if (StatusCode.IsBad(error)) - { - monitoredItem.QueueValue(null, error); - continue; - } - - if (!somethingToDo && queued) - { - // add server handle to read request. - HdaReadRequest request = (HdaReadRequest)valueToRead.Handle; - request.ServerHandle = entry.Value.ServerHandle.Value; - - // save mapping between subscribe request and read requests. - subscribeRequests.Add(entry.Value); - readRequestsForSubscribeRequests.Add(request); - somethingToDo = true; - } - } - } - - // check if nothing to do. - if (requests.Count == 0) - { - return; - } - } - - // read the attributes from the server. - client.Read(itemsToRead, true); - - // update the monitored items. - lock (m_lock) - { - for (int ii = 0; ii < subscribeRequests.Count; ii++) - { - subscribeRequests[ii].QueueValues(m_context, readRequestsForSubscribeRequests[ii], initialUpdate); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error scanning attributes in HDA COM server."); - } - } - - /// - /// Called when the scan attributes timer expires. - /// - private void OnScanAttributes(object state) - { - DoScan(m_requests, false); - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private ComHdaClientConfiguration m_configuration; - private int m_localeId; - private Timer m_attributeScanTimer; - private ServerSystemContext m_context; - private Dictionary m_monitoredItems; - private Dictionary m_requests; - #endregion - } -} diff --git a/ComIOP/Common/Client/ParsedNodeId.cs b/ComIOP/Common/Client/ParsedNodeId.cs deleted file mode 100644 index 6ea009168..000000000 --- a/ComIOP/Common/Client/ParsedNodeId.cs +++ /dev/null @@ -1,357 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using Opc.Ua; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the elements of a NodeId after it is parsed. - /// - /// - /// The NodeIds used by the samples are strings with an optional path appended. - /// The RootType identifies the type of Root Node. The RootId is the unique identifier - /// for the Root Node. The ComponentPath is constructed from the SymbolicNames - /// of one or more children of the Root Node. - /// - public class ParsedNodeId - { - #region Public Interface - /// - /// The namespace index that qualified the NodeId. - /// - public ushort NamespaceIndex - { - get { return m_namespaceIndex; } - set { m_namespaceIndex = value; } - } - - /// - /// The identifier for the root of the NodeId. - /// - public string RootId - { - get { return m_rootId; } - set { m_rootId = value; } - } - - /// - /// The type of root node. - /// - public int RootType - { - get { return m_rootType; } - set { m_rootType = value; } - } - - /// - /// The relative path to the component identified by the NodeId. - /// - public string ComponentPath - { - get { return m_componentPath; } - set { m_componentPath = value; } - } - - /// - /// Parses the specified node identifier. - /// - /// The node identifier. - /// The parsed node identifier. Null if the identifier cannot be parsed. - public static ParsedNodeId Parse(NodeId nodeId) - { - // can only parse non-null string node identifiers. - if (NodeId.IsNull(nodeId)) - { - return null; - } - - string identifier = nodeId.Identifier as string; - - if (String.IsNullOrEmpty(identifier)) - { - return null; - } - - ParsedNodeId parsedNodeId = new ParsedNodeId(); - parsedNodeId.NamespaceIndex = nodeId.NamespaceIndex; - - int start = 0; - - // extract the type of identifier. - parsedNodeId.RootType = (int)ExtractNumber(identifier, ref start); - - if (start >= identifier.Length || identifier[start] != ':') - { - return null; - } - - // extract any component path. - StringBuilder buffer = new StringBuilder(); - - int index = start+1; - int end = identifier.Length; - - bool escaped = false; - - while (index < end) - { - char ch = identifier[index++]; - - // skip any escape character but keep the one after it. - if (ch == '&') - { - escaped = true; - continue; - } - - if (!escaped && ch == '?') - { - end = index; - break; - } - - buffer.Append(ch); - escaped = false; - } - - // extract any component. - parsedNodeId.RootId = buffer.ToString(); - parsedNodeId.ComponentPath = null; - - if (end < identifier.Length) - { - parsedNodeId.ComponentPath = identifier.Substring(end); - } - - return parsedNodeId; - } - - /// - /// Constructs a node identifier. - /// - /// The node identifier. - public NodeId Construct() - { - StringBuilder buffer = new StringBuilder(); - - // add the root type. - buffer.Append(RootType); - buffer.Append(':'); - - // add the root identifier. - if (this.RootId != null) - { - for (int ii = 0; ii < this.RootId.Length; ii++) - { - char ch = this.RootId[ii]; - - // escape any special characters. - if (ch == '&' || ch == '?') - { - buffer.Append('&'); - } - - buffer.Append(ch); - } - } - - // add the component path. - if (!String.IsNullOrEmpty(this.ComponentPath)) - { - buffer.Append('?'); - buffer.Append(this.ComponentPath); - } - - // construct the node id with the namespace index provided. - return new NodeId(buffer.ToString(), this.NamespaceIndex); - } - - /// - /// Constructs the node identifier for a component. - /// - /// The component. - /// Index of the namespace. - /// The node identifier for a component. - public static NodeId ConstructIdForComponent(NodeState component, ushort namespaceIndex) - { - if (component == null) - { - return null; - } - - // components must be instances with a parent. - BaseInstanceState instance = component as BaseInstanceState; - - if (instance == null || instance.Parent == null) - { - return component.NodeId; - } - - // parent must have a string identifier. - string parentId = instance.Parent.NodeId.Identifier as string; - - if (parentId == null) - { - return null; - } - - StringBuilder buffer = new StringBuilder(); - buffer.Append(parentId); - - // check if the parent is another component. - int index = parentId.IndexOf('?'); - - if (index < 0) - { - buffer.Append('?'); - } - else - { - buffer.Append('/'); - } - - buffer.Append(component.SymbolicName); - - // return the node identifier. - return new NodeId(buffer.ToString(), namespaceIndex); - } - - /// - /// Extracts a number from the string. - /// - /// The identifier. - /// The start. Set the first non-digit character. - /// The number - protected static uint ExtractNumber(string identifier, ref int start) - { - uint number = 0; - - for (int ii = start; ii < identifier.Length; ii++) - { - if (!Char.IsDigit(identifier[ii])) - { - start = ii; - return number; - } - - number *= 10; - number += (byte)(identifier[ii] - '0'); - } - - start = identifier.Length; - return number; - } - - /// - /// Escapes and appends a string. - /// - /// The buffer. - /// The text. - /// The special chars. - protected static void EscapeAndAppendString(StringBuilder buffer, string text, params char[] specialChars) - { - // add the root identifier. - if (text != null) - { - for (int ii = 0; ii < text.Length; ii++) - { - char ch = text[ii]; - - // escape any special characters. - for (int jj = 0; jj < specialChars.Length; jj++) - { - if (specialChars[jj] == ch) - { - buffer.Append(specialChars[0]); - } - } - - buffer.Append(ch); - } - } - } - - /// - /// Extracts the and unescapes a string. - /// - /// The text. - /// The start. - /// The special chars. - /// - protected static string ExtractAndUnescapeString(string text, ref int start, params char[] specialChars) - { - StringBuilder buffer = new StringBuilder(); - - int index = start; - bool escaped = false; - - while (index < text.Length) - { - char ch = text[index++]; - - if (!escaped) - { - // skip any escape character but keep the one after it. - if (ch == specialChars[0]) - { - escaped = true; - continue; - } - - // terminate on any special char other than the escape char. - for (int jj = 1; jj < specialChars.Length; jj++) - { - if (specialChars[jj] == ch) - { - start = index-1; - return buffer.ToString(); - } - } - } - - buffer.Append(ch); - escaped = false; - } - - start = text.Length; - return buffer.ToString(); - } - #endregion - - #region Private Fields - private ushort m_namespaceIndex; - private string m_rootId; - private int m_rootType; - private string m_componentPath; - #endregion - } -} diff --git a/ComIOP/Common/Client/UserNameValidator.cs b/ComIOP/Common/Client/UserNameValidator.cs deleted file mode 100644 index a7e923272..000000000 --- a/ComIOP/Common/Client/UserNameValidator.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography; -using Opc.Ua.Configuration; - - -namespace Opc.Ua.Com.Client -{ - /// - /// Validates UserName. - /// - public class UserNameValidator - { - /// - /// Triple DES Key - /// - private const string strKey = "h13h6m9F"; - - /// - /// Triple DES initialization vector - /// - private const string strIV = "Zse5"; - - #region Constructors - /// - /// The default constructor. - /// - public UserNameValidator(string applicationName) - { - m_UserNameIdentityTokens = UserNameCreator.LoadUserName(applicationName); - } - #endregion - - #region Public Methods - - /// - /// Validates a User. - /// - /// UserNameIdentityToken. - /// True if the list contains a valid item. - public bool Validate(UserNameIdentityToken token) - { - return Validate(token.UserName, token.DecryptedPassword); - } - - /// - /// Validates a User. - /// - /// user name. - /// password. - /// True if the list contains a valid item. - public bool Validate(string name, string password) - { - lock (m_lock) - { - if (!m_UserNameIdentityTokens.ContainsKey(name)) - { - return false; - } - - return (m_UserNameIdentityTokens[name].DecryptedPassword == password); - } - } - - #endregion - - #region Private Fields - private object m_lock = new object(); - private Dictionary m_UserNameIdentityTokens = new Dictionary(); - #endregion - } -} diff --git a/ComIOP/Common/Common/BuildDesign.bat b/ComIOP/Common/Common/BuildDesign.bat deleted file mode 100644 index f30cb62c5..000000000 --- a/ComIOP/Common/Common/BuildDesign.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -setlocal - -Opc.Ua.ModelCompiler.exe compile -version v104 -d2 ".\ModelDesign.xml" -cg ".\ModelDesign.csv" -o2 .\ \ No newline at end of file diff --git a/ComIOP/Common/Common/ComUtils.cs b/ComIOP/Common/Common/ComUtils.cs deleted file mode 100644 index f622be531..000000000 --- a/ComIOP/Common/Common/ComUtils.cs +++ /dev/null @@ -1,2940 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Configuration; -using System.IO; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Xml; -using System.Xml.Serialization; -using System.Net; -using System.Net.Sockets; -using System.Globalization; -using System.Runtime.InteropServices; -using System.Security.Principal; - -using OpcRcw.Hda; - -namespace Opc.Ua.Com -{ - /// - /// Exposes WIN32 and COM API functions. - /// - public static class ComUtils - { - #region NetApi Function Declarations - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - private struct SERVER_INFO_100 - { - public uint sv100_platform_id; - [MarshalAs(UnmanagedType.LPWStr)] - public string sv100_name; - } - - private const uint LEVEL_SERVER_INFO_100 = 100; - private const uint LEVEL_SERVER_INFO_101 = 101; - - private const int MAX_PREFERRED_LENGTH = -1; - - private const uint SV_TYPE_WORKSTATION = 0x00000001; - private const uint SV_TYPE_SERVER = 0x00000002; - - [DllImport("Netapi32.dll")] - private static extern int NetServerEnum( - IntPtr servername, - uint level, - out IntPtr bufptr, - int prefmaxlen, - out int entriesread, - out int totalentries, - uint servertype, - IntPtr domain, - IntPtr resume_handle); - - [DllImport("Netapi32.dll")] - private static extern int NetApiBufferFree(IntPtr buffer); - - /// - /// Enumerates computers on the local network. - /// - public static string[] EnumComputers() - { - IntPtr pInfo; - - int entriesRead = 0; - int totalEntries = 0; - - int result = NetServerEnum( - IntPtr.Zero, - LEVEL_SERVER_INFO_100, - out pInfo, - MAX_PREFERRED_LENGTH, - out entriesRead, - out totalEntries, - SV_TYPE_WORKSTATION | SV_TYPE_SERVER, - IntPtr.Zero, - IntPtr.Zero); - - if (result != 0) - { - throw new ApplicationException("NetApi Error = " + String.Format("0x{0:X8}", result)); - } - - string[] computers = new string[entriesRead]; - - IntPtr pos = pInfo; - - for (int ii = 0; ii < entriesRead; ii++) - { - SERVER_INFO_100 info = (SERVER_INFO_100)Marshal.PtrToStructure(pos, typeof(SERVER_INFO_100)); - - computers[ii] = info.sv100_name; - - pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(SERVER_INFO_100))); - } - - NetApiBufferFree(pInfo); - - return computers; - } - #endregion - - #region OLE32 Function/Interface Declarations - private const int MAX_MESSAGE_LENGTH = 1024; - - private const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; - private const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; - - [DllImport("Kernel32.dll")] - private static extern int FormatMessageW( - int dwFlags, - IntPtr lpSource, - int dwMessageId, - int dwLanguageId, - IntPtr lpBuffer, - int nSize, - IntPtr Arguments); - - [DllImport("Kernel32.dll")] - private static extern int GetSystemDefaultLangID(); - - [DllImport("Kernel32.dll")] - private static extern int GetUserDefaultLangID(); - - /// - /// The WIN32 system default locale. - /// - public const int LOCALE_SYSTEM_DEFAULT = 0x800; - - /// - /// The WIN32 user default locale. - /// - public const int LOCALE_USER_DEFAULT = 0x400; - - /// - /// The base for the WIN32 FILETIME structure. - /// - private static readonly DateTime FILETIME_BaseTime = new DateTime(1601, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - /// - /// WIN32 GUID struct declaration. - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - private struct GUID - { - public int Data1; - public short Data2; - public short Data3; - [MarshalAs(UnmanagedType.ByValArray, SizeConst=8)] - public byte[] Data4; - } - - /// - /// The size, in bytes, of a VARIANT structure. - /// - private static int VARIANT_SIZE { get { return (IntPtr.Size > 4) ? 0x18 : 0x10; } } - - [DllImport("OleAut32.dll")] - private static extern int VariantChangeTypeEx( - IntPtr pvargDest, - IntPtr pvarSrc, - int lcid, - ushort wFlags, - short vt); - - /// - /// Intializes a pointer to a VARIANT. - /// - [DllImport("oleaut32.dll")] - private static extern void VariantInit(IntPtr pVariant); - - /// - /// Frees all memory referenced by a VARIANT stored in unmanaged memory. - /// - [DllImport("oleaut32.dll")] - public static extern void VariantClear(IntPtr pVariant); - - private const int DISP_E_TYPEMISMATCH = -0x7FFDFFFB; // 0x80020005 - private const int DISP_E_OVERFLOW = -0x7FFDFFF6; // 0x8002000A - - private const int VARIANT_NOVALUEPROP = 0x01; - private const int VARIANT_ALPHABOOL = 0x02; // For VT_BOOL to VT_BSTR conversions convert to "True"/"False" instead of - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - private struct SOLE_AUTHENTICATION_SERVICE - { - public uint dwAuthnSvc; - public uint dwAuthzSvc; - [MarshalAs(UnmanagedType.LPWStr)] - public string pPrincipalName; - public int hr; - } - - private const uint RPC_C_AUTHN_NONE = 0; - private const uint RPC_C_AUTHN_DCE_PRIVATE = 1; - private const uint RPC_C_AUTHN_DCE_PUBLIC = 2; - private const uint RPC_C_AUTHN_DEC_PUBLIC = 4; - private const uint RPC_C_AUTHN_GSS_NEGOTIATE = 9; - private const uint RPC_C_AUTHN_WINNT = 10; - private const uint RPC_C_AUTHN_GSS_SCHANNEL = 14; - private const uint RPC_C_AUTHN_GSS_KERBEROS = 16; - private const uint RPC_C_AUTHN_DPA = 17; - private const uint RPC_C_AUTHN_MSN = 18; - private const uint RPC_C_AUTHN_DIGEST = 21; - private const uint RPC_C_AUTHN_MQ = 100; - private const uint RPC_C_AUTHN_DEFAULT = 0xFFFFFFFF; - - private const uint RPC_C_AUTHZ_NONE = 0; - private const uint RPC_C_AUTHZ_NAME = 1; - private const uint RPC_C_AUTHZ_DCE = 2; - private const uint RPC_C_AUTHZ_DEFAULT = 0xffffffff; - - private const uint RPC_C_AUTHN_LEVEL_DEFAULT = 0; - private const uint RPC_C_AUTHN_LEVEL_NONE = 1; - private const uint RPC_C_AUTHN_LEVEL_CONNECT = 2; - private const uint RPC_C_AUTHN_LEVEL_CALL = 3; - private const uint RPC_C_AUTHN_LEVEL_PKT = 4; - private const uint RPC_C_AUTHN_LEVEL_PKT_INTEGRITY = 5; - private const uint RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6; - - private const uint RPC_C_IMP_LEVEL_ANONYMOUS = 1; - private const uint RPC_C_IMP_LEVEL_IDENTIFY = 2; - private const uint RPC_C_IMP_LEVEL_IMPERSONATE = 3; - private const uint RPC_C_IMP_LEVEL_DELEGATE = 4; - - private const uint EOAC_NONE = 0x00; - private const uint EOAC_MUTUAL_AUTH = 0x01; - private const uint EOAC_CLOAKING = 0x10; - private const uint EOAC_STATIC_CLOAKING = 0x20; - private const uint EOAC_DYNAMIC_CLOAKING = 0x40; - private const uint EOAC_SECURE_REFS = 0x02; - private const uint EOAC_ACCESS_CONTROL = 0x04; - private const uint EOAC_APPID = 0x08; - - [DllImport("ole32.dll")] - private static extern int CoInitializeSecurity( - IntPtr pSecDesc, - int cAuthSvc, - SOLE_AUTHENTICATION_SERVICE[] asAuthSvc, - IntPtr pReserved1, - uint dwAuthnLevel, - uint dwImpLevel, - IntPtr pAuthList, - uint dwCapabilities, - IntPtr pReserved3); - - [DllImport("ole32.dll")] - private static extern int CoQueryProxyBlanket( - [MarshalAs(UnmanagedType.IUnknown)] - object pProxy, - ref uint pAuthnSvc, - ref uint pAuthzSvc, - [MarshalAs(UnmanagedType.LPWStr)] - ref string pServerPrincName, - ref uint pAuthnLevel, - ref uint pImpLevel, - ref IntPtr pAuthInfo, - ref uint pCapabilities); - - [DllImport("ole32.dll")] - private static extern int CoSetProxyBlanket( - [MarshalAs(UnmanagedType.IUnknown)] - object pProxy, - uint pAuthnSvc, - uint pAuthzSvc, - IntPtr pServerPrincName, - uint pAuthnLevel, - uint pImpLevel, - IntPtr pAuthInfo, - uint pCapabilities); - - private static readonly IntPtr COLE_DEFAULT_PRINCIPAL = new IntPtr(-1); - private static readonly IntPtr COLE_DEFAULT_AUTHINFO = new IntPtr(-1); - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - private struct COSERVERINFO - { - public uint dwReserved1; - [MarshalAs(UnmanagedType.LPWStr)] - public string pwszName; - public IntPtr pAuthInfo; - public uint dwReserved2; - }; - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - private struct COAUTHINFO - { - public uint dwAuthnSvc; - public uint dwAuthzSvc; - public IntPtr pwszServerPrincName; - public uint dwAuthnLevel; - public uint dwImpersonationLevel; - public IntPtr pAuthIdentityData; - public uint dwCapabilities; - } - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - private struct COAUTHIDENTITY - { - public IntPtr User; - public uint UserLength; - public IntPtr Domain; - public uint DomainLength; - public IntPtr Password; - public uint PasswordLength; - public uint Flags; - } - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - private struct MULTI_QI - { - public IntPtr iid; - [MarshalAs(UnmanagedType.IUnknown)] - public object pItf; - public uint hr; - } - - private const uint CLSCTX_INPROC_SERVER = 0x1; - private const uint CLSCTX_INPROC_HANDLER = 0x2; - private const uint CLSCTX_LOCAL_SERVER = 0x4; - private const uint CLSCTX_REMOTE_SERVER = 0x10; - private const uint CLSCTX_DISABLE_AAA = 0x8000; - - private static readonly Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046"); - - private const uint SEC_WINNT_AUTH_IDENTITY_ANSI = 0x1; - private const uint SEC_WINNT_AUTH_IDENTITY_UNICODE = 0x2; - - [DllImport("ole32.dll")] - private static extern void CoCreateInstanceEx( - ref Guid clsid, - [MarshalAs(UnmanagedType.IUnknown)] - object punkOuter, - uint dwClsCtx, - [In] - ref COSERVERINFO pServerInfo, - uint dwCount, - [In, Out] - MULTI_QI[] pResults); - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - private struct LICINFO - { - public int cbLicInfo; - [MarshalAs(UnmanagedType.Bool)] - public bool fRuntimeKeyAvail; - [MarshalAs(UnmanagedType.Bool)] - public bool fLicVerified; - } - - [ComImport] - [GuidAttribute("00000001-0000-0000-C000-000000000046")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - private interface IClassFactory - { - void CreateInstance( - [MarshalAs(UnmanagedType.IUnknown)] - object punkOuter, - [MarshalAs(UnmanagedType.LPStruct)] - Guid riid, - [MarshalAs(UnmanagedType.Interface)] - [Out] out object ppvObject); - - void LockServer( - [MarshalAs(UnmanagedType.Bool)] - bool fLock); - } - - [ComImport] - [GuidAttribute("B196B28F-BAB4-101A-B69C-00AA00341D07")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - private interface IClassFactory2 - { - void CreateInstance( - [MarshalAs(UnmanagedType.IUnknown)] - object punkOuter, - [MarshalAs(UnmanagedType.LPStruct)] - Guid riid, - [MarshalAs(UnmanagedType.Interface)] - [Out] out object ppvObject); - - void LockServer( - [MarshalAs(UnmanagedType.Bool)] - bool fLock); - - void GetLicInfo( - [In,Out] ref LICINFO pLicInfo); - - void RequestLicKey( - int dwReserved, - [MarshalAs(UnmanagedType.BStr)] - string pbstrKey); - - void CreateInstanceLic( - [MarshalAs(UnmanagedType.IUnknown)] - object punkOuter, - [MarshalAs(UnmanagedType.IUnknown)] - object punkReserved, - [MarshalAs(UnmanagedType.LPStruct)] - Guid riid, - [MarshalAs(UnmanagedType.BStr)] - string bstrKey, - [MarshalAs(UnmanagedType.IUnknown)] - [Out] out object ppvObject); - } - - [DllImport("ole32.dll")] - private static extern void CoGetClassObject( - [MarshalAs(UnmanagedType.LPStruct)] - Guid clsid, - uint dwClsContext, - [In] ref COSERVERINFO pServerInfo, - [MarshalAs(UnmanagedType.LPStruct)] - Guid riid, - [MarshalAs(UnmanagedType.IUnknown)] - [Out] out object ppv); - - private const int LOGON32_PROVIDER_DEFAULT = 0; - private const int LOGON32_LOGON_INTERACTIVE = 2; - private const int LOGON32_LOGON_NETWORK = 3; - - private const int SECURITY_ANONYMOUS = 0; - private const int SECURITY_IDENTIFICATION = 1; - private const int SECURITY_IMPERSONATION = 2; - private const int SECURITY_DELEGATION = 3; - - [DllImport("advapi32.dll", SetLastError=true)] - private static extern bool LogonUser( - string lpszUsername, - string lpszDomain, - string lpszPassword, - int dwLogonType, - int dwLogonProvider, - ref IntPtr phToken); - - [DllImport("kernel32.dll", CharSet=CharSet.Auto)] - private extern static bool CloseHandle(IntPtr handle); - - [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] - private extern static bool DuplicateToken( - IntPtr ExistingTokenHandle, - int SECURITY_IMPERSONATION_LEVEL, - ref IntPtr DuplicateTokenHandle); - #endregion - - #region ServerInfo Class - /// - /// A class used to allocate and deallocate the elements of a COSERVERINFO structure. - /// - class ServerInfo - { - #region Public Interface - /// - /// Allocates a COSERVERINFO structure. - /// - public COSERVERINFO Allocate(string hostName, UserIdentity identity) - { - // initialize server info structure. - COSERVERINFO serverInfo = new COSERVERINFO(); - - serverInfo.pwszName = hostName; - serverInfo.pAuthInfo = IntPtr.Zero; - serverInfo.dwReserved1 = 0; - serverInfo.dwReserved2 = 0; - - // no authentication for default identity - if (UserIdentity.IsDefault(identity)) - { - return serverInfo; - } - - m_hUserName = GCHandle.Alloc(identity.Username, GCHandleType.Pinned); - m_hPassword = GCHandle.Alloc(identity.Password, GCHandleType.Pinned); - m_hDomain = GCHandle.Alloc(identity.Domain, GCHandleType.Pinned); - - m_hIdentity = new GCHandle(); - - // create identity structure. - COAUTHIDENTITY authIdentity = new COAUTHIDENTITY(); - - authIdentity.User = m_hUserName.AddrOfPinnedObject(); - authIdentity.UserLength = (uint)((identity.Username != null)?identity.Username.Length:0); - authIdentity.Password = m_hPassword.AddrOfPinnedObject(); - authIdentity.PasswordLength = (uint)((identity.Password != null)?identity.Password.Length:0); - authIdentity.Domain = m_hDomain.AddrOfPinnedObject(); - authIdentity.DomainLength = (uint)((identity.Domain != null)?identity.Domain.Length:0); - authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - - m_hIdentity = GCHandle.Alloc(authIdentity, GCHandleType.Pinned); - - // create authorization info structure. - COAUTHINFO authInfo = new COAUTHINFO(); - - authInfo.dwAuthnSvc = RPC_C_AUTHN_WINNT; - authInfo.dwAuthzSvc = RPC_C_AUTHZ_NONE; - authInfo.pwszServerPrincName = IntPtr.Zero; - authInfo.dwAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT; - authInfo.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE; - authInfo.pAuthIdentityData = m_hIdentity.AddrOfPinnedObject(); - authInfo.dwCapabilities = EOAC_NONE; // EOAC_DYNAMIC_CLOAKING; - - m_hAuthInfo = GCHandle.Alloc(authInfo, GCHandleType.Pinned); - - // update server info structure. - serverInfo.pAuthInfo = m_hAuthInfo.AddrOfPinnedObject(); - - return serverInfo; - } - - /// - /// Deallocated memory allocated when the COSERVERINFO structure was created. - /// - public void Deallocate() - { - if (m_hUserName.IsAllocated) m_hUserName.Free(); - if (m_hPassword.IsAllocated) m_hPassword.Free(); - if (m_hDomain.IsAllocated) m_hDomain.Free(); - if (m_hIdentity.IsAllocated) m_hIdentity.Free(); - if (m_hAuthInfo.IsAllocated) m_hAuthInfo.Free(); - } - #endregion - - #region Private Members - private GCHandle m_hUserName; - private GCHandle m_hPassword; - private GCHandle m_hDomain; - private GCHandle m_hIdentity; - private GCHandle m_hAuthInfo; - #endregion - } - #endregion - - #region Initialization Functions - /// - /// Initializes COM security. - /// - public static void InitializeSecurity() - { - int error = CoInitializeSecurity( - IntPtr.Zero, - -1, - null, - IntPtr.Zero, - RPC_C_AUTHN_LEVEL_CONNECT, - RPC_C_IMP_LEVEL_IMPERSONATE, - IntPtr.Zero, - EOAC_DYNAMIC_CLOAKING, - IntPtr.Zero); - - // this call will fail in the debugger if the - // 'Debug | Enable Visual Studio Hosting Process' - // option is checked in the project properties. - if (error != 0) - { - // throw new ExternalException("CoInitializeSecurity: " + GetSystemMessage(error), error); - } - } - - /// - /// Determines if the host is the local host. - /// - private static bool IsLocalHost(string hostName) - { - // lookup requested host. - IPHostEntry requestedHost = Dns.GetHostEntry(hostName); - - if (requestedHost == null || requestedHost.AddressList == null) - { - return true; - } - - // check for loopback. - for (int ii = 0; ii < requestedHost.AddressList.Length; ii++) - { - IPAddress requestedIP = requestedHost.AddressList[ii]; - - if (requestedIP == null || requestedIP.Equals(IPAddress.Loopback)) - { - return true; - } - } - - // lookup local host. - IPHostEntry localHost = Dns.GetHostEntry(Dns.GetHostName()); - - if (localHost == null || localHost.AddressList == null) - { - return false; - } - - // check for localhost. - for (int ii = 0; ii < requestedHost.AddressList.Length; ii++) - { - IPAddress requestedIP = requestedHost.AddressList[ii]; - - for (int jj = 0; jj < localHost.AddressList.Length; jj++) - { - if (requestedIP.Equals(localHost.AddressList[jj])) - { - return true; - } - } - } - - // must be remote. - return false; - } - - /// - /// Creates an instance of a COM server using the specified license key. - /// - public static object CreateInstance(Guid clsid, string hostName, UserIdentity identity) - { - return CreateInstance1(clsid, hostName, identity); - } - - /// - /// Creates an instance of a COM server. - /// - public static object CreateInstance1(Guid clsid, string hostName, UserIdentity identity) - { - ServerInfo serverInfo = new ServerInfo(); - COSERVERINFO coserverInfo = serverInfo.Allocate(hostName, identity); - - GCHandle hIID = GCHandle.Alloc(IID_IUnknown, GCHandleType.Pinned); - - MULTI_QI[] results = new MULTI_QI[1]; - - results[0].iid = hIID.AddrOfPinnedObject(); - results[0].pItf = null; - results[0].hr = 0; - - try - { - // check whether connecting locally or remotely. - uint clsctx = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER; - - if (!String.IsNullOrEmpty(hostName) && hostName != "localhost") - { - clsctx = CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER; - } - - // create an instance. - CoCreateInstanceEx( - ref clsid, - null, - clsctx, - ref coserverInfo, - 1, - results); - } - finally - { - if (hIID.IsAllocated) hIID.Free(); - serverInfo.Deallocate(); - } - - if (results[0].hr != 0) - { - throw ServiceResultException.Create( - StatusCodes.BadCommunicationError, - "Could not create COM server '{0}' on host '{1}'. Reason: {2}.", clsid, hostName, - GetSystemMessage((int)results[0].hr, LOCALE_SYSTEM_DEFAULT)); - } - - return results[0].pItf; - } - - // COM impersonation is a nice feature but variations between behaviors on different - // windows platforms make it virtually impossible to support. This code is left here - // in case it becomes a critical requirement in the future. - #if COM_IMPERSONATION_SUPPORT - /// - /// Returns the WindowsIdentity associated with a UserIdentity. - /// - public static WindowsPrincipal GetPrincipalFromUserIdentity(UserIdentity user) - { - if (UserIdentity.IsDefault(user)) - { - return null; - } - - // validate the credentials. - IntPtr token = IntPtr.Zero; - - bool result = LogonUser( - user.Username, - user.Domain, - user.Password, - LOGON32_LOGON_NETWORK, - LOGON32_PROVIDER_DEFAULT, - ref token); - - if (!result) - { - throw ServiceResultException.Create( - StatusCodes.BadIdentityTokenRejected, - "Could not logon as user '{0}'. Reason: {1}.", - user.Username, - GetSystemMessage(Marshal.GetLastWin32Error(), LOCALE_SYSTEM_DEFAULT)); - } - - try - { - // create the windows identity. - WindowsIdentity identity = new WindowsIdentity(token); - - // validate the identity. - identity.Impersonate(); - - // return a principal. - return new WindowsPrincipal(identity); - } - finally - { - CloseHandle(token); - } - } - - /// - /// Sets the security settings for the proxy. - /// - public static void SetProxySecurity(object server, UserIdentity user) - { - // allocate the - GCHandle hUserName = GCHandle.Alloc(user.Username, GCHandleType.Pinned); - GCHandle hPassword = GCHandle.Alloc(user.Password, GCHandleType.Pinned); - GCHandle hDomain = GCHandle.Alloc(user.Domain, GCHandleType.Pinned); - - GCHandle hIdentity = new GCHandle(); - - // create identity structure. - COAUTHIDENTITY authIdentity = new COAUTHIDENTITY(); - - authIdentity.User = hUserName.AddrOfPinnedObject(); - authIdentity.UserLength = (uint)((user.Username != null) ? user.Username.Length : 0); - authIdentity.Password = hPassword.AddrOfPinnedObject(); - authIdentity.PasswordLength = (uint)((user.Password != null) ? user.Password.Length : 0); - authIdentity.Domain = hDomain.AddrOfPinnedObject(); - authIdentity.DomainLength = (uint)((user.Domain != null) ? user.Domain.Length : 0); - authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - - hIdentity = GCHandle.Alloc(authIdentity, GCHandleType.Pinned); - - try - { - SetProxySecurity(server, hIdentity.AddrOfPinnedObject()); - } - finally - { - hUserName.Free(); - hPassword.Free(); - hDomain.Free(); - hIdentity.Free(); - } - } - - /// - /// Sets the security settings for the proxy. - /// - public static void SetProxySecurity(object server, IntPtr pAuthInfo) - { - // get the existing proxy settings. - uint pAuthnSvc = 0; - uint pAuthzSvc = 0; - string pServerPrincName = ""; - uint pAuthnLevel = 0; - uint pImpLevel = 0; - IntPtr pAuthInfo2 = IntPtr.Zero; - uint pCapabilities = 0; - - CoQueryProxyBlanket( - server, - ref pAuthnSvc, - ref pAuthzSvc, - ref pServerPrincName, - ref pAuthnLevel, - ref pImpLevel, - ref pAuthInfo2, - ref pCapabilities); - - pAuthnSvc = RPC_C_AUTHN_WINNT; - pAuthzSvc = RPC_C_AUTHZ_NONE; - pAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT; - pImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE; - pCapabilities = EOAC_DYNAMIC_CLOAKING; - - // update proxy security settings. - CoSetProxyBlanket( - server, - pAuthnSvc, - pAuthzSvc, - COLE_DEFAULT_PRINCIPAL, - pAuthnLevel, - pImpLevel, - pAuthInfo, - pCapabilities); - } - - /// - /// Creates an instance of a COM server using the specified license key. - /// - public static object CreateInstance2(Guid clsid, string hostName, UserIdentity identity) - { - // validate the host name before proceeding (exception thrown if host is not valid). - bool isLocalHost = IsLocalHost(hostName); - - // allocate the connection info. - ServerInfo serverInfo = new ServerInfo(); - COSERVERINFO coserverInfo = serverInfo.Allocate(hostName, identity); - object instance = null; - IClassFactory factory = null; - - try - { - // create the factory. - object unknown = null; - - CoGetClassObject( - clsid, - (isLocalHost)?CLSCTX_LOCAL_SERVER:CLSCTX_REMOTE_SERVER, - ref coserverInfo, - IID_IUnknown, - out unknown); - - // SetProxySecurity(unknown, coserverInfo.pAuthInfo); - - factory = (IClassFactory)unknown; - - // check for valid factory. - if (factory == null) - { - throw ServiceResultException.Create(StatusCodes.BadCommunicationError, "Could not load IClassFactory for COM server '{0}' on host '{1}'.", clsid, hostName); - } - - // SetProxySecurity(factory, coserverInfo.pAuthInfo); - - factory.CreateInstance(null, IID_IUnknown, out instance); - - // SetProxySecurity(instance, coserverInfo.pAuthInfo); - } - finally - { - serverInfo.Deallocate(); - } - - return instance; - } - - /// - /// Creates an instance of a COM server using the specified license key. - /// - public static object CreateInstanceWithLicenseKey(Guid clsid, string hostName, UserIdentity identity, string licenseKey) - { - ServerInfo serverInfo = new ServerInfo(); - COSERVERINFO coserverInfo = serverInfo.Allocate(hostName, identity); - object instance = null; - IClassFactory2 factory = null; - - try - { - // check whether connecting locally or remotely. - uint clsctx = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER; - - if (hostName != null && hostName.Length > 0) - { - clsctx = CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER; - } - - // get the class factory. - object unknown = null; - - CoGetClassObject( - clsid, - clsctx, - ref coserverInfo, - typeof(IClassFactory2).GUID, - out unknown); - - // SetProxySecurity(unknown, coserverInfo.pAuthInfo); - - factory = (IClassFactory2)unknown; - - // check for valid factory. - if (factory == null) - { - throw ServiceResultException.Create(StatusCodes.BadCommunicationError, "Could not load IClassFactory2 for COM server '{0}' on host '{1}'.", clsid, hostName); - } - - // SetProxySecurity(factory, coserverInfo.pAuthInfo); - - // create instance. - factory.CreateInstanceLic( - null, - null, - IID_IUnknown, - licenseKey, - out instance); - - // SetProxySecurity(instance, coserverInfo.pAuthInfo); - } - finally - { - serverInfo.Deallocate(); - ComUtils.ReleaseServer(factory); - } - - return instance; - } - #endif - #endregion - - #region Conversion Functions - /// - /// Converts a HDA Aggregate ID to a UA aggregate ID - /// - /// The aggregate id. - /// - public static NodeId GetHdaAggregateId(uint aggregateId) - { - switch ((OPCHDA_AGGREGATE)aggregateId) - { - case OPCHDA_AGGREGATE.OPCHDA_INTERPOLATIVE: { return Opc.Ua.ObjectIds.AggregateFunction_Interpolative; } - case OPCHDA_AGGREGATE.OPCHDA_TOTAL: { return Opc.Ua.ObjectIds.AggregateFunction_Total; } - case OPCHDA_AGGREGATE.OPCHDA_AVERAGE: { return Opc.Ua.ObjectIds.AggregateFunction_Average; } - case OPCHDA_AGGREGATE.OPCHDA_TIMEAVERAGE: { return Opc.Ua.ObjectIds.AggregateFunction_TimeAverage; } - case OPCHDA_AGGREGATE.OPCHDA_COUNT: { return Opc.Ua.ObjectIds.AggregateFunction_Count; } - case OPCHDA_AGGREGATE.OPCHDA_MINIMUMACTUALTIME: { return Opc.Ua.ObjectIds.AggregateFunction_MinimumActualTime; } - case OPCHDA_AGGREGATE.OPCHDA_MINIMUM: { return Opc.Ua.ObjectIds.AggregateFunction_Minimum; } - case OPCHDA_AGGREGATE.OPCHDA_MAXIMUMACTUALTIME: { return Opc.Ua.ObjectIds.AggregateFunction_MaximumActualTime; } - case OPCHDA_AGGREGATE.OPCHDA_MAXIMUM: { return Opc.Ua.ObjectIds.AggregateFunction_Maximum; } - case OPCHDA_AGGREGATE.OPCHDA_START: { return Opc.Ua.ObjectIds.AggregateFunction_Start; } - case OPCHDA_AGGREGATE.OPCHDA_END: { return Opc.Ua.ObjectIds.AggregateFunction_End; } - case OPCHDA_AGGREGATE.OPCHDA_DELTA: { return Opc.Ua.ObjectIds.AggregateFunction_Delta; } - case OPCHDA_AGGREGATE.OPCHDA_RANGE: { return Opc.Ua.ObjectIds.AggregateFunction_Range; } - case OPCHDA_AGGREGATE.OPCHDA_DURATIONGOOD: { return Opc.Ua.ObjectIds.AggregateFunction_DurationGood; } - case OPCHDA_AGGREGATE.OPCHDA_DURATIONBAD: { return Opc.Ua.ObjectIds.AggregateFunction_DurationBad; } - case OPCHDA_AGGREGATE.OPCHDA_PERCENTGOOD: { return Opc.Ua.ObjectIds.AggregateFunction_PercentGood; } - case OPCHDA_AGGREGATE.OPCHDA_PERCENTBAD: { return Opc.Ua.ObjectIds.AggregateFunction_PercentBad; } - case OPCHDA_AGGREGATE.OPCHDA_WORSTQUALITY: { return Opc.Ua.ObjectIds.AggregateFunction_WorstQuality; } - case OPCHDA_AGGREGATE.OPCHDA_ANNOTATIONS: { return Opc.Ua.ObjectIds.AggregateFunction_AnnotationCount; } - } - - return null; - } - - /// - /// Converts a UA Aggregate ID to a HDA aggregate ID - /// - /// The node id. - /// - public static uint GetHdaAggregateId(NodeId nodeId) - { - // check for valid node. - if (nodeId == null) - { - return 0; - } - - // check for UA defined aggregate. - if (nodeId.NamespaceIndex == 0) - { - if (nodeId.IdType != IdType.Numeric) - { - return 0; - } - - switch ((uint)nodeId.Identifier) - { - case Opc.Ua.Objects.AggregateFunction_Interpolative: { return (uint)OPCHDA_AGGREGATE.OPCHDA_INTERPOLATIVE; } - case Opc.Ua.Objects.AggregateFunction_Total: { return (uint)OPCHDA_AGGREGATE.OPCHDA_TOTAL; } - case Opc.Ua.Objects.AggregateFunction_Average: { return (uint)OPCHDA_AGGREGATE.OPCHDA_AVERAGE; } - case Opc.Ua.Objects.AggregateFunction_TimeAverage: { return (uint)OPCHDA_AGGREGATE.OPCHDA_TIMEAVERAGE; } - case Opc.Ua.Objects.AggregateFunction_Count: { return (uint)OPCHDA_AGGREGATE.OPCHDA_COUNT; } - case Opc.Ua.Objects.AggregateFunction_MinimumActualTime: { return (uint)OPCHDA_AGGREGATE.OPCHDA_MINIMUMACTUALTIME; } - case Opc.Ua.Objects.AggregateFunction_Minimum: { return (uint)OPCHDA_AGGREGATE.OPCHDA_MINIMUMACTUALTIME; } - case Opc.Ua.Objects.AggregateFunction_MaximumActualTime: { return (uint)OPCHDA_AGGREGATE.OPCHDA_MAXIMUMACTUALTIME; } - case Opc.Ua.Objects.AggregateFunction_Maximum: { return (uint)OPCHDA_AGGREGATE.OPCHDA_MAXIMUM; } - case Opc.Ua.Objects.AggregateFunction_Start: { return (uint)OPCHDA_AGGREGATE.OPCHDA_START; } - case Opc.Ua.Objects.AggregateFunction_End: { return (uint)OPCHDA_AGGREGATE.OPCHDA_END; } - case Opc.Ua.Objects.AggregateFunction_Delta: { return (uint)OPCHDA_AGGREGATE.OPCHDA_DELTA; } - case Opc.Ua.Objects.AggregateFunction_Range: { return (uint)OPCHDA_AGGREGATE.OPCHDA_RANGE; } - case Opc.Ua.Objects.AggregateFunction_DurationGood: { return (uint)OPCHDA_AGGREGATE.OPCHDA_DURATIONGOOD; } - case Opc.Ua.Objects.AggregateFunction_DurationBad: { return (uint)OPCHDA_AGGREGATE.OPCHDA_DURATIONBAD; } - case Opc.Ua.Objects.AggregateFunction_PercentGood: { return (uint)OPCHDA_AGGREGATE.OPCHDA_PERCENTGOOD; } - case Opc.Ua.Objects.AggregateFunction_PercentBad: { return (uint)OPCHDA_AGGREGATE.OPCHDA_PERCENTBAD; } - case Opc.Ua.Objects.AggregateFunction_WorstQuality: { return (uint)OPCHDA_AGGREGATE.OPCHDA_WORSTQUALITY; } - case Opc.Ua.Objects.AggregateFunction_AnnotationCount: { return (uint)OPCHDA_AGGREGATE.OPCHDA_ANNOTATIONS; } - } - } - - return 0; - } - - /// - /// Converts the UA access level to DA access rights. - /// - public static int GetAccessRights(byte accessLevel) - { - int accessRights = 0; - - if ((accessLevel & AccessLevels.CurrentRead) != 0) - { - accessRights |= OpcRcw.Da.Constants.OPC_READABLE; - } - - if ((accessLevel & AccessLevels.CurrentWrite) != 0) - { - accessRights |= OpcRcw.Da.Constants.OPC_WRITEABLE; - } - - return accessRights; - } - - /// - /// Tests if the specified string matches the specified pattern. - /// - public static bool Match(string target, string pattern, bool caseSensitive) - { - // an empty pattern always matches. - if (pattern == null || pattern.Length == 0) - { - return true; - } - - // an empty string never matches. - if (target == null || target.Length == 0) - { - return false; - } - - // check for exact match - if (caseSensitive) - { - if (target == pattern) - { - return true; - } - } - else - { - if (String.Equals(target, pattern, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - - char c; - char p; - char l; - - int pIndex = 0; - int tIndex = 0; - - while (tIndex < target.Length && pIndex < pattern.Length) - { - p = ConvertCase(pattern[pIndex++], caseSensitive); - - if (pIndex > pattern.Length) - { - return (tIndex >= target.Length); // if end of string true - } - - switch (p) - { - // match zero or more char. - case '*': - { - while (pIndex < pattern.Length && pattern[pIndex] == '*') - { - pIndex++; - } - - while (tIndex < target.Length) - { - if (Match(target.Substring(tIndex++), pattern.Substring(pIndex), caseSensitive)) - { - return true; - } - } - - return Match(target, pattern.Substring(pIndex), caseSensitive); - } - - // match any one char. - case '?': - { - // check if end of string when looking for a single character. - if (tIndex >= target.Length) - { - return false; - } - - // check if end of pattern and still string data left. - if (pIndex >= pattern.Length && tIndex < target.Length-1) - { - return false; - } - - tIndex++; - break; - } - - // match char set - case '[': - { - c = ConvertCase(target[tIndex++], caseSensitive); - - if (tIndex > target.Length) - { - return false; // syntax - } - - l = '\0'; - - // match a char if NOT in set [] - if (pattern[pIndex] == '!') - { - ++pIndex; - - p = ConvertCase(pattern[pIndex++], caseSensitive); - - while (pIndex < pattern.Length) - { - if (p == ']') // if end of char set, then - { - break; // no match found - } - - if (p == '-') - { - // check a range of chars? - p = ConvertCase(pattern[pIndex], caseSensitive); - - // get high limit of range - if (pIndex > pattern.Length || p == ']') - { - return false; // syntax - } - - if (c >= l && c <= p) - { - return false; // if in range, return false - } - } - - l = p; - - if (c == p) // if char matches this element - { - return false; // return false - } - - p = ConvertCase(pattern[pIndex++], caseSensitive); - } - } - - // match if char is in set [] - else - { - p = ConvertCase(pattern[pIndex++], caseSensitive); - - while (pIndex < pattern.Length) - { - if (p == ']') // if end of char set, then no match found - { - return false; - } - - if (p == '-') - { - // check a range of chars? - p = ConvertCase(pattern[pIndex], caseSensitive); - - // get high limit of range - if (pIndex > pattern.Length || p == ']') - { - return false; // syntax - } - - if (c >= l && c <= p) - { - break; // if in range, move on - } - } - - l = p; - - if (c == p) // if char matches this element move on - { - break; - } - - p = ConvertCase(pattern[pIndex++], caseSensitive); - } - - while (pIndex < pattern.Length && p != ']') // got a match in char set skip to end of set - { - p = pattern[pIndex++]; - } - } - - break; - } - - // match digit. - case '#': - { - c = target[tIndex++]; - - if (!Char.IsDigit(c)) - { - return false; // not a digit - } - - break; - } - - // match exact char. - default: - { - c = ConvertCase(target[tIndex++], caseSensitive); - - if (c != p) // check for exact char - { - return false; // not a match - } - - // check if end of pattern and still string data left. - if (pIndex >= pattern.Length && tIndex < target.Length-1) - { - return false; - } - - break; - } - } - } - - return true; - } - - // ConvertCase - private static char ConvertCase(char c, bool caseSensitive) - { - return (caseSensitive)?c:Char.ToUpper(c); - } - - /// - /// Unmarshals and frees an array of HRESULTs. - /// - public static int[] GetStatusCodes(ref IntPtr pArray, int size, bool deallocate) - { - if (pArray == IntPtr.Zero || size <= 0) - { - return null; - } - - // unmarshal HRESULT array. - int[] output = new int[size]; - Marshal.Copy(pArray, output, 0, size); - - if (deallocate) - { - Marshal.FreeCoTaskMem(pArray); - pArray = IntPtr.Zero; - } - - return output; - } - - /// - /// Unmarshals and frees an array of 32 bit integers. - /// - public static int[] GetInt32s(ref IntPtr pArray, int size, bool deallocate) - { - if (pArray == IntPtr.Zero || size <= 0) - { - return null; - } - - int[] array = new int[size]; - Marshal.Copy(pArray, array, 0, size); - - if (deallocate) - { - Marshal.FreeCoTaskMem(pArray); - pArray = IntPtr.Zero; - } - - return array; - } - - /// - /// Unmarshals and frees an array of 32 bit integers. - /// - public static int[] GetUInt32s(ref IntPtr pArray, int size, bool deallocate) - { - if (pArray == IntPtr.Zero || size <= 0) - { - return null; - } - - int[] array = new int[size]; - Marshal.Copy(pArray, array, 0, size); - - if (deallocate) - { - Marshal.FreeCoTaskMem(pArray); - pArray = IntPtr.Zero; - } - - return array; - } - - - /// - /// Allocates and marshals an array of 32 bit integers. - /// - public static IntPtr GetInt32s(int[] input) - { - IntPtr output = IntPtr.Zero; - - if (input != null) - { - output = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Int32))*input.Length); - Marshal.Copy(input, 0, output, input.Length); - } - - return output; - } - - /// - /// Unmarshals and frees a array of 16 bit integers. - /// - public static short[] GetInt16s(ref IntPtr pArray, int size, bool deallocate) - { - if (pArray == IntPtr.Zero || size <= 0) - { - return null; - } - - short[] array = new short[size]; - Marshal.Copy(pArray, array, 0, size); - - if (deallocate) - { - Marshal.FreeCoTaskMem(pArray); - pArray = IntPtr.Zero; - } - - return array; - } - - /// - /// Allocates and marshals an array of 16 bit integers. - /// - public static IntPtr GetInt16s(short[] input) - { - IntPtr output = IntPtr.Zero; - - if (input != null) - { - output = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Int16))*input.Length); - Marshal.Copy(input, 0, output, input.Length); - } - - return output; - } - - /// - /// Marshals an array of strings into a unmanaged memory buffer - /// - /// The array of strings to marshal - /// The pointer to the unmanaged memory buffer - public static IntPtr GetUnicodeStrings(string[] values) - { - int size = (values != null)?values.Length:0; - - if (size <= 0) - { - return IntPtr.Zero; - } - - IntPtr pValues = IntPtr.Zero; - - int[] pointers = new int[size]; - - for (int ii = 0; ii < size; ii++) - { - pointers[ii] = (int)Marshal.StringToCoTaskMemUni(values[ii]); - } - - pValues = Marshal.AllocCoTaskMem(values.Length*Marshal.SizeOf(typeof(IntPtr))); - Marshal.Copy(pointers, 0, pValues, size); - - return pValues; - } - - /// - /// Unmarshals and frees a array of unicode strings. - /// - public static string[] GetUnicodeStrings(ref IntPtr pArray, int size, bool deallocate) - { - if (pArray == IntPtr.Zero || size <= 0) - { - return null; - } - - IntPtr[] pointers = new IntPtr[size]; - Marshal.Copy(pArray, pointers, 0, size); - - string[] strings = new string[size]; - - for (int ii = 0; ii < size; ii++) - { - IntPtr pString = pointers[ii]; - strings[ii] = Marshal.PtrToStringUni(pString); - if (deallocate) Marshal.FreeCoTaskMem(pString); - } - - if (deallocate) - { - Marshal.FreeCoTaskMem(pArray); - pArray = IntPtr.Zero; - } - - return strings; - } - - /// - /// Marshals a DateTime as a WIN32 FILETIME. - /// - /// The DateTime object to marshal - /// The WIN32 FILETIME - public static System.Runtime.InteropServices.ComTypes.FILETIME GetFILETIME(DateTime datetime) - { - System.Runtime.InteropServices.ComTypes.FILETIME filetime; - - if (datetime <= FILETIME_BaseTime) - { - filetime.dwHighDateTime = 0; - filetime.dwLowDateTime = 0; - return filetime; - } - - // adjust for WIN32 FILETIME base. - long ticks = 0; - ticks = datetime.Subtract(new TimeSpan(FILETIME_BaseTime.Ticks)).Ticks; - - filetime.dwHighDateTime = (int)((ticks>>32) & 0xFFFFFFFF); - filetime.dwLowDateTime = (int)(ticks & 0xFFFFFFFF); - - return filetime; - } - - /// - /// Unmarshals an array of FILETIMEs - /// - public static System.Runtime.InteropServices.ComTypes.FILETIME[] GetFILETIMEs(ref IntPtr pArray, int size) - { - if (pArray == IntPtr.Zero || size <= 0) - { - return null; - } - - System.Runtime.InteropServices.ComTypes.FILETIME[] values = new System.Runtime.InteropServices.ComTypes.FILETIME[size]; - - IntPtr pos = pArray; - - for (int ii = 0; ii < size; ii++) - { - try - { - values[ii] = (System.Runtime.InteropServices.ComTypes.FILETIME)Marshal.PtrToStructure(pos, typeof(System.Runtime.InteropServices.ComTypes.FILETIME)); - } - catch (Exception) - { - } - - pos = (IntPtr)(pos.ToInt64() + 8); - } - - - Marshal.FreeCoTaskMem(pArray); - pArray = IntPtr.Zero; - - return values; - } - - /// - /// Unmarshals a WIN32 FILETIME from a pointer. - /// - /// A pointer to a FILETIME structure. - /// A DateTime object. - public static DateTime GetDateTime(IntPtr pFiletime) - { - if (pFiletime == IntPtr.Zero) - { - return DateTime.MinValue; - } - - return GetDateTime((System.Runtime.InteropServices.ComTypes.FILETIME)Marshal.PtrToStructure(pFiletime, typeof(System.Runtime.InteropServices.ComTypes.FILETIME))); - } - - /// - /// Unmarshals a WIN32 FILETIME. - /// - public static DateTime GetDateTime(System.Runtime.InteropServices.ComTypes.FILETIME filetime) - { - // check for invalid value. - if (filetime.dwHighDateTime < 0) - { - return DateTime.MinValue; - } - - // convert FILETIME structure to a 64 bit integer. - long buffer = (long)filetime.dwHighDateTime; - - if (buffer < 0) - { - buffer += ((long)UInt32.MaxValue+1); - } - - long ticks = (buffer<<32); - - buffer = (long)filetime.dwLowDateTime; - - if (buffer < 0) - { - buffer += ((long)UInt32.MaxValue+1); - } - - ticks += buffer; - - // check for invalid value. - if (ticks == 0) - { - return DateTime.MinValue; - } - - // adjust for WIN32 FILETIME base. - return FILETIME_BaseTime.Add(new TimeSpan(ticks)); - } - - /// - /// Marshals an array of DateTimes into an unmanaged array of FILETIMEs - /// - /// The array of DateTimes to marshal - /// The IntPtr array of FILETIMEs - public static IntPtr GetFILETIMEs(DateTime[] datetimes) - { - int count = (datetimes != null)?datetimes.Length:0; - - if (count <= 0) - { - return IntPtr.Zero; - } - - IntPtr pFiletimes = Marshal.AllocCoTaskMem(count*Marshal.SizeOf(typeof(System.Runtime.InteropServices.ComTypes.FILETIME))); - - IntPtr pos = pFiletimes; - - for (int ii = 0; ii < count; ii++) - { - Marshal.StructureToPtr(GetFILETIME(datetimes[ii]), pos, false); - pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(System.Runtime.InteropServices.ComTypes.FILETIME))); - } - - return pFiletimes; - } - - /// - /// Unmarshals an array of WIN32 FILETIMEs as DateTimes. - /// - public static DateTime[] GetDateTimes(ref IntPtr pArray, int size, bool deallocate) - { - if (pArray == IntPtr.Zero || size <= 0) - { - return null; - } - - DateTime[] datetimes = new DateTime[size]; - - IntPtr pos = pArray; - - for (int ii = 0; ii < size; ii++) - { - datetimes[ii] = GetDateTime(pos); - pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(System.Runtime.InteropServices.ComTypes.FILETIME))); - } - - if (deallocate) - { - Marshal.FreeCoTaskMem(pArray); - pArray = IntPtr.Zero; - } - - return datetimes; - } - - /// - /// Unmarshals an array of WIN32 GUIDs as Guid. - /// - public static Guid[] GetGUIDs(ref IntPtr pInput, int size, bool deallocate) - { - if (pInput == IntPtr.Zero || size <= 0) - { - return null; - } - - Guid[] guids = new Guid[size]; - - IntPtr pos = pInput; - - for (int ii = 0; ii < size; ii++) - { - GUID input = (GUID)Marshal.PtrToStructure(pInput, typeof(GUID)); - - guids[ii] = new Guid(input.Data1, input.Data2, input.Data3, input.Data4); - - pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(GUID))); - } - - if (deallocate) - { - Marshal.FreeCoTaskMem(pInput); - pInput = IntPtr.Zero; - } - - return guids; - } - - /// - /// Converts an object into a value that can be marshalled to a VARIANT. - /// - /// The object to convert. - /// The converted object. - public static object GetVARIANT(object source) - { - // check for invalid args. - if (source == null) - { - return null; - } - - return GetVARIANT(source, TypeInfo.Construct(source)); - } - - /// - /// Converts an object into a value that can be marshalled to a VARIANT. - /// - /// The object to convert. - /// The converted object. - public static object GetVARIANT(Variant source) - { - return GetVARIANT(source.Value, source.TypeInfo); - } - - /// - /// Converts an object into a value that can be marshalled to a VARIANT. - /// - /// The object to convert. - /// The type info. - /// The converted object. - public static object GetVARIANT(object source, TypeInfo typeInfo) - { - // check for invalid args. - if (source == null) - { - return null; - } - - try - { - switch (typeInfo.BuiltInType) - { - case BuiltInType.Boolean: - case BuiltInType.Byte: - case BuiltInType.Int16: - case BuiltInType.UInt16: - case BuiltInType.Int32: - case BuiltInType.UInt32: - case BuiltInType.Int64: - case BuiltInType.UInt64: - case BuiltInType.Float: - case BuiltInType.Double: - case BuiltInType.String: - case BuiltInType.DateTime: - { - return source; - } - - case BuiltInType.ByteString: - { - if (typeInfo.ValueRank < 0) - { - return source; - } - - return VariantToObjectArray((Array)source); - } - - case BuiltInType.Guid: - case BuiltInType.LocalizedText: - case BuiltInType.QualifiedName: - case BuiltInType.NodeId: - case BuiltInType.ExpandedNodeId: - case BuiltInType.XmlElement: - { - return TypeInfo.Cast(source, typeInfo, BuiltInType.String); - } - - case BuiltInType.StatusCode: - { - return TypeInfo.Cast(source, typeInfo, BuiltInType.UInt32); - } - - case BuiltInType.Variant: - { - if (typeInfo.ValueRank < 0) - { - return GetVARIANT(((Variant)source).Value); - } - - return VariantToObjectArray((Array)source); - } - - case BuiltInType.ExtensionObject: - { - if (typeInfo.ValueRank < 0) - { - byte[] body = null; - - ExtensionObject extension = (ExtensionObject)source; - - switch (extension.Encoding) - { - case ExtensionObjectEncoding.Binary: - { - body = (byte[])extension.Body; - break; - } - - case ExtensionObjectEncoding.Xml: - { - body = new UTF8Encoding().GetBytes(((XmlElement)extension.Body).OuterXml); - break; - } - - case ExtensionObjectEncoding.EncodeableObject: - { - BinaryEncoder encoder = new BinaryEncoder(ServiceMessageContext.GlobalContext); - encoder.WriteEncodeable(null, (IEncodeable)extension.Body, null); - body = encoder.CloseAndReturnBuffer(); - break; - } - } - - return body; - } - - return VariantToObjectArray((Array)source); - } - - case BuiltInType.DataValue: - case BuiltInType.DiagnosticInfo: - { - return "(unsupported)"; - } - } - } - catch (Exception e) - { - return e.Message; - } - - // no conversion required. - return source; - } - - /// - /// Converts a Variant array to an Object array. - /// - private static Array VariantToObjectArray(Array input) - { - int[] dimensions = new int[input.Rank]; - - for (int ii = 0; ii < dimensions.Length; ii++) - { - dimensions[ii] = input.GetLength(ii); - } - - Array output = Array.CreateInstance(typeof(object), dimensions); - - int length = output.Length; - int[] indexes = new int[dimensions.Length]; - - for (int ii = 0; ii < length; ii++) - { - int divisor = output.Length; - - for (int jj = 0; jj < indexes.Length; jj++) - { - divisor /= dimensions[jj]; - indexes[jj] = (ii/divisor)%dimensions[jj]; - } - - object value = input.GetValue(indexes); - output.SetValue(GetVARIANT(value), indexes); - } - - return output; - } - - /// - /// Marshals an array objects into an unmanaged array of VARIANTs. - /// - /// An array of the objects to be marshalled - /// Whether the objects should have troublesome types removed before marhalling. - /// An pointer to the array in unmanaged memory - public static IntPtr GetVARIANTs(object[] values, bool preprocess) - { - int count = (values != null)?values.Length:0; - - if (count <= 0) - { - return IntPtr.Zero; - } - - IntPtr pValues = Marshal.AllocCoTaskMem(count*VARIANT_SIZE); - - IntPtr pos = pValues; - - for (int ii = 0; ii < count; ii++) - { - if (preprocess) - { - Marshal.GetNativeVariantForObject(GetVARIANT(values[ii]), pos); - } - else - { - Marshal.GetNativeVariantForObject(values[ii], pos); - } - - pos = (IntPtr)(pos.ToInt64() + VARIANT_SIZE); - } - - return pValues; - } - - /// - /// Unmarshals an array of VARIANTs as objects. - /// - public static object[] GetVARIANTs(ref IntPtr pArray, int size, bool deallocate) - { - // this method unmarshals VARIANTs one at a time because a single bad value throws - // an exception with GetObjectsForNativeVariants(). This approach simply sets the - // offending value to null. - - if (pArray == IntPtr.Zero || size <= 0) - { - return null; - } - - object[] values = new object[size]; - - IntPtr pos = pArray; - - for (int ii = 0; ii < size; ii++) - { - try - { - values[ii] = Marshal.GetObjectForNativeVariant(pos); - values[ii] = ProcessComValue(values[ii]); - if (deallocate) VariantClear(pos); - } - catch (Exception) - { - values[ii] = null; - } - - pos = (IntPtr)(pos.ToInt64() + VARIANT_SIZE); - } - - if (deallocate) - { - Marshal.FreeCoTaskMem(pArray); - pArray = IntPtr.Zero; - } - - return values; - } - - /// - /// Converts a LCID to a Locale string. - /// - public static string GetLocale(int input) - { - try - { - if (input == LOCALE_SYSTEM_DEFAULT || input == LOCALE_USER_DEFAULT || input == 0) - { - return CultureInfo.InvariantCulture.Name; - } - - return new CultureInfo(input).Name; - } - catch (Exception e) - { - throw new ServiceResultException(StatusCodes.Bad, "Unrecognized locale provided.", e); - } - } - - /// - /// Converts a Locale string to a LCID. - /// - public static int GetLocale(string input) - { - // check for the default culture. - if (input == null || input == "") - { - return 0; - } - - CultureInfo locale = null; - - try { locale = new CultureInfo(input); } - catch { locale = CultureInfo.CurrentCulture; } - - return locale.LCID; - } - - /// - /// Converts the VARTYPE to a UA Data Type ID. - /// - public static NodeId GetDataTypeId(short input) - { - switch ((VarEnum)Enum.ToObject(typeof(VarEnum), (input & ~(short)VarEnum.VT_ARRAY))) - { - case VarEnum.VT_I1: return DataTypes.SByte; - case VarEnum.VT_UI1: return DataTypes.Byte; - case VarEnum.VT_I2: return DataTypes.Int16; - case VarEnum.VT_UI2: return DataTypes.UInt16; - case VarEnum.VT_I4: return DataTypes.Int32; - case VarEnum.VT_UI4: return DataTypes.UInt32; - case VarEnum.VT_I8: return DataTypes.Int64; - case VarEnum.VT_UI8: return DataTypes.UInt64; - case VarEnum.VT_R4: return DataTypes.Float; - case VarEnum.VT_R8: return DataTypes.Double; - case VarEnum.VT_BOOL: return DataTypes.Boolean; - case VarEnum.VT_DATE: return DataTypes.DateTime; - case VarEnum.VT_BSTR: return DataTypes.String; - case VarEnum.VT_CY: return DataTypes.String; - case VarEnum.VT_EMPTY: return DataTypes.BaseDataType; - - case VarEnum.VT_VARIANT: - { - return DataTypes.BaseDataType; - } - } - - return NodeId.Null; - } - - /// - /// Converts the VARTYPE to a UA ValueRank. - /// - public static int GetValueRank(short input) - { - if ((((short)VarEnum.VT_ARRAY & input) != 0)) - { - return ValueRanks.OneDimension; - } - - return ValueRanks.Scalar; - } - - /// - /// Converts the VARTYPE to a UA Data Type ID. - /// - public static NodeId GetDataTypeId(short input, out bool isArray) - { - isArray = (((short)VarEnum.VT_ARRAY & input) != 0); - return GetDataTypeId(input); - } - - /// - /// Converts the VARTYPE to a SystemType - /// - public static Type GetSystemType(short input) - { - bool isArray = (((short)VarEnum.VT_ARRAY & input) != 0); - VarEnum varType = (VarEnum)Enum.ToObject(typeof(VarEnum), (input & ~(short)VarEnum.VT_ARRAY)); - - if (!isArray) - { - switch (varType) - { - case VarEnum.VT_I1: return typeof(sbyte); - case VarEnum.VT_UI1: return typeof(byte); - case VarEnum.VT_I2: return typeof(short); - case VarEnum.VT_UI2: return typeof(ushort); - case VarEnum.VT_I4: return typeof(int); - case VarEnum.VT_UI4: return typeof(uint); - case VarEnum.VT_I8: return typeof(long); - case VarEnum.VT_UI8: return typeof(ulong); - case VarEnum.VT_R4: return typeof(float); - case VarEnum.VT_R8: return typeof(double); - case VarEnum.VT_BOOL: return typeof(bool); - case VarEnum.VT_DATE: return typeof(DateTime); - case VarEnum.VT_BSTR: return typeof(string); - case VarEnum.VT_CY: return typeof(decimal); - case VarEnum.VT_EMPTY: return typeof(object); - case VarEnum.VT_VARIANT: return typeof(object); - } - } - else - { - switch (varType) - { - case VarEnum.VT_I1: return typeof(sbyte[]); - case VarEnum.VT_UI1: return typeof(byte[]); - case VarEnum.VT_I2: return typeof(short[]); - case VarEnum.VT_UI2: return typeof(ushort[]); - case VarEnum.VT_I4: return typeof(int[]); - case VarEnum.VT_UI4: return typeof(uint[]); - case VarEnum.VT_I8: return typeof(long[]); - case VarEnum.VT_UI8: return typeof(ulong[]); - case VarEnum.VT_R4: return typeof(float[]); - case VarEnum.VT_R8: return typeof(double[]); - case VarEnum.VT_BOOL: return typeof(bool[]); - case VarEnum.VT_DATE: return typeof(DateTime[]); - case VarEnum.VT_BSTR: return typeof(string[]); - case VarEnum.VT_CY: return typeof(decimal[]); - case VarEnum.VT_EMPTY: return typeof(object[]); - case VarEnum.VT_VARIANT: return typeof(object[]); - } - } - - return null; - } - - /// - /// Returns the VARTYPE for the value. - /// - public static VarEnum GetVarType(object input) - { - if (input == null) - { - return VarEnum.VT_EMPTY; - } - - return GetVarType(input.GetType()); - } - - /// - /// Converts the system type to a VARTYPE. - /// - public static VarEnum GetVarType(System.Type type) - { - if (type == null) - { - return VarEnum.VT_EMPTY; - } - - if (type == null) return VarEnum.VT_EMPTY; - if (type == typeof(sbyte)) return VarEnum.VT_I1; - if (type == typeof(byte)) return VarEnum.VT_UI1; - if (type == typeof(short)) return VarEnum.VT_I2; - if (type == typeof(ushort)) return VarEnum.VT_UI2; - if (type == typeof(int)) return VarEnum.VT_I4; - if (type == typeof(uint)) return VarEnum.VT_UI4; - if (type == typeof(long)) return VarEnum.VT_I8; - if (type == typeof(ulong)) return VarEnum.VT_UI8; - if (type == typeof(float)) return VarEnum.VT_R4; - if (type == typeof(double)) return VarEnum.VT_R8; - if (type == typeof(decimal)) return VarEnum.VT_CY; - if (type == typeof(bool)) return VarEnum.VT_BOOL; - if (type == typeof(DateTime)) return VarEnum.VT_DATE; - if (type == typeof(string)) return VarEnum.VT_BSTR; - if (type == typeof(sbyte[])) return VarEnum.VT_ARRAY | VarEnum.VT_I1; - if (type == typeof(byte[])) return VarEnum.VT_ARRAY | VarEnum.VT_UI1; - if (type == typeof(short[])) return VarEnum.VT_ARRAY | VarEnum.VT_I2; - if (type == typeof(ushort[])) return VarEnum.VT_ARRAY | VarEnum.VT_UI2; - if (type == typeof(int[])) return VarEnum.VT_ARRAY | VarEnum.VT_I4; - if (type == typeof(uint[])) return VarEnum.VT_ARRAY | VarEnum.VT_UI4; - if (type == typeof(long[])) return VarEnum.VT_ARRAY | VarEnum.VT_I8; - if (type == typeof(ulong[])) return VarEnum.VT_ARRAY | VarEnum.VT_UI8; - if (type == typeof(float[])) return VarEnum.VT_ARRAY | VarEnum.VT_R4; - if (type == typeof(double[])) return VarEnum.VT_ARRAY | VarEnum.VT_R8; - if (type == typeof(decimal[])) return VarEnum.VT_ARRAY | VarEnum.VT_CY; - if (type == typeof(bool[])) return VarEnum.VT_ARRAY | VarEnum.VT_BOOL; - if (type == typeof(DateTime[])) return VarEnum.VT_ARRAY | VarEnum.VT_DATE; - if (type == typeof(string[])) return VarEnum.VT_ARRAY | VarEnum.VT_BSTR; - if (type == typeof(object[])) return VarEnum.VT_ARRAY | VarEnum.VT_VARIANT; - - return VarEnum.VT_EMPTY; - } - - /// - /// Converts the TypeInfo to a VARTYPE. - /// - public static VarEnum GetVarType(TypeInfo typeInfo) - { - if (typeInfo == null) - { - return VarEnum.VT_EMPTY; - } - - VarEnum vtType = VarEnum.VT_EMPTY; - - switch (typeInfo.BuiltInType) - { - case BuiltInType.Boolean: { vtType = VarEnum.VT_BOOL; break; } - case BuiltInType.SByte: { vtType = VarEnum.VT_I1; break; } - case BuiltInType.Byte: { vtType = VarEnum.VT_UI1; break; } - case BuiltInType.Int16: { vtType = VarEnum.VT_I2; break; } - case BuiltInType.UInt16: { vtType = VarEnum.VT_UI2; break; } - case BuiltInType.Int32: { vtType = VarEnum.VT_I4; break; } - case BuiltInType.UInt32: { vtType = VarEnum.VT_UI4; break; } - case BuiltInType.Int64: { vtType = VarEnum.VT_I8; break; } - case BuiltInType.UInt64: { vtType = VarEnum.VT_UI8; break; } - case BuiltInType.Float: { vtType = VarEnum.VT_R4; break; } - case BuiltInType.Double: { vtType = VarEnum.VT_R8; break; } - case BuiltInType.String: { vtType = VarEnum.VT_BSTR; break; } - case BuiltInType.DateTime: { vtType = VarEnum.VT_DATE; break; } - case BuiltInType.Guid: { vtType = VarEnum.VT_BSTR; break; } - case BuiltInType.ByteString: { vtType = VarEnum.VT_ARRAY | VarEnum.VT_UI1; break; } - case BuiltInType.XmlElement: { vtType = VarEnum.VT_BSTR; break; } - case BuiltInType.NodeId: { vtType = VarEnum.VT_BSTR; break; } - case BuiltInType.ExpandedNodeId: { vtType = VarEnum.VT_BSTR; break; } - case BuiltInType.QualifiedName: { vtType = VarEnum.VT_BSTR; break; } - case BuiltInType.LocalizedText: { vtType = VarEnum.VT_BSTR; break; } - case BuiltInType.StatusCode: { vtType = VarEnum.VT_UI4; break; } - case BuiltInType.ExtensionObject: { vtType = VarEnum.VT_ARRAY | VarEnum.VT_UI1; break; } - case BuiltInType.Enumeration: { vtType = VarEnum.VT_I4; break; } - case BuiltInType.Number: { vtType = VarEnum.VT_R8; break; } - case BuiltInType.Integer: { vtType = VarEnum.VT_I8; break; } - case BuiltInType.UInteger: { vtType = VarEnum.VT_UI8; break; } - - case BuiltInType.Variant: - { - if (typeInfo.ValueRank == ValueRanks.Scalar) - { - return VarEnum.VT_EMPTY; - } - - vtType = VarEnum.VT_VARIANT; - break; - } - - default: - { - return VarEnum.VT_EMPTY; - } - } - - if (typeInfo.ValueRank > 0) - { - vtType |= VarEnum.VT_ARRAY; - } - - return vtType; - } - - /// - /// Converts a value to the specified type using COM conversion rules. - /// - public static int ChangeTypeForCOM(object source, VarEnum targetType, out object target) - { - return ChangeTypeForCOM(source, GetVarType(source), targetType, out target); - } - - /// - /// Converts a value to the specified type using COM conversion rules. - /// - public static int ChangeTypeForCOM(object source, VarEnum sourceType, VarEnum targetType, out object target) - { - target = source; - - // check for trivial case. - if (sourceType == targetType) - { - return ResultIds.S_OK; - } - - // check for conversions to date time from string. - string stringValue = source as string; - - if (stringValue != null && targetType == VarEnum.VT_DATE) - { - try - { - target = System.Convert.ToDateTime(stringValue); - return ResultIds.S_OK; - } - catch - { - target = null; - return ResultIds.DISP_E_OVERFLOW; - } - } - - // check for conversions from date time to boolean. - if (sourceType == VarEnum.VT_DATE && targetType == VarEnum.VT_BOOL) - { - target = !(new DateTime(1899, 12, 30, 0, 0, 0).Equals((DateTime)source)); - return ResultIds.S_OK; - } - - // check for conversions from float to double. - if (sourceType == VarEnum.VT_R4 && targetType == VarEnum.VT_R8) - { - target = System.Convert.ToDouble((float)source); - return ResultIds.S_OK; - } - - // check for array conversion. - Array array = source as Array; - bool targetIsArray = ((targetType & VarEnum.VT_ARRAY) != 0); - - if (array != null && targetIsArray) - { - VarEnum elementType = (VarEnum)((short)targetType & ~(short)VarEnum.VT_ARRAY); - - Array convertedArray = Array.CreateInstance(GetSystemType((short)elementType), array.Length); - - for (int ii = 0; ii < array.Length; ii++) - { - object elementValue = null; - int error = ChangeTypeForCOM(array.GetValue(ii), elementType, out elementValue); - - if (error < 0) - { - target = null; - return ResultIds.DISP_E_OVERFLOW; - } - - convertedArray.SetValue(elementValue, ii); - } - - target = convertedArray; - return ResultIds.S_OK; - } - else if (array == null && !targetIsArray) - { - IntPtr pvargDest = Marshal.AllocCoTaskMem(16); - IntPtr pvarSrc = Marshal.AllocCoTaskMem(16); - - VariantInit(pvargDest); - VariantInit(pvarSrc); - - Marshal.GetNativeVariantForObject(source, pvarSrc); - - try - { - // change type. - int error = VariantChangeTypeEx( - pvargDest, - pvarSrc, - Thread.CurrentThread.CurrentCulture.LCID, - VARIANT_NOVALUEPROP | VARIANT_ALPHABOOL, - (short)targetType); - - // check error code. - if (error != 0) - { - target = null; - return error; - } - - // unmarshal result. - object result = Marshal.GetObjectForNativeVariant(pvargDest); - - // check for invalid unsigned <=> signed conversions. - switch (targetType) - { - case VarEnum.VT_I1: - case VarEnum.VT_I2: - case VarEnum.VT_I4: - case VarEnum.VT_I8: - case VarEnum.VT_UI1: - case VarEnum.VT_UI2: - case VarEnum.VT_UI4: - case VarEnum.VT_UI8: - { - // ignore issue for conversions from boolean. - if (sourceType == VarEnum.VT_BOOL) - { - break; - } - - decimal sourceAsDecimal = 0; - decimal resultAsDecimal = System.Convert.ToDecimal(result); - - try { sourceAsDecimal = System.Convert.ToDecimal(source); } - catch { sourceAsDecimal = 0; } - - if ((sourceAsDecimal < 0 && resultAsDecimal > 0) || (sourceAsDecimal > 0 && resultAsDecimal < 0)) - { - target = null; - return ResultIds.E_RANGE; - } - - // conversion from datetime should have failed. - if (sourceType == VarEnum.VT_DATE) - { - if (resultAsDecimal == 0) - { - target = null; - return ResultIds.E_RANGE; - } - } - - break; - } - - case VarEnum.VT_R8: - { - // fix precision problem introduced with conversion from float to double. - if (sourceType == VarEnum.VT_R4) - { - result = System.Convert.ToDouble(source.ToString()); - } - - break; - } - } - - target = result; - return ResultIds.S_OK; - } - finally - { - VariantClear(pvargDest); - VariantClear(pvarSrc); - - Marshal.FreeCoTaskMem(pvargDest); - Marshal.FreeCoTaskMem(pvarSrc); - } - } - else if (array != null && targetType == VarEnum.VT_BSTR) - { - int count = ((Array)source).Length; - - StringBuilder buffer = new StringBuilder(); - - buffer.Append("{"); - - foreach (object element in (Array)source) - { - object elementValue = null; - - int error = ChangeTypeForCOM(element, VarEnum.VT_BSTR, out elementValue); - - if (error < 0) - { - target = null; - return error; - } - - buffer.Append((string)elementValue); - - count--; - - if (count > 0) - { - buffer.Append(" | "); - } - } - - buffer.Append("}"); - - target = buffer.ToString(); - return ResultIds.S_OK; - } - - // no conversions between scalar and array types allowed. - target = null; - return ResultIds.E_BADTYPE; - } - - /// - /// Returns true is the object is a valid COM type. - /// - public static bool IsValidComType(object input) - { - Array array = input as Array; - - if (array != null) - { - foreach (object value in array) - { - if (!IsValidComType(value)) - { - return false; - } - } - - return true; - } - - return GetVarType(input) != VarEnum.VT_EMPTY; - } - - /// - /// Converts a COM value to something that UA clients can deal with. - /// - public static object ProcessComValue(object value) - { - // flatten any multi-dimensional array. - Array array = value as Array; - - if (array != null) - { - if (array.Rank > 1) - { - value = array = Utils.FlattenArray(array); - } - - // convert array of decimal to strings. - if (array != null && array.GetType().GetElementType() == typeof(decimal)) - { - string[] clone = new string[array.Length]; - - for (int ii = 0; ii < array.Length; ii++) - { - clone[ii] = Convert.ToString(array.GetValue(ii)); - } - - value = clone; - } - } - - // convert scalar decimal to a string. - if (value is decimal) - { - value = Convert.ToString(value); - } - - // convert scalar DBNull to a null. - if (value is DBNull) - { - value = null; - } - - return value; - } - - /// - /// Converts a DA quality code to a status code. - /// - public static StatusCode GetQualityCode(short quality) - { - StatusCode code = 0; - - // convert quality status. - switch ((short)(quality & 0x00FC)) - { - case OpcRcw.Da.Qualities.OPC_QUALITY_GOOD: { code = StatusCodes.Good; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_LOCAL_OVERRIDE: { code = StatusCodes.GoodLocalOverride; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_UNCERTAIN: { code = StatusCodes.Uncertain; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_SUB_NORMAL: { code = StatusCodes.UncertainSubNormal; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_SENSOR_CAL: { code = StatusCodes.UncertainSensorNotAccurate; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_EGU_EXCEEDED: { code = StatusCodes.UncertainEngineeringUnitsExceeded; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_LAST_USABLE: { code = StatusCodes.UncertainLastUsableValue; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_BAD: { code = StatusCodes.Bad; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_CONFIG_ERROR: { code = StatusCodes.BadConfigurationError; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_NOT_CONNECTED: { code = StatusCodes.BadNotConnected; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_COMM_FAILURE: { code = StatusCodes.BadNoCommunication; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_DEVICE_FAILURE: { code = StatusCodes.BadDeviceFailure; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_SENSOR_FAILURE: { code = StatusCodes.BadSensorFailure; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_LAST_KNOWN: { code = StatusCodes.BadOutOfService; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_OUT_OF_SERVICE: { code = StatusCodes.BadOutOfService; break; } - case OpcRcw.Da.Qualities.OPC_QUALITY_WAITING_FOR_INITIAL_DATA: { code = StatusCodes.BadWaitingForInitialData; break; } - } - - // convert the limit status. - switch ((short)(quality & 0x0003)) - { - case OpcRcw.Da.Qualities.OPC_LIMIT_LOW: { code.LimitBits = LimitBits.Low; break; } - case OpcRcw.Da.Qualities.OPC_LIMIT_HIGH: { code.LimitBits = LimitBits.High; break; } - case OpcRcw.Da.Qualities.OPC_LIMIT_CONST: { code.LimitBits = LimitBits.Constant; break; } - } - - // return the combined code. - return code; - } - - /// - /// Converts a UA status code to a DA quality code. - /// - public static short GetQualityCode(StatusCode input) - { - short code = 0; - - // convert quality status. - switch (input.CodeBits) - { - case StatusCodes.Good: { code = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD; break; } - case StatusCodes.GoodLocalOverride: { code = OpcRcw.Da.Qualities.OPC_QUALITY_LOCAL_OVERRIDE; break; } - case StatusCodes.Uncertain: { code = OpcRcw.Da.Qualities.OPC_QUALITY_UNCERTAIN; break; } - case StatusCodes.UncertainSubNormal: { code = OpcRcw.Da.Qualities.OPC_QUALITY_SUB_NORMAL; break; } - case StatusCodes.UncertainSensorNotAccurate: { code = OpcRcw.Da.Qualities.OPC_QUALITY_SENSOR_CAL; break; } - case StatusCodes.UncertainEngineeringUnitsExceeded: { code = OpcRcw.Da.Qualities.OPC_QUALITY_EGU_EXCEEDED; break; } - case StatusCodes.UncertainLastUsableValue: { code = OpcRcw.Da.Qualities.OPC_QUALITY_LAST_USABLE; break; } - case StatusCodes.Bad: { code = OpcRcw.Da.Qualities.OPC_QUALITY_BAD; break; } - case StatusCodes.BadConfigurationError: { code = OpcRcw.Da.Qualities.OPC_QUALITY_CONFIG_ERROR; break; } - case StatusCodes.BadNotConnected: { code = OpcRcw.Da.Qualities.OPC_QUALITY_NOT_CONNECTED; break; } - case StatusCodes.BadNoCommunication: { code = OpcRcw.Da.Qualities.OPC_QUALITY_COMM_FAILURE; break; } - case StatusCodes.BadOutOfService: { code = OpcRcw.Da.Qualities.OPC_QUALITY_OUT_OF_SERVICE; break; } - case StatusCodes.BadDeviceFailure: { code = OpcRcw.Da.Qualities.OPC_QUALITY_DEVICE_FAILURE; break; } - case StatusCodes.BadSensorFailure: { code = OpcRcw.Da.Qualities.OPC_QUALITY_SENSOR_FAILURE; break; } - case StatusCodes.BadWaitingForInitialData: { code = OpcRcw.Da.Qualities.OPC_QUALITY_WAITING_FOR_INITIAL_DATA; break; } - - default: - { - if (StatusCode.IsBad(input)) - { - code = OpcRcw.Da.Qualities.OPC_QUALITY_BAD; - break; - } - - if (StatusCode.IsUncertain(input)) - { - code = OpcRcw.Da.Qualities.OPC_QUALITY_UNCERTAIN; - break; - } - - code = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD; - break; - } - } - - // convert the limit status. - switch (input.LimitBits) - { - case LimitBits.Low: { code |= OpcRcw.Da.Qualities.OPC_LIMIT_LOW; break; } - case LimitBits.High: { code |= OpcRcw.Da.Qualities.OPC_LIMIT_HIGH; break; } - case LimitBits.Constant: { code |= OpcRcw.Da.Qualities.OPC_LIMIT_CONST; break; } - } - - // return the combined code. - return code; - } - - /// - /// Converts a HDA quality code to a StatusCode. - /// - public static StatusCode GetHdaQualityCode(uint quality) - { - uint hdaCode = quality & 0xFFFF0000; - - // check for bits indicating an out right error. - if ((hdaCode & OpcRcw.Hda.Constants.OPCHDA_NOBOUND) != 0) - { - return StatusCodes.BadBoundNotFound; - } - - if ((hdaCode & OpcRcw.Hda.Constants.OPCHDA_NODATA) != 0) - { - return StatusCodes.BadNoData; - } - - if ((hdaCode & OpcRcw.Hda.Constants.OPCHDA_DATALOST) != 0) - { - return StatusCodes.BadDataLost; - } - - if ((hdaCode & OpcRcw.Hda.Constants.OPCHDA_CONVERSION) != 0) - { - return StatusCodes.BadTypeMismatch; - } - - // Get DA part (lower 2 bytes). - StatusCode code = GetQualityCode((short)(quality & 0x0000FFFF)); - - // check for bits that are placed in the info bits. - AggregateBits aggregateBits = 0; - - if ((hdaCode & OpcRcw.Hda.Constants.OPCHDA_EXTRADATA) != 0) - { - aggregateBits |= AggregateBits.ExtraData; - } - - if ((hdaCode & OpcRcw.Hda.Constants.OPCHDA_INTERPOLATED) != 0) - { - aggregateBits |= AggregateBits.Interpolated; - } - - if ((hdaCode & OpcRcw.Hda.Constants.OPCHDA_RAW) != 0) - { - aggregateBits |= AggregateBits.Raw; - } - - if ((hdaCode & OpcRcw.Hda.Constants.OPCHDA_CALCULATED) != 0) - { - aggregateBits |= AggregateBits.Calculated; - } - - if ((hdaCode & OpcRcw.Hda.Constants.OPCHDA_PARTIAL) != 0) - { - aggregateBits |= AggregateBits.Partial; - } - - if (aggregateBits != 0) - { - return code.SetAggregateBits(aggregateBits); - } - - return code; - } - - /// - /// Converts a UA status code to a HDA quality code. - /// - public static uint GetHdaQualityCode(StatusCode input) - { - // check for fatal errors. - switch (input.CodeBits) - { - case StatusCodes.BadBoundNotFound: { return OpcRcw.Hda.Constants.OPCHDA_NOBOUND; } - case StatusCodes.BadBoundNotSupported: { return OpcRcw.Hda.Constants.OPCHDA_NOBOUND; } - case StatusCodes.BadNoData: { return OpcRcw.Hda.Constants.OPCHDA_NODATA; } - case StatusCodes.BadDataLost: { return OpcRcw.Hda.Constants.OPCHDA_DATALOST; } - } - - // handle normal case. - uint code = Utils.ToUInt32(GetQualityCode(input)); - - // check for bits that are placed in the info bits. - AggregateBits aggregateBits = input.AggregateBits; - - if ((aggregateBits & AggregateBits.ExtraData) != 0) - { - code |= OpcRcw.Hda.Constants.OPCHDA_EXTRADATA; - } - - // set the source of the data. - if ((aggregateBits & AggregateBits.Interpolated) != 0) - { - code |= OpcRcw.Hda.Constants.OPCHDA_INTERPOLATED; - } - else if ((aggregateBits & AggregateBits.Calculated) != 0) - { - code |= OpcRcw.Hda.Constants.OPCHDA_CALCULATED; - } - else if ((aggregateBits & AggregateBits.Partial) != 0) - { - code |= OpcRcw.Hda.Constants.OPCHDA_PARTIAL; - } - else - { - code |= OpcRcw.Hda.Constants.OPCHDA_RAW; - } - - // return the combined code. - return code; - } - - /// - /// Returns the symbolic name for the specified error. - /// - public static string GetErrorText(Type type, int error) - { - FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Static); - - foreach (FieldInfo field in fields) - { - if (error == (int)field.GetValue(type)) - { - return field.Name; - } - } - - return String.Format("0x{0:X8}", error); - } - - /// - /// Gets the error code for the exception. - /// - /// The exception. - /// The default code. - /// The error code - /// This method ignores the exception but makes it possible to keep track of ignored exceptions. - public static int GetErrorCode(Exception e, int defaultCode) - { - return defaultCode; - } - - /// - /// Releases the server if it is a true COM server. - /// - public static void ReleaseServer(object server) - { - if (server != null && server.GetType().IsCOMObject) - { - Marshal.ReleaseComObject(server); - } - } - - /// - /// Retrieves the system message text for the specified error. - /// - public static string GetSystemMessage(int error, int localeId) - { - int langId = 0; - - switch (localeId) - { - case LOCALE_SYSTEM_DEFAULT: - { - langId = GetSystemDefaultLangID(); - break; - } - - case LOCALE_USER_DEFAULT: - { - langId = GetUserDefaultLangID(); - break; - } - - default: - { - langId = (0xFFFF & localeId); - break; - } - } - - IntPtr buffer = Marshal.AllocCoTaskMem(MAX_MESSAGE_LENGTH); - - int result = FormatMessageW( - (int)FORMAT_MESSAGE_FROM_SYSTEM, - IntPtr.Zero, - error, - langId, - buffer, - MAX_MESSAGE_LENGTH-1, - IntPtr.Zero); - - if (result > 0) - { - string msg = Marshal.PtrToStringUni(buffer); - Marshal.FreeCoTaskMem(buffer); - - if (msg != null && msg.Length > 0) - { - return msg.Trim(); - } - } - - return String.Format("0x{0:X8}", error); - } - - /// - /// Converts an exception to an exception that returns a COM error code. - /// - public static Exception CreateComException(Exception e, int errorId) - { - return new COMException(e.Message, errorId); - } - - /// - /// Creates a COM exception. - /// - public static Exception CreateComException(string message, int errorId) - { - return new COMException(message, errorId); - } - - /// - /// Converts an exception to an exception that returns a COM error code. - /// - public static Exception CreateComException(int errorId) - { - return new COMException(String.Format("0x{0:X8}", errorId), errorId); - } - - /// - /// Converts an exception to an exception that returns a COM error code. - /// - public static Exception CreateComException(Exception e) - { - // nothing special required for external exceptions. - if (e is COMException) - { - return e; - } - - // convert other exceptions to E_FAIL. - return new COMException(e.Message, ResultIds.E_FAIL); - } - - /// - /// Creates an error message for a failed COM function call. - /// - public static Exception CreateException(Exception e, string function) - { - return ServiceResultException.Create( - StatusCodes.BadCommunicationError, - "Call to {0} failed. Error: {1}.", - function, - ComUtils.GetSystemMessage(Marshal.GetHRForException(e), LOCALE_SYSTEM_DEFAULT)); - } - - /// - /// Checks if the error is an RPC error. - /// - public static bool IsRpcError(Exception e) - { - int error = Marshal.GetHRForException(e); - - // Assume that any 0x8007 is a fatal communication error. - // May need to update this check if the assumption proves to be incorrect. - if ((error & 0xFFFF0000) == 0x80070000) - { - error &= 0xFFFF; - - // check the RPC error range define in WinError.h - if (error >= 1700 && error < 1918) - { - return true; - } - } - - return false; - } - - /// - /// Checks if the error for the exception is one of the recognized errors. - /// - public static bool IsUnknownError(Exception e, params int[] knownErrors) - { - int error = Marshal.GetHRForException(e); - - if (knownErrors != null) - { - for (int ii = 0; ii < knownErrors.Length; ii++) - { - if (knownErrors[ii] == error) - { - return false; - } - } - } - - return true; - } - #endregion - - #region Utility Functions - /// - /// Compares a string locale to a WIN32 localeId - /// - public static bool CompareLocales(int localeId, string locale, bool ignoreRegion) - { - // parse locale. - CultureInfo culture = null; - - try - { - culture = new CultureInfo(locale); - } - catch (Exception) - { - return false; - } - - // only match the language portion of the locale id. - if (ignoreRegion) - { - if ((localeId & culture.LCID & 0x3FF) == (localeId & 0x3FF)) - { - return true; - } - } - - // check for exact match. - else - { - if (localeId == culture.LCID) - { - return true; - } - } - - return false; - } - - /// - /// Reports an unexpected exception during a COM operation. - /// - public static void TraceComError(Exception e, string format, params object[] args) - { - string message = Utils.Format(format, args); - - int code = Marshal.GetHRForException(e); - - string error = ResultIds.GetBrowseName(code); - - if (error == null) - { - Utils.Trace(e, message); - return; - } - - Utils.Trace(e, "{0}: {1}", error, message); - } - #endregion - } -} diff --git a/ComIOP/Common/Common/ModelDesign.csv b/ComIOP/Common/Common/ModelDesign.csv deleted file mode 100644 index c91e3fc0e..000000000 --- a/ComIOP/Common/Common/ModelDesign.csv +++ /dev/null @@ -1,8 +0,0 @@ -ComServerStatusType,9,ObjectType -ComServerStatusType_ServerUrl,10,Variable -ComServerStatusType_VendorInfo,11,Variable -ComServerStatusType_SoftwareVersion,12,Variable -ComServerStatusType_ServerState,13,Variable -ComServerStatusType_CurrentTime,14,Variable -ComServerStatusType_StartTime,15,Variable -ComServerStatusType_LastUpdateTime,16,Variable diff --git a/ComIOP/Common/Common/ModelDesign.xml b/ComIOP/Common/Common/ModelDesign.xml deleted file mode 100644 index 0d0129635..000000000 --- a/ComIOP/Common/Common/ModelDesign.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - http://opcfoundation.org/UA/ - http://opcfoundation.org/UA/SDK/COMInterop - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ComIOP/Common/Common/Namespaces.cs b/ComIOP/Common/Common/Namespaces.cs deleted file mode 100644 index e54175a1b..000000000 --- a/ComIOP/Common/Common/Namespaces.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Opc.Ua.Com -{ - /// - /// Defines constants for namespaces used by the application. - /// - public static partial class Namespaces - { - /// - /// The namespace for the nodes provided by the server. - /// - public const string ComInterop = Opc.Ua.Namespaces.OpcUaSdk + "COMInterop"; - } -} diff --git a/ComIOP/Common/Common/Opc.Ua.Com.Classes.cs b/ComIOP/Common/Common/Opc.Ua.Com.Classes.cs deleted file mode 100644 index 333ddd3be..000000000 --- a/ComIOP/Common/Common/Opc.Ua.Com.Classes.cs +++ /dev/null @@ -1,477 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Xml; -using System.Runtime.Serialization; -using Opc.Ua; - -namespace Opc.Ua.Com -{ - #region ComServerStatusState Class - #if (!OPCUA_EXCLUDE_ComServerStatusState) - /// - /// Stores an instance of the ComServerStatusType ObjectType. - /// - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] - public partial class ComServerStatusState : BaseObjectState - { - #region Constructors - /// - /// Initializes the type with its default attribute values. - /// - public ComServerStatusState(NodeState parent) : base(parent) - { - } - - /// - /// Returns the id of the default type definition node for the instance. - /// - protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) - { - return Opc.Ua.NodeId.Create(Opc.Ua.Com.ObjectTypes.ComServerStatusType, Opc.Ua.Com.Namespaces.OpcUaCom, namespaceUris); - } - - #if (!OPCUA_EXCLUDE_InitializationStrings) - /// - /// Initializes the instance. - /// - protected override void Initialize(ISystemContext context) - { - base.Initialize(context); - Initialize(context, InitializationString); - InitializeOptionalChildren(context); - } - - /// - /// Initializes the instance with a node. - /// - protected override void Initialize(ISystemContext context, NodeState source) - { - InitializeOptionalChildren(context); - base.Initialize(context, source); - } - - /// - /// Initializes the any option children defined for the instance. - /// - protected override void InitializeOptionalChildren(ISystemContext context) - { - base.InitializeOptionalChildren(context); - } - - #region Initialization String - private const string InitializationString = - "AQAAACoAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvU0RLL0NPTUludGVyb3D/////BGCAAgEA" + - "AAABABsAAABDb21TZXJ2ZXJTdGF0dXNUeXBlSW5zdGFuY2UBAQkAAQEJAAkAAAD/////BwAAABVgiQoC" + - "AAAAAQAJAAAAU2VydmVyVXJsAQEKAAAuAEQKAAAAAAz/////AQH/////AAAAABVgiQoCAAAAAQAKAAAA" + - "VmVuZG9ySW5mbwEBCwAALgBECwAAAAAM/////wEB/////wAAAAAVYIkKAgAAAAEADwAAAFNvZnR3YXJl" + - "VmVyc2lvbgEBDAAALgBEDAAAAAAM/////wEB/////wAAAAAVYIkKAgAAAAEACwAAAFNlcnZlclN0YXRl" + - "AQENAAAuAEQNAAAAAAz/////AQH/////AAAAABVgiQoCAAAAAQALAAAAQ3VycmVudFRpbWUBAQ4AAC4A" + - "RA4AAAAADf////8BAf////8AAAAAFWCJCgIAAAABAAkAAABTdGFydFRpbWUBAQ8AAC4ARA8AAAAADf//" + - "//8BAf////8AAAAAFWCJCgIAAAABAA4AAABMYXN0VXBkYXRlVGltZQEBEAAALgBEEAAAAAAN/////wEB" + - "/////wAAAAA="; - #endregion - #endif - #endregion - - #region Public Properties - /// - public PropertyState ServerUrl - { - get - { - return m_serverUrl; - } - - set - { - if (!Object.ReferenceEquals(m_serverUrl, value)) - { - ChangeMasks |= NodeStateChangeMasks.Children; - } - - m_serverUrl = value; - } - } - - /// - public PropertyState VendorInfo - { - get - { - return m_vendorInfo; - } - - set - { - if (!Object.ReferenceEquals(m_vendorInfo, value)) - { - ChangeMasks |= NodeStateChangeMasks.Children; - } - - m_vendorInfo = value; - } - } - - /// - public PropertyState SoftwareVersion - { - get - { - return m_softwareVersion; - } - - set - { - if (!Object.ReferenceEquals(m_softwareVersion, value)) - { - ChangeMasks |= NodeStateChangeMasks.Children; - } - - m_softwareVersion = value; - } - } - - /// - public PropertyState ServerState - { - get - { - return m_serverState; - } - - set - { - if (!Object.ReferenceEquals(m_serverState, value)) - { - ChangeMasks |= NodeStateChangeMasks.Children; - } - - m_serverState = value; - } - } - - /// - public PropertyState CurrentTime - { - get - { - return m_currentTime; - } - - set - { - if (!Object.ReferenceEquals(m_currentTime, value)) - { - ChangeMasks |= NodeStateChangeMasks.Children; - } - - m_currentTime = value; - } - } - - /// - public PropertyState StartTime - { - get - { - return m_startTime; - } - - set - { - if (!Object.ReferenceEquals(m_startTime, value)) - { - ChangeMasks |= NodeStateChangeMasks.Children; - } - - m_startTime = value; - } - } - - /// - public PropertyState LastUpdateTime - { - get - { - return m_lastUpdateTime; - } - - set - { - if (!Object.ReferenceEquals(m_lastUpdateTime, value)) - { - ChangeMasks |= NodeStateChangeMasks.Children; - } - - m_lastUpdateTime = value; - } - } - #endregion - - #region Overridden Methods - /// - /// Populates a list with the children that belong to the node. - /// - /// The context for the system being accessed. - /// The list of children to populate. - public override void GetChildren( - ISystemContext context, - IList children) - { - if (m_serverUrl != null) - { - children.Add(m_serverUrl); - } - - if (m_vendorInfo != null) - { - children.Add(m_vendorInfo); - } - - if (m_softwareVersion != null) - { - children.Add(m_softwareVersion); - } - - if (m_serverState != null) - { - children.Add(m_serverState); - } - - if (m_currentTime != null) - { - children.Add(m_currentTime); - } - - if (m_startTime != null) - { - children.Add(m_startTime); - } - - if (m_lastUpdateTime != null) - { - children.Add(m_lastUpdateTime); - } - - base.GetChildren(context, children); - } - - /// - /// Finds the child with the specified browse name. - /// - protected override BaseInstanceState FindChild( - ISystemContext context, - QualifiedName browseName, - bool createOrReplace, - BaseInstanceState replacement) - { - if (QualifiedName.IsNull(browseName)) - { - return null; - } - - BaseInstanceState instance = null; - - switch (browseName.Name) - { - case Opc.Ua.Com.BrowseNames.ServerUrl: - { - if (createOrReplace) - { - if (ServerUrl == null) - { - if (replacement == null) - { - ServerUrl = new PropertyState(this); - } - else - { - ServerUrl = (PropertyState)replacement; - } - } - } - - instance = ServerUrl; - break; - } - - case Opc.Ua.Com.BrowseNames.VendorInfo: - { - if (createOrReplace) - { - if (VendorInfo == null) - { - if (replacement == null) - { - VendorInfo = new PropertyState(this); - } - else - { - VendorInfo = (PropertyState)replacement; - } - } - } - - instance = VendorInfo; - break; - } - - case Opc.Ua.Com.BrowseNames.SoftwareVersion: - { - if (createOrReplace) - { - if (SoftwareVersion == null) - { - if (replacement == null) - { - SoftwareVersion = new PropertyState(this); - } - else - { - SoftwareVersion = (PropertyState)replacement; - } - } - } - - instance = SoftwareVersion; - break; - } - - case Opc.Ua.Com.BrowseNames.ServerState: - { - if (createOrReplace) - { - if (ServerState == null) - { - if (replacement == null) - { - ServerState = new PropertyState(this); - } - else - { - ServerState = (PropertyState)replacement; - } - } - } - - instance = ServerState; - break; - } - - case Opc.Ua.Com.BrowseNames.CurrentTime: - { - if (createOrReplace) - { - if (CurrentTime == null) - { - if (replacement == null) - { - CurrentTime = new PropertyState(this); - } - else - { - CurrentTime = (PropertyState)replacement; - } - } - } - - instance = CurrentTime; - break; - } - - case Opc.Ua.Com.BrowseNames.StartTime: - { - if (createOrReplace) - { - if (StartTime == null) - { - if (replacement == null) - { - StartTime = new PropertyState(this); - } - else - { - StartTime = (PropertyState)replacement; - } - } - } - - instance = StartTime; - break; - } - - case Opc.Ua.Com.BrowseNames.LastUpdateTime: - { - if (createOrReplace) - { - if (LastUpdateTime == null) - { - if (replacement == null) - { - LastUpdateTime = new PropertyState(this); - } - else - { - LastUpdateTime = (PropertyState)replacement; - } - } - } - - instance = LastUpdateTime; - break; - } - } - - if (instance != null) - { - return instance; - } - - return base.FindChild(context, browseName, createOrReplace, replacement); - } - #endregion - - #region Private Fields - private PropertyState m_serverUrl; - private PropertyState m_vendorInfo; - private PropertyState m_softwareVersion; - private PropertyState m_serverState; - private PropertyState m_currentTime; - private PropertyState m_startTime; - private PropertyState m_lastUpdateTime; - #endregion - } - #endif - #endregion -} \ No newline at end of file diff --git a/ComIOP/Common/Common/Opc.Ua.Com.Constants.cs b/ComIOP/Common/Common/Opc.Ua.Com.Constants.cs deleted file mode 100644 index e15f53976..000000000 --- a/ComIOP/Common/Common/Opc.Ua.Com.Constants.cs +++ /dev/null @@ -1,227 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; -using System.Xml; -using System.Runtime.Serialization; -using Opc.Ua; - -namespace Opc.Ua.Com -{ - #region ObjectType Identifiers - /// - /// A class that declares constants for all ObjectTypes in the Model Design. - /// - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] - public static partial class ObjectTypes - { - /// - /// The identifier for the ComServerStatusType ObjectType. - /// - public const uint ComServerStatusType = 9; - } - #endregion - - #region Variable Identifiers - /// - /// A class that declares constants for all Variables in the Model Design. - /// - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] - public static partial class Variables - { - /// - /// The identifier for the ComServerStatusType_ServerUrl Variable. - /// - public const uint ComServerStatusType_ServerUrl = 10; - - /// - /// The identifier for the ComServerStatusType_VendorInfo Variable. - /// - public const uint ComServerStatusType_VendorInfo = 11; - - /// - /// The identifier for the ComServerStatusType_SoftwareVersion Variable. - /// - public const uint ComServerStatusType_SoftwareVersion = 12; - - /// - /// The identifier for the ComServerStatusType_ServerState Variable. - /// - public const uint ComServerStatusType_ServerState = 13; - - /// - /// The identifier for the ComServerStatusType_CurrentTime Variable. - /// - public const uint ComServerStatusType_CurrentTime = 14; - - /// - /// The identifier for the ComServerStatusType_StartTime Variable. - /// - public const uint ComServerStatusType_StartTime = 15; - - /// - /// The identifier for the ComServerStatusType_LastUpdateTime Variable. - /// - public const uint ComServerStatusType_LastUpdateTime = 16; - } - #endregion - - #region ObjectType Node Identifiers - /// - /// A class that declares constants for all ObjectTypes in the Model Design. - /// - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] - public static partial class ObjectTypeIds - { - /// - /// The identifier for the ComServerStatusType ObjectType. - /// - public static readonly ExpandedNodeId ComServerStatusType = new ExpandedNodeId(Opc.Ua.Com.ObjectTypes.ComServerStatusType, Opc.Ua.Com.Namespaces.OpcUaCom); - } - #endregion - - #region Variable Node Identifiers - /// - /// A class that declares constants for all Variables in the Model Design. - /// - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] - public static partial class VariableIds - { - /// - /// The identifier for the ComServerStatusType_ServerUrl Variable. - /// - public static readonly ExpandedNodeId ComServerStatusType_ServerUrl = new ExpandedNodeId(Opc.Ua.Com.Variables.ComServerStatusType_ServerUrl, Opc.Ua.Com.Namespaces.OpcUaCom); - - /// - /// The identifier for the ComServerStatusType_VendorInfo Variable. - /// - public static readonly ExpandedNodeId ComServerStatusType_VendorInfo = new ExpandedNodeId(Opc.Ua.Com.Variables.ComServerStatusType_VendorInfo, Opc.Ua.Com.Namespaces.OpcUaCom); - - /// - /// The identifier for the ComServerStatusType_SoftwareVersion Variable. - /// - public static readonly ExpandedNodeId ComServerStatusType_SoftwareVersion = new ExpandedNodeId(Opc.Ua.Com.Variables.ComServerStatusType_SoftwareVersion, Opc.Ua.Com.Namespaces.OpcUaCom); - - /// - /// The identifier for the ComServerStatusType_ServerState Variable. - /// - public static readonly ExpandedNodeId ComServerStatusType_ServerState = new ExpandedNodeId(Opc.Ua.Com.Variables.ComServerStatusType_ServerState, Opc.Ua.Com.Namespaces.OpcUaCom); - - /// - /// The identifier for the ComServerStatusType_CurrentTime Variable. - /// - public static readonly ExpandedNodeId ComServerStatusType_CurrentTime = new ExpandedNodeId(Opc.Ua.Com.Variables.ComServerStatusType_CurrentTime, Opc.Ua.Com.Namespaces.OpcUaCom); - - /// - /// The identifier for the ComServerStatusType_StartTime Variable. - /// - public static readonly ExpandedNodeId ComServerStatusType_StartTime = new ExpandedNodeId(Opc.Ua.Com.Variables.ComServerStatusType_StartTime, Opc.Ua.Com.Namespaces.OpcUaCom); - - /// - /// The identifier for the ComServerStatusType_LastUpdateTime Variable. - /// - public static readonly ExpandedNodeId ComServerStatusType_LastUpdateTime = new ExpandedNodeId(Opc.Ua.Com.Variables.ComServerStatusType_LastUpdateTime, Opc.Ua.Com.Namespaces.OpcUaCom); - } - #endregion - - #region BrowseName Declarations - /// - /// Declares all of the BrowseNames used in the Model Design. - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] - public static partial class BrowseNames - { - /// - /// The BrowseName for the ComServerStatusType component. - /// - public const string ComServerStatusType = "ComServerStatusType"; - - /// - /// The BrowseName for the CurrentTime component. - /// - public const string CurrentTime = "CurrentTime"; - - /// - /// The BrowseName for the LastUpdateTime component. - /// - public const string LastUpdateTime = "LastUpdateTime"; - - /// - /// The BrowseName for the ServerState component. - /// - public const string ServerState = "ServerState"; - - /// - /// The BrowseName for the ServerUrl component. - /// - public const string ServerUrl = "ServerUrl"; - - /// - /// The BrowseName for the SoftwareVersion component. - /// - public const string SoftwareVersion = "SoftwareVersion"; - - /// - /// The BrowseName for the StartTime component. - /// - public const string StartTime = "StartTime"; - - /// - /// The BrowseName for the VendorInfo component. - /// - public const string VendorInfo = "VendorInfo"; - } - #endregion - - #region Namespace Declarations - /// - /// Defines constants for all namespaces referenced by the model design. - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] - public static partial class Namespaces - { - /// - /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). - /// - public const string OpcUa = "http://opcfoundation.org/UA/"; - - /// - /// The URI for the OpcUaCom namespace (.NET code namespace is 'Opc.Ua.Com'). - /// - public const string OpcUaCom = "http://opcfoundation.org/UA/SDK/COMInterop"; - } - #endregion -} \ No newline at end of file diff --git a/ComIOP/Common/Common/Opc.Ua.Com.DataTypes.cs b/ComIOP/Common/Common/Opc.Ua.Com.DataTypes.cs deleted file mode 100644 index 5a65bcf53..000000000 --- a/ComIOP/Common/Common/Opc.Ua.Com.DataTypes.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Xml; -using System.Runtime.Serialization; -using Opc.Ua; - -namespace Opc.Ua.Com -{ -} \ No newline at end of file diff --git a/ComIOP/Common/Common/Opc.Ua.Com.NodeIds.csv b/ComIOP/Common/Common/Opc.Ua.Com.NodeIds.csv deleted file mode 100644 index 11335f38e..000000000 --- a/ComIOP/Common/Common/Opc.Ua.Com.NodeIds.csv +++ /dev/null @@ -1 +0,0 @@ -ComServerStatusType,9,ObjectType diff --git a/ComIOP/Common/Common/Opc.Ua.Com.NodeSet.xml b/ComIOP/Common/Common/Opc.Ua.Com.NodeSet.xml deleted file mode 100644 index 1b84c429a..000000000 --- a/ComIOP/Common/Common/Opc.Ua.Com.NodeSet.xml +++ /dev/null @@ -1,553 +0,0 @@ - - - - http://opcfoundation.org/UA/ - http://opcfoundation.org/UA/SDK/COMInterop - - - - - - ns=1;i=9 - - ObjectType_8 - - 1 - ComServerStatusType - - - - ComServerStatusType - - - 0 - 0 - - - 0 - - - - i=45 - - true - - i=58 - - - - - i=46 - - false - - ns=1;i=10 - - - - - i=46 - - false - - ns=1;i=11 - - - - - i=46 - - false - - ns=1;i=12 - - - - - i=46 - - false - - ns=1;i=13 - - - - - i=46 - - false - - ns=1;i=14 - - - - - i=46 - - false - - ns=1;i=15 - - - - - i=46 - - false - - ns=1;i=16 - - - - false - - - - ns=1;i=10 - - Variable_2 - - 1 - ServerUrl - - - - ServerUrl - - - 0 - 0 - - - 0 - - - - i=46 - - true - - ns=1;i=9 - - - - - i=40 - - false - - i=68 - - - - - i=37 - - false - - i=78 - - - - - - - - - - i=12 - - -1 - - 1 - 1 - 0 - false - 0 - - - - ns=1;i=11 - - Variable_2 - - 1 - VendorInfo - - - - VendorInfo - - - 0 - 0 - - - 0 - - - - i=46 - - true - - ns=1;i=9 - - - - - i=40 - - false - - i=68 - - - - - i=37 - - false - - i=78 - - - - - - - - - - i=12 - - -1 - - 1 - 1 - 0 - false - 0 - - - - ns=1;i=12 - - Variable_2 - - 1 - SoftwareVersion - - - - SoftwareVersion - - - 0 - 0 - - - 0 - - - - i=46 - - true - - ns=1;i=9 - - - - - i=40 - - false - - i=68 - - - - - i=37 - - false - - i=78 - - - - - - - - - - i=12 - - -1 - - 1 - 1 - 0 - false - 0 - - - - ns=1;i=13 - - Variable_2 - - 1 - ServerState - - - - ServerState - - - 0 - 0 - - - 0 - - - - i=46 - - true - - ns=1;i=9 - - - - - i=40 - - false - - i=68 - - - - - i=37 - - false - - i=78 - - - - - - - - - - i=12 - - -1 - - 1 - 1 - 0 - false - 0 - - - - ns=1;i=14 - - Variable_2 - - 1 - CurrentTime - - - - CurrentTime - - - 0 - 0 - - - 0 - - - - i=46 - - true - - ns=1;i=9 - - - - - i=40 - - false - - i=68 - - - - - i=37 - - false - - i=78 - - - - - - 0001-01-01T00:00:00 - - - - i=13 - - -1 - - 1 - 1 - 0 - false - 0 - - - - ns=1;i=15 - - Variable_2 - - 1 - StartTime - - - - StartTime - - - 0 - 0 - - - 0 - - - - i=46 - - true - - ns=1;i=9 - - - - - i=40 - - false - - i=68 - - - - - i=37 - - false - - i=78 - - - - - - 0001-01-01T00:00:00 - - - - i=13 - - -1 - - 1 - 1 - 0 - false - 0 - - - - ns=1;i=16 - - Variable_2 - - 1 - LastUpdateTime - - - - LastUpdateTime - - - 0 - 0 - - - 0 - - - - i=46 - - true - - ns=1;i=9 - - - - - i=40 - - false - - i=68 - - - - - i=37 - - false - - i=78 - - - - - - 0001-01-01T00:00:00 - - - - i=13 - - -1 - - 1 - 1 - 0 - false - 0 - - - \ No newline at end of file diff --git a/ComIOP/Common/Common/Opc.Ua.Com.NodeSet2.xml b/ComIOP/Common/Common/Opc.Ua.Com.NodeSet2.xml deleted file mode 100644 index 482e208e9..000000000 --- a/ComIOP/Common/Common/Opc.Ua.Com.NodeSet2.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - http://opcfoundation.org/UA/SDK/COMInterop - - - - - - - - i=1 - i=2 - i=3 - i=4 - i=5 - i=6 - i=7 - i=8 - i=9 - i=10 - i=11 - i=13 - i=12 - i=15 - i=14 - i=16 - i=17 - i=18 - i=20 - i=21 - i=19 - i=22 - i=26 - i=27 - i=28 - i=47 - i=46 - i=35 - i=36 - i=48 - i=45 - i=40 - i=37 - i=38 - i=39 - i=53 - i=52 - i=51 - i=54 - i=9004 - i=9005 - i=17597 - i=9006 - i=15112 - i=17604 - i=17603 - - - ComServerStatusType - - ns=1;i=10 - ns=1;i=11 - ns=1;i=12 - ns=1;i=13 - ns=1;i=14 - ns=1;i=15 - ns=1;i=16 - i=58 - - - - ServerUrl - - i=68 - i=78 - ns=1;i=9 - - - - VendorInfo - - i=68 - i=78 - ns=1;i=9 - - - - SoftwareVersion - - i=68 - i=78 - ns=1;i=9 - - - - ServerState - - i=68 - i=78 - ns=1;i=9 - - - - CurrentTime - - i=68 - i=78 - ns=1;i=9 - - - - StartTime - - i=68 - i=78 - ns=1;i=9 - - - - LastUpdateTime - - i=68 - i=78 - ns=1;i=9 - - - \ No newline at end of file diff --git a/ComIOP/Common/Common/Opc.Ua.Com.PredefinedNodes.uanodes b/ComIOP/Common/Common/Opc.Ua.Com.PredefinedNodes.uanodes deleted file mode 100644 index 776bf0e1c..000000000 Binary files a/ComIOP/Common/Common/Opc.Ua.Com.PredefinedNodes.uanodes and /dev/null differ diff --git a/ComIOP/Common/Common/Opc.Ua.Com.PredefinedNodes.xml b/ComIOP/Common/Common/Opc.Ua.Com.PredefinedNodes.xml deleted file mode 100644 index 27d668cd9..000000000 --- a/ComIOP/Common/Common/Opc.Ua.Com.PredefinedNodes.xml +++ /dev/null @@ -1,201 +0,0 @@ - - - - http://opcfoundation.org/UA/SDK/COMInterop - - - ObjectType_8 - - ns=1;i=9 - - - 1 - ComServerStatusType - - - i=58 - - - Variable_2 - - ns=1;i=10 - - - 1 - ServerUrl - - - i=46 - - - i=68 - - - i=78 - - 10 - - i=12 - - -1 - 1 - 1 - - - Variable_2 - - ns=1;i=11 - - - 1 - VendorInfo - - - i=46 - - - i=68 - - - i=78 - - 11 - - i=12 - - -1 - 1 - 1 - - - Variable_2 - - ns=1;i=12 - - - 1 - SoftwareVersion - - - i=46 - - - i=68 - - - i=78 - - 12 - - i=12 - - -1 - 1 - 1 - - - Variable_2 - - ns=1;i=13 - - - 1 - ServerState - - - i=46 - - - i=68 - - - i=78 - - 13 - - i=12 - - -1 - 1 - 1 - - - Variable_2 - - ns=1;i=14 - - - 1 - CurrentTime - - - i=46 - - - i=68 - - - i=78 - - 14 - - i=13 - - -1 - 1 - 1 - - - Variable_2 - - ns=1;i=15 - - - 1 - StartTime - - - i=46 - - - i=68 - - - i=78 - - 15 - - i=13 - - -1 - 1 - 1 - - - Variable_2 - - ns=1;i=16 - - - 1 - LastUpdateTime - - - i=46 - - - i=68 - - - i=78 - - 16 - - i=13 - - -1 - 1 - 1 - - - \ No newline at end of file diff --git a/ComIOP/Common/Common/Opc.Ua.Com.Types.bsd b/ComIOP/Common/Common/Opc.Ua.Com.Types.bsd deleted file mode 100644 index 91fced647..000000000 --- a/ComIOP/Common/Common/Opc.Ua.Com.Types.bsd +++ /dev/null @@ -1,11 +0,0 @@ - - - - \ No newline at end of file diff --git a/ComIOP/Common/Common/Opc.Ua.Com.Types.xsd b/ComIOP/Common/Common/Opc.Ua.Com.Types.xsd deleted file mode 100644 index 7ed146eb1..000000000 --- a/ComIOP/Common/Common/Opc.Ua.Com.Types.xsd +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file diff --git a/ComIOP/Common/Common/PropertyIds.cs b/ComIOP/Common/Common/PropertyIds.cs deleted file mode 100644 index 4e07eddef..000000000 --- a/ComIOP/Common/Common/PropertyIds.cs +++ /dev/null @@ -1,391 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace Opc.Ua.Com -{ - #region PropertyIds Class - /// - /// Defines constants for all DA property Ids. - /// - public class PropertyIds - { - /// - public const int DataType = 1; - /// - public const int Value = 2; - /// - public const int Quality = 3; - /// - public const int Timestamp = 4; - /// - public const int AccessRights = 5; - /// - public const int ScanRate = 6; - /// - public const int EuType = 7; - /// - public const int EuInfo = 8; - /// - public const int EngineeringUnits = 100; - /// - public const int Description = 101; - /// - public const int HighEU = 102; - /// - public const int LowEU = 103; - /// - public const int HighIR = 104; - /// - public const int LowIR = 105; - /// - public const int CloseLabel = 106; - /// - public const int OpenLabel = 107; - /// - public const int TimeZone = 108; - /// - public const int ConditionStatus = 300; - /// - public const int AlarmQuickHelp = 301; - /// - public const int AlarmAreaList = 302; - /// - public const int PrimaryAlarmArea = 303; - /// - public const int ConditionLogic = 304; - /// - public const int LimitExceeded = 305; - /// - public const int Deadband = 306; - /// - public const int HiHiLimit = 307; - /// - public const int HiLimit = 308; - /// - public const int LoLimit = 309; - /// - public const int LoLoLimit = 310; - /// - public const int RateChangeLimit = 311; - /// - public const int DeviationLimit = 312; - /// - public const int SoundFile = 313; - /// - public const int TypeSystemId = 600; - /// - public const int DictionaryId = 601; - /// - public const int TypeId = 602; - /// - public const int Dictionary = 603; - /// - public const int TypeDescription = 604; - /// - public const int ConsistencyWindow = 605; - /// - public const int WriteBehavior = 606; - /// - public const int UnconvertedItemId = 607; - /// - public const int UnfilteredItemId = 608; - /// - public const int DataFilterValue = 609; - /// - public const int UaBuiltInType = 610; - /// - public const int UaDataTypeId = 611; - /// - public const int UaValueRank = 612; - /// - public const int UaBrowseName = 613; - /// - public const int UaDescription = 614; - /// - public const int VendorDefined = 5000; - - //Ravil 17 Sep 2008: HDA Attributes (5.2 of OPC HDA 1.20 Spec) - /// - public const int Stepped = 700; - /// - public const int Archiving = 701; - /// - public const int DeriveEquation = 702; - /// - public const int NodeName = 703; - /// - public const int ProcessName = 704; - /// - public const int SourceName = 705; - /// - public const int SourceType = 706; - /// - public const int NormalMaximum = 707; - /// - public const int NormalMinimum = 708; - /// - public const int ItemId = 709; - /// - public const int MaxTimeInt = 710; - /// - public const int MinTimeInt = 711; - /// - public const int ExceptionDev = 712; - /// - public const int ExceptionDevType = 713; - /// - public const int HighEntryLimit = 714; - /// - public const int LowEntryLimit = 715; - - /// - /// Returns the UA data type for the specified property. - /// - public static NodeId GetDataTypeId(int propertyId) - { - switch (propertyId) - { - case PropertyIds.DataType: { return DataTypes.NodeId; } - case PropertyIds.Value: { return DataTypes.BaseDataType; } - case PropertyIds.Quality: { return DataTypes.UInt16; } - case PropertyIds.Timestamp: { return DataTypes.DateTime; } - case PropertyIds.AccessRights: { return DataTypes.Int32; } - case PropertyIds.ScanRate: { return DataTypes.Float; } - case PropertyIds.EuType: { return DataTypes.Int32; } - case PropertyIds.EuInfo: { return DataTypes.String; } - case PropertyIds.EngineeringUnits: { return DataTypes.String; } - case PropertyIds.Description: { return DataTypes.String; } - case PropertyIds.HighEU: { return DataTypes.Double; } - case PropertyIds.LowEU: { return DataTypes.Double; } - case PropertyIds.HighIR: { return DataTypes.Double; } - case PropertyIds.LowIR: { return DataTypes.Double; } - case PropertyIds.CloseLabel: { return DataTypes.String; } - case PropertyIds.OpenLabel: { return DataTypes.String; } - case PropertyIds.TimeZone: { return DataTypes.Int32; } - case PropertyIds.ConditionStatus: { return DataTypes.String; } - case PropertyIds.AlarmQuickHelp: { return DataTypes.String; } - case PropertyIds.AlarmAreaList: { return DataTypes.String; } - case PropertyIds.PrimaryAlarmArea: { return DataTypes.String; } - case PropertyIds.ConditionLogic: { return DataTypes.String; } - case PropertyIds.LimitExceeded: { return DataTypes.String; } - case PropertyIds.Deadband: { return DataTypes.Double; } - case PropertyIds.HiHiLimit: { return DataTypes.Double; } - case PropertyIds.HiLimit: { return DataTypes.Double; } - case PropertyIds.LoLimit: { return DataTypes.Double; } - case PropertyIds.LoLoLimit: { return DataTypes.Double; } - case PropertyIds.RateChangeLimit: { return DataTypes.Double; } - case PropertyIds.DeviationLimit: { return DataTypes.Double; } - case PropertyIds.SoundFile: { return DataTypes.String; } - case PropertyIds.TypeSystemId: { return DataTypes.String; } - case PropertyIds.DictionaryId: { return DataTypes.String; } - case PropertyIds.TypeId: { return DataTypes.String; } - case PropertyIds.Dictionary: { return DataTypes.String; } - case PropertyIds.TypeDescription: { return DataTypes.String; } - case PropertyIds.ConsistencyWindow: { return DataTypes.String; } - case PropertyIds.WriteBehavior: { return DataTypes.String; } - case PropertyIds.UnconvertedItemId: { return DataTypes.String; } - case PropertyIds.UnfilteredItemId: { return DataTypes.String; } - case PropertyIds.DataFilterValue: { return DataTypes.String; } - case PropertyIds.UaBuiltInType: { return DataTypes.Int32; } - case PropertyIds.UaDataTypeId: { return DataTypes.String; } - case PropertyIds.UaValueRank: { return DataTypes.Int32; } - case PropertyIds.UaBrowseName: { return DataTypes.String; } - case PropertyIds.UaDescription: { return DataTypes.String; } - } - - return DataTypes.BaseDataType; - } - - /// - /// Returns the VARTYPE for the specified property. - /// - public static VarEnum GetVarType(int propertyId) - { - switch (propertyId) - { - case PropertyIds.DataType: { return VarEnum.VT_I2; } - case PropertyIds.Value: { return VarEnum.VT_VARIANT; } - case PropertyIds.Quality: { return VarEnum.VT_I2; } - case PropertyIds.Timestamp: { return VarEnum.VT_DATE; } - case PropertyIds.AccessRights: { return VarEnum.VT_I4; } - case PropertyIds.ScanRate: { return VarEnum.VT_R4; } - case PropertyIds.EuType: { return VarEnum.VT_I4; } - case PropertyIds.EuInfo: { return VarEnum.VT_BSTR | VarEnum.VT_ARRAY; } - case PropertyIds.EngineeringUnits: { return VarEnum.VT_BSTR; } - case PropertyIds.Description: { return VarEnum.VT_BSTR; } - case PropertyIds.HighEU: { return VarEnum.VT_R8; } - case PropertyIds.LowEU: { return VarEnum.VT_R8; } - case PropertyIds.HighIR: { return VarEnum.VT_R8; } - case PropertyIds.LowIR: { return VarEnum.VT_R8; } - case PropertyIds.CloseLabel: { return VarEnum.VT_BSTR; } - case PropertyIds.OpenLabel: { return VarEnum.VT_BSTR; } - case PropertyIds.TimeZone: { return VarEnum.VT_I4; } - case PropertyIds.ConditionStatus: { return VarEnum.VT_BSTR; } - case PropertyIds.AlarmQuickHelp: { return VarEnum.VT_BSTR; } - case PropertyIds.AlarmAreaList: { return VarEnum.VT_BSTR; } - case PropertyIds.PrimaryAlarmArea: { return VarEnum.VT_BSTR; } - case PropertyIds.ConditionLogic: { return VarEnum.VT_BSTR; } - case PropertyIds.LimitExceeded: { return VarEnum.VT_BSTR; } - case PropertyIds.Deadband: { return VarEnum.VT_R8; } - case PropertyIds.HiHiLimit: { return VarEnum.VT_R8; } - case PropertyIds.HiLimit: { return VarEnum.VT_R8; } - case PropertyIds.LoLimit: { return VarEnum.VT_R8; } - case PropertyIds.LoLoLimit: { return VarEnum.VT_R8; } - case PropertyIds.RateChangeLimit: { return VarEnum.VT_R8; } - case PropertyIds.DeviationLimit: { return VarEnum.VT_R8; } - case PropertyIds.SoundFile: { return VarEnum.VT_BSTR; } - case PropertyIds.TypeSystemId: { return VarEnum.VT_BSTR; } - case PropertyIds.DictionaryId: { return VarEnum.VT_BSTR; } - case PropertyIds.TypeId: { return VarEnum.VT_BSTR; } - case PropertyIds.Dictionary: { return VarEnum.VT_BSTR; } - case PropertyIds.TypeDescription: { return VarEnum.VT_BSTR; } - case PropertyIds.ConsistencyWindow: { return VarEnum.VT_BSTR; } - case PropertyIds.WriteBehavior: { return VarEnum.VT_BSTR; } - case PropertyIds.UnconvertedItemId: { return VarEnum.VT_BSTR; } - case PropertyIds.UnfilteredItemId: { return VarEnum.VT_BSTR; } - case PropertyIds.DataFilterValue: { return VarEnum.VT_BSTR; } - case PropertyIds.UaBuiltInType: { return VarEnum.VT_I4; } - case PropertyIds.UaDataTypeId: { return VarEnum.VT_BSTR; } - case PropertyIds.UaValueRank: { return VarEnum.VT_I4; } - case PropertyIds.UaBrowseName: { return VarEnum.VT_BSTR; } - case PropertyIds.UaDescription: { return VarEnum.VT_BSTR; } - } - - return VarEnum.VT_EMPTY; - } - - /// - /// Returns the UA array size for the specified property. - /// - public static int GetValueRank(int propertyId) - { - switch (propertyId) - { - case PropertyIds.EuInfo: - case PropertyIds.AlarmAreaList: - { - return ValueRanks.OneDimension; - } - } - - return -1; - } - - /// - /// Returns the UA browse name for the specified property. - /// - public static string GetBrowseName(int propertyId) - { - // check for non-standard properties. - if (propertyId < 0 || propertyId > PropertyIds.VendorDefined) - { - return null; - } - - // use reflection to find the browse name. - FieldInfo[] fields = typeof(PropertyIds).GetFields(BindingFlags.Static | BindingFlags.Public); - - for (int ii = 0; ii < fields.Length; ii++) - { - if ((int)fields[ii].GetValue(typeof(PropertyIds)) == propertyId) - { - return fields[ii].Name; - } - } - - // property not found. - return null; - } - - /// - /// Returns the UA description for the specified property. - /// - public static string GetDescription(int propertyId) - { - switch (propertyId) - { - case PropertyIds.DataType: { return "Item Canonical DataType"; } - case PropertyIds.Value: { return "Item Value"; } - case PropertyIds.Quality: { return "Item Quality"; } - case PropertyIds.Timestamp: { return "Item Timestamp"; } - case PropertyIds.AccessRights: { return "Item Access Rights"; } - case PropertyIds.ScanRate: { return "Server Scan Rate"; } - case PropertyIds.EuType: { return "Item EU Type"; } - case PropertyIds.EuInfo: { return "Item EU Info"; } - case PropertyIds.EngineeringUnits: { return "EU Units"; } - case PropertyIds.Description: { return "Item Description"; } - case PropertyIds.HighEU: { return "High EU"; } - case PropertyIds.LowEU: { return "Low EU"; } - case PropertyIds.HighIR: { return "High Instrument Range"; } - case PropertyIds.LowIR: { return "Low Instrument Range"; } - case PropertyIds.CloseLabel: { return "Contact Close Label"; } - case PropertyIds.OpenLabel: { return "Contact Open Label"; } - case PropertyIds.TimeZone: { return "Timezone"; } - case PropertyIds.ConditionStatus: { return "Condition ErrorId"; } - case PropertyIds.AlarmQuickHelp: { return "Alarm Quick Help"; } - case PropertyIds.AlarmAreaList: { return "Alarm Area List"; } - case PropertyIds.PrimaryAlarmArea: { return "Primary Alarm Area"; } - case PropertyIds.ConditionLogic: { return "Condition Logic"; } - case PropertyIds.LimitExceeded: { return "Limit Exceeded"; } - case PropertyIds.Deadband: { return "Deadband"; } - case PropertyIds.HiHiLimit: { return "HiHi Limit"; } - case PropertyIds.HiLimit: { return "Hi Limit"; } - case PropertyIds.LoLimit: { return "Lo Limit"; } - case PropertyIds.LoLoLimit: { return "LoLo Limit"; } - case PropertyIds.RateChangeLimit: { return "Rate of Change Limit"; } - case PropertyIds.DeviationLimit: { return "Deviation Limit"; } - case PropertyIds.SoundFile: { return "Sound File"; } - case PropertyIds.TypeSystemId: { return "Type System Id"; } - case PropertyIds.DictionaryId: { return "Dictionary Id"; } - case PropertyIds.TypeId: { return "Type Id"; } - case PropertyIds.Dictionary: { return "Dictionary"; } - case PropertyIds.TypeDescription: { return "Type Description"; } - case PropertyIds.ConsistencyWindow: { return "Consistency Window"; } - case PropertyIds.WriteBehavior: { return "Write Behavior"; } - case PropertyIds.UnconvertedItemId: { return "Unconverted Item Id"; } - case PropertyIds.UnfilteredItemId: { return "Unfiltered Item Id"; } - case PropertyIds.DataFilterValue: { return "Data Filter Value"; } - case PropertyIds.UaBuiltInType: { return "UA BuiltIn Type"; } - case PropertyIds.UaDataTypeId: { return "UA Data Type Id"; } - case PropertyIds.UaValueRank: { return "UA Value Rank"; } - case PropertyIds.UaBrowseName: { return "UA Browse Name"; } - case PropertyIds.UaDescription: { return "UA Description"; } - } - - return null; - } - } - #endregion -} diff --git a/ComIOP/Common/Common/ResultIds.cs b/ComIOP/Common/Common/ResultIds.cs deleted file mode 100644 index 13cc4ac07..000000000 --- a/ComIOP/Common/Common/ResultIds.cs +++ /dev/null @@ -1,231 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections; -using System.Configuration; -using System.IO; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Xml; -using System.Xml.Serialization; -using System.Net; -using System.Net.Sockets; -using System.Globalization; -using System.Runtime.InteropServices; -using System.Security.Principal; - -namespace Opc.Ua.Com -{ - /// - /// Defines all well known COM DA HRESULT codes. - /// - public static class ResultIds - { - // Defines all well known COM DA HRESULT codes. - - /// - public const int S_OK = +0x00000000; // 0x00000000 - /// - public const int S_FALSE = +0x00000001; // 0x00000001 - /// - public const int E_NOTIMPL = -0x7FFFBFFF; // 0x80004001 - /// - public const int E_OUTOFMEMORY = -0x7FF8FFF2; // 0x8007000E - /// - public const int E_INVALIDARG = -0x7FF8FFA9; // 0x80070057 - /// - public const int E_NOINTERFACE = -0x7FFFBFFE; // 0x80004002 - /// - public const int E_POINTER = -0x7FFFBFFD; // 0x80004003 - /// - public const int E_FAIL = -0x7FFFBFFB; // 0x80004005 - /// - public const int E_ACCESSDENIED = -0x7FF8FFFB; // 0x80070005 - - /// - public const int CONNECT_E_NOCONNECTION = -0x7FFBFE00; // 0x80040200 - /// - public const int CONNECT_E_ADVISELIMIT = -0x7FFBFDFF; // 0x80040201 - /// - public const int DISP_E_TYPEMISMATCH = -0x7FFDFFFB; // 0x80020005 - /// - public const int DISP_E_OVERFLOW = -0x7FFDFFF6; // 0x8002000A - /// - public const int E_INVALIDHANDLE = -0x3FFBFFFF; // 0xC0040001 - /// - public const int E_BADTYPE = -0x3FFBFFFC; // 0xC0040004 - /// - public const int E_PUBLIC = -0x3FFBFFFB; // 0xC0040005 - /// - public const int E_BADRIGHTS = -0x3FFBFFFA; // 0xC0040006 - /// - public const int E_UNKNOWNITEMID = -0x3FFBFFF9; // 0xC0040007 - /// - public const int E_INVALIDITEMID = -0x3FFBFFF8; // 0xC0040008 - /// - public const int E_INVALIDFILTER = -0x3FFBFFF7; // 0xC0040009 - /// - public const int E_UNKNOWNPATH = -0x3FFBFFF6; // 0xC004000A - /// - public const int E_RANGE = -0x3FFBFFF5; // 0xC004000B - /// - public const int E_DUPLICATENAME = -0x3FFBFFF4; // 0xC004000C - /// - public const int S_UNSUPPORTEDRATE = +0x0004000D; // 0x0004000D - /// - public const int S_CLAMP = +0x0004000E; // 0x0004000E - /// - public const int S_INUSE = +0x0004000F; // 0x0004000F - /// - public const int E_INVALIDCONFIGFILE = -0x3FFBFFF0; // 0xC0040010 - /// - public const int E_NOTFOUND = -0x3FFBFFEF; // 0xC0040011 - /// - public const int E_INVALID_PID = -0x3FFBFDFD; // 0xC0040203 - /// - public const int E_DEADBANDNOTSET = -0x3FFBFC00; // 0xC0040400 - /// - public const int E_DEADBANDNOTSUPPORTED = -0x3FFBFBFF; // 0xC0040401 - /// - public const int E_NOBUFFERING = -0x3FFBFBFE; // 0xC0040402 - /// - public const int E_INVALIDCONTINUATIONPOINT = -0x3FFBFBFD; // 0xC0040403 - /// - public const int S_DATAQUEUEOVERFLOW = +0x00040404; // 0x00040404 - /// - public const int E_RATENOTSET = -0x3FFBFBFB; // 0xC0040405 - /// - public const int E_NOTSUPPORTED = -0x3FFBFBFA; // 0xC0040406 - - // Defines all well known Complex Data HRESULT codes. - - /// - public const int E_TYPE_CHANGED = -0x3FFBFBF9; // 0xC0040407 - /// - public const int E_FILTER_DUPLICATE = -0x3FFBFBF8; // 0xC0040408 - /// - public const int E_FILTER_INVALID = -0x3FFBFBF7; // 0xC0040409 - /// - public const int E_FILTER_ERROR = -0x3FFBFBF6; // 0xC004040A - /// - public const int S_FILTER_NO_DATA = +0x0004040B; // 0xC004040B - - // Defines all well known COM HDA HRESULT codes. - - /// - public const int E_MAXEXCEEDED = -0X3FFBEFFF; // 0xC0041001 - /// - public const int S_NODATA = +0x40041002; // 0x40041002 - /// - public const int S_MOREDATA = +0x40041003; // 0x40041003 - /// - public const int E_INVALIDAGGREGATE = -0X3FFBEFFC; // 0xC0041004 - /// - public const int S_CURRENTVALUE = +0x40041005; // 0x40041005 - /// - public const int S_EXTRADATA = +0x40041006; // 0x40041006 - /// - public const int W_NOFILTER = -0x7FFBEFF9; // 0x80041007 - /// - public const int E_UNKNOWNATTRID = -0x3FFBEFF8; // 0xC0041008 - /// - public const int E_NOT_AVAIL = -0x3FFBEFF7; // 0xC0041009 - /// - public const int E_INVALIDDATATYPE = -0x3FFBEFF6; // 0xC004100A - /// - public const int E_DATAEXISTS = -0x3FFBEFF5; // 0xC004100B - /// - public const int E_INVALIDATTRID = -0x3FFBEFF4; // 0xC004100C - /// - public const int E_NODATAEXISTS = -0x3FFBEFF3; // 0xC004100D - /// - public const int S_INSERTED = +0x4004100E; // 0x4004100E - /// - public const int S_REPLACED = +0x4004100F; // 0x4004100F - - // Defines all well known COM AE HRESULT codes. - - /// - public const int S_ALREADYACKED = +0x00040200; // 0x00040200 - /// - public const int S_INVALIDBUFFERTIME = +0x00040201; // 0x00040201 - /// - public const int S_INVALIDMAXSIZE = +0x00040202; // 0x00040202 - /// - public const int S_INVALIDKEEPALIVETIME = +0x00040203; // 0x00040203 - /// - public const int E_INVALIDBRANCHNAME = -0x3FFBFDFD; // 0xC0040203 - /// - public const int E_INVALIDTIME = -0x3FFBFDFC; // 0xC0040204 - /// - public const int E_BUSY = -0x3FFBFDFB; // 0xC0040205 - /// - public const int E_NOINFO = -0x3FFBFDFA; // 0xC0040206 - - #region Static Helper Functions - /// - /// Returns the name of the error code. - /// - public static string GetBrowseName(int identifier) - { - FieldInfo[] fields = typeof(ResultIds).GetFields(BindingFlags.Public | BindingFlags.Static); - - foreach (FieldInfo field in fields) - { - if (identifier == (int)field.GetValue(typeof(ResultIds))) - { - return field.Name; - } - } - - return System.String.Empty; - } - - /// - /// Returns the numeric value for the error code. - /// - public static uint GetIdentifier(string browseName) - { - FieldInfo[] fields = typeof(ResultIds).GetFields(BindingFlags.Public | BindingFlags.Static); - - foreach (FieldInfo field in fields) - { - if (field.Name == browseName) - { - return (uint)field.GetValue(typeof(ResultIds)); - } - } - - return 0; - } - #endregion - } -} diff --git a/ComIOP/Common/Common/ServerFactory.cs b/ComIOP/Common/Common/ServerFactory.cs deleted file mode 100644 index 8c167a805..000000000 --- a/ComIOP/Common/Common/ServerFactory.cs +++ /dev/null @@ -1,721 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Security.Principal; -using System.Threading; - -using OpcRcw.Comn; - -namespace Opc.Ua.Com -{ - /// - /// A unique identifier for the result of an operation of an item. - /// - public class ServerFactory : IDisposable - { - #region Constructors - /// - /// Initializes an empty instance. - /// - public ServerFactory() - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - m_server = null; - m_host = null; - } - #endregion - - #region IDisposable Members - /// - /// The finializer implementation. - /// - ~ServerFactory() - { - Dispose(false); - } - - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (m_server != null) - { - ComUtils.ReleaseServer(m_server); - m_server = null; - } - } - #endregion - - #region Public Methods - /// - /// Connects to OPCEnum on the local machine. - /// - public void Connect() - { - Connect(null, null); - } - - /// - /// Connects to OPCEnum on the specified machine. - /// - public void Connect(string host, UserIdentity identity) - { - // disconnect from current server. - Disconnect(); - - // create in the instance. - object unknown = null; - - try - { - unknown = ComUtils.CreateInstance(OPCEnumCLSID, host, identity); - } - catch (Exception e) - { - throw ServiceResultException.Create(StatusCodes.BadCommunicationError, e, "Could not connect to OPCEnum server."); - } - - m_server = unknown as IOPCServerList2; - - if (m_server == null) - { - ComUtils.ReleaseServer(unknown); - - StringBuilder error = new StringBuilder(); - - error.Append("Server does not support IOPCServerList2. "); - error.Append("The OPC proxy/stubs may not be installed properly or the client or server machine. "); - error.Append("The also could be a problem with DCOM security configuration."); - - throw ServiceResultException.Create(StatusCodes.BadCommunicationError, error.ToString()); - } - - m_host = host; - - if (String.IsNullOrEmpty(m_host)) - { - m_host = "localhost"; - } - } - - /// - /// Releases the active server. - /// - public void Disconnect() - { - try - { - if (m_server != null) - { - ComUtils.ReleaseServer(m_server); - m_server = null; - } - } - catch (Exception e) - { - throw ServiceResultException.Create(StatusCodes.BadCommunicationError, e, "Could not release OPCEnum server."); - } - } - - /// - /// Enumerates hosts that may be accessed for server discovery. - /// - public string[] EnumerateHosts() - { - return ComUtils.EnumComputers(); - } - - /// - /// Parses the URL and fetches the information about the server. - /// - /// The URI. - /// The server description. - public ComServerDescription ParseUrl(Uri uri) - { - // 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)) - { - // 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."); - } - } - - ComServerDescription server = new ComServerDescription(); - - server.Url = uri.ToString(); - server.Clsid = guid; - server.ProgId = progID; - server.VersionIndependentProgId = server.ProgId; - server.Description = progID; - - try - { - // fetch class details from the enumerator. - string description = null; - string verIndProgID = null; - - m_server.GetClassDetails( - ref guid, - out progID, - out description, - out verIndProgID); - - // use version independent prog id if available. - if (!String.IsNullOrEmpty(verIndProgID)) - { - progID = verIndProgID; - } - - server.Url = uri.ToString(); - server.Clsid = guid; - server.ProgId = progID; - server.VersionIndependentProgId = verIndProgID; - server.Description = description; - } - catch - { - server.Url = uri.ToString(); - server.Clsid = guid; - server.ProgId = progID; - server.VersionIndependentProgId = server.ProgId; - server.Description = guid.ToString(); - } - - // return the server uri. - return server; - } - - /// - /// Returns a list of servers that support the specified specification. - /// - public Uri[] GetAvailableServers(params Specification[] specifications) - { - // enumerate servers on specified machine. - try - { - // convert the interface version to a guid. - Guid[] catids = new Guid[specifications.Length]; - - for (int ii = 0; ii < catids.Length; ii++) - { - catids[ii] = new Guid(specifications[ii].Id); - } - - // get list of servers in the specified specification. - IOPCEnumGUID enumerator = null; - - m_server.EnumClassesOfCategories( - catids.Length, - catids, - 0, - null, - out enumerator); - - // read clsids. - List clsids = ReadClasses(enumerator); - - // release enumerator object. - ComUtils.ReleaseServer(enumerator); - enumerator = null; - - // fetch class descriptions. - Uri[] uris = new Uri[clsids.Count]; - - for (int ii = 0; ii < uris.Length; ii++) - { - uris[ii] = CreateUri(clsids[ii]); - } - - return uris; - } - catch (Exception e) - { - throw ServiceResultException.Create(StatusCodes.BadCommunicationError, e, "Could not enumerate COM servers."); - } - } - - /// - /// Looks up the CLSID for the specified prog id on a remote host. - /// - public Guid CLSIDFromProgID(string progID) - { - // lookup prog id. - Guid clsid; - - try - { - m_server.CLSIDFromProgID(progID, out clsid); - } - catch - { - clsid = Guid.Empty; - } - - // return empty guid if prog id not found. - return clsid; - } - - /// - /// Connects to the specified COM server server. - /// - 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 - } - #endregion - - #region Private Methods - /// - /// Reads the guids from the enumerator. - /// - private List ReadClasses(IOPCEnumGUID enumerator) - { - List guids = new List(); - - int fetched = 0; - Guid[] buffer = new Guid[10]; - - do - { - try - { - IntPtr pGuids = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Guid))*buffer.Length); - - try - { - enumerator.Next(buffer.Length, pGuids, out fetched); - - if (fetched > 0) - { - IntPtr pos = pGuids; - - for (int ii = 0; ii < fetched; ii++) - { - buffer[ii] = (Guid)Marshal.PtrToStructure(pos, typeof(Guid)); - pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(Guid))); - guids.Add(buffer[ii]); - } - } - } - finally - { - Marshal.FreeCoTaskMem(pGuids); - } - } - catch - { - break; - } - } - while (fetched > 0); - - return guids; - } - - /// - /// Reads the server details from the enumerator. - /// - private Uri CreateUri(Guid clsid) - { - // initialize the server uri. - StringBuilder uri = new StringBuilder(); - - // append scheme and host. - uri.Append("opc.com://"); - uri.Append(m_host); - - string progID = null; - - try - { - // fetch class details from the enumerator. - string description = null; - string verIndProgID = null; - - m_server.GetClassDetails( - ref clsid, - out progID, - out description, - out verIndProgID); - - // use version independent prog id if available. - if (!String.IsNullOrEmpty(verIndProgID)) - { - progID = verIndProgID; - } - } - catch - { - // cannot get prog id. - progID = null; - } - - // append prog id. - if (!String.IsNullOrEmpty(progID)) - { - uri.AppendFormat("/{0}", progID); - } - - // append prog id. - uri.AppendFormat("/{0}", clsid); - - // return the server uri. - return new Uri(uri.ToString()); - } - #endregion - - #region Private Members - private IOPCServerList2 m_server = null; - private string m_host = null; - #endregion - - #region Private Constants - private static readonly Guid OPCEnumCLSID = new Guid("13486D51-4821-11D2-A494-3CB306C10000"); - #endregion - } - - /// - /// The user identity to use when connecting to the COM server. - /// - public class UserIdentity - { - #region Constructors - /// - /// Sets the username and password (extracts the domain from the username if a '\' is present). - /// - public UserIdentity(string username, string password) - { - m_username = username; - m_password = password; - - if (!String.IsNullOrEmpty(m_username)) - { - int index = m_username.IndexOf('\\'); - - if (index != -1) - { - m_domain = m_username.Substring(0, index); - m_username = m_username.Substring(index+1); - } - } - } - #endregion - - #region Static Methods - /// - /// Whether the identity represents an the default identity. - /// - public static bool IsDefault(UserIdentity identity) - { - if (identity != null) - { - return String.IsNullOrEmpty(identity.m_username); - } - - return true; - } - #endregion - - #region Public Properties - /// - /// The windows domain name. - /// - public string Domain - { - get { return m_domain; } - } - - /// - /// The user name. - /// - public string Username - { - get { return m_username; } - } - - /// - /// The password. - /// - public string Password - { - get { return m_password; } - } - - /// - /// Gets or sets a license key to use when activating the server. - /// - public string LicenseKey - { - get { return m_licenseKey; } - set { m_licenseKey = value; } - } - #endregion - - #region Comparison Operators - /// - /// Determines if the object is equal to the specified value. - /// - public override bool Equals(object target) - { - object identity = target as UserIdentity; - - if (identity == null) - { - return false; - } - - return false; - } - - /// - /// Converts the object to a string used for display. - /// - public override string ToString() - { - if (!String.IsNullOrEmpty(m_domain)) - { - return Utils.Format("{0}\\{1}", m_domain, m_username); - } - - return m_username; - } - - /// - /// Returns a suitable hash code for the result. - /// - public override int GetHashCode() - { - if (!String.IsNullOrEmpty(m_username)) - { - return m_username.GetHashCode(); - } - - return 0; - } - - /// - /// Returns true if the objects are equal. - /// - public static bool operator==(UserIdentity a, UserIdentity b) - { - if (Object.ReferenceEquals(a, null)) - { - return Object.ReferenceEquals(b, null); - } - - return a.Equals(b); - } - - /// - /// Returns true if the objects are not equal. - /// - public static bool operator!=(UserIdentity a, UserIdentity b) - { - if (Object.ReferenceEquals(a, null)) - { - return !Object.ReferenceEquals(b, null); - } - - return !a.Equals(b); - } - #endregion - - #region Private Members - private string m_domain; - private string m_username; - private string m_password; - private string m_licenseKey; - #endregion - } - - /// - /// Stores the description of a COM server. - /// - public class ComServerDescription - { - /// - /// The URL for the server. - /// - public string Url; - - /// - /// The programmatic identifier for the server. - /// - public string ProgId; - - /// - /// The version independent programmatic identifier for the server. - /// - public string VersionIndependentProgId; - - /// - /// The description for thr server. - /// - public string Description; - - /// - /// The CLSID for thr server. - /// - public Guid Clsid; - } -} diff --git a/ComIOP/Common/Common/Specification.cs b/ComIOP/Common/Common/Specification.cs deleted file mode 100644 index 32be9333d..000000000 --- a/ComIOP/Common/Common/Specification.cs +++ /dev/null @@ -1,145 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; - -namespace Opc.Ua.Com -{ - /// - /// A description of an interface version defined by an OPC specification. - /// - public struct Specification - { - #region Constructors - /// - /// Initializes the object with the description and a GUId as a string. - /// - public Specification(string id, string description) - { - m_id = id; - m_description = description; - } - #endregion - - #region Public Properties - /// - /// The unique Identifier for the interface version. - /// - public string Id - { - get { return m_id; } - internal set { m_id = value; } - } - - /// - /// The human readable description for the interface version. - /// - public string Description - { - get { return m_description; } - internal set { m_description = value; } - } - #endregion - - #region Comparison Operators - /// - /// Determines if the object is equal to the specified value. - /// - public override bool Equals(object target) - { - if (target != null && target.GetType() == typeof(Specification)) - { - return (Id == ((Specification)target).Id); - } - - return false; - } - - /// - /// Converts the object to a string used for display. - /// - public override string ToString() - { - return Description; - } - - /// - /// Returns a suitable hash code for the result. - /// - public override int GetHashCode() - { - return (Id != null)?Id.GetHashCode():base.GetHashCode(); - } - - /// - /// Returns true if the objects are equal. - /// - public static bool operator==(Specification a, Specification b) - { - return a.Equals(b); - } - - /// - /// Returns true if the objects are not equal. - /// - public static bool operator!=(Specification a, Specification b) - { - return !a.Equals(b); - } - #endregion - - #region Private Members - private string m_id; - private string m_description; - #endregion - - #region Specification Constants - /// - /// A set of Specification objects for existing OPC specifications. - /// - public static readonly Specification Ae10 = new Specification("58E13251-AC87-11d1-84D5-00608CB8A7E9", "Alarms and Event 1.XX"); - /// - public static readonly Specification Batch10 = new Specification("A8080DA0-E23E-11D2-AFA7-00C04F539421", "Batch 1.00"); - /// - public static readonly Specification Batch20 = new Specification("843DE67B-B0C9-11d4-A0B7-000102A980B1", "Batch 2.00"); - /// - public static readonly Specification Da10 = new Specification("63D5F430-CFE4-11d1-B2C8-0060083BA1FB", "Data Access 1.0a"); - /// - public static readonly Specification Da20 = new Specification("63D5F432-CFE4-11d1-B2C8-0060083BA1FB", "Data Access 2.XX"); - /// - public static readonly Specification Da30 = new Specification("CC603642-66D7-48f1-B69A-B625E73652D7", "Data Access 3.00"); - /// - public static readonly Specification Dx10 = new Specification("A0C85BB8-4161-4fd6-8655-BB584601C9E0", "Data eXchange 1.00"); - /// - public static readonly Specification Hda10 = new Specification("7DE5B060-E089-11d2-A5E6-000086339399", "Historical Data Access 1.XX"); - /// - public static readonly Specification XmlDa10 = new Specification("3098EDA4-A006-48b2-A27F-247453959408", "XML Data Access 1.00"); - #endregion - } -} diff --git a/ComIOP/Common/Common/UserNameCreator.cs b/ComIOP/Common/Common/UserNameCreator.cs deleted file mode 100644 index a7ce361e1..000000000 --- a/ComIOP/Common/Common/UserNameCreator.cs +++ /dev/null @@ -1,297 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography; - - -namespace Opc.Ua.Configuration -{ - /// - /// Creates UserName. - /// - public class UserNameCreator - { - /// - /// Triple DES Key - /// - private const string strKey = "h13h6m9F"; - - /// - /// Triple DES initialization vector - /// - private const string strIV = "Zse5"; - - #region Constructors - /// - /// The default constructor. - /// - public UserNameCreator(string applicationName) - { - m_UserNameIdentityTokens = LoadUserName(applicationName); - } - #endregion - - #region Public Methods - - /// - /// Add a User. - /// - /// The Application Name. - /// The UserName. - /// The Password. - public void Add(string applicationName, string userName, string password) - { - lock (m_lock) - { - UserNameIdentityToken newUserNameToken = new UserNameIdentityToken() - { - UserName = userName, - DecryptedPassword = password, - }; - - newUserNameToken.Password = new UTF8Encoding().GetBytes(newUserNameToken.DecryptedPassword); - - m_UserNameIdentityTokens.Add(newUserNameToken.UserName, newUserNameToken); - - SaveUserName(applicationName, newUserNameToken); - } - } - - /// - /// Delete a User. - /// - /// The Application Name. - /// The UserName. - /// True if the item deleted from list. - public bool Delete(string applicationName, string userName) - { - lock (m_lock) - { - string relativePath = Utils.Format("%CommonApplicationData%\\OPC Foundation\\Accounts\\{0}\\{1}.xml", applicationName, userName); - string absolutePath = Utils.GetAbsoluteFilePath(relativePath, false, false, true); - - // oops - nothing found. - if (absolutePath == null) - { - absolutePath = Utils.GetAbsoluteFilePath(relativePath, true, false, true); - } - - if (File.Exists(absolutePath)) - { // delete a file. - File.Delete(absolutePath); - } - - return m_UserNameIdentityTokens.Remove(userName); - } - } - - /// - /// Load UserNameIdentityToken. - /// - /// UserNameIdentityToken list. - public static Dictionary LoadUserName(string applicationName) - { - Dictionary resultTokens = new Dictionary(); - - try - { - string relativePath = Utils.Format("%CommonApplicationData%\\OPC Foundation\\Accounts\\{0}", applicationName); - string absolutePath = Utils.GetAbsoluteDirectoryPath(relativePath, false, false, false); - - if (string.IsNullOrEmpty(absolutePath)) - { - return resultTokens; - } - - foreach (string filePath in Directory.GetFiles(absolutePath)) - { - // oops - nothing found. - if (filePath == null) - { - continue; - } - - // open the file. - using (FileStream istrm = File.Open(filePath, FileMode.Open, FileAccess.Read)) - { - using (XmlTextReader reader = new XmlTextReader(istrm)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(UserNameIdentityToken)); - UserNameIdentityToken userNameToken = (UserNameIdentityToken)serializer.ReadObject(reader, false); - - if (userNameToken.UserName == null || userNameToken.Password == null) - { // The configuration file has problem. - Utils.Trace("Unexpected error saving user configuration for COM Wrapper."); - continue; - } - - if (resultTokens.ContainsKey(userNameToken.UserName)) - { // When I already exist, I ignore it. - Utils.Trace("When I already exist, I ignore it. UserName={0}", userNameToken.UserName); - continue; - } - - userNameToken.Password = DecryptPassword(userNameToken.Password); - userNameToken.DecryptedPassword = new UTF8Encoding().GetString(userNameToken.Password); - - resultTokens.Add(userNameToken.UserName, userNameToken); - } - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error saving user configuration for COM Wrapper."); - } - - return resultTokens; - } - - #endregion - - #region Private Methods - - /// - /// Save UserNameIdentityToken. - /// - private static void SaveUserName(string applicationName, UserNameIdentityToken userNameToken) - { - try - { - string relativePath = Utils.Format("%CommonApplicationData%\\OPC Foundation\\Accounts\\{0}\\{1}.xml", applicationName, userNameToken.UserName); - string absolutePath = Utils.GetAbsoluteFilePath(relativePath, false, false, true); - - // oops - nothing found. - if (absolutePath == null) - { - absolutePath = Utils.GetAbsoluteFilePath(relativePath, true, false, true); - } - - UserNameIdentityToken outputToken = new UserNameIdentityToken() - { - UserName = userNameToken.UserName, - Password = EncryptPassword(userNameToken.Password), - EncryptionAlgorithm = "Triple DES", - }; - - // open the file. - FileStream ostrm = File.Open(absolutePath, FileMode.Create, FileAccess.ReadWrite); - - using (XmlTextWriter writer = new XmlTextWriter(ostrm, System.Text.Encoding.UTF8)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(UserNameIdentityToken)); - serializer.WriteObject(writer, outputToken); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error saving user configuration for COM Wrapper with UserName={0}.", userNameToken.UserName); - } - } - - /// - /// Encrypt Password. - /// - /// The Source Password. - /// Encrypted Password. - private static byte[] EncryptPassword(byte[] srcPassword) - { - byte[] encryptedPassword; - TripleDESCryptoServiceProvider tdes; // Triple DES service provider - MemoryStream outStream = null; - CryptoStream encStream = null; - string dst = string.Empty; - - // Create Triple DES service provider. - tdes = new TripleDESCryptoServiceProvider(); - // Get encrypt key and initialization vector. - byte[] key = Encoding.Unicode.GetBytes(strKey); - byte[] IV = Encoding.Unicode.GetBytes(strIV); - - // Create result stream and encrypt stream. - using (outStream = new MemoryStream()) - using (encStream = new CryptoStream(outStream, tdes.CreateEncryptor(key, IV), CryptoStreamMode.Write)) - { - // Encrypt - encStream.Write(srcPassword, 0, srcPassword.Length); - encStream.Close(); - encryptedPassword = outStream.ToArray(); - } - - return encryptedPassword; - } - - /// - /// Decrypt Password. - /// - /// The Source Password. - /// Decrypted Password. - private static byte[] DecryptPassword(byte[] srcPassword) - { - byte[] decryptedPassword; - TripleDESCryptoServiceProvider tdes; // Triple DES service provider - MemoryStream outStream = null; - CryptoStream decStream = null; - string dst = string.Empty; - - // Create Triple DES service provider. - tdes = new TripleDESCryptoServiceProvider(); - // Get encrypt key and initialization vector. - byte[] key = Encoding.Unicode.GetBytes(strKey); - byte[] IV = Encoding.Unicode.GetBytes(strIV); - - // Create result stream and decrypt stream. - using (outStream = new MemoryStream()) - using (decStream = new CryptoStream(outStream, tdes.CreateDecryptor(key, IV), CryptoStreamMode.Write)) - { - // Decrypt - decStream.Write(srcPassword, 0, srcPassword.Length); - decStream.Close(); - decryptedPassword = outStream.ToArray(); - } - - return decryptedPassword; - } - - #endregion - - #region Private Fields - private object m_lock = new object(); - private Dictionary m_UserNameIdentityTokens = new Dictionary(); - #endregion - } -} diff --git a/ComIOP/Common/Config/DaWrapperConfiguration.cs b/ComIOP/Common/Config/DaWrapperConfiguration.cs deleted file mode 100644 index ca1b9d02a..000000000 --- a/ComIOP/Common/Config/DaWrapperConfiguration.cs +++ /dev/null @@ -1,494 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.ServiceModel; -using System.Runtime.Serialization; -using System.Collections.Generic; - -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Client -{ - /// - /// Stores the configuration for the DA wrapper. - /// - [KnownType(typeof(Da.DaWrapperConfiguration))] - [KnownType(typeof(Ae.AeWrapperConfiguration))] - [KnownType(typeof(Hda.HdaWrapperConfiguration))] - [DataContract(Namespace=Opc.Ua.Namespaces.OpcUaSdk + "COM/Configuration.xsd")] - public class WrapperConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public WrapperConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - m_namespaceUri = null; - m_browseName = m_DefaultBrowseName; - m_url = null; - m_minMetadataLifetime = m_DefaultMinMetadataLifetime; - m_seperatorChars = m_DefaultSeperatorChars; - m_maxQueueSize = m_DefaultMaxQueueSize; - m_minReconnectWait = m_DefaultMinReconnectWait; - m_maxReconnectWait = m_DefaultMaxReconnectWait; - m_maxReconnectAttempts = m_DefaultMaxReconnectAttempts; - m_defaultSamplingRates = new List(); - } - #endregion - - #region Public Properties - /// - /// The URI that qualifies all nodes within the server address space. - /// - [DataMember(Order = 1)] - public string NamespaceUri - { - get { return m_namespaceUri; } - set { m_namespaceUri = value; } - } - - /// - /// The browse name for the node that represents the root of the server address space. - /// - [DataMember(Order = 2)] - public string BrowseName - { - get { return m_browseName; } - set { m_browseName = value; } - } - - /// - /// The URL that identifies the COM server to connect to. - /// - [DataMember(Order = 3)] - public string Url - { - get { return m_url; } - set { m_url = value; } - } - - /// - /// The minimum sampling rate for metadata (browse names and properties). - /// - [DataMember(Order = 4)] - public int MinMetadataLifetime - { - get { return m_minMetadataLifetime; } - set { m_minMetadataLifetime = value; } - } - - /// - /// The characters that can be used to extract browse names from the end of item ids. - /// - /// - /// A null or empty string indicates that it is not possible to parse item ids for the server. - /// - [DataMember(Order = 6)] - public string SeperatorChars - { - get { return m_seperatorChars; } - set { m_seperatorChars = value; } - } - - /// - /// The maximum number of messages that can be saved in the publish queue. - /// - [DataMember(Order = 7)] - public uint MaxQueueSize - { - get { return m_maxQueueSize; } - set { m_maxQueueSize = value; } - } - - /// - /// The maximum number of messages that can be saved in the publish queue. - /// - [DataMember(Order = 8)] - public int MinReconnectWait - { - get { return m_minReconnectWait; } - set { m_minReconnectWait = value; } - } - - /// - /// The maximum number of messages that can be saved in the publish queue. - /// - [DataMember(Order = 9)] - public int MaxReconnectWait - { - get { return m_maxReconnectWait; } - set { m_maxReconnectWait = value; } - } - - /// - /// The maximum number of messages that can be saved in the publish queue. - /// - [DataMember(Order = 10)] - public int MaxReconnectAttempts - { - get { return m_maxReconnectAttempts; } - set { m_maxReconnectAttempts = value; } - } - - /// - /// The default set of sampling rates which the server uses. - /// - [DataMember(Order = 11)] - public List DefaultSamplingRates - { - get - { - return m_defaultSamplingRates; - } - - set - { - if (value != null) - { - m_defaultSamplingRates = value; - } - else - { - m_defaultSamplingRates.Clear(); - } - } - } - #endregion - - #region Private Members - private string m_namespaceUri; - private string m_browseName; - private string m_url; - private int m_minMetadataLifetime; - private string m_seperatorChars; - private uint m_maxQueueSize; - private int m_minReconnectWait; - private int m_maxReconnectWait; - private int m_maxReconnectAttempts; - private List m_defaultSamplingRates; - - private const string m_DefaultBrowseName = "DA"; - private const int m_DefaultMinMetadataLifetime = 10000; - private const int m_DefaultMaxQueueSize = 100; - private const int m_DefaultMinReconnectWait = 1000; - private const int m_DefaultMaxReconnectWait = 30000; - private const int m_DefaultMaxReconnectAttempts = 10; - private const string m_DefaultSeperatorChars = null; - #endregion - } - - /// - /// A collection of COM WrapperConfiguration objects. - /// - [CollectionDataContract(Name = "ListOfWrapperConfiguration", Namespace = Opc.Ua.Namespaces.OpcUaSdk + "COM/Configuration.xsd", ItemName = "WrapperConfiguration")] - public partial class WrapperConfigurationCollection : List - { - /// - /// Initializes an empty collection. - /// - public WrapperConfigurationCollection() {} - - /// - /// Initializes the collection with the specified capacity. - /// - public WrapperConfigurationCollection(int capacity) : base(capacity) {} - - /// - /// Initializes the collection from another collection. - /// - /// A collection of used to pre-populate the collection. - public WrapperConfigurationCollection(IEnumerable collection) : base(collection) {} - } -} - -namespace Opc.Ua.Com.Client.Da -{ - /// - /// Stores the configuration for the DA wrapper. - /// - [DataContract(Namespace=Opc.Ua.Namespaces.OpcUaSdk + "COM/Configuration.xsd")] - public class DaWrapperConfiguration : WrapperConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public DaWrapperConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - } - #endregion - - #region Public Properties - #endregion - - #region Private Members - #endregion - } -} - -namespace Opc.Ua.Com.Client.Ae -{ - /// - /// Stores the configuration for the DA wrapper. - /// - [DataContract(Namespace=Opc.Ua.Namespaces.OpcUaSdk + "COM/Configuration.xsd")] - public class AeWrapperConfiguration : WrapperConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public AeWrapperConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - } - #endregion - - #region Public Properties - #endregion - - #region Private Members - #endregion - } -} - -namespace Opc.Ua.Com.Client.Hda -{ - /// - /// Stores the configuration for the HDA wrapper. - /// - [DataContract(Namespace = Opc.Ua.Namespaces.OpcUaSdk + "COM/Configuration.xsd")] - public class HdaWrapperConfiguration : WrapperConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public HdaWrapperConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - //m_treatUncertainAsBad = false; - //m_percentDataBad = ; - //m_percentDataGood; - //m_steppedSlopedExtrapolation; - m_stepped = false; - //m_definition = ""; - //m_maxTimeInterval; - //m_minTimeInterval; - //m_exceptionDeviation; - //m_exceptionDeviationFormat; - } - #endregion - - #region Public Properties - /// - /// TreatUncertainAsBad. - /// - [DataMember(Order = 12)] - - public bool TreatUncertainAsBad - { - get { return m_treatUncertainAsBad; } - set { m_treatUncertainAsBad = value; } - } - - /// - /// PercentDataBad. - /// - [DataMember(Order = 13)] - public byte PercentDataBad - { - get { return m_percentDataBad; } - set { m_percentDataBad = value; } - } - - /// - /// PercentDataGood. - /// - [DataMember(Order = 14)] - public byte PercentDataGood - { - get { return m_percentDataGood; } - set { m_percentDataGood = value; } - } - - /// - /// SteppedSlopedExtrapolation. - /// - [DataMember(Order = 15)] - public bool SteppedSlopedExtrapolation - { - get { return m_steppedSlopedExtrapolation; } - set { m_steppedSlopedExtrapolation = value; } - } - - /// - /// Stepped. - /// - [DataMember(Order = 16)] - public bool Stepped - { - get { return m_stepped; } - set { m_stepped = value; } - } - - /// - /// Definition. - /// - [DataMember(Order = 17)] - public string Definition - { - get { return m_definition; } - set { m_definition = value; } - } - - /// - /// MaxTimeInterval. - /// - [DataMember(Order = 18)] - public double MaxTimeInterval - { - get { return m_maxTimeInterval; } - set { m_maxTimeInterval = value; } - } - - /// - /// MinTimeInterval - /// - [DataMember(Order = 19)] - public double MinTimeInterval - { - get { return m_minTimeInterval; } - set { m_minTimeInterval = value; } - } - - /// - /// ExceptionDeviation - /// - [DataMember(Order = 20)] - public double ExceptionDeviation - { - get { return m_exceptionDeviation; } - set { m_exceptionDeviation = value; } - } - - /// - /// ExceptionDeviationFormat - /// - [DataMember(Order = 21)] - public ExceptionDeviationFormat ExceptionDeviationFormat - { - get { return m_exceptionDeviationFormat; } - set { m_exceptionDeviationFormat = value; } - } - #endregion - - #region Private Members - //Ravil 23 Sep 2008: Valuies to initialize HistoricalConfiguration members: - private bool m_treatUncertainAsBad; - private byte m_percentDataBad; - private byte m_percentDataGood; - private bool m_steppedSlopedExtrapolation; - private bool m_stepped; - private string m_definition; - private double m_maxTimeInterval; - private double m_minTimeInterval; - private double m_exceptionDeviation; - private ExceptionDeviationFormat m_exceptionDeviationFormat; - #endregion - } -} diff --git a/ComIOP/Common/Properties/AssemblyInfo.cs b/ComIOP/Common/Properties/AssemblyInfo.cs deleted file mode 100644 index 3afe1e25e..000000000 --- a/ComIOP/Common/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Opc.Ua.ComInterop")] -[assembly: AssemblyDescription("OPC UA COM Interop Library")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("OPC Foundation")] -[assembly: AssemblyProduct("OPC UA SDK")] -[assembly: AssemblyCopyright(AssemblyVersionInfo.Copyright)] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("285777b7-6107-472e-9fda-62ad20284c4e")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion(AssemblyVersionInfo.CurrentVersion)] -[assembly: AssemblyFileVersion(AssemblyVersionInfo.CurrentFileVersion)] diff --git a/ComIOP/Common/Properties/AssemblyVersionInfo.cs b/ComIOP/Common/Properties/AssemblyVersionInfo.cs deleted file mode 100644 index 69b36368a..000000000 --- a/ComIOP/Common/Properties/AssemblyVersionInfo.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Reciprocal Community License ("RCL") Version 1.00 - * - * Unless explicitly acquired and licensed from Licensor under another - * license, the contents of this file are subject to the Reciprocal - * Community License ("RCL") Version 1.00, or subsequent versions - * as allowed by the RCL, and You may not copy or use this file in either - * source code or executable form, except in compliance with the terms and - * conditions of the RCL. - * - * All software distributed under the RCL is provided strictly on an - * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, - * AND LICENSOR HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT - * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, QUIET ENJOYMENT, OR NON-INFRINGEMENT. See the RCL for specific - * language governing rights and limitations under the RCL. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/RCL/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; - -/// -/// Defines string constants for SDK version information. -/// -internal static class AssemblyVersionInfo -{ - /// - /// The current copy right notice. - /// - public const string Copyright = "Copyright © 2004-2019 OPC Foundation, Inc"; - - /// - /// The current build version. - /// - public const string CurrentVersion = "1.04.353"; - - /// - /// The current build file version. - /// - public const string CurrentFileVersion = "1.04.353.0"; -} diff --git a/ComIOP/Common/Proxy/ComDaGroup.cs b/ComIOP/Common/Proxy/ComDaGroup.cs deleted file mode 100644 index 3a7448dbc..000000000 --- a/ComIOP/Common/Proxy/ComDaGroup.cs +++ /dev/null @@ -1,159 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com -{ - /// - /// A class that implements a COM DA group. - /// - public class ComDaGroup : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The name. - /// The server handle. - public ComDaGroup(string name, int serverHandle) - { - m_name = name; - m_serverHandle = serverHandle; - } - #endregion - - #region IDisposable Members - /// - /// The finializer implementation. - /// - ~ComDaGroup() - { - Dispose(false); - } - - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - // TBD - } - } - #endregion - - #region Public Members - /// - /// Gets or sets the handle. - /// - /// The handle. - public IntPtr Handle - { - get { return m_handle; } - set { m_handle = value; } - } - - /// - /// Gets the name of the group. - /// - /// The name. - public string Name - { - get { return m_name; } - } - - /// - /// Gets the server handle. - /// - /// The server handle. - public int ServerHandle - { - get { return m_serverHandle; } - } - - /// - /// Gets the update rate. - /// - /// The update rate. - public int UpdateRate - { - get { return m_updateRate; } - } - - /// - /// Gets the actual update rate. - /// - /// The actual update rate. - public int ActualUpdateRate - { - get { return m_actualUpdateRate; } - } - - /// - /// Creates the specified update rate. - /// - /// The update rate. - public void Create(int updateRate) - { - m_updateRate = updateRate; - m_actualUpdateRate = updateRate; - } - #endregion - - #region Private Methods - #endregion - - #region Private Fields - private object m_lock = new object(); - private IntPtr m_handle; - private int m_serverHandle; - private string m_name; - private int m_updateRate; - private int m_actualUpdateRate; - #endregion - } -} diff --git a/ComIOP/Common/Proxy/ComDaProxy.cs b/ComIOP/Common/Proxy/ComDaProxy.cs deleted file mode 100644 index ae18ac090..000000000 --- a/ComIOP/Common/Proxy/ComDaProxy.cs +++ /dev/null @@ -1,418 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; - -namespace Opc.Ua.Com -{ - /// - /// A base class for classes that implement an OPC COM specification. - /// - public class ComDaProxy : ComProxy - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComDaProxy() - { - m_groups = new List(); - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - lock (Lock) - { - for (int ii = 0; ii < m_groups.Count; ii++) - { - Utils.SilentDispose(m_groups[ii]); - } - - m_groups.Clear(); - } - } - - base.Dispose(disposing); - } - #endregion - - #region Public Methods - /// - /// Gets the group count. - /// - /// The group count. - public int GroupCount - { - get - { - lock (Lock) - { - return m_groups.Count; - } - } - } - - /// - /// Gets the last update time. - /// - /// The group count. - public DateTime LastUpdateTime - { - get - { - lock (Lock) - { - return m_lastUpdateTime; - } - } - } - - /// - /// Gets the group with the specified name. - /// - /// Name of the group. - /// The group. Null if it does not exist. - public ComDaGroup GetGroupByName(string groupName) - { - lock (Lock) - { - for (int ii = 0; ii < m_groups.Count; ii++) - { - ComDaGroup group = m_groups[ii]; - - if (group.Name == groupName) - { - return group; - } - } - - return null; - } - } - - /// - /// Gets the group by handle. - /// - /// The server handle. - /// The group. - public ComDaGroup GetGroupByHandle(int serverHandle) - { - lock (Lock) - { - for (int ii = 0; ii < m_groups.Count; ii++) - { - ComDaGroup group = m_groups[ii]; - - if (group.ServerHandle == serverHandle) - { - return group; - } - } - - return null; - } - } - - /// - /// Adds a group to the server. - /// - /// Name of the group. - /// The new group. - public ComDaGroup AddGroup(string groupName) - { - lock (Lock) - { - // assign a unique name. - if (String.IsNullOrEmpty(groupName)) - { - groupName = Guid.NewGuid().ToString(); - } - - // create the group. - ComDaGroup group = new ComDaGroup(groupName, ++m_groupCounter); - m_groups.Add(group); - return group; - } - } - - /// - /// Removes the group. - /// - /// The group. - public void RemoveGroup(ComDaGroup group) - { - lock (Lock) - { - for (int ii = 0; ii < m_groups.Count; ii++) - { - if (Object.ReferenceEquals(group, m_groups[ii])) - { - m_groups.RemoveAt(ii); - group.Dispose(); - } - } - } - } - - /// - /// Returns the current set of groups. - /// - /// The list of groups. - public ComDaGroup[] GetGroups() - { - lock (Lock) - { - ComDaGroup[] groups = new ComDaGroup[m_groups.Count]; - - for (int ii = 0; ii < m_groups.Count; ii++) - { - groups[ii] = m_groups[ii]; - } - - return groups; - } - } - - /// - /// Reads the values for the specified item ids. - /// - /// The item ids. - /// The values. - public DaValue[] Read(string[] itemIds) - { - DaValue[] values = new DaValue[itemIds.Length]; - - for (int ii = 0; ii < values.Length; ii++) - { - values[ii] = new DaValue(); - values[ii].Error = ResultIds.E_UNKNOWNITEMID; - } - - return values; - } - - /// - /// Writes the values for the specified item ids. - /// - /// The item ids. - /// The values. - /// The results. - public int[] Write(string[] itemIds, DaValue[] values) - { - int[] results = new int[itemIds.Length]; - - for (int ii = 0; ii < results.Length; ii++) - { - results[ii] = ResultIds.E_UNKNOWNITEMID; - } - - return results; - } - - /// - /// Moves the current browse position up. - /// - public void BrowseUp() - { - if (NodeId.IsNull(m_browsePosition)) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - } - - /// - /// Moves the current browse position down. - /// - public void BrowseDown(string targetName) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - /// - /// Moves the current browse position to the specified item. - /// - public void BrowseTo(string itemId) - { - if (String.IsNullOrEmpty(itemId)) - { - m_browsePosition = null; - return; - } - - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - /// - /// Browses the current branch. - /// - /// if set to true the return branches. - /// The filter. - /// Type of the data. - /// The access rights. - /// - public List Browse(bool isBranch, string filter, short dataType, int accessRights) - { - return new List(); - } - - /// - /// Gets the item id for the specified browse element. - /// - /// The name of the browse element. - /// - public string GetItemId(string browseName) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - /// - /// Gets the properties. - /// - /// The item id. - /// - public IList GetProperties(string itemId) - { - if (String.IsNullOrEmpty(itemId)) - { - return new DaProperty[0]; - } - - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - /// - /// Gets the property values. - /// - /// The item id. - /// The property ids. - /// The property values. - public DaValue[] GetPropertyValues(string itemId, int[] propertyIds) - { - DaValue[] results = new DaValue[propertyIds.Length]; - - for (int ii = 0; ii < results.Length; ii++) - { - results[ii] = new DaValue(); - results[ii].Error = ResultIds.E_UNKNOWNITEMID; - } - - return results; - } - - /// - /// Gets the item ids for the properties. - /// - /// The item id. - /// The property ids. - /// The item ids. - /// Any errors. - public int[] GetItemIds(string itemId, int[] propertyIds, out string[] itemIds) - { - itemIds = new string[propertyIds.Length]; - int[] results = new int[propertyIds.Length]; - - for (int ii = 0; ii < results.Length; ii++) - { - results[ii] = ResultIds.E_UNKNOWNITEMID; - } - - return results; - } - #endregion - - /* - private ushort[] m_namespaceMapping; - - private void CreateNamespaceMapping(Session session, ConfiguredEndpoint endpoint) - { - - } - - private NodeId ParseItemId(string itemId) - { - try - { - NodeId nodeId = NodeId.Parse(itemId); - - // check if the namespace index needs to be updated. - if (nodeId.NamespaceIndex > 1 && nodeId.NamespaceIndex < m_namespaceMapping.Length) - { - if (nodeId.NamespaceIndex != m_namespaceMapping[nodeId.NamespaceIndex]) - { - nodeId = new NodeId(nodeId.Identifier, m_namespaceMapping[nodeId.NamespaceIndex]); - } - } - - return nodeId; - } - catch (Exception) - { - return null; - } - } - */ - - private List Browse(string itemId) - { - m_lastUpdateTime = DateTime.UtcNow; - - // get the session to use. - Session session = Session; - - if (session == null) - { - return new List(); - } - - return null; - } - - #region Private Fields - private DateTime m_lastUpdateTime; - private List m_groups; - private int m_groupCounter; - private NodeId m_browsePosition; - #endregion - } -} diff --git a/ComIOP/Common/Proxy/ComProxy.cs b/ComIOP/Common/Proxy/ComProxy.cs deleted file mode 100644 index 7b2e1fa5a..000000000 --- a/ComIOP/Common/Proxy/ComProxy.cs +++ /dev/null @@ -1,554 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; -using System.Threading.Tasks; - -namespace Opc.Ua.Com -{ - /// - /// A base class for classes that implement an OPC COM specification. - /// - public class ComProxy : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComProxy() - { - } - #endregion - - #region IDisposable Members - /// - /// The finializer implementation. - /// - ~ComProxy() - { - Dispose(false); - } - - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - lock (m_lock) - { - m_running = false; - - if (m_reconnectTimer != null) - { - m_reconnectTimer.Dispose(); - m_reconnectTimer = null; - } - - if (m_session != null) - { - m_session.Dispose(); - m_session = null; - } - } - } - } - #endregion - - #region Initialization - /// - /// Gets the endpoint. - /// - /// The endpoint. - public ConfiguredEndpoint Endpoint - { - get { return m_endpoint; } - } - - /// - /// Gets a value indicating whether this is connected. - /// - /// true if connected; otherwise, false. - public bool Connected - { - get - { - lock (m_lock) - { - if (m_session == null) - { - return false; - } - - return m_session.Connected; - } - } - } - - /// - /// Called when the object is loaded by the COM process. - /// - /// The CLSID used to activate the server. - /// The application configuration for the COM process. - public virtual void Load(Guid clsid, ApplicationConfiguration configuration) - { - lock (m_lock) - { - // save the application configuration. - m_configuration = configuration; - - // set the start time. - m_startTime = DateTime.UtcNow; - - // look up default time zone. - DateTime now = DateTime.Now; - - m_timebias = (int)-TimeZone.CurrentTimeZone.GetUtcOffset(now).TotalMinutes; - - if (TimeZone.CurrentTimeZone.IsDaylightSavingTime(now)) - { - m_timebias += 60; - } - - // load endpoint information. - m_endpoint = LoadConfiguredEndpoint(clsid); - - // create a dummy endpoint so the COM client receives an indication of the problem. - if (m_endpoint == null) - { - ApplicationDescription server = new ApplicationDescription(); - - server.ApplicationName = "(Missing Configuration File)"; - server.ApplicationType = ApplicationType.Server; - server.ApplicationUri = clsid.ToString(); - - m_endpoint = new ConfiguredEndpoint(server, null); - } - - m_clsid = clsid; - m_running = true; - - // connect to the server on a background thread. - ThreadPool.QueueUserWorkItem(OnCreateSession, null); - } - } - - /// - /// Unloads this instance. - /// - public virtual void Unload() - { - Dispose(); - } - #endregion - - #region Protected Properties - /// - /// Gets the lock. - /// - /// The lock. - protected object Lock - { - get { return m_lock; } - } - - /// - /// Gets the configuration. - /// - /// The configuration. - protected ApplicationConfiguration Configuration - { - get { return m_configuration; } - } - - /// - /// Gets a value indicating whether this is running. - /// - /// true if running; otherwise, false. - protected bool Running - { - get { return m_running; } - } - - /// - /// Gets the start time. - /// - /// The start time. - protected DateTime StartTime - { - get { return m_startTime; } - } - - /// - /// Gets the timebias. - /// - /// The timebias. - protected int Timebias - { - get { return m_timebias; } - } - - /// - /// Gets the session. - /// - /// The session. - protected Opc.Ua.Client.Session Session - { - get { return m_session; } - } - #endregion - - #region Private Methods - /// - /// Creates a session with the server. - /// - /// The state. - private async void OnCreateSession(object state) - { - // check if nothing to do. - lock (m_lock) - { - if (!m_running || m_session != null) - { - return; - } - - // stop the reconnect timer. - if (m_reconnectTimer != null) - { - m_reconnectTimer.Dispose(); - m_reconnectTimer = null; - } - } - - // create the session. - try - { - Session session = await Connect(m_clsid); - session.KeepAlive += new KeepAliveEventHandler(Session_KeepAlive); - - lock (m_lock) - { - // discard unneeded session. - if (m_session != null) - { - session.Dispose(); - return; - } - - // update the session. - m_session = session; - } - } - catch (Exception e) - { - Utils.Trace(e, "Could not create a Session with the UA Server."); - - // schedule a reconnect. - lock (m_lock) - { - m_reconnectTimer = new Timer(OnCreateSession, null, 20000, Timeout.Infinite); - } - } - } - - /// - /// Creates a session with the server. - /// - /// The state. - private void OnReconnectSession(object state) - { - // get the CLSID of the COM server. - Session session = state as Session; - - if (session == null) - { - return; - } - - // check if nothing to do. - lock (m_lock) - { - if (!m_running || !Object.ReferenceEquals(m_session, session)) - { - return; - } - - // stop the reconnect timer. - if (m_reconnectTimer != null) - { - m_reconnectTimer.Dispose(); - m_reconnectTimer = null; - } - } - - // reconnect the session. - try - { - session.Reconnect(); - - lock (m_lock) - { - if (!m_running || !Object.ReferenceEquals(m_session, session)) - { - session.Dispose(); - return; - } - } - } - catch (Exception e) - { - Utils.Trace("Unexpected reconnecting a Session with the UA Server. {0}", e.Message); - - // schedule a reconnect. - lock (m_lock) - { - // check if session has been replaced. - if (!m_running || !Object.ReferenceEquals(m_session, session)) - { - session.Dispose(); - return; - } - - // check if the session has been closed. - ServiceResultException sre = e as ServiceResultException; - - if (sre == null || sre.StatusCode != StatusCodes.BadSessionClosed) - { - m_session = null; - session.Dispose(); - ThreadPool.QueueUserWorkItem(OnCreateSession, null); - return; - } - - // check if reconnecting is still an option. - if (m_lastKeepAliveTime.AddMilliseconds(session.SessionTimeout) > DateTime.UtcNow) - { - m_reconnectTimer = new Timer(OnReconnectSession, session, 20000, Timeout.Infinite); - return; - } - - // give up and re-create the session. - m_session = null; - session.Dispose(); - m_reconnectTimer = new Timer(OnCreateSession, null, 20000, Timeout.Infinite); - } - } - } - - /// - /// The session the keep alive handler. - /// - /// The session. - /// The instance containing the event data. - private void Session_KeepAlive(Session session, KeepAliveEventArgs e) - { - int missedKeepAlives = 0; - - lock (m_lock) - { - // check if the session is closed. - if (!m_running || !Object.ReferenceEquals(m_session, session)) - { - return; - } - - // check if everything is ok. - if (ServiceResult.IsGood(e.Status)) - { - m_missedKeepAlives = 0; - m_lastKeepAliveTime = DateTime.UtcNow; - return; - } - - // increment miss count. - missedKeepAlives = ++m_missedKeepAlives; - } - - // attempt to reconnect after two misses. - if (missedKeepAlives > 2) - { - ThreadPool.QueueUserWorkItem(OnReconnectSession, session); - } - } - - /// - /// Connects to the UA server identfied by the CLSID. - /// - /// The CLSID. - /// The UA server. - private async Task Connect(Guid clsid) - { - // load the endpoint information. - ConfiguredEndpoint endpoint = m_endpoint = LoadConfiguredEndpoint(clsid); - - if (endpoint == null) - { - throw new ServiceResultException(StatusCodes.BadConfigurationError); - } - - // update security information. - if (endpoint.UpdateBeforeConnect) - { - endpoint.UpdateFromServer(); - - // check if halted while waiting for a response. - if (!m_running) - { - throw new ServiceResultException(StatusCodes.BadServerHalted); - } - } - - // look up the client certificate. - X509Certificate2 clientCertificate = await m_configuration.SecurityConfiguration.ApplicationCertificate.Find(true); - - // create a message context to use with the channel. - ServiceMessageContext messageContext = m_configuration.CreateMessageContext(); - - // create the channel. - ITransportChannel channel = SessionChannel.Create( - m_configuration, - endpoint.Description, - endpoint.Configuration, - clientCertificate, - messageContext); - - // create the session. - Session session = new Session(channel, m_configuration, endpoint, clientCertificate); - - // create a session name that is useful for debugging. - string sessionName = Utils.Format("COM Client (Host={0}, CLSID={1})", System.Net.Dns.GetHostName(), clsid); - - // open the session. - session.Open(sessionName, null); - - // return the new session. - return session; - } - - /// - /// Reads the UA endpoint information associated the CLSID - /// - /// The CLSID used to activate the COM server. - /// The endpoint. - private ConfiguredEndpoint LoadConfiguredEndpoint(Guid clsid) - { - try - { - string relativePath = Utils.Format("%CommonApplicationData%\\OPC Foundation\\ComPseudoServers\\{0}.xml", clsid); - string absolutePath = Utils.GetAbsoluteFilePath(relativePath, false, false, false); - - // oops - nothing found. - if (absolutePath == null) - { - return null; - } - - // open the file. - FileStream istrm = File.Open(absolutePath, FileMode.Open, FileAccess.Read); - - using (XmlTextReader reader = new XmlTextReader(istrm)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(ConfiguredEndpoint)); - return (ConfiguredEndpoint)serializer.ReadObject(reader, false); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error loading endpoint configuration for COM Proxy with CLSID={0}.", clsid); - return null; - } - } - - /// - /// Saves the UA endpoint information associated the CLSID. - /// - /// The CLSID used to activate the COM server. - /// The endpoint. - private void SaveConfiguredEndpoint(Guid clsid, ConfiguredEndpoint endpoint) - { - try - { - string relativePath = Utils.Format("%CommonApplicationData%\\OPC Foundation\\ComPseudoServers\\{0}.xml", clsid); - string absolutePath = Utils.GetAbsoluteFilePath(relativePath, false, false, true); - - // oops - nothing found. - if (absolutePath == null) - { - absolutePath = Utils.GetAbsoluteFilePath(relativePath, true, false, true); - } - - // open the file. - FileStream ostrm = File.Open(absolutePath, FileMode.Open, FileAccess.ReadWrite); - - using (XmlTextWriter writer = new XmlTextWriter(ostrm, System.Text.Encoding.UTF8)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(ConfiguredEndpoint)); - serializer.WriteObject(writer, endpoint); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error saving endpoint configuration for COM Proxy with CLSID={0}.", clsid); - } - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private Guid m_clsid; - private ApplicationConfiguration m_configuration; - private ConfiguredEndpoint m_endpoint; - private bool m_running; - private DateTime m_startTime; - private int m_timebias; - private Timer m_reconnectTimer; - private int m_missedKeepAlives; - private DateTime m_lastKeepAliveTime; - private Opc.Ua.Client.Session m_session; - #endregion - } -} diff --git a/ComIOP/Common/Proxy/DaElement.cs b/ComIOP/Common/Proxy/DaElement.cs deleted file mode 100644 index 421965065..000000000 --- a/ComIOP/Common/Proxy/DaElement.cs +++ /dev/null @@ -1,324 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com -{ - /// - /// Stores information an element in the DA server address space. - /// - public class DaElement - { - #region Public Members - /// - /// Initializes a new instance of the class. - /// - public DaElement() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Gets or sets the parent item id. - /// - /// The parent item id. - public string ParentId - { - get { return m_parentId; } - set { m_parentId = value; } - } - - /// - /// Gets or sets the type of the element. - /// - /// The type of the element. - public DaElementType ElementType - { - get { return m_elementType; } - set { m_elementType = value; } - } - - /// - /// Gets or sets the properties available for the element. - /// - /// The available properties. - public DaProperty[] Properties - { - get { return m_properties; } - set { m_properties = value; } - } - - /// - /// Gets or sets the COM data type for the value. - /// - /// The COM data type for the value. - public short DataType - { - get { return m_dataType; } - set { m_dataType = value; } - } - - /// - /// Gets or sets the access rights for the item. - /// - /// The access rights. - public int AccessRights - { - get { return m_accessRights; } - set { m_accessRights = value; } - } - - /// - /// Gets or sets the scan rate. - /// - /// The scan rate. - public float ScanRate - { - get { return m_scanRate; } - set { m_scanRate = value; } - } - - /// - /// Gets or sets the description. - /// - /// The description. - public string Description - { - get { return m_description; } - set { m_description = value; } - } - - /// - /// Gets or sets the engineering units. - /// - /// The engineering units. - public string EngineeringUnits - { - get { return m_engineeringUnits; } - set { m_engineeringUnits = value; } - } - - /// - /// Gets or sets EUType forthe item. - /// - /// The EUType for the item. - public int EuType - { - get { return m_euType; } - set { m_euType = value; } - } - - /// - /// Gets or sets the EU information for the item. - /// - /// The EU information for the item. - public string[] EuInfo - { - get { return m_euInfo; } - set { m_euInfo = value; } - } - - /// - /// Gets or sets the high EU value. - /// - /// The high EU value. - public double HighEU - { - get { return m_highEU; } - set { m_highEU = value; } - } - - /// - /// Gets or sets the low EU value. - /// - /// The low EU value. - public double LowEU - { - get { return m_lowEU; } - set { m_lowEU = value; } - } - - /// - /// Gets or sets the high IR value. - /// - /// The high IR value. - public double HighIR - { - get { return m_highIR; } - set { m_highIR = value; } - } - - /// - /// Gets or sets the low IR value. - /// - /// The low IR value. - public double LowIR - { - get { return m_lowIR; } - set { m_lowIR = value; } - } - - /// - /// Gets or sets the open label. - /// - /// The open label. - public string OpenLabel - { - get { return m_openLabel; } - set { m_openLabel = value; } - } - - /// - /// Gets or sets the close label. - /// - /// The close label. - public string CloseLabel - { - get { return m_closeLabel; } - set { m_closeLabel = value; } - } - - /// - /// Gets or sets the time zone for the item. - /// - /// The time zone. - public int? TimeZone - { - get { return m_timeZone; } - set { m_timeZone = value; } - } - - /// - /// Returns true if the element supports the specified property. - /// - /// The property id. - /// Rrue if the element supports the specified property. - public bool SupportsProperty(int propertyId) - { - if (m_properties != null) - { - for (int ii = 0; ii < m_properties.Length; ii++) - { - if (propertyId == m_properties[ii].PropertyId) - { - return true; - } - } - } - - return false; - } - #endregion - - #region Private Methods - #endregion - - #region Private Fields - private string m_itemId; - private string m_name; - private string m_parentId; - private DaElementType m_elementType; - private DaProperty[] m_properties; - private short m_dataType; - private int m_accessRights; - private float m_scanRate; - private string m_description; - private string m_engineeringUnits; - private int m_euType; - private string[] m_euInfo; - private double m_highEU; - private double m_lowEU; - private double m_highIR; - private double m_lowIR; - private string m_openLabel; - private string m_closeLabel; - private int? m_timeZone; - #endregion - } - - /// - /// The possible type of elements. - /// - public enum DaElementType - { - /// - /// Unknown element type. - /// - Undefined = 0, - - /// - /// A branch - /// - Branch = 1, - - /// - /// An item. - /// - Item = 2, - - /// - /// An analog item. - /// - AnalogItem = 3, - - /// - /// An enumerated item. - /// - EnumeratedItem = 4, - - /// - /// An digital item. - /// - DigitalItem = 5 - } -} diff --git a/ComIOP/Common/Proxy/DaProperty.cs b/ComIOP/Common/Proxy/DaProperty.cs deleted file mode 100644 index 6a436a9cf..000000000 --- a/ComIOP/Common/Proxy/DaProperty.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com -{ - /// - /// Stores information an element in the DA server address space. - /// - public class DaProperty - { - #region Public Members - /// - /// Initializes a new instance of the class. - /// - public DaProperty() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the property id. - /// - /// The property id. - public int PropertyId - { - get { return m_propertyId; } - set { m_propertyId = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the COM data type. - /// - /// The COM data type for the property. - public short DataType - { - get { return m_dataType; } - set { m_dataType = value; } - } - #endregion - - #region Private Fields - private int m_propertyId; - private string m_name; - private string m_itemId; - private short m_dataType; - #endregion - } -} diff --git a/ComIOP/Common/Proxy/DaValue.cs b/ComIOP/Common/Proxy/DaValue.cs deleted file mode 100644 index 9f37954a5..000000000 --- a/ComIOP/Common/Proxy/DaValue.cs +++ /dev/null @@ -1,119 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com -{ - /// - /// Stores information an element in the DA server address space. - /// - public class DaValue - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public DaValue() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the value. - /// - /// The value. - public object Value - { - get { return m_value; } - set { m_value = value; } - } - - /// - /// Gets or sets the timestamp. - /// - /// The timestamp. - public DateTime Timestamp - { - get { return m_timestamp; } - set { m_timestamp = value; } - } - - /// - /// Gets or sets the quality. - /// - /// The quality. - public short Quality - { - get { return m_quality; } - set { m_quality = value; } - } - - /// - /// Gets or sets the COM error. - /// - /// The COM error. - public int Error - { - get { return m_error; } - set { m_error = value; } - } - - /// - /// Gets the value. - /// - /// The type of value to return. - /// The value if no error and a valid value exists. The default value for the type otherwise. - public T GetValue() - { - if (m_error < 0) - { - return default(T); - } - - if (typeof(T).IsInstanceOfType(m_value)) - { - return (T)m_value; - } - - return default(T); - } - #endregion - - #region Private Fields - private object m_value; - private short m_quality; - private DateTime m_timestamp; - private int m_error; - #endregion - } -} diff --git a/ComIOP/Common/Proxy/OpcProxyUtils.cs b/ComIOP/Common/Proxy/OpcProxyUtils.cs deleted file mode 100644 index f09540398..000000000 --- a/ComIOP/Common/Proxy/OpcProxyUtils.cs +++ /dev/null @@ -1,112 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; - -namespace Opc.Ua.Com -{ - /// - /// A helper class for COpcProxyUtils.cpp - /// - public static class ProxyUtils - { - /// - /// Synchronous helper implementation of CheckApplicationInstanceCertificate for C++ Proxy - /// - public static void CheckApplicationInstanceCertificate(ApplicationConfiguration configuration) - { - // create a default certificate id none specified. - CertificateIdentifier id = configuration.SecurityConfiguration.ApplicationCertificate; - - if (id == null) - { - id = new CertificateIdentifier(); - id.StoreType = Utils.DefaultStoreType; - id.StorePath = Utils.DefaultStorePath; - id.SubjectName = configuration.ApplicationName; - } - - // check for certificate with a private key. - X509Certificate2 certificate = id.Find(true).Result; - - if (certificate != null) - { - return; - } - - // construct the subject name from the - List hostNames = new List(); - hostNames.Add(Utils.GetHostName()); - - string commonName = Utils.Format("CN={0}", configuration.ApplicationName); - string domainName = Utils.Format("DC={0}", hostNames[0]); - string subjectName = Utils.Format("{0}, {1}", commonName, domainName); - - // create a new certificate with a new public key pair. - certificate = CertificateFactory.CreateCertificate( - configuration.ApplicationUri, - configuration.ApplicationName, - subjectName, - hostNames) - .CreateForRSA() - .AddToStore( - id.StoreType, - id.StorePath); - - id.Certificate = certificate; - - // update and save the configuration file. - configuration.SaveToFile(configuration.SourceFilePath); - - // add certificate to the trusted peer store so other applications will trust it. - using (ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore()) - { - X509Certificate2Collection certificateCollection = store.FindByThumbprint(certificate.Thumbprint).Result; - if (certificateCollection != null) - { - store.Add(certificateCollection[0]).Wait(); - } - } - - // tell the certificate validator about the new certificate. - configuration.CertificateValidator.Update(configuration.SecurityConfiguration).Wait(); - } - - /// - /// Synchronous helper implementation of ApplicationConfiguration.Load for C++ Proxy - /// - public static ApplicationConfiguration ApplicationConfigurationLoad(string sectionName, ApplicationType applicationType) - { - ApplicationConfiguration config = null; - config = ApplicationConfiguration.Load(sectionName, applicationType).Result; - return config; - } - } -} diff --git a/ComIOP/Common/Rcw/AlarmsAndEvents.cs b/ComIOP/Common/Rcw/AlarmsAndEvents.cs deleted file mode 100644 index 73d0b8e3c..000000000 --- a/ComIOP/Common/Rcw/AlarmsAndEvents.cs +++ /dev/null @@ -1,808 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; - -#pragma warning disable 1591 - -namespace OpcRcw.Ae -{ - /// - [ComImport] - [GuidAttribute("58E13251-AC87-11d1-84D5-00608CB8A7E9")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface CATID_OPCAEServer10 {} - - /// - public enum OPCAEBROWSEDIRECTION - { - OPCAE_BROWSE_UP = 1, - OPCAE_BROWSE_DOWN, - OPCAE_BROWSE_TO - } - - /// - public enum OPCAEBROWSETYPE - { - OPC_AREA = 1, - OPC_SOURCE - } - - /// - public enum OPCEVENTSERVERSTATE - { - OPCAE_STATUS_RUNNING = 1, - OPCAE_STATUS_FAILED, - OPCAE_STATUS_NOCONFIG, - OPCAE_STATUS_SUSPENDED, - OPCAE_STATUS_TEST, - OPCAE_STATUS_COMM_FAULT - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct ONEVENTSTRUCT - { - [MarshalAs(UnmanagedType.I2)] - public short wChangeMask; - [MarshalAs(UnmanagedType.I2)] - public short wNewState; - [MarshalAs(UnmanagedType.LPWStr)] - public string szSource; - public System.Runtime.InteropServices.ComTypes.FILETIME ftTime; - [MarshalAs(UnmanagedType.LPWStr)] - public string szMessage; - [MarshalAs(UnmanagedType.I4)] - public int dwEventType; - [MarshalAs(UnmanagedType.I4)] - public int dwEventCategory; - [MarshalAs(UnmanagedType.I4)] - public int dwSeverity; - [MarshalAs(UnmanagedType.LPWStr)] - public string szConditionName; - [MarshalAs(UnmanagedType.LPWStr)] - public string szSubconditionName; - [MarshalAs(UnmanagedType.I2)] - public short wQuality; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - [MarshalAs(UnmanagedType.I4)] - public int bAckRequired; - public System.Runtime.InteropServices.ComTypes.FILETIME ftActiveTime; - [MarshalAs(UnmanagedType.I4)] - public int dwCookie; - [MarshalAs(UnmanagedType.I4)] - public int dwNumEventAttrs; - public IntPtr pEventAttributes; - [MarshalAs(UnmanagedType.LPWStr)] - public string szActorID; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCEVENTSERVERSTATUS - { - public System.Runtime.InteropServices.ComTypes.FILETIME ftStartTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftCurrentTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftLastUpdateTime; - public OPCEVENTSERVERSTATE dwServerState; - [MarshalAs(UnmanagedType.I2)] - public short wMajorVersion; - [MarshalAs(UnmanagedType.I2)] - public short wMinorVersion; - [MarshalAs(UnmanagedType.I2)] - public short wBuildNumber; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - [MarshalAs(UnmanagedType.LPWStr)] - public string szVendorInfo; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCCONDITIONSTATE - { - [MarshalAs(UnmanagedType.I2)] - public short wState; - [MarshalAs(UnmanagedType.I2)] - public short wReserved1; - [MarshalAs(UnmanagedType.LPWStr)] - public string szActiveSubCondition; - [MarshalAs(UnmanagedType.LPWStr)] - public string szASCDefinition; - [MarshalAs(UnmanagedType.I4)] - public int dwASCSeverity; - [MarshalAs(UnmanagedType.LPWStr)] - public string szASCDescription; - [MarshalAs(UnmanagedType.I2)] - public short wQuality; - [MarshalAs(UnmanagedType.I2)] - public short wReserved2; - public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAckTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftSubCondLastActive; - public System.Runtime.InteropServices.ComTypes.FILETIME ftCondLastActive; - public System.Runtime.InteropServices.ComTypes.FILETIME ftCondLastInactive; - [MarshalAs(UnmanagedType.LPWStr)] - public string szAcknowledgerID; - [MarshalAs(UnmanagedType.LPWStr)] - public string szComment; - [MarshalAs(UnmanagedType.I4)] - public int dwNumSCs; - public IntPtr pszSCNames; - public IntPtr pszSCDefinitions; - public IntPtr pdwSCSeverities; - public IntPtr pszSCDescriptions; - public int dwNumEventAttrs; - public IntPtr pEventAttributes; - public IntPtr pErrors; - } - - /// - [ComImport] - [GuidAttribute("65168851-5783-11D1-84A0-00608CB8A7E9")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCEventServer - { - void GetStatus( - out IntPtr ppEventServerStatus); - - void CreateEventSubscription( - [MarshalAs(UnmanagedType.I4)] - int bActive, - [MarshalAs(UnmanagedType.I4)] - int dwBufferTime, - [MarshalAs(UnmanagedType.I4)] - int dwMaxSize, - [MarshalAs(UnmanagedType.I4)] - int hClientSubscription, - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=4)] - out object ppUnk, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedBufferTime, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedMaxSize); - - void QueryAvailableFilters( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwFilterMask); - - void QueryEventCategories( - [MarshalAs(UnmanagedType.I4)] - int dwEventType, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppdwEventCategories, - [Out] - out IntPtr ppszEventCategoryDescs); - - [PreserveSig] - int QueryConditionNames( - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppszConditionNames); - - void QuerySubConditionNames( - [MarshalAs(UnmanagedType.LPWStr)] - string szConditionName, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppszSubConditionNames); - - void QuerySourceConditions( - [MarshalAs(UnmanagedType.LPWStr)] - string szSource, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppszConditionNames); - - void QueryEventAttributes( - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppdwAttrIDs, - [Out] - out IntPtr ppszAttrDescs, - [Out] - out IntPtr ppvtAttrTypes); - - void TranslateToItemIDs( - [MarshalAs(UnmanagedType.LPWStr)] - string szSource, - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [MarshalAs(UnmanagedType.LPWStr)] - string szConditionName, - [MarshalAs(UnmanagedType.LPWStr)] - string szSubconditionName, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] pdwAssocAttrIDs, - out IntPtr ppszAttrItemIDs, - out IntPtr ppszNodeNames, - out IntPtr ppCLSIDs); - - void GetConditionState( - [MarshalAs(UnmanagedType.LPWStr)] - string szSource, - [MarshalAs(UnmanagedType.LPWStr)] - string szConditionName, - [MarshalAs(UnmanagedType.I4)] - int dwNumEventAttrs, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] pdwAttributeIDs, - [Out] - out IntPtr ppConditionState); - - void EnableConditionByArea( - [MarshalAs(UnmanagedType.I4)] - int dwNumAreas, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszAreas); - - void EnableConditionBySource( - [MarshalAs(UnmanagedType.I4)] - int dwNumSources, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszSources); - - void DisableConditionByArea( - [MarshalAs(UnmanagedType.I4)] - int dwNumAreas, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszAreas); - - void DisableConditionBySource( - [MarshalAs(UnmanagedType.I4)] - int dwNumSources, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszSources); - - void AckCondition( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPWStr)] - string szAcknowledgerID, - [MarshalAs(UnmanagedType.LPWStr)] - string szComment, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszSource, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] szConditionName, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - System.Runtime.InteropServices.ComTypes.FILETIME[] pftActiveTime, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwCookie, - [Out] - out IntPtr ppErrors); - - void CreateAreaBrowser( - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=0)] - out object ppUnk); - } - - /// - [ComImport] - [GuidAttribute("65168855-5783-11D1-84A0-00608CB8A7E9")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCEventSubscriptionMgt - { - void SetFilter( - [MarshalAs(UnmanagedType.I4)] - int dwEventType, - [MarshalAs(UnmanagedType.I4)] - int dwNumCategories, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] pdwEventCategories, - [MarshalAs(UnmanagedType.I4)] - int dwLowSeverity, - [MarshalAs(UnmanagedType.I4)] - int dwHighSeverity, - [MarshalAs(UnmanagedType.I4)] - int dwNumAreas, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=5)] - string[] pszAreaList, - [MarshalAs(UnmanagedType.I4)] - int dwNumSources, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=7)] - string[] pszSourceList); - - void GetFilter( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwEventType, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwNumCategories, - [Out] - out IntPtr ppdwEventCategories, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwLowSeverity, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwHighSeverity, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwNumAreas, - [Out] - out IntPtr ppszAreaList, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwNumSources, - [Out] - out IntPtr ppszSourceList); - - void SelectReturnedAttributes( - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] dwAttributeIDs); - - void GetReturnedAttributes( - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppdwAttributeIDs); - - void Refresh( - [MarshalAs(UnmanagedType.I4)] - int dwConnection); - - void CancelRefresh( - [MarshalAs(UnmanagedType.I4)] - int dwConnection); - - void GetState( - [Out][MarshalAs(UnmanagedType.I4)] - out int pbActive, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwBufferTime, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwMaxSize, - [Out][MarshalAs(UnmanagedType.I4)] - out int phClientSubscription); - - void SetState( - IntPtr pbActive, - IntPtr pdwBufferTime, - IntPtr pdwMaxSize, - [MarshalAs(UnmanagedType.I4)] - int hClientSubscription, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedBufferTime, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedMaxSize); - } - - /// - [ComImport] - [GuidAttribute("65168857-5783-11D1-84A0-00608CB8A7E9")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCEventAreaBrowser - { - void ChangeBrowsePosition( - OPCAEBROWSEDIRECTION dwBrowseDirection, - [MarshalAs(UnmanagedType.LPWStr)] - string szString); - - void BrowseOPCAreas( - OPCAEBROWSETYPE dwBrowseFilterType, - [MarshalAs(UnmanagedType.LPWStr)] - string szFilterCriteria, - [Out] - out OpcRcw.Comn.IEnumString ppIEnumString); - - void GetQualifiedAreaName( - [MarshalAs(UnmanagedType.LPWStr)] - string szAreaName, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string pszQualifiedAreaName); - - void GetQualifiedSourceName( - [MarshalAs(UnmanagedType.LPWStr)] - string szSourceName, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string pszQualifiedSourceName); - } - - /// - [ComImport] - [GuidAttribute("6516885F-5783-11D1-84A0-00608CB8A7E9")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCEventSink - { - void OnEvent( - [MarshalAs(UnmanagedType.I4)] - int hClientSubscription, - [MarshalAs(UnmanagedType.I4)] - int bRefresh, - [MarshalAs(UnmanagedType.I4)] - int bLastRefresh, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=3)] - ONEVENTSTRUCT[] pEvents); - } - - /// - [ComImport] - [GuidAttribute("71BBE88E-9564-4bcd-BCFC-71C558D94F2D")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCEventServer2 // : IOPCEventServer - { - void GetStatus( - out IntPtr ppEventServerStatus); - - void CreateEventSubscription( - [MarshalAs(UnmanagedType.I4)] - int bActive, - [MarshalAs(UnmanagedType.I4)] - int dwBufferTime, - [MarshalAs(UnmanagedType.I4)] - int dwMaxSize, - [MarshalAs(UnmanagedType.I4)] - int hClientSubscription, - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=4)] - out object ppUnk, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedBufferTime, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedMaxSize); - - void QueryAvailableFilters( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwFilterMask); - - void QueryEventCategories( - [MarshalAs(UnmanagedType.I4)] - int dwEventType, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppdwEventCategories, - [Out] - out IntPtr ppszEventCategoryDescs); - - [PreserveSig] - int QueryConditionNames( - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppszConditionNames); - - void QuerySubConditionNames( - [MarshalAs(UnmanagedType.LPWStr)] - string szConditionName, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppszSubConditionNames); - - void QuerySourceConditions( - [MarshalAs(UnmanagedType.LPWStr)] - string szSource, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppszConditionNames); - - void QueryEventAttributes( - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppdwAttrIDs, - [Out] - out IntPtr ppszAttrDescs, - [Out] - out IntPtr ppvtAttrTypes); - - void TranslateToItemIDs( - [MarshalAs(UnmanagedType.LPWStr)] - string szSource, - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [MarshalAs(UnmanagedType.LPWStr)] - string szConditionName, - [MarshalAs(UnmanagedType.LPWStr)] - string szSubconditionName, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] pdwAssocAttrIDs, - out IntPtr ppszAttrItemIDs, - out IntPtr ppszNodeNames, - out IntPtr ppCLSIDs); - - void GetConditionState( - [MarshalAs(UnmanagedType.LPWStr)] - string szSource, - [MarshalAs(UnmanagedType.LPWStr)] - string szConditionName, - [MarshalAs(UnmanagedType.I4)] - int dwNumEventAttrs, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] pdwAttributeIDs, - [Out] - out IntPtr ppConditionState); - - void EnableConditionByArea( - [MarshalAs(UnmanagedType.I4)] - int dwNumAreas, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszAreas); - - void EnableConditionBySource( - [MarshalAs(UnmanagedType.I4)] - int dwNumSources, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszSources); - - void DisableConditionByArea( - [MarshalAs(UnmanagedType.I4)] - int dwNumAreas, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszAreas); - - void DisableConditionBySource( - [MarshalAs(UnmanagedType.I4)] - int dwNumSources, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszSources); - - void AckCondition( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPWStr)] - string szAcknowledgerID, - [MarshalAs(UnmanagedType.LPWStr)] - string szComment, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszSource, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] szConditionName, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - System.Runtime.InteropServices.ComTypes.FILETIME[] pftActiveTime, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwCookie, - [Out] - out IntPtr ppErrors); - - void CreateAreaBrowser( - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=0)] - out object ppUnk); - - void EnableConditionByArea2( - [MarshalAs(UnmanagedType.I4)] - int dwNumAreas, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszAreas, - [Out] - out IntPtr ppErrors); - - void EnableConditionBySource2( - [MarshalAs(UnmanagedType.I4)] - int dwNumSources, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszSources, - [Out] - out IntPtr ppErrors); - - void DisableConditionByArea2( - [MarshalAs(UnmanagedType.I4)] - int dwNumAreas, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszAreas, - [Out] - out IntPtr ppErrors); - - void DisableConditionBySource2( - [MarshalAs(UnmanagedType.I4)] - int dwNumSources, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszSources, - [Out] - out IntPtr ppErrors); - - void GetEnableStateByArea( - [MarshalAs(UnmanagedType.I4)] - int dwNumAreas, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszAreas, - [Out] - out IntPtr pbEnabled, - [Out] - out IntPtr pbEffectivelyEnabled, - [Out] - out IntPtr ppErrors); - - void GetEnableStateBySource( - [MarshalAs(UnmanagedType.I4)] - int dwNumSources, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszSources, - out IntPtr pbEnabled, - out IntPtr pbEffectivelyEnabled, - out IntPtr ppErrors); - }; - - /// - [ComImport] - [GuidAttribute("94C955DC-3684-4ccb-AFAB-F898CE19AAC3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCEventSubscriptionMgt2 // : IOPCEventSubscriptionMgt - { - void SetFilter( - [MarshalAs(UnmanagedType.I4)] - int dwEventType, - [MarshalAs(UnmanagedType.I4)] - int dwNumCategories, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] pdwEventCategories, - [MarshalAs(UnmanagedType.I4)] - int dwLowSeverity, - [MarshalAs(UnmanagedType.I4)] - int dwHighSeverity, - [MarshalAs(UnmanagedType.I4)] - int dwNumAreas, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=5)] - string[] pszAreaList, - [MarshalAs(UnmanagedType.I4)] - int dwNumSources, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=7)] - string[] pszSourceList); - - void GetFilter( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwEventType, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwNumCategories, - [Out] - out IntPtr ppdwEventCategories, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwLowSeverity, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwHighSeverity, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwNumAreas, - [Out] - out IntPtr ppszAreaList, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwNumSources, - [Out] - out IntPtr ppszSourceList); - - void SelectReturnedAttributes( - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] dwAttributeIDs); - - void GetReturnedAttributes( - [MarshalAs(UnmanagedType.I4)] - int dwEventCategory, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppdwAttributeIDs); - - void Refresh( - [MarshalAs(UnmanagedType.I4)] - int dwConnection); - - void CancelRefresh( - [MarshalAs(UnmanagedType.I4)] - int dwConnection); - - void GetState( - [Out][MarshalAs(UnmanagedType.I4)] - out int pbActive, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwBufferTime, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwMaxSize, - [Out][MarshalAs(UnmanagedType.I4)] - out int phClientSubscription); - - void SetState( - IntPtr pbActive, - IntPtr pdwBufferTime, - IntPtr pdwMaxSize, - [MarshalAs(UnmanagedType.I4)] - int hClientSubscription, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedBufferTime, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedMaxSize); - - void SetKeepAlive( - [MarshalAs(UnmanagedType.I4)] - int dwKeepAliveTime, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedKeepAliveTime); - - void GetKeepAlive( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwKeepAliveTime); - } - - /// - public static class Constants - { - // category description string. - public const string OPC_CATEGORY_DESCRIPTION_AE10 = "OPC Alarm & Event Server Version 1.0"; - - // state bit masks. - public const int CONDITION_ENABLED = 0x0001; - public const int CONDITION_ACTIVE = 0x0002; - public const int CONDITION_ACKED = 0x0004; - - // bit masks for change mask. - public const int CHANGE_ACTIVE_STATE = 0x0001; - public const int CHANGE_ACK_STATE = 0x0002; - public const int CHANGE_ENABLE_STATE = 0x0004; - public const int CHANGE_QUALITY = 0x0008; - public const int CHANGE_SEVERITY = 0x0010; - public const int CHANGE_SUBCONDITION = 0x0020; - public const int CHANGE_MESSAGE = 0x0040; - public const int CHANGE_ATTRIBUTE = 0x0080; - - // event type. - public const int SIMPLE_EVENT = 0x0001; - public const int TRACKING_EVENT = 0x0002; - public const int CONDITION_EVENT = 0x0004; - public const int ALL_EVENTS = 0x0007; - - // bit masks for QueryAvailableFilters(). - public const int FILTER_BY_EVENT = 0x0001; - public const int FILTER_BY_CATEGORY = 0x0002; - public const int FILTER_BY_SEVERITY = 0x0004; - public const int FILTER_BY_AREA = 0x0008; - public const int FILTER_BY_SOURCE = 0x0010; - } -} diff --git a/ComIOP/Common/Rcw/Common.cs b/ComIOP/Common/Rcw/Common.cs deleted file mode 100644 index 9cb7eaa6e..000000000 --- a/ComIOP/Common/Rcw/Common.cs +++ /dev/null @@ -1,351 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; - -#pragma warning disable 1591 - -namespace OpcRcw.Comn -{ - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] - public struct CONNECTDATA - { - [MarshalAs(UnmanagedType.IUnknown)] - object pUnk; - [MarshalAs(UnmanagedType.I4)] - int dwCookie; - } - - /// - [ComImport] - [GuidAttribute("B196B287-BAB4-101A-B69C-00AA00341D07")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IEnumConnections - { - void RemoteNext( - [MarshalAs(UnmanagedType.I4)] - int cConnections, - [Out] - IntPtr rgcd, - [Out][MarshalAs(UnmanagedType.I4)] - out int pcFetched); - - void Skip( - [MarshalAs(UnmanagedType.I4)] - int cConnections); - - void Reset(); - - void Clone( - [Out] - out IEnumConnections ppEnum); - } - - /// - [ComImport] - [GuidAttribute("B196B286-BAB4-101A-B69C-00AA00341D07")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IConnectionPoint - { - void GetConnectionInterface( - [Out] - out Guid pIID); - - void GetConnectionPointContainer( - [Out] - out IConnectionPointContainer ppCPC); - - void Advise( - [MarshalAs(UnmanagedType.IUnknown)] - object pUnkSink, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCookie); - - void Unadvise( - [MarshalAs(UnmanagedType.I4)] - int dwCookie); - - void EnumConnections( - [Out] - out IEnumConnections ppEnum); - } - - /// - [ComImport] - [GuidAttribute("B196B285-BAB4-101A-B69C-00AA00341D07")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IEnumConnectionPoints - { - void RemoteNext( - [MarshalAs(UnmanagedType.I4)] - int cConnections, - [Out] - IntPtr ppCP, - [Out][MarshalAs(UnmanagedType.I4)] - out int pcFetched); - - void Skip( - [MarshalAs(UnmanagedType.I4)] - int cConnections); - - void Reset(); - - void Clone( - [Out] - out IEnumConnectionPoints ppEnum); - } - - /// - [ComImport] - [GuidAttribute("B196B284-BAB4-101A-B69C-00AA00341D07")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IConnectionPointContainer - { - void EnumConnectionPoints( - [Out] - out IEnumConnectionPoints ppEnum); - - void FindConnectionPoint( - ref Guid riid, - [Out] - out IConnectionPoint ppCP); - } - - /// - [ComImport] - [GuidAttribute("F31DFDE1-07B6-11d2-B2D8-0060083BA1FB")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCShutdown - { - void ShutdownRequest( - [MarshalAs(UnmanagedType.LPWStr)] - string szReason); - } - - /// - [ComImport] - [GuidAttribute("F31DFDE2-07B6-11d2-B2D8-0060083BA1FB")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCCommon - { - void SetLocaleID( - [MarshalAs(UnmanagedType.I4)] - int dwLcid); - - void GetLocaleID( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwLcid); - - void QueryAvailableLocaleIDs( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr pdwLcid); - - void GetErrorString( - [MarshalAs(UnmanagedType.I4)] - int dwError, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out String ppString); - - void SetClientName( - [MarshalAs(UnmanagedType.LPWStr)] - String szName); - } - - /// - [ComImport] - [GuidAttribute("13486D50-4821-11D2-A494-3CB306C10000")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCServerList - { - void EnumClassesOfCategories( - [MarshalAs(UnmanagedType.I4)] - int cImplemented, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - Guid[] rgcatidImpl, - [MarshalAs(UnmanagedType.I4)] - int cRequired, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=2)] - Guid[] rgcatidReq, - [Out][MarshalAs(UnmanagedType.IUnknown)] - out object ppenumClsid); - - void GetClassDetails( - ref Guid clsid, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppszProgID, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppszUserType); - - void CLSIDFromProgID( - [MarshalAs(UnmanagedType.LPWStr)] - string szProgId, - [Out] - out Guid clsid); - } - - /// - [ComImport] - [GuidAttribute("55C382C8-21C7-4e88-96C1-BECFB1E3F483")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCEnumGUID - { - void Next( - [MarshalAs(UnmanagedType.I4)] - int celt, - [Out] - IntPtr rgelt, - [Out][MarshalAs(UnmanagedType.I4)] - out int pceltFetched); - - void Skip( - [MarshalAs(UnmanagedType.I4)] - int celt); - - void Reset(); - - void Clone( - [Out] - out IOPCEnumGUID ppenum); - } - - /// - [ComImport] - [GuidAttribute("0002E000-0000-0000-C000-000000000046")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IEnumGUID - { - void Next( - [MarshalAs(UnmanagedType.I4)] - int celt, - [Out] - IntPtr rgelt, - [Out][MarshalAs(UnmanagedType.I4)] - out int pceltFetched); - - void Skip( - [MarshalAs(UnmanagedType.I4)] - int celt); - - void Reset(); - - void Clone( - [Out] - out IEnumGUID ppenum); - } - - /// - [ComImport] - [GuidAttribute("00000100-0000-0000-C000-000000000046")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IEnumUnknown - { - void RemoteNext( - [MarshalAs(UnmanagedType.I4)] - int celt, - [Out] - IntPtr rgelt, - [Out][MarshalAs(UnmanagedType.I4)] - out int pceltFetched); - - void Skip( - [MarshalAs(UnmanagedType.I4)] - int celt); - - void Reset(); - - void Clone( - [Out] - out IEnumUnknown ppenum); - } - - /// - [ComImport] - [GuidAttribute("00000101-0000-0000-C000-000000000046")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IEnumString - { - [PreserveSig] - int RemoteNext( - [MarshalAs(UnmanagedType.I4)] - int celt, - IntPtr rgelt, - [Out][MarshalAs(UnmanagedType.I4)] - out int pceltFetched); - - void Skip( - [MarshalAs(UnmanagedType.I4)] - int celt); - - void Reset(); - - void Clone( - [Out] - out IEnumString ppenum); - } - - /// - [ComImport] - [GuidAttribute("9DD0B56C-AD9E-43ee-8305-487F3188BF7A")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCServerList2 - { - void EnumClassesOfCategories( - [MarshalAs(UnmanagedType.I4)] - int cImplemented, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - Guid[] rgcatidImpl, - [MarshalAs(UnmanagedType.I4)] - int cRequired, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - Guid[] rgcatidReq, - [Out] - out IOPCEnumGUID ppenumClsid); - - void GetClassDetails( - ref Guid clsid, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppszProgID, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppszUserType, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppszVerIndProgID); - - void CLSIDFromProgID( - [MarshalAs(UnmanagedType.LPWStr)] - string szProgId, - [Out] - out Guid clsid); - } -} diff --git a/ComIOP/Common/Rcw/DataAccess.cs b/ComIOP/Common/Rcw/DataAccess.cs deleted file mode 100644 index a115125f3..000000000 --- a/ComIOP/Common/Rcw/DataAccess.cs +++ /dev/null @@ -1,1425 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; - -#pragma warning disable 1591 - -namespace OpcRcw.Da -{ - /// - [ComImport] - [GuidAttribute("63D5F430-CFE4-11d1-B2C8-0060083BA1FB")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface CATID_OPCDAServer10 {} - - /// - [ComImport] - [GuidAttribute("63D5F432-CFE4-11d1-B2C8-0060083BA1FB")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface CATID_OPCDAServer20 {} - - /// - [ComImport] - [GuidAttribute("CC603642-66D7-48f1-B69A-B625E73652D7")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface CATID_OPCDAServer30 {} - - /// - [ComImport] - [GuidAttribute("3098EDA4-A006-48b2-A27F-247453959408")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface CATID_XMLDAServer10 {} - - /// - public enum OPCDATASOURCE - { - OPC_DS_CACHE = 1, - OPC_DS_DEVICE - } - - /// - public enum OPCBROWSETYPE - { - OPC_BRANCH = 1, - OPC_LEAF, - OPC_FLAT - } - - /// - public enum OPCNAMESPACETYPE - { - OPC_NS_HIERARCHIAL = 1, - OPC_NS_FLAT - } - - /// - public enum OPCBROWSEDIRECTION - { - OPC_BROWSE_UP = 1, - OPC_BROWSE_DOWN, - OPC_BROWSE_TO - } - - /// - public enum OPCEUTYPE - { - OPC_NOENUM = 0, - OPC_ANALOG, - OPC_ENUMERATED - } - - /// - public enum OPCSERVERSTATE - { - OPC_STATUS_RUNNING = 1, - OPC_STATUS_FAILED, - OPC_STATUS_NOCONFIG, - OPC_STATUS_SUSPENDED, - OPC_STATUS_TEST, - OPC_STATUS_COMM_FAULT - } - - /// - public enum OPCENUMSCOPE - { - OPC_ENUM_PRIVATE_CONNECTIONS = 1, - OPC_ENUM_PUBLIC_CONNECTIONS, - OPC_ENUM_ALL_CONNECTIONS, - OPC_ENUM_PRIVATE, - OPC_ENUM_PUBLIC, - OPC_ENUM_ALL - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCGROUPHEADER - { - [MarshalAs(UnmanagedType.I4)] - public int dwSize; - [MarshalAs(UnmanagedType.I4)] - public int dwItemCount; - [MarshalAs(UnmanagedType.I4)] - public int hClientGroup; - [MarshalAs(UnmanagedType.I4)] - public int dwTransactionID; - [MarshalAs(UnmanagedType.I4)] - public int hrStatus; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMHEADER1 - { - [MarshalAs(UnmanagedType.I4)] - public int hClient; - [MarshalAs(UnmanagedType.I4)] - public int dwValueOffset; - [MarshalAs(UnmanagedType.I2)] - public short wQuality; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - public System.Runtime.InteropServices.ComTypes.FILETIME ftTimeStampItem; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMHEADER2 - { - [MarshalAs(UnmanagedType.I4)] - public int hClient; - [MarshalAs(UnmanagedType.I4)] - public int dwValueOffset; - [MarshalAs(UnmanagedType.I2)] - public short wQuality; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCGROUPHEADERWRITE - { - [MarshalAs(UnmanagedType.I4)] - public int dwItemCount; - [MarshalAs(UnmanagedType.I4)] - public int hClientGroup; - [MarshalAs(UnmanagedType.I4)] - public int dwTransactionID; - [MarshalAs(UnmanagedType.I4)] - public int hrStatus; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMHEADERWRITE - { - [MarshalAs(UnmanagedType.I4)] - public int hClient; - [MarshalAs(UnmanagedType.I4)] - public int dwError; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMSTATE - { - [MarshalAs(UnmanagedType.I4)] - public int hClient; - public System.Runtime.InteropServices.ComTypes.FILETIME ftTimeStamp; - [MarshalAs(UnmanagedType.I2)] - public short wQuality; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - [MarshalAs(UnmanagedType.Struct)] - public object vDataValue; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCSERVERSTATUS - { - public System.Runtime.InteropServices.ComTypes.FILETIME ftStartTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftCurrentTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftLastUpdateTime; - public OPCSERVERSTATE dwServerState; - [MarshalAs(UnmanagedType.I4)] - public int dwGroupCount; - [MarshalAs(UnmanagedType.I4)] - public int dwBandWidth; - [MarshalAs(UnmanagedType.I2)] - public short wMajorVersion; - [MarshalAs(UnmanagedType.I2)] - public short wMinorVersion; - [MarshalAs(UnmanagedType.I2)] - public short wBuildNumber; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - [MarshalAs(UnmanagedType.LPWStr)] - public string szVendorInfo; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMDEF - { - [MarshalAs(UnmanagedType.LPWStr)] - public string szAccessPath; - [MarshalAs(UnmanagedType.LPWStr)] - public string szItemID; - [MarshalAs(UnmanagedType.I4)] - public int bActive; - [MarshalAs(UnmanagedType.I4)] - public int hClient; - [MarshalAs(UnmanagedType.I4)] - public int dwBlobSize; - public IntPtr pBlob; - [MarshalAs(UnmanagedType.I2)] - public short vtRequestedDataType; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - }; - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMATTRIBUTES - { - [MarshalAs(UnmanagedType.LPWStr)] - public string szAccessPath; - [MarshalAs(UnmanagedType.LPWStr)] - public string szItemID; - [MarshalAs(UnmanagedType.I4)] - public int bActive; - [MarshalAs(UnmanagedType.I4)] - public int hClient; - [MarshalAs(UnmanagedType.I4)] - public int hServer; - [MarshalAs(UnmanagedType.I4)] - public int dwAccessRights; - [MarshalAs(UnmanagedType.I4)] - public int dwBlobSize; - public IntPtr pBlob; - [MarshalAs(UnmanagedType.I2)] - public short vtRequestedDataType; - [MarshalAs(UnmanagedType.I2)] - public short vtCanonicalDataType; - public OPCEUTYPE dwEUType; - [MarshalAs(UnmanagedType.Struct)] - public object vEUInfo; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMRESULT - { - [MarshalAs(UnmanagedType.I4)] - public int hServer; - [MarshalAs(UnmanagedType.I2)] - public short vtCanonicalDataType; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - [MarshalAs(UnmanagedType.I4)] - public int dwAccessRights; - [MarshalAs(UnmanagedType.I4)] - public int dwBlobSize; - public IntPtr pBlob; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMPROPERTY - { - [MarshalAs(UnmanagedType.I2)] - public short vtDataType; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - [MarshalAs(UnmanagedType.I4)] - public int dwPropertyID; - [MarshalAs(UnmanagedType.LPWStr)] - public string szItemID; - [MarshalAs(UnmanagedType.LPWStr)] - public string szDescription; - [MarshalAs(UnmanagedType.Struct)] - public object vValue; - [MarshalAs(UnmanagedType.I4)] - public int hrErrorID; - [MarshalAs(UnmanagedType.I4)] - public int dwReserved; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMPROPERTIES - { - [MarshalAs(UnmanagedType.I4)] - public int hrErrorID; - [MarshalAs(UnmanagedType.I4)] - public int dwNumProperties; - public IntPtr pItemProperties; - [MarshalAs(UnmanagedType.I4)] - public int dwReserved; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCBROWSEELEMENT - { - [MarshalAs(UnmanagedType.LPWStr)] - public string szName; - [MarshalAs(UnmanagedType.LPWStr)] - public string szItemID; - [MarshalAs(UnmanagedType.I4)] - public int dwFlagValue; - [MarshalAs(UnmanagedType.I4)] - public int dwReserved; - public OPCITEMPROPERTIES ItemProperties; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCITEMVQT - { - [MarshalAs(UnmanagedType.Struct)] - public object vDataValue; - [MarshalAs(UnmanagedType.I4)] - public int bQualitySpecified; - [MarshalAs(UnmanagedType.I2)] - public short wQuality; - [MarshalAs(UnmanagedType.I2)] - public short wReserved; - [MarshalAs(UnmanagedType.I4)] - public int bTimeStampSpecified; - [MarshalAs(UnmanagedType.I4)] - public int dwReserved; - public System.Runtime.InteropServices.ComTypes.FILETIME ftTimeStamp; - } - - /// - public enum OPCBROWSEFILTER - { - OPC_BROWSE_FILTER_ALL = 1, - OPC_BROWSE_FILTER_BRANCHES, - OPC_BROWSE_FILTER_ITEMS, - } - - /// - [ComImport] - [GuidAttribute("39c13a4d-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCServer - { - void AddGroup( - [MarshalAs(UnmanagedType.LPWStr)] - string szName, - [MarshalAs(UnmanagedType.I4)] - int bActive, - [MarshalAs(UnmanagedType.I4)] - int dwRequestedUpdateRate, - [MarshalAs(UnmanagedType.I4)] - int hClientGroup, - IntPtr pTimeBias, - IntPtr pPercentDeadband, - [MarshalAs(UnmanagedType.I4)] - int dwLCID, - [Out][MarshalAs(UnmanagedType.I4)] - out int phServerGroup, - [Out][MarshalAs(UnmanagedType.I4)] - out int pRevisedUpdateRate, - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=9)] - out object ppUnk); - - void GetErrorString( - [MarshalAs(UnmanagedType.I4)] - int dwError, - [MarshalAs(UnmanagedType.I4)] - int dwLocale, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppString); - - void GetGroupByName( - [MarshalAs(UnmanagedType.LPWStr)] - string szName, - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=1)] - out object ppUnk); - - void GetStatus( - [Out] - out IntPtr ppServerStatus); - - void RemoveGroup( - [MarshalAs(UnmanagedType.I4)] - int hServerGroup, - [MarshalAs(UnmanagedType.I4)] - int bForce); - - void CreateGroupEnumerator( - OPCENUMSCOPE dwScope, - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=1)] - out object ppUnk); - } - - /// - [ComImport] - [GuidAttribute("39c13a4e-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCServerPublicGroups - { - void GetPublicGroupByName( - [MarshalAs(UnmanagedType.LPWStr)] - string szName, - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=1)] - out object ppUnk); - - void RemovePublicGroup( - [MarshalAs(UnmanagedType.I4)] - int hServerGroup, - [MarshalAs(UnmanagedType.I4)] - int bForce); - } - - /// - [ComImport] - [GuidAttribute("39c13a4f-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCBrowseServerAddressSpace - { - void QueryOrganization( - [Out] - out OPCNAMESPACETYPE pNameSpaceType); - - void ChangeBrowsePosition( - OPCBROWSEDIRECTION dwBrowseDirection, - [MarshalAs(UnmanagedType.LPWStr)] - string szString); - - void BrowseOPCItemIDs( - OPCBROWSETYPE dwBrowseFilterType, - [MarshalAs(UnmanagedType.LPWStr)] - string szFilterCriteria, - [MarshalAs(UnmanagedType.I2)] - short vtDataTypeFilter, - [MarshalAs(UnmanagedType.I4)] - int dwAccessRightsFilter, - [Out] - out OpcRcw.Comn.IEnumString ppIEnumString); - - void GetItemID( - [MarshalAs(UnmanagedType.LPWStr)] - string szItemDataID, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string szItemID); - - void BrowseAccessPaths( - [MarshalAs(UnmanagedType.LPWStr)] - string szItemID, - [Out] - out OpcRcw.Comn.IEnumString pIEnumString); - } - - /// - [ComImport] - [GuidAttribute("39c13a50-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCGroupStateMgt - { - void GetState( - [Out][MarshalAs(UnmanagedType.I4)] - out int pUpdateRate, - [Out][MarshalAs(UnmanagedType.I4)] - out int pActive, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppName, - [Out][MarshalAs(UnmanagedType.I4)] - out int pTimeBias, - [Out][MarshalAs(UnmanagedType.R4)] - out float pPercentDeadband, - [Out][MarshalAs(UnmanagedType.I4)] - out int pLCID, - [Out][MarshalAs(UnmanagedType.I4)] - out int phClientGroup, - [Out][MarshalAs(UnmanagedType.I4)] - out int phServerGroup); - - void SetState( - IntPtr pRequestedUpdateRate, - [Out][MarshalAs(UnmanagedType.I4)] - out int pRevisedUpdateRate, - IntPtr pActive, - IntPtr pTimeBias, - IntPtr pPercentDeadband, - IntPtr pLCID, - IntPtr phClientGroup); - - void SetName( - [MarshalAs(UnmanagedType.LPWStr)] - string szName); - - void CloneGroup( - [MarshalAs(UnmanagedType.LPWStr)] - string szName, - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=1)] - out object ppUnk); - } - - /// - [ComImport] - [GuidAttribute("39c13a51-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCPublicGroupStateMgt - { - void GetState( - [Out][MarshalAs(UnmanagedType.I4)] - out int pPublic); - - void MoveToPublic(); - } - - /// - [ComImport] - [GuidAttribute("39c13a52-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCSyncIO - { - void Read( - OPCDATASOURCE dwSource, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] phServer, - [Out] - out IntPtr ppItemValues, - [Out] - out IntPtr ppErrors); - - void Write( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=0)] - object[] pItemValues, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("39c13a53-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCAsyncIO - { - void Read( - [MarshalAs(UnmanagedType.I4)] - int dwConnection, - OPCDATASOURCE dwSource, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phServer, - [Out][MarshalAs(UnmanagedType.I4)] - out int pTransactionID, - [Out] - out IntPtr ppErrors); - - void Write( - [MarshalAs(UnmanagedType.I4)] - int dwConnection, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=1)] - object[] pItemValues, - [Out][MarshalAs(UnmanagedType.I4)] - out int pTransactionID, - [Out] - out IntPtr ppErrors); - - void Refresh( - [MarshalAs(UnmanagedType.I4)] - int dwConnection, - OPCDATASOURCE dwSource, - [Out][MarshalAs(UnmanagedType.I4)] - out int pTransactionID); - - void Cancel( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID); - } - - /// - [ComImport] - [GuidAttribute("39c13a54-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCItemMgt - { - void AddItems( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - OPCITEMDEF[] pItemArray, - [Out] - out IntPtr ppAddResults, - [Out] - out IntPtr ppErrors); - - void ValidateItems( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - OPCITEMDEF[] pItemArray, - [MarshalAs(UnmanagedType.I4)] - int bBlobUpdate, - [Out] - out IntPtr ppValidationResults, - [Out] - out IntPtr ppErrors); - - void RemoveItems( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [Out] - out IntPtr ppErrors); - - void SetActiveState( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.I4)] - int bActive, - [Out] - out IntPtr ppErrors); - - void SetClientHandles( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phClient, - [Out] - out IntPtr ppErrors); - - void SetDatatypes( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I2, SizeParamIndex=0)] - short[] pRequestedDatatypes, - [Out] - out IntPtr ppErrors); - - void CreateEnumerator( - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=0)] - out object ppUnk); - } - - /// - [ComImport] - [GuidAttribute("39c13a55-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IEnumOPCItemAttributes - { - void Next( - [MarshalAs(UnmanagedType.I4)] - int celt, - [Out] - out IntPtr ppItemArray, - [Out][MarshalAs(UnmanagedType.I4)] - out int pceltFetched); - - void Skip( - [MarshalAs(UnmanagedType.I4)] - int celt); - - void Reset(); - - void Clone( - [Out] - out IEnumOPCItemAttributes ppEnumItemAttributes); - } - - /// - [ComImport] - [GuidAttribute("39c13a70-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCDataCallback - { - void OnDataChange( - [MarshalAs(UnmanagedType.I4)] - int dwTransid, - [MarshalAs(UnmanagedType.I4)] - int hGroup, - [MarshalAs(UnmanagedType.I4)] - int hrMasterquality, - [MarshalAs(UnmanagedType.I4)] - int hrMastererror, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] phClientItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=4)] - object[] pvValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I2, SizeParamIndex=4)] - short[] pwQualities, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=4)] - System.Runtime.InteropServices.ComTypes.FILETIME[] pftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] pErrors); - - void OnReadComplete( - [MarshalAs(UnmanagedType.I4)] - int dwTransid, - [MarshalAs(UnmanagedType.I4)] - int hGroup, - [MarshalAs(UnmanagedType.I4)] - int hrMasterquality, - [MarshalAs(UnmanagedType.I4)] - int hrMastererror, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] phClientItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=4)] - object[] pvValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I2, SizeParamIndex=4)] - short[] pwQualities, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=4)] - System.Runtime.InteropServices.ComTypes.FILETIME[] pftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] pErrors); - - void OnWriteComplete( - [MarshalAs(UnmanagedType.I4)] - int dwTransid, - [MarshalAs(UnmanagedType.I4)] - int hGroup, - [MarshalAs(UnmanagedType.I4)] - int hrMastererr, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] pClienthandles, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] pErrors); - - void OnCancelComplete( - [MarshalAs(UnmanagedType.I4)] - int dwTransid, - [MarshalAs(UnmanagedType.I4)] - int hGroup); - } - - /// - [ComImport] - [GuidAttribute("39c13a71-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCAsyncIO2 - { - void Read( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Write( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=0)] - object[] pItemValues, - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Refresh2( - OPCDATASOURCE dwSource, - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCancelID); - - void Cancel2( - [MarshalAs(UnmanagedType.I4)] - int dwCancelID); - - void SetEnable( - [MarshalAs(UnmanagedType.I4)] - int bEnable); - - void GetEnable( - [Out][MarshalAs(UnmanagedType.I4)] - out int pbEnable); - } - - /// - [ComImport] - [GuidAttribute("39c13a72-011e-11d0-9675-0020afd8adb3")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCItemProperties - { - void QueryAvailableProperties( - [MarshalAs(UnmanagedType.LPWStr)] - string szItemID, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppPropertyIDs, - [Out] - out IntPtr ppDescriptions, - [Out] - out IntPtr ppvtDataTypes); - - void GetItemProperties( - [MarshalAs(UnmanagedType.LPWStr)] - string szItemID, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] pdwPropertyIDs, - [Out] - out IntPtr ppvData, - [Out] - out IntPtr ppErrors); - - void LookupItemIDs( - [MarshalAs(UnmanagedType.LPWStr)] - string szItemID, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] pdwPropertyIDs, - [Out] - out IntPtr ppszNewItemIDs, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("5946DA93-8B39-4ec8-AB3D-AA73DF5BC86F")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCItemDeadbandMgt - { - void SetItemDeadband( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.R4, SizeParamIndex=0)] - float[] pPercentDeadband, - [Out] - out IntPtr ppErrors); - - void GetItemDeadband( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [Out] - out IntPtr ppPercentDeadband, - [Out] - out IntPtr ppErrors); - - void ClearItemDeadband( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("3E22D313-F08B-41a5-86C8-95E95CB49FFC")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCItemSamplingMgt - { - void SetItemSamplingRate( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwRequestedSamplingRate, - [Out] - out IntPtr ppdwRevisedSamplingRate, - [Out] - out IntPtr ppErrors); - - void GetItemSamplingRate( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [Out] - out IntPtr ppdwSamplingRate, - [Out] - out IntPtr ppErrors); - - void ClearItemSamplingRate( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [Out] - out IntPtr ppErrors); - - void SetItemBufferEnable( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pbEnable, - [Out] - out IntPtr ppErrors); - - void GetItemBufferEnable( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [Out] - out IntPtr ppbEnable, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("39227004-A18F-4b57-8B0A-5235670F4468")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCBrowse - { - void GetProperties( - [MarshalAs(UnmanagedType.I4)] - int dwItemCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszItemIDs, - [MarshalAs(UnmanagedType.I4)] - int bReturnPropertyValues, - [MarshalAs(UnmanagedType.I4)] - int dwPropertyCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] dwPropertyIDs, - [Out] - out IntPtr ppItemProperties); - - void Browse( - [MarshalAs(UnmanagedType.LPWStr)] - string szItemID, - ref IntPtr pszContinuationPoint, - [MarshalAs(UnmanagedType.I4)] - int dwMaxElementsReturned, - OPCBROWSEFILTER dwBrowseFilter, - [MarshalAs(UnmanagedType.LPWStr)] - string szElementNameFilter, - [MarshalAs(UnmanagedType.LPWStr)] - string szVendorFilter, - [MarshalAs(UnmanagedType.I4)] - int bReturnAllProperties, - [MarshalAs(UnmanagedType.I4)] - int bReturnPropertyValues, - [MarshalAs(UnmanagedType.I4)] - int dwPropertyCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=8)] - int[] pdwPropertyIDs, - [Out][MarshalAs(UnmanagedType.I4)] - out int pbMoreElements, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppBrowseElements); - } - - /// - [ComImport] - [GuidAttribute("85C0B427-2893-4cbc-BD78-E5FC5146F08F")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCItemIO - { - void Read( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszItemIDs, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwMaxAge, - [Out] - out IntPtr ppvValues, - [Out] - out IntPtr ppwQualities, - [Out] - out IntPtr ppftTimeStamps, - [Out] - out IntPtr ppErrors); - - void WriteVQT( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszItemIDs, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - OPCITEMVQT[] pItemVQT, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("730F5F0F-55B1-4c81-9E18-FF8A0904E1FA")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCSyncIO2 // : IOPCSyncIO - { - void Read( - OPCDATASOURCE dwSource, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] phServer, - [Out] - out IntPtr ppItemValues, - [Out] - out IntPtr ppErrors); - - void Write( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=0)] - object[] pItemValues, - [Out] - out IntPtr ppErrors); - - void ReadMaxAge( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwMaxAge, - [Out] - out IntPtr ppvValues, - [Out] - out IntPtr ppwQualities, - [Out] - out IntPtr ppftTimeStamps, - [Out] - out IntPtr ppErrors); - - void WriteVQT( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - OPCITEMVQT[] pItemVQT, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("0967B97B-36EF-423e-B6F8-6BFF1E40D39D")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCAsyncIO3 // : IOPCAsyncIO2 - { - void Read( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Write( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=0)] - object[] pItemValues, - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Refresh2( - OPCDATASOURCE dwSource, - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCancelID); - - void Cancel2( - [MarshalAs(UnmanagedType.I4)] - int dwCancelID); - - void SetEnable( - [MarshalAs(UnmanagedType.I4)] - int bEnable); - - void GetEnable( - [Out][MarshalAs(UnmanagedType.I4)] - out int pbEnable); - - void ReadMaxAge( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwMaxAge, - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [Out] - [MarshalAs(UnmanagedType.I4)] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void WriteVQT( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - OPCITEMVQT[] pItemVQT, - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [Out] - [MarshalAs(UnmanagedType.I4)] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void RefreshMaxAge( - [MarshalAs(UnmanagedType.I4)] - int dwMaxAge, - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [Out] - [MarshalAs(UnmanagedType.I4)] - out int pdwCancelID); - } - - /// - [ComImport] - [GuidAttribute("8E368666-D72E-4f78-87ED-647611C61C9F")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCGroupStateMgt2 // : IOPCGroupStateMgt - { - void GetState( - [Out][MarshalAs(UnmanagedType.I4)] - out int pUpdateRate, - [Out][MarshalAs(UnmanagedType.I4)] - out int pActive, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppName, - [Out][MarshalAs(UnmanagedType.I4)] - out int pTimeBias, - [Out][MarshalAs(UnmanagedType.R4)] - out float pPercentDeadband, - [Out][MarshalAs(UnmanagedType.I4)] - out int pLCID, - [Out][MarshalAs(UnmanagedType.I4)] - out int phClientGroup, - [Out][MarshalAs(UnmanagedType.I4)] - out int phServerGroup); - - void SetState( - IntPtr pRequestedUpdateRate, - [Out][MarshalAs(UnmanagedType.I4)] - out int pRevisedUpdateRate, - IntPtr pActive, - IntPtr pTimeBias, - IntPtr pPercentDeadband, - IntPtr pLCID, - IntPtr phClientGroup); - - void SetName( - [MarshalAs(UnmanagedType.LPWStr)] - string szName); - - void CloneGroup( - [MarshalAs(UnmanagedType.LPWStr)] - string szName, - ref Guid riid, - [Out][MarshalAs(UnmanagedType.IUnknown, IidParameterIndex=1)] - out object ppUnk); - - void SetKeepAlive( - [MarshalAs(UnmanagedType.I4)] - int dwKeepAliveTime, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwRevisedKeepAliveTime); - - void GetKeepAlive( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwKeepAliveTime); - } - - /// - public static class Constants - { - // category description strings. - public const string OPC_CATEGORY_DESCRIPTION_DA10 = "OPC Data Access Servers Version 1.0"; - public const string OPC_CATEGORY_DESCRIPTION_DA20 = "OPC Data Access Servers Version 2.0"; - public const string OPC_CATEGORY_DESCRIPTION_DA30 = "OPC Data Access Servers Version 3.0"; - public const string OPC_CATEGORY_DESCRIPTION_XMLDA10 = "OPC XML Data Access Servers Version 1.0"; - - // values for access rights mask. - public const int OPC_READABLE = 0x01; - public const int OPC_WRITEABLE = 0x02; - - // values for browse element flags. - public const int OPC_BROWSE_HASCHILDREN = 0x01; - public const int OPC_BROWSE_ISITEM = 0x02; - - // well known complex type description systems. - public const string OPC_TYPE_SYSTEM_OPCBINARY = "OPCBinary"; - public const string OPC_TYPE_SYSTEM_XMLSCHEMA = "XMLSchema"; - - // complex data consitency window values. - public const string OPC_CONSISTENCY_WINDOW_UNKNOWN = "Unknown"; - public const string OPC_CONSISTENCY_WINDOW_NOT_CONSISTENT = "Not Consistent"; - - // complex data write behavior values. - public const string OPC_WRITE_BEHAVIOR_BEST_EFFORT = "Best Effort"; - public const string OPC_WRITE_BEHAVIOR_ALL_OR_NOTHING = "All or Nothing"; - } - - /// - public static class Qualities - { - // Values for fields in the quality word - public const short OPC_QUALITY_MASK = 0xC0; - public const short OPC_STATUS_MASK = 0xFC; - public const short OPC_LIMIT_MASK = 0x03; - - // Values for QUALITY_MASK bit field - public const short OPC_QUALITY_BAD = 0x00; - public const short OPC_QUALITY_UNCERTAIN = 0x40; - public const short OPC_QUALITY_GOOD = 0xC0; - - // STATUS_MASK Values for Quality = BAD - public const short OPC_QUALITY_CONFIG_ERROR = 0x04; - public const short OPC_QUALITY_NOT_CONNECTED = 0x08; - public const short OPC_QUALITY_DEVICE_FAILURE = 0x0c; - public const short OPC_QUALITY_SENSOR_FAILURE = 0x10; - public const short OPC_QUALITY_LAST_KNOWN = 0x14; - public const short OPC_QUALITY_COMM_FAILURE = 0x18; - public const short OPC_QUALITY_OUT_OF_SERVICE = 0x1C; - public const short OPC_QUALITY_WAITING_FOR_INITIAL_DATA = 0x20; - - // STATUS_MASK Values for Quality = UNCERTAIN - public const short OPC_QUALITY_LAST_USABLE = 0x44; - public const short OPC_QUALITY_SENSOR_CAL = 0x50; - public const short OPC_QUALITY_EGU_EXCEEDED = 0x54; - public const short OPC_QUALITY_SUB_NORMAL = 0x58; - - // STATUS_MASK Values for Quality = GOOD - public const short OPC_QUALITY_LOCAL_OVERRIDE = 0xD8; - - // Values for Limit Bitfield - public const short OPC_LIMIT_OK = 0x00; - public const short OPC_LIMIT_LOW = 0x01; - public const short OPC_LIMIT_HIGH = 0x02; - public const short OPC_LIMIT_CONST = 0x03; - } - - //========================================================================== - // Properties - - /// - public static class Properties - { - // property ids. - public const int OPC_PROPERTY_DATATYPE = 1; - public const int OPC_PROPERTY_VALUE = 2; - public const int OPC_PROPERTY_QUALITY = 3; - public const int OPC_PROPERTY_TIMESTAMP = 4; - public const int OPC_PROPERTY_ACCESS_RIGHTS = 5; - public const int OPC_PROPERTY_SCAN_RATE = 6; - public const int OPC_PROPERTY_EU_TYPE = 7; - public const int OPC_PROPERTY_EU_INFO = 8; - public const int OPC_PROPERTY_EU_UNITS = 100; - public const int OPC_PROPERTY_DESCRIPTION = 101; - public const int OPC_PROPERTY_HIGH_EU = 102; - public const int OPC_PROPERTY_LOW_EU = 103; - public const int OPC_PROPERTY_HIGH_IR = 104; - public const int OPC_PROPERTY_LOW_IR = 105; - public const int OPC_PROPERTY_CLOSE_LABEL = 106; - public const int OPC_PROPERTY_OPEN_LABEL = 107; - public const int OPC_PROPERTY_TIMEZONE = 108; - public const int OPC_PROPERTY_CONDITION_STATUS = 300; - public const int OPC_PROPERTY_ALARM_QUICK_HELP = 301; - public const int OPC_PROPERTY_ALARM_AREA_LIST = 302; - public const int OPC_PROPERTY_PRIMARY_ALARM_AREA = 303; - public const int OPC_PROPERTY_CONDITION_LOGIC = 304; - public const int OPC_PROPERTY_LIMIT_EXCEEDED = 305; - public const int OPC_PROPERTY_DEADBAND = 306; - public const int OPC_PROPERTY_HIHI_LIMIT = 307; - public const int OPC_PROPERTY_HI_LIMIT = 308; - public const int OPC_PROPERTY_LO_LIMIT = 309; - public const int OPC_PROPERTY_LOLO_LIMIT = 310; - public const int OPC_PROPERTY_CHANGE_RATE_LIMIT = 311; - public const int OPC_PROPERTY_DEVIATION_LIMIT = 312; - public const int OPC_PROPERTY_SOUND_FILE = 313; - - // complex data properties. - public const int OPC_PROPERTY_TYPE_SYSTEM_ID = 600; - public const int OPC_PROPERTY_DICTIONARY_ID = 601; - public const int OPC_PROPERTY_TYPE_ID = 602; - public const int OPC_PROPERTY_DICTIONARY = 603; - public const int OPC_PROPERTY_TYPE_DESCRIPTION = 604; - public const int OPC_PROPERTY_CONSISTENCY_WINDOW = 605; - public const int OPC_PROPERTY_WRITE_BEHAVIOR = 606; - public const int OPC_PROPERTY_UNCONVERTED_ITEM_ID = 607; - public const int OPC_PROPERTY_UNFILTERED_ITEM_ID = 608; - public const int OPC_PROPERTY_DATA_FILTER_VALUE = 609; - - // property descriptions. - public const string OPC_PROPERTY_DESC_DATATYPE = "Item Canonical Data Type"; - public const string OPC_PROPERTY_DESC_VALUE = "Item Value"; - public const string OPC_PROPERTY_DESC_QUALITY = "Item Quality"; - public const string OPC_PROPERTY_DESC_TIMESTAMP = "Item Timestamp"; - public const string OPC_PROPERTY_DESC_ACCESS_RIGHTS = "Item Access Rights"; - public const string OPC_PROPERTY_DESC_SCAN_RATE = "Server Scan Rate"; - public const string OPC_PROPERTY_DESC_EU_TYPE = "Item EU Type"; - public const string OPC_PROPERTY_DESC_EU_INFO = "Item EU Info"; - public const string OPC_PROPERTY_DESC_EU_UNITS = "EU Units"; - public const string OPC_PROPERTY_DESC_DESCRIPTION = "Item Description"; - public const string OPC_PROPERTY_DESC_HIGH_EU = "High EU"; - public const string OPC_PROPERTY_DESC_LOW_EU = "Low EU"; - public const string OPC_PROPERTY_DESC_HIGH_IR = "High Instrument Range"; - public const string OPC_PROPERTY_DESC_LOW_IR = "Low Instrument Range"; - public const string OPC_PROPERTY_DESC_CLOSE_LABEL = "Contact Close Label"; - public const string OPC_PROPERTY_DESC_OPEN_LABEL = "Contact Open Label"; - public const string OPC_PROPERTY_DESC_TIMEZONE = "Item Timezone"; - public const string OPC_PROPERTY_DESC_CONDITION_STATUS = "Condition Status"; - public const string OPC_PROPERTY_DESC_ALARM_QUICK_HELP = "Alarm Quick Help"; - public const string OPC_PROPERTY_DESC_ALARM_AREA_LIST = "Alarm Area List"; - public const string OPC_PROPERTY_DESC_PRIMARY_ALARM_AREA = "Primary Alarm Area"; - public const string OPC_PROPERTY_DESC_CONDITION_LOGIC = "Condition Logic"; - public const string OPC_PROPERTY_DESC_LIMIT_EXCEEDED = "Limit Exceeded"; - public const string OPC_PROPERTY_DESC_DEADBAND = "Deadband"; - public const string OPC_PROPERTY_DESC_HIHI_LIMIT = "HiHi Limit"; - public const string OPC_PROPERTY_DESC_HI_LIMIT = "Hi Limit"; - public const string OPC_PROPERTY_DESC_LO_LIMIT = "Lo Limit"; - public const string OPC_PROPERTY_DESC_LOLO_LIMIT = "LoLo Limit"; - public const string OPC_PROPERTY_DESC_CHANGE_RATE_LIMIT = "Rate of Change Limit"; - public const string OPC_PROPERTY_DESC_DEVIATION_LIMIT = "Deviation Limit"; - public const string OPC_PROPERTY_DESC_SOUND_FILE = "Sound File"; - - // complex data properties. - public const string OPC_PROPERTY_DESC_TYPE_SYSTEM_ID = "Type System ID"; - public const string OPC_PROPERTY_DESC_DICTIONARY_ID = "Dictionary ID"; - public const string OPC_PROPERTY_DESC_TYPE_ID = "Type ID"; - public const string OPC_PROPERTY_DESC_DICTIONARY = "Dictionary"; - public const string OPC_PROPERTY_DESC_TYPE_DESCRIPTION = "Type Description"; - public const string OPC_PROPERTY_DESC_CONSISTENCY_WINDOW = "Consistency Window"; - public const string OPC_PROPERTY_DESC_WRITE_BEHAVIOR = "Write Behavior"; - public const string OPC_PROPERTY_DESC_UNCONVERTED_ITEM_ID = "Unconverted Item ID"; - public const string OPC_PROPERTY_DESC_UNFILTERED_ITEM_ID = "Unfiltered Item ID"; - public const string OPC_PROPERTY_DESC_DATA_FILTER_VALUE = "Data Filter Value"; - } -} diff --git a/ComIOP/Common/Rcw/HistoricalDataAccess.cs b/ComIOP/Common/Rcw/HistoricalDataAccess.cs deleted file mode 100644 index 1c602fc4e..000000000 --- a/ComIOP/Common/Rcw/HistoricalDataAccess.cs +++ /dev/null @@ -1,1022 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; - -#pragma warning disable 1591 - -namespace OpcRcw.Hda -{ - - /// - [ComImport] - [GuidAttribute("7DE5B060-E089-11d2-A5E6-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface CATID_OPCHDAServer10 {} - - /// - public enum OPCHDA_SERVERSTATUS - { - OPCHDA_UP = 1, - OPCHDA_DOWN, - OPCHDA_INDETERMINATE - } - - /// - public enum OPCHDA_BROWSEDIRECTION - { - OPCHDA_BROWSE_UP = 1, - OPCHDA_BROWSE_DOWN, - OPCHDA_BROWSE_DIRECT - } - - /// - public enum OPCHDA_BROWSETYPE - { - OPCHDA_BRANCH = 1, - OPCHDA_LEAF, - OPCHDA_FLAT, - OPCHDA_ITEMS - } - - /// - public enum OPCHDA_ANNOTATIONCAPABILITIES - { - OPCHDA_READANNOTATIONCAP = 0x01, - OPCHDA_INSERTANNOTATIONCAP = 0x02 - } - - /// - public enum OPCHDA_UPDATECAPABILITIES - { - OPCHDA_INSERTCAP = 0x01, - OPCHDA_REPLACECAP = 0x02, - OPCHDA_INSERTREPLACECAP = 0x04, - OPCHDA_DELETERAWCAP = 0x08, - OPCHDA_DELETEATTIMECAP = 0x10 - } - - /// - public enum OPCHDA_OPERATORCODES - { - OPCHDA_EQUAL = 1, - OPCHDA_LESS, - OPCHDA_LESSEQUAL, - OPCHDA_GREATER, - OPCHDA_GREATEREQUAL, - OPCHDA_NOTEQUAL - } - - /// - public enum OPCHDA_EDITTYPE - { - OPCHDA_INSERT = 1, - OPCHDA_REPLACE, - OPCHDA_INSERTREPLACE, - OPCHDA_DELETE - } - - /// - public enum OPCHDA_AGGREGATE - { - OPCHDA_NOAGGREGATE = 0, - OPCHDA_INTERPOLATIVE, - OPCHDA_TOTAL, - OPCHDA_AVERAGE, - OPCHDA_TIMEAVERAGE, - OPCHDA_COUNT, - OPCHDA_STDEV, - OPCHDA_MINIMUMACTUALTIME, - OPCHDA_MINIMUM, - OPCHDA_MAXIMUMACTUALTIME, - OPCHDA_MAXIMUM, - OPCHDA_START, - OPCHDA_END, - OPCHDA_DELTA, - OPCHDA_REGSLOPE, - OPCHDA_REGCONST, - OPCHDA_REGDEV, - OPCHDA_VARIANCE, - OPCHDA_RANGE, - OPCHDA_DURATIONGOOD, - OPCHDA_DURATIONBAD, - OPCHDA_PERCENTGOOD, - OPCHDA_PERCENTBAD, - OPCHDA_WORSTQUALITY, - OPCHDA_ANNOTATIONS - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCHDA_ANNOTATION - { - [MarshalAs(UnmanagedType.I4)] - public int hClient; - [MarshalAs(UnmanagedType.I4)] - public int dwNumValues; - public IntPtr ftTimeStamps; - public IntPtr szAnnotation; - public IntPtr ftAnnotationTime; - public IntPtr szUser; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCHDA_MODIFIEDITEM - { - [MarshalAs(UnmanagedType.I4)] - public int hClient; - [MarshalAs(UnmanagedType.I4)] - public int dwCount; - public IntPtr pftTimeStamps; - public IntPtr pdwQualities; - public IntPtr pvDataValues; - public IntPtr pftModificationTime; - public IntPtr pEditType; - public IntPtr szUser; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCHDA_ATTRIBUTE - { - [MarshalAs(UnmanagedType.I4)] - public int hClient; - [MarshalAs(UnmanagedType.I4)] - public int dwNumValues; - [MarshalAs(UnmanagedType.I4)] - public int dwAttributeID; - public IntPtr ftTimeStamps; - public IntPtr vAttributeValues; - }; - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCHDA_TIME - { - [MarshalAs(UnmanagedType.I4)] - public int bString; - [MarshalAs(UnmanagedType.LPWStr)] - public string szTime; - public System.Runtime.InteropServices.ComTypes.FILETIME ftTime; - } - - /// - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct OPCHDA_ITEM - { - [MarshalAs(UnmanagedType.I4)] - public int hClient; - [MarshalAs(UnmanagedType.I4)] - public int haAggregate; - [MarshalAs(UnmanagedType.I4)] - public int dwCount; - public IntPtr pftTimeStamps; - public IntPtr pdwQualities; - public IntPtr pvDataValues; - } - - /// - [ComImport] - [GuidAttribute("1F1217B1-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_Browser - { - void GetEnum( - OPCHDA_BROWSETYPE dwBrowseType, - [Out] - out OpcRcw.Comn.IEnumString ppIEnumString); - - void ChangeBrowsePosition( - OPCHDA_BROWSEDIRECTION dwBrowseDirection, - [MarshalAs(UnmanagedType.LPWStr)] - string szString); - - void GetItemID( - [MarshalAs(UnmanagedType.LPWStr)] - string szNode, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string pszItemID); - - void GetBranchPosition( - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string pszBranchPos); - } - - /// - [ComImport] - [GuidAttribute("1F1217B0-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_Server - { - void GetItemAttributes( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppdwAttrID, - [Out] - out IntPtr ppszAttrName, - [Out] - out IntPtr ppszAttrDesc, - [Out] - out IntPtr ppvtAttrDataType); - - void GetAggregates( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwCount, - [Out] - out IntPtr ppdwAggrID, - [Out] - out IntPtr ppszAggrName, - [Out] - out IntPtr ppszAggrDesc); - - void GetHistorianStatus( - [Out] - out OPCHDA_SERVERSTATUS pwStatus, - [Out] - out IntPtr pftCurrentTime, - [Out] - out IntPtr pftStartTime, - [Out][MarshalAs(UnmanagedType.I2)] - out short pwMajorVersion, - [Out][MarshalAs(UnmanagedType.I2)] - out short wMinorVersion, - [Out][MarshalAs(UnmanagedType.I2)] - out short pwBuildNumber, - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwMaxReturnValues, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppszStatusString, - [Out][MarshalAs(UnmanagedType.LPWStr)] - out string ppszVendorInfo); - - void GetItemHandles( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszItemID, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phClient, - [Out] - out IntPtr pphServer, - [Out] - out IntPtr ppErrors); - - void ReleaseItemHandles( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [Out] - out IntPtr ppErrors); - - void ValidateItemIDs( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] - string[] pszItemID, - [Out] - out IntPtr ppErrors); - - void CreateBrowse( - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwAttrID, - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] - OPCHDA_OPERATORCODES[] pOperator, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=0)] - object[] vFilter, - out IOPCHDA_Browser pphBrowser, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("1F1217B2-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_SyncRead - { - void ReadRaw( - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int dwNumValues, - [MarshalAs(UnmanagedType.I4)] - int bBounds, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] phServer, - [Out] - out IntPtr ppItemValues, - [Out] - out IntPtr ppErrors); - - void ReadProcessed( - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - System.Runtime.InteropServices.ComTypes.FILETIME ftResampleInterval, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] haAggregate, - [Out] - out IntPtr ppItemValues, - [Out] - out IntPtr ppErrors); - - void ReadAtTime( - [MarshalAs(UnmanagedType.I4)] - int dwNumTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phServer, - [Out] - out IntPtr ppItemValues, - [Out] - out IntPtr ppErrors); - - void ReadModified( - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int dwNumValues, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] phServer, - [Out] - out IntPtr ppItemValues, - [Out] - out IntPtr ppErrors); - - void ReadAttribute( - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int hServer, - [MarshalAs(UnmanagedType.I4)] - int dwNumAttributes, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] pdwAttributeIDs, - [Out] - out IntPtr ppAttributeValues, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("1F1217B3-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_SyncUpdate - { - void QueryCapabilities( - [Out] - out OPCHDA_UPDATECAPABILITIES pCapabilities); - - void Insert( - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=0)] - object[] vDataValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwQualities, - [Out] - out IntPtr ppErrors); - - void Replace( - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=0)] - object[] vDataValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwQualities, - [Out] - out IntPtr ppErrors); - - void InsertReplace( - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=0)] - object[] vDataValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] pdwQualities, - [Out] - out IntPtr ppErrors); - - void DeleteRaw( - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phServer, - [Out] - out IntPtr ppErrors); - - void DeleteAtTime( - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("1F1217B4-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_SyncAnnotations - { - void QueryCapabilities( - [Out] - out OPCHDA_ANNOTATIONCAPABILITIES pCapabilities); - - void Read( - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phServer, - [Out] - out IntPtr ppAnnotationValues, - [Out] - out IntPtr ppErrors); - - void Insert( - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=0)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)] - OPCHDA_ANNOTATION[] pAnnotationValues, - [Out] - out IntPtr ppErrors); - } - - /// - [ComImport] - [GuidAttribute("1F1217B5-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_AsyncRead - { - void ReadRaw( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int dwNumValues, - [MarshalAs(UnmanagedType.I4)] - int bBounds, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=5)] - int[] phServer, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void AdviseRaw( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - System.Runtime.InteropServices.ComTypes.FILETIME ftUpdateInterval, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] phServer, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void ReadProcessed( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - System.Runtime.InteropServices.ComTypes.FILETIME ftResampleInterval, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] haAggregate, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void AdviseProcessed( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - System.Runtime.InteropServices.ComTypes.FILETIME ftResampleInterval, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] haAggregate, - [MarshalAs(UnmanagedType.I4)] - int dwNumIntervals, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void ReadAtTime( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int dwNumTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=1)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] phServer, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void ReadModified( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int dwNumValues, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] phServer, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void ReadAttribute( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int hServer, - [MarshalAs(UnmanagedType.I4)] - int dwNumAttributes, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=4)] - int[] dwAttributeIDs, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Cancel( - [MarshalAs(UnmanagedType.I4)] - int dwCancelID); - } - - /// - [ComImport] - [GuidAttribute("1F1217B6-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_AsyncUpdate - { - void QueryCapabilities( - out OPCHDA_UPDATECAPABILITIES pCapabilities - ); - - void Insert( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=1)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=1)] - object[] vDataValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] pdwQualities, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Replace( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=1)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=1)] - object[] vDataValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] pdwQualities, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void InsertReplace( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=1)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=1)] - object[] vDataValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] pdwQualities, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void DeleteRaw( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] phServer, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void DeleteAtTime( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=1)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Cancel( - [MarshalAs(UnmanagedType.I4)] - int dwCancelID); - } - - /// - [ComImport] - [GuidAttribute("1F1217B7-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_AsyncAnnotations - { - void QueryCapabilities( - out OPCHDA_ANNOTATIONCAPABILITIES pCapabilities); - - void Read( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] phServer, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Insert( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=1)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=1)] - System.Runtime.InteropServices.ComTypes.FILETIME[] ftTimeStamps, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=1)] - OPCHDA_ANNOTATION[] pAnnotationValues, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Cancel( - [MarshalAs(UnmanagedType.I4)] - int dwCancelID); - } - - /// - [ComImport] - [GuidAttribute("1F1217B8-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_Playback - { - void ReadRawWithUpdate( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - [MarshalAs(UnmanagedType.I4)] - int dwNumValues, - System.Runtime.InteropServices.ComTypes.FILETIME ftUpdateDuration, - System.Runtime.InteropServices.ComTypes.FILETIME ftUpdateInterval, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=6)] - int[] phServer, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void ReadProcessedWithUpdate( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - ref OPCHDA_TIME htStartTime, - ref OPCHDA_TIME htEndTime, - System.Runtime.InteropServices.ComTypes.FILETIME ftResampleInterval, - [MarshalAs(UnmanagedType.I4)] - int dwNumIntervals, - System.Runtime.InteropServices.ComTypes.FILETIME ftUpdateInterval, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=6)] - int[] phServer, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=6)] - int[] haAggregate, - [Out] - out int pdwCancelID, - [Out] - out IntPtr ppErrors); - - void Cancel( - [MarshalAs(UnmanagedType.I4)] - int dwCancelID); - } - - /// - [ComImport] - [GuidAttribute("1F1217B9-DEE0-11d2-A5E5-000086339399")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCHDA_DataCallback - { - void OnDataChange( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int hrStatus, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=2)] - OPCHDA_ITEM[] pItemValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phrErrors); - - void OnReadComplete( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int hrStatus, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=2)] - OPCHDA_ITEM[] pItemValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phrErrors); - - void OnReadModifiedComplete( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int hrStatus, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=2)] - OPCHDA_MODIFIEDITEM[] pItemValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phrErrors); - - void OnReadAttributeComplete( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int hrStatus, - [MarshalAs(UnmanagedType.I4)] - int hClient, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=3)] - OPCHDA_ATTRIBUTE[] pAttributeValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=3)] - int[] phrErrors); - - void OnReadAnnotations( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int hrStatus, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=2)] - OPCHDA_ANNOTATION[] pAnnotationValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phrErrors); - - void OnInsertAnnotations ( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int hrStatus, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phClients, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phrErrors); - - void OnPlayback ( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int hrStatus, - [MarshalAs(UnmanagedType.I4)] - int dwNumItems, - IntPtr ppItemValues, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phrErrors); - - void OnUpdateComplete ( - [MarshalAs(UnmanagedType.I4)] - int dwTransactionID, - [MarshalAs(UnmanagedType.I4)] - int hrStatus, - [MarshalAs(UnmanagedType.I4)] - int dwCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phClients, - [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeParamIndex=2)] - int[] phrErrors); - - void OnCancelComplete( - [MarshalAs(UnmanagedType.I4)] - int dwCancelID); - } - - /// - public static class Constants - { - // category description. - public const string OPC_CATEGORY_DESCRIPTION_HDA10 = "OPC History Data Access Servers Version 1.0"; - - // attribute ids. - public const int OPCHDA_DATA_TYPE = 0x01; - public const int OPCHDA_DESCRIPTION = 0x02; - public const int OPCHDA_ENG_UNITS = 0x03; - public const int OPCHDA_STEPPED = 0x04; - public const int OPCHDA_ARCHIVING = 0x05; - public const int OPCHDA_DERIVE_EQUATION = 0x06; - public const int OPCHDA_NODE_NAME = 0x07; - public const int OPCHDA_PROCESS_NAME = 0x08; - public const int OPCHDA_SOURCE_NAME = 0x09; - public const int OPCHDA_SOURCE_TYPE = 0x0a; - public const int OPCHDA_NORMAL_MAXIMUM = 0x0b; - public const int OPCHDA_NORMAL_MINIMUM = 0x0c; - public const int OPCHDA_ITEMID = 0x0d; - public const int OPCHDA_MAX_TIME_INT = 0x0e; - public const int OPCHDA_MIN_TIME_INT = 0x0f; - public const int OPCHDA_EXCEPTION_DEV = 0x10; - public const int OPCHDA_EXCEPTION_DEV_TYPE = 0x11; - public const int OPCHDA_HIGH_ENTRY_LIMIT = 0x12; - public const int OPCHDA_LOW_ENTRY_LIMIT = 0x13; - - // attribute names. - public const string OPCHDA_ATTRNAME_DATA_TYPE = "Data Type"; - public const string OPCHDA_ATTRNAME_DESCRIPTION = "Description"; - public const string OPCHDA_ATTRNAME_ENG_UNITS = "Eng Units"; - public const string OPCHDA_ATTRNAME_STEPPED = "Stepped"; - public const string OPCHDA_ATTRNAME_ARCHIVING = "Archiving"; - public const string OPCHDA_ATTRNAME_DERIVE_EQUATION = "Derive Equation"; - public const string OPCHDA_ATTRNAME_NODE_NAME = "Node Name"; - public const string OPCHDA_ATTRNAME_PROCESS_NAME = "Process Name"; - public const string OPCHDA_ATTRNAME_SOURCE_NAME = "Source Name"; - public const string OPCHDA_ATTRNAME_SOURCE_TYPE = "Source Type"; - public const string OPCHDA_ATTRNAME_NORMAL_MAXIMUM = "Normal Maximum"; - public const string OPCHDA_ATTRNAME_NORMAL_MINIMUM = "Normal Minimum"; - public const string OPCHDA_ATTRNAME_ITEMID = "ItemID"; - public const string OPCHDA_ATTRNAME_MAX_TIME_INT = "Max Time Interval"; - public const string OPCHDA_ATTRNAME_MIN_TIME_INT = "Min Time Interval"; - public const string OPCHDA_ATTRNAME_EXCEPTION_DEV = "Exception Deviation"; - public const string OPCHDA_ATTRNAME_EXCEPTION_DEV_TYPE = "Exception Dev Type"; - public const string OPCHDA_ATTRNAME_HIGH_ENTRY_LIMIT = "High Entry Limit"; - public const string OPCHDA_ATTRNAME_LOW_ENTRY_LIMIT = "Low Entry Limit"; - - // aggregate names. - public const string OPCHDA_AGGRNAME_INTERPOLATIVE = "Interpolative"; - public const string OPCHDA_AGGRNAME_TOTAL = "Total"; - public const string OPCHDA_AGGRNAME_AVERAGE = "Average"; - public const string OPCHDA_AGGRNAME_TIMEAVERAGE = "Time Average"; - public const string OPCHDA_AGGRNAME_COUNT = "Count"; - public const string OPCHDA_AGGRNAME_STDEV = "Standard Deviation"; - public const string OPCHDA_AGGRNAME_MINIMUMACTUALTIME = "Minimum Actual Time"; - public const string OPCHDA_AGGRNAME_MINIMUM = "Minimum"; - public const string OPCHDA_AGGRNAME_MAXIMUMACTUALTIME = "Maximum Actual Time"; - public const string OPCHDA_AGGRNAME_MAXIMUM = "Maximum"; - public const string OPCHDA_AGGRNAME_START = "Start"; - public const string OPCHDA_AGGRNAME_END = "End"; - public const string OPCHDA_AGGRNAME_DELTA = "Delta"; - public const string OPCHDA_AGGRNAME_REGSLOPE = "Regression Line Slope"; - public const string OPCHDA_AGGRNAME_REGCONST = "Regression Line Constant"; - public const string OPCHDA_AGGRNAME_REGDEV = "Regression Line Error"; - public const string OPCHDA_AGGRNAME_VARIANCE = "Variance"; - public const string OPCHDA_AGGRNAME_RANGE = "Range"; - public const string OPCHDA_AGGRNAME_DURATIONGOOD = "Duration Good"; - public const string OPCHDA_AGGRNAME_DURATIONBAD = "Duration Bad"; - public const string OPCHDA_AGGRNAME_PERCENTGOOD = "Percent Good"; - public const string OPCHDA_AGGRNAME_PERCENTBAD = "Percent Bad"; - public const string OPCHDA_AGGRNAME_WORSTQUALITY = "Worst Quality"; - public const string OPCHDA_AGGRNAME_ANNOTATIONS = "Annotations"; - - // OPCHDA_QUALITY -- these are the high-order 16 bits, OPC DA Quality occupies low-order 16 bits. - public const int OPCHDA_EXTRADATA = 0x00010000; - public const int OPCHDA_INTERPOLATED = 0x00020000; - public const int OPCHDA_RAW = 0x00040000; - public const int OPCHDA_CALCULATED = 0x00080000; - public const int OPCHDA_NOBOUND = 0x00100000; - public const int OPCHDA_NODATA = 0x00200000; - public const int OPCHDA_DATALOST = 0x00400000; - public const int OPCHDA_CONVERSION = 0x00800000; - public const int OPCHDA_PARTIAL = 0x01000000; - } -} diff --git a/ComIOP/Common/Rcw/Security.cs b/ComIOP/Common/Rcw/Security.cs deleted file mode 100644 index eb01b18f8..000000000 --- a/ComIOP/Common/Rcw/Security.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; - -#pragma warning disable 1591 - -namespace OpcRcw.Security -{ - /// - [ComImport] - [GuidAttribute("7AA83A01-6C77-11d3-84F9-00008630A38B")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCSecurityNT - { - void IsAvailableNT( - [Out][MarshalAs(UnmanagedType.I4)] - out int pbAvailable); - - void QueryMinImpersonationLevel( - [Out][MarshalAs(UnmanagedType.I4)] - out int pdwMinImpLevel); - - void ChangeUser(); - }; - - /// - [ComImport] - [GuidAttribute("7AA83A02-6C77-11d3-84F9-00008630A38B")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOPCSecurityPrivate - { - void IsAvailablePriv( - [Out][MarshalAs(UnmanagedType.I4)] - out int pbAvailable); - - void Logon( - [MarshalAs(UnmanagedType.LPWStr)] - string szUserID, - [MarshalAs(UnmanagedType.LPWStr)] - string szPassword); - - void Logoff(); - }; -} diff --git a/ComIOP/Common/Server/Ae/COpcUaAeProxyBrowser.cpp b/ComIOP/Common/Server/Ae/COpcUaAeProxyBrowser.cpp deleted file mode 100644 index d8cf5793e..000000000 --- a/ComIOP/Common/Server/Ae/COpcUaAeProxyBrowser.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcUaAeProxyBrowser.h" -#include "COpcUaAeProxyServer.h" -#include "COpcEnumStringWrapper.h" - -//========================================================================== -// Local Functions - - - -//========================================================================== -// COpcUaAeProxySubscription - -// Constructor -COpcUaAeProxyBrowser::COpcUaAeProxyBrowser() -{ - m_pServer = NULL; - m_ipUnknown = NULL; -} - -// Constructor -COpcUaAeProxyBrowser::COpcUaAeProxyBrowser(COpcUaAeProxyServer* pServer, IUnknown* ipUnknown) -{ - m_pServer = pServer; - m_ipUnknown = ipUnknown; - - if (ipUnknown != NULL) - { - ipUnknown->AddRef(); - } -} - -// Destructor -COpcUaAeProxyBrowser::~COpcUaAeProxyBrowser() -{ - if (m_ipUnknown != NULL) - { - m_ipUnknown->Release(); - m_ipUnknown = NULL; - } -} - -// Delete -void COpcUaAeProxyBrowser::Delete() -{ - COpcLock cLock(*this); - m_pServer = NULL; -} - - - -//========================================================================= -// IOPCEventAreaBrowser - -// ChangeBrowsePosition -HRESULT COpcUaAeProxyBrowser::ChangeBrowsePosition(OPCAEBROWSEDIRECTION dwBrowseDirection, - LPCWSTR szString) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventAreaBrowser* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventAreaBrowser, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->ChangeBrowsePosition(dwBrowseDirection, - szString); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// BrowseOPCAreas -HRESULT COpcUaAeProxyBrowser::BrowseOPCAreas(OPCAEBROWSETYPE dwBrowseFilterType, - LPCWSTR szFilterCriteria, - LPENUMSTRING *ppIEnumString) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventAreaBrowser* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventAreaBrowser, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - IEnumString* ipEnum = NULL; - - // invoke method. - HRESULT hResult = ipInterface->BrowseOPCAreas(dwBrowseFilterType, - szFilterCriteria, - &ipEnum); - - if (SUCCEEDED(hResult) && ipEnum != NULL) - { - // create enumerator wrapper. - IUnknown* ipWrapper = new COpcEnumStringWrapper(ipEnum); - - // release local reference. - ipEnum->Release(); - - // query for desired interface. - hResult = ipWrapper->QueryInterface(IID_IEnumString, (void**)ppIEnumString); - if (SUCCEEDED(hResult)) - { - // check if enumerator has any entries. - ULONG ulFetched = 0; - LPWSTR szName = NULL; - - hResult = (*ppIEnumString)->Next(1, &szName, &ulFetched); - if (SUCCEEDED(hResult)) - { - (*ppIEnumString)->Reset(); - OpcFree(szName); - } - } - // release local reference. - ipWrapper->Release(); - } - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// GetQualifiedAreaName -HRESULT COpcUaAeProxyBrowser::GetQualifiedAreaName(LPCWSTR szAreaName, - LPWSTR *pszQualifiedAreaName) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventAreaBrowser* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventAreaBrowser, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->GetQualifiedAreaName(szAreaName, - pszQualifiedAreaName); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// GetQualifiedSourceName -HRESULT COpcUaAeProxyBrowser::GetQualifiedSourceName(LPCWSTR szSourceName, - LPWSTR *pszQualifiedSourceName) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventAreaBrowser* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventAreaBrowser, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->GetQualifiedSourceName(szSourceName, - pszQualifiedSourceName); - - // release interface. - ipInterface->Release(); - - return hResult; -} diff --git a/ComIOP/Common/Server/Ae/COpcUaAeProxyServer.cpp b/ComIOP/Common/Server/Ae/COpcUaAeProxyServer.cpp deleted file mode 100644 index 17789e4b3..000000000 --- a/ComIOP/Common/Server/Ae/COpcUaAeProxyServer.cpp +++ /dev/null @@ -1,1238 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" - -#include "OpcUaComProxyServer.h" - -#include "COpcUaAeProxyServer.h" -#include "COpcUaAeProxySubscription.h" -#include "COpcUaAeProxyBrowser.h" -#include "COpcUaProxyUtils.h" - -using namespace System; -using namespace System::Text; -using namespace System::Runtime::InteropServices; -using namespace System::Collections::Generic; -using namespace Opc::Ua; -using namespace Opc::Ua::Com; -using namespace Opc::Ua::Com::Server; - -//============================================================================== -// Static Functions -/// -/// Writes a trace message. -/// -static void TraceState(String^ context, ... array^ args) -{ - #ifdef TRACESTATE - COpcUaProxyUtils::TraceState("COpcUaAeProxyServer", context, args); - #endif -} - -//============================================================================ -// COpcUaDaProxyServer - -// Constructor -COpcUaAeProxyServer::COpcUaAeProxyServer() -{ - TraceState("COpcUaAeProxyServer"); - - m_pInnerServer = NULL; - m_ipUnknown = NULL; - m_dwConnection = NULL; - - try - { - ComAeProxy^ server = gcnew ComAeProxy(); - GCHandle hInnerServer = GCHandle::Alloc(server); - m_pInnerServer = ((IntPtr)hInnerServer).ToPointer(); - } - catch (Exception^ e) - { - Utils::Trace(e, "COpcUaAeProxyServer: Unexpected error creating AE proxy."); - } -} - -// Destructor -COpcUaAeProxyServer::~COpcUaAeProxyServer() -{ - TraceState("~COpcUaAeProxyServer"); - - Marshal::Release((IntPtr)m_ipUnknown); - - if (m_pInnerServer != NULL) - { - GCHandle hInnerServer = (GCHandle)IntPtr(m_pInnerServer); - hInnerServer.Free(); - m_pInnerServer = NULL; - } -} - -// FinalConstruct -HRESULT COpcUaAeProxyServer::FinalConstruct() -{ - TraceState("FinalConstruct"); - - COpcLock cLock(*this); - - HRESULT hResult = S_OK; - - ApplicationConfiguration^ configuration = nullptr; - - // load configuration. - if (!COpcUaProxyUtils::Initialize(configuration)) - { - return E_FAIL; - } - - // get the CLSID being used. - CLSID cClsid = GetCLSID(); - Guid clsid = (Guid)Marshal::PtrToStructure((IntPtr)&cClsid, Guid::typeid); - - // load the server. - ComAeProxy^ server = nullptr; - - try - { - server = GetInnerServer(); - server->Load(clsid, configuration); - } - catch (Exception^ e) - { - Utils::Trace(e, "COpcUaAeProxyServer: Unexpected error loading proxy for CLSID={0}.", clsid); - } - - try - { - // register shutdown interface. - RegisterInterface(IID_IOPCShutdown); - - // get the interface pointer. - m_ipUnknown = (IUnknown*)Marshal::GetComInterfaceForObject(server, OpcRcw::Ae::IOPCEventServer2::typeid).ToPointer(); - } - catch (Exception^ e) - { - Utils::Trace(e, "COpcUaAeProxyServer: Unexpected getting COM interface for AE proxy.", clsid); - } - - return S_OK; -} - -// FinalRelease -bool COpcUaAeProxyServer::FinalRelease() -{ - TraceState("FinalRelease"); - - try - { - COpcLock cLock(*this); - - ComAeProxy^ server = GetInnerServer(); - server->Unload(); - - cLock.Unlock(); - } - catch (Exception^ e) - { - Utils::Trace(e, "COpcUaAeProxyServer: Unexpected error unloading proxy."); - } - - // decrement global reference count. - COpcUaProxyUtils::Uninitialize(); - - return true; -} - -// GetInnerServer -ComAeProxy^ COpcUaAeProxyServer::GetInnerServer() -{ - if (m_pInnerServer == NULL) - { - return nullptr; - } - - GCHandle hInnerServer = (GCHandle)IntPtr(m_pInnerServer); - - if (hInnerServer.IsAllocated) - { - return (ComAeProxy^)hInnerServer.Target; - } - - return nullptr; -} - -// OnAdvise -void COpcUaAeProxyServer::OnAdvise(REFIID riid, - DWORD dwCookie) -{ - COpcLock cLock(*this); - - if (riid == IID_IOPCShutdown) - { - if (FAILED(OpcConnect(m_ipUnknown, (IOPCShutdown*)this, riid, &m_dwConnection))) - { - m_dwConnection = NULL; - } - } -} - -// OnUnadvise -void COpcUaAeProxyServer::OnUnadvise(REFIID riid, - DWORD dwCookie) -{ - if (riid == IID_IOPCShutdown) - { - OpcDisconnect(m_ipUnknown, riid, m_dwConnection); - m_dwConnection = NULL; - } -} - -//============================================================================== -// IOPCCommon - -// SetLocaleID -HRESULT COpcUaAeProxyServer::SetLocaleID(LCID dwLcid) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCCommon* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCCommon, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->SetLocaleID( - dwLcid - ); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// GetLocaleID -HRESULT COpcUaAeProxyServer::GetLocaleID(LCID *pdwLcid) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCCommon* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCCommon, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->GetLocaleID( - pdwLcid - ); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// QueryAvailableLocaleIDs -HRESULT COpcUaAeProxyServer::QueryAvailableLocaleIDs(DWORD* pdwCount, - LCID** pdwLcid) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCCommon* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCCommon, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->QueryAvailableLocaleIDs( - pdwCount, - pdwLcid - ); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// GetErrorString -HRESULT COpcUaAeProxyServer::GetErrorString(HRESULT dwError, - LPWSTR* ppString) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCCommon* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCCommon, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->GetErrorString( - dwError, - ppString - ); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// SetClientName -HRESULT COpcUaAeProxyServer::SetClientName(LPCWSTR szName) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCCommon* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCCommon, - (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->SetClientName( - szName - ); - - // release interface. - ipInterface->Release(); - - return hResult; -} - - -// WrapSubscription -HRESULT COpcUaAeProxyServer::WrapSubscription(REFIID riid, - IUnknown** ippUnknown) -{ - // wrap subscription. - COpcUaAeProxySubscription* pSubscription = new COpcUaAeProxySubscription(this, *ippUnknown); - - // release reference. - (*ippUnknown)->Release(); - *ippUnknown = NULL; - - // query for desired interface, - HRESULT hResult = pSubscription->QueryInterface(riid, (void**)ippUnknown); - - if (FAILED(hResult)) - { - pSubscription->Release(); - return hResult; - } - - // save reference to subscription locally. - COpcLock cLock(*this); - m_cSubscriptions.AddTail(pSubscription); - cLock.Unlock(); - - return S_OK; -} - -// WrapBrowser -HRESULT COpcUaAeProxyServer::WrapBrowser(REFIID riid, - IUnknown** ippUnknown) -{ - // wrap subscription. - COpcUaAeProxyBrowser* pBrowser = new COpcUaAeProxyBrowser(this, *ippUnknown); - - // release reference. - (*ippUnknown)->Release(); - *ippUnknown = NULL; - - // query for desired interface, - HRESULT hResult = pBrowser->QueryInterface(riid, (void**)ippUnknown); - - if (FAILED(hResult)) - { - pBrowser->Release(); - return hResult; - } - - // save reference to subscription locally. - COpcLock cLock(*this); - m_cBrowsers.AddTail(pBrowser); - cLock.Unlock(); - - return S_OK; -} - - -//============================================================================ -// IOPCEventServer - - -// GetStatus -HRESULT COpcUaAeProxyServer::GetStatus(OPCEVENTSERVERSTATUS **ppEventServerStatus) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->GetStatus( - ppEventServerStatus - ); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// CreateEventSubscription -HRESULT COpcUaAeProxyServer::CreateEventSubscription(BOOL bActive, - DWORD dwBufferTime, - DWORD dwMaxSize, - OPCHANDLE hClientSubscription, - REFIID riid, - LPUNKNOWN *ppUnk, - DWORD *pdwRevisedBufferTime, - DWORD *pdwRevisedMaxSize) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->CreateEventSubscription( - bActive, - dwBufferTime, - dwMaxSize, - hClientSubscription, - riid, - ppUnk, - pdwRevisedBufferTime, - pdwRevisedMaxSize - ); - - // release interface. - ipInterface->Release(); - ipInterface = NULL; - - // wrap subscription object. - if (SUCCEEDED(hResult)) - { - hResult = WrapSubscription(riid, ppUnk); - - if (FAILED(hResult)) - { - // release unknown. - if ((*ppUnk) != NULL) - { - (*ppUnk)->Release(); - *ppUnk = NULL; - } - - // return failure. - return hResult; - } - } - - // insert necessary success code. - if (hResult == S_OK) - { - if(*pdwRevisedBufferTime != dwBufferTime) - hResult = OPC_S_INVALIDBUFFERTIME; - else if(*pdwRevisedMaxSize != dwMaxSize) - hResult = OPC_S_INVALIDMAXSIZE; - } - - return hResult; -} - -// QueryAvailableFilters -HRESULT COpcUaAeProxyServer::QueryAvailableFilters(DWORD *pdwFilterMask) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->QueryAvailableFilters(pdwFilterMask); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// QueryEventCategories -HRESULT COpcUaAeProxyServer::QueryEventCategories(DWORD dwEventType, - DWORD *pdwCount, - DWORD **ppdwEventCategories, - LPWSTR **ppszEventCategoryDescs) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->QueryEventCategories(dwEventType, - pdwCount, - ppdwEventCategories, - ppszEventCategoryDescs); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// QueryConditionNames -HRESULT COpcUaAeProxyServer::QueryConditionNames(DWORD dwEventCategory, - DWORD *pdwCount, - LPWSTR **ppszConditionNames) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->QueryConditionNames(dwEventCategory, - pdwCount, - ppszConditionNames); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// QuerySubConditionNames -HRESULT COpcUaAeProxyServer::QuerySubConditionNames(LPWSTR szConditionName, - DWORD *pdwCount, - LPWSTR **ppszSubConditionNames) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->QuerySubConditionNames(szConditionName, - pdwCount, - ppszSubConditionNames); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// QuerySourceConditions -HRESULT COpcUaAeProxyServer::QuerySourceConditions(LPWSTR szSource, - DWORD *pdwCount, - LPWSTR **ppszConditionNames) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->QuerySourceConditions(szSource, - pdwCount, - ppszConditionNames); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// QueryEventAttributes -HRESULT COpcUaAeProxyServer::QueryEventAttributes(DWORD dwEventCategory, - DWORD *pdwCount, - DWORD **ppdwAttrIDs, - LPWSTR **ppszAttrDescs, - VARTYPE **ppvtAttrTypes) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->QueryEventAttributes(dwEventCategory, - pdwCount, - ppdwAttrIDs, - ppszAttrDescs, - ppvtAttrTypes); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// TranslateToItemIDs -HRESULT COpcUaAeProxyServer::TranslateToItemIDs(LPWSTR szSource, - DWORD dwEventCategory, - LPWSTR szConditionName, - LPWSTR szSubconditionName, - DWORD dwCount, - DWORD *pdwAssocAttrIDs, - LPWSTR **ppszAttrItemIDs, - LPWSTR **ppszNodeNames, - CLSID **ppCLSIDs) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->TranslateToItemIDs(szSource, - dwEventCategory, - szConditionName, - szSubconditionName, - dwCount, - pdwAssocAttrIDs, - ppszAttrItemIDs, - ppszNodeNames, - ppCLSIDs); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// GetConditionState -HRESULT COpcUaAeProxyServer::GetConditionState(LPWSTR szSource, - LPWSTR szConditionName, - DWORD dwNumEventAttrs, - DWORD *dwAttributeIDs, - OPCCONDITIONSTATE **ppConditionState) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->GetConditionState(szSource, - szConditionName, - dwNumEventAttrs, - dwAttributeIDs, - ppConditionState); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// EnableConditionByArea -HRESULT COpcUaAeProxyServer::EnableConditionByArea(DWORD dwNumAreas, - LPWSTR *pszAreas) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->EnableConditionByArea(dwNumAreas, - pszAreas); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// EnableConditionBySource -HRESULT COpcUaAeProxyServer::EnableConditionBySource(DWORD dwNumSources, - LPWSTR *pszSources) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->EnableConditionBySource(dwNumSources, - pszSources); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// DisableConditionByArea -HRESULT COpcUaAeProxyServer::DisableConditionByArea(DWORD dwNumAreas, - LPWSTR *pszAreas) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->DisableConditionByArea(dwNumAreas, - pszAreas); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// DisableConditionBySource -HRESULT COpcUaAeProxyServer::DisableConditionBySource(DWORD dwNumSources, - LPWSTR *pszSources) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->DisableConditionBySource(dwNumSources, - pszSources); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// AckCondition -HRESULT COpcUaAeProxyServer::AckCondition(DWORD dwCount, - LPWSTR szAcknowledgerID, - LPWSTR szComment, - LPWSTR *pszSource, - LPWSTR *pszConditionName, - ::FILETIME *pftActiveTime, - DWORD *pdwCookie, - HRESULT **ppErrors) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->AckCondition(dwCount, - szAcknowledgerID, - szComment, - pszSource, - pszConditionName, - pftActiveTime, - pdwCookie, - ppErrors); - - // release interface. - ipInterface->Release(); - - RETURN_SFALSE(hResult, dwCount, ppErrors); -} - -// CreateAreaBrowser -HRESULT COpcUaAeProxyServer::CreateAreaBrowser(REFIID riid, - LPUNKNOWN *ppUnk) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->CreateAreaBrowser(riid, ppUnk); - - // release interface. - ipInterface->Release(); - ipInterface = NULL; - - - // wrap subscription object. - if (SUCCEEDED(hResult)) - { - hResult = WrapBrowser(riid, ppUnk); - - if (FAILED(hResult)) - { - // release unknown. - if ((*ppUnk) != NULL) - { - (*ppUnk)->Release(); - *ppUnk = NULL; - } - - // return failure. - return hResult; - } - } - - return hResult; -} - - -//========================================================================== -// IOPCEventServer2 - - -// EnableConditionByArea2 -HRESULT COpcUaAeProxyServer::EnableConditionByArea2(DWORD dwNumAreas, - LPWSTR *pszAreas, - HRESULT **ppErrors) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer2* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer2, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->EnableConditionByArea2(dwNumAreas, - pszAreas, - ppErrors); - - // release interface. - ipInterface->Release(); - - RETURN_SFALSE(hResult, dwNumAreas, ppErrors); -} - -// EnableConditionBySource2 -HRESULT COpcUaAeProxyServer::EnableConditionBySource2(DWORD dwNumSources, - LPWSTR *pszSources, - HRESULT **ppErrors) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer2* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer2, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->EnableConditionBySource2(dwNumSources, - pszSources, - ppErrors); - - // release interface. - ipInterface->Release(); - - RETURN_SFALSE(hResult, dwNumSources, ppErrors); -} - -// DisableConditionByArea2 -HRESULT COpcUaAeProxyServer::DisableConditionByArea2(DWORD dwNumAreas, - LPWSTR *pszAreas, - HRESULT **ppErrors) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer2* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer2, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->DisableConditionByArea2(dwNumAreas, - pszAreas, - ppErrors); - - // release interface. - ipInterface->Release(); - - RETURN_SFALSE(hResult, dwNumAreas, ppErrors); -} - -// DisableConditionBySource2 -HRESULT COpcUaAeProxyServer::DisableConditionBySource2(DWORD dwNumSources, - LPWSTR *pszSources, - HRESULT **ppErrors) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer2* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer2, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->DisableConditionBySource2(dwNumSources, - pszSources, - ppErrors); - - // release interface. - ipInterface->Release(); - - RETURN_SFALSE(hResult, dwNumSources, ppErrors); -} - -// GetEnableStateByArea -HRESULT COpcUaAeProxyServer::GetEnableStateByArea(DWORD dwNumAreas, - LPWSTR *pszAreas, - BOOL **pbEnabled, - BOOL **pbEffectivelyEnabled, - HRESULT **ppErrors) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer2* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer2, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->GetEnableStateByArea(dwNumAreas, - pszAreas, - pbEnabled, - pbEffectivelyEnabled, - ppErrors); - - // release interface. - ipInterface->Release(); - - RETURN_SFALSE(hResult, dwNumAreas, ppErrors); -} - -// GetEnableStateBySource -HRESULT COpcUaAeProxyServer::GetEnableStateBySource(DWORD dwNumSources, - LPWSTR *pszSources, - BOOL **pbEnabled, - BOOL **pbEffectivelyEnabled, - HRESULT **ppErrors) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventServer2* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventServer2, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - HRESULT hResult = ipInterface->GetEnableStateBySource(dwNumSources, - pszSources, - pbEnabled, - pbEffectivelyEnabled, - ppErrors); - - // release interface. - ipInterface->Release(); - - RETURN_SFALSE(hResult, dwNumSources, ppErrors); -} - - -//============================================================================== -// IOPCShutdown - -// ShutdownRequest -HRESULT COpcUaAeProxyServer::ShutdownRequest( - LPCWSTR szReason - ) -{ - // get callback object. - IOPCShutdown* ipCallback = NULL; - - HRESULT hResult = GetCallback(IID_IOPCShutdown, (IUnknown**)&ipCallback); - - if (FAILED(hResult) || ipCallback == NULL) - { - return S_OK; - } - - // invoke callback. - ipCallback->ShutdownRequest(szReason); - - // release callback. - ipCallback->Release(); - - return S_OK; -} diff --git a/ComIOP/Common/Server/Ae/COpcUaAeProxyServer.h b/ComIOP/Common/Server/Ae/COpcUaAeProxyServer.h deleted file mode 100644 index be3626c63..000000000 --- a/ComIOP/Common/Server/Ae/COpcUaAeProxyServer.h +++ /dev/null @@ -1,290 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcUaAeProxyServer_H_ -#define _COpcUaAeProxyServer_H_ - - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcUaComProxyServer.h" - -class COpcUaAeProxySubscription; -class COpcUaAeProxyBrowser; - -using namespace Opc::Ua::Com::Server; -using namespace Opc::Ua::Com::Server::Ae; - -///////////////////////////////////////////////////////////////////////////// -// COPCEventServer -class COpcUaAeProxyServer : - public COpcComObject, - public COpcCPContainer, - public IOPCEventServer2, - public IOPCCommon, - public IOPCShutdown, - public COpcSynchObject -{ -private: - OPC_CLASS_NEW_DELETE() - - OPC_BEGIN_INTERFACE_TABLE(COpcUaAeProxyServer) - OPC_INTERFACE_ENTRY(IOPCCommon) - OPC_INTERFACE_ENTRY(IConnectionPointContainer) - OPC_INTERFACE_ENTRY(IOPCEventServer) -// OPC_INTERFACE_ENTRY(IOPCEventServer2) - OPC_END_INTERFACE_TABLE() - -public: - //========================================================================= - // Operators - - // Constructor - COpcUaAeProxyServer(); - - // Destructor - ~COpcUaAeProxyServer(); - - //========================================================================= - // Public Methods - - // FinalConstruct - virtual HRESULT FinalConstruct(); - - // FinalRelease - virtual bool FinalRelease(); - - // WrapSubscription - HRESULT WrapSubscription(REFIID riid, IUnknown** ippUnknown); - - // WrapBrowser - HRESULT WrapBrowser(REFIID riid, IUnknown** ippUnknown); - - // OnAdvise - virtual void OnAdvise(REFIID riid, DWORD dwCookie); - - // OnUnadvise - virtual void OnUnadvise(REFIID riid, DWORD dwCookie); - - //========================================================================= - // IOPCShutdown - - // ShutdownRequest - STDMETHODIMP ShutdownRequest( - LPCWSTR szReason - ); - - //========================================================================== - // IOPCCommon - - // SetLocaleID - STDMETHODIMP SetLocaleID(LCID dwLcid); - - // GetLocaleID - STDMETHODIMP GetLocaleID(LCID *pdwLcid); - - // QueryAvailableLocaleIDs - STDMETHODIMP QueryAvailableLocaleIDs(DWORD* pdwCount, LCID** pdwLcid); - - // GetErrorString - STDMETHODIMP GetErrorString(HRESULT dwError, LPWSTR* ppString); - - // SetClientName - STDMETHODIMP SetClientName(LPCWSTR szName); - - //========================================================================== - // IOPCEventServer - - STDMETHODIMP GetStatus( - /* [out] */ OPCEVENTSERVERSTATUS __RPC_FAR **ppEventServerStatus); - - STDMETHODIMP CreateEventSubscription( - /* [in] */ BOOL bActive, - /* [in] */ DWORD dwBufferTime, - /* [in] */ DWORD dwMaxSize, - /* [in] */ OPCHANDLE hClientSubscription, - /* [in] */ REFIID riid, - /* [iid_is][out] */ LPUNKNOWN __RPC_FAR *ppUnk, - /* [out] */ DWORD __RPC_FAR *pdwRevisedBufferTime, - /* [out] */ DWORD __RPC_FAR *pdwRevisedMaxSize); - - STDMETHODIMP QueryAvailableFilters( - /* [out] */ DWORD __RPC_FAR *pdwFilterMask); - - STDMETHODIMP QueryEventCategories( - /* [in] */ DWORD dwEventType, - /* [out] */ DWORD __RPC_FAR *pdwCount, - /* [size_is][size_is][out] */ DWORD __RPC_FAR *__RPC_FAR *ppdwEventCategories, - /* [size_is][size_is][out] */ LPWSTR __RPC_FAR *__RPC_FAR *ppszEventCategoryDescs); - - STDMETHODIMP QueryConditionNames( - /* [in] */ DWORD dwEventCategory, - /* [out] */ DWORD __RPC_FAR *pdwCount, - /* [size_is][size_is][out] */ LPWSTR __RPC_FAR *__RPC_FAR *ppszConditionNames); - - STDMETHODIMP QuerySubConditionNames( - /* [in] */ LPWSTR szConditionName, - /* [out] */ DWORD __RPC_FAR *pdwCount, - /* [size_is][size_is][out] */ LPWSTR __RPC_FAR *__RPC_FAR *ppszSubConditionNames); - - STDMETHODIMP QuerySourceConditions( - /* [in] */ LPWSTR szSource, - /* [out] */ DWORD __RPC_FAR *pdwCount, - /* [size_is][size_is][out] */ LPWSTR __RPC_FAR *__RPC_FAR *ppszConditionNames); - - STDMETHODIMP QueryEventAttributes( - /* [in] */ DWORD dwEventCategory, - /* [out] */ DWORD __RPC_FAR *pdwCount, - /* [size_is][size_is][out] */ DWORD __RPC_FAR *__RPC_FAR *ppdwAttrIDs, - /* [size_is][size_is][out] */ LPWSTR __RPC_FAR *__RPC_FAR *ppszAttrDescs, - /* [size_is][size_is][out] */ VARTYPE __RPC_FAR *__RPC_FAR *ppvtAttrTypes); - - STDMETHODIMP TranslateToItemIDs( - /* [in] */ LPWSTR szSource, - /* [in] */ DWORD dwEventCategory, - /* [in] */ LPWSTR szConditionName, - /* [in] */ LPWSTR szSubconditionName, - /* [in] */ DWORD dwCount, - /* [size_is][in] */ DWORD __RPC_FAR *pdwAssocAttrIDs, - /* [size_is][size_is][out] */ LPWSTR __RPC_FAR *__RPC_FAR *ppszAttrItemIDs, - /* [size_is][size_is][out] */ LPWSTR __RPC_FAR *__RPC_FAR *ppszNodeNames, - /* [size_is][out] */ CLSID __RPC_FAR **ppCLSIDs); - - STDMETHODIMP GetConditionState( - /* [in] */ LPWSTR szSource, - /* [in] */ LPWSTR szConditionName, - /* [in] */ DWORD dwNumEventAttrs, - /* [size_is][in] */ DWORD __RPC_FAR *dwAttributeIDs, - /* [out] */ OPCCONDITIONSTATE __RPC_FAR *__RPC_FAR *ppConditionState); - - STDMETHODIMP EnableConditionByArea( - /* [in] */ DWORD dwNumAreas, - /* [size_is][in] */ LPWSTR __RPC_FAR *pszAreas); - - STDMETHODIMP EnableConditionBySource( - /* [in] */ DWORD dwNumSources, - /* [size_is][in] */ LPWSTR __RPC_FAR *pszSources); - - STDMETHODIMP DisableConditionByArea( - /* [in] */ DWORD dwNumAreas, - /* [size_is][in] */ LPWSTR __RPC_FAR *pszAreas); - - STDMETHODIMP DisableConditionBySource( - /* [in] */ DWORD dwNumSources, - /* [size_is][in] */ LPWSTR __RPC_FAR *pszSources); - - STDMETHODIMP AckCondition( - /* [in] */ DWORD dwCount, - /* [string][in] */ LPWSTR szAcknowledgerID, - /* [string][in] */ LPWSTR szComment, - /* [size_is][in] */ LPWSTR __RPC_FAR *pszSource, - /* [size_is][in] */ LPWSTR __RPC_FAR *pszConditionName, - /* [size_is][in] */ FILETIME __RPC_FAR *pftActiveTime, - /* [size_is][in] */ DWORD __RPC_FAR *pdwCookie, - /* [size_is][out] */ HRESULT __RPC_FAR *__RPC_FAR *ppErrors); - - STDMETHODIMP CreateAreaBrowser( - /* [in] */ REFIID riid, - /* [iid_is][out] */ LPUNKNOWN __RPC_FAR *ppUnk); - - - //========================================================================== - // IOPCEventServer2 - - STDMETHODIMP EnableConditionByArea2( - /* [in] */ DWORD dwNumAreas, - /* [size_is][string][in] */ LPWSTR __RPC_FAR *pszAreas, - /* [size_is][size_is][out] */ HRESULT __RPC_FAR *__RPC_FAR *ppErrors); - - STDMETHODIMP EnableConditionBySource2( - /* [in] */ DWORD dwNumSources, - /* [size_is][string][in] */ LPWSTR __RPC_FAR *pszSources, - /* [size_is][size_is][out] */ HRESULT __RPC_FAR *__RPC_FAR *ppErrors); - - STDMETHODIMP DisableConditionByArea2( - /* [in] */ DWORD dwNumAreas, - /* [size_is][string][in] */ LPWSTR __RPC_FAR *pszAreas, - /* [size_is][size_is][out] */ HRESULT __RPC_FAR *__RPC_FAR *ppErrors); - - STDMETHODIMP DisableConditionBySource2( - /* [in] */ DWORD dwNumSources, - /* [size_is][string][in] */ LPWSTR __RPC_FAR *pszSources, - /* [size_is][size_is][out] */ HRESULT __RPC_FAR *__RPC_FAR *ppErrors); - - STDMETHODIMP GetEnableStateByArea( - /* [in] */ DWORD dwNumAreas, - /* [size_is][string][in] */ LPWSTR __RPC_FAR *pszAreas, - /* [size_is][size_is][out] */ BOOL __RPC_FAR *__RPC_FAR *pbEnabled, - /* [size_is][size_is][out] */ BOOL __RPC_FAR *__RPC_FAR *pbEffectivelyEnabled, - /* [size_is][size_is][out] */ HRESULT __RPC_FAR *__RPC_FAR *ppErrors); - - STDMETHODIMP GetEnableStateBySource( - /* [in] */ DWORD dwNumSources, - /* [size_is][string][in] */ LPWSTR __RPC_FAR *pszSources, - /* [size_is][size_is][out] */ BOOL __RPC_FAR *__RPC_FAR *pbEnabled, - /* [size_is][size_is][out] */ BOOL __RPC_FAR *__RPC_FAR *pbEffectivelyEnabled, - /* [size_is][size_is][out] */ HRESULT __RPC_FAR *__RPC_FAR *ppErrors); - - -private: - - // GetInnerServer - ComAeProxy^ GetInnerServer(); - - //========================================================================== - // Private Members - - IUnknown* m_ipUnknown; - void* m_pInnerServer; - DWORD m_dwConnection; - COpcList m_cSubscriptions; - COpcList m_cBrowsers; - -}; - -//============================================================================ -// MACRO: RETURN_SFALSE -// PURPOSE: Returns SFALSE if any elements in the array are not S_OK - -#define RETURN_SFALSE(xResult, xCount, xErrors) \ -if ((xResult) == S_OK && (*(xErrors)) != NULL)\ -{ \ - for (DWORD xx = 0; xx < (DWORD)(xCount); xx++) \ - { \ - if ((*(xErrors))[xx] != S_OK) \ - { \ - return S_FALSE; \ - } \ - } \ -} \ -return xResult; - -#endif // _COpcUaAeProxyServer_H_ diff --git a/ComIOP/Common/Server/Ae/COpcUaAeProxySubscription.cpp b/ComIOP/Common/Server/Ae/COpcUaAeProxySubscription.cpp deleted file mode 100644 index 88c027f58..000000000 --- a/ComIOP/Common/Server/Ae/COpcUaAeProxySubscription.cpp +++ /dev/null @@ -1,497 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcUaAeProxySubscription.h" -#include "COpcUaAeProxyServer.h" -#include "COpcUaProxyUtils.h" - -//========================================================================== -// COpcUaAeProxySubscription - -// Constructor -COpcUaAeProxySubscription::COpcUaAeProxySubscription() -{ - RegisterInterface(IID_IOPCEventSink); - - m_pServer = NULL; - m_ipUnknown = NULL; - m_dwConnection = NULL; -} - -// Constructor -COpcUaAeProxySubscription::COpcUaAeProxySubscription(COpcUaAeProxyServer* pServer, IUnknown* ipUnknown) -{ - RegisterInterface(IID_IOPCEventSink); - - m_pServer = pServer; - m_ipUnknown = ipUnknown; - m_dwConnection = NULL; - - if (ipUnknown != NULL) - { - ipUnknown->AddRef(); - } -} - -// Destructor -COpcUaAeProxySubscription::~COpcUaAeProxySubscription() -{ - if (m_ipUnknown != NULL) - { - m_ipUnknown->Release(); - m_ipUnknown = NULL; - } -} - -// Delete -void COpcUaAeProxySubscription::Delete() -{ - COpcLock cLock(*this); - m_pServer = NULL; -} - -// OnAdvise -void COpcUaAeProxySubscription::OnAdvise(REFIID riid, DWORD dwCookie) -{ - COpcLock cLock(*this); - - if (riid == IID_IOPCEventSink) - { - if (FAILED(OpcConnect(m_ipUnknown, (IOPCEventSink*)this, riid, &m_dwConnection))) - { - m_dwConnection = NULL; - } - } -} - -// OnUnadvise -void COpcUaAeProxySubscription::OnUnadvise(REFIID riid, DWORD dwCookie) -{ - if (riid == IID_IOPCEventSink) - { - OpcDisconnect(m_ipUnknown, riid, m_dwConnection); - m_dwConnection = NULL; - } -} - -//========================================================================= -// IOPCEventSubscriptionMgt - -// SetFilter -HRESULT COpcUaAeProxySubscription::SetFilter(DWORD dwEventType, - DWORD dwNumCategories, - DWORD *pdwEventCategories, - DWORD dwLowSeverity, - DWORD dwHighSeverity, - DWORD dwNumAreas, - LPWSTR *pszAreaList, - DWORD dwNumSources, - LPWSTR *pszSourceList) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->SetFilter(dwEventType, - dwNumCategories, - pdwEventCategories, - dwLowSeverity, - dwHighSeverity, - dwNumAreas, - pszAreaList, - dwNumSources, - pszSourceList); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// GetFilter -HRESULT COpcUaAeProxySubscription::GetFilter(DWORD *pdwEventType, - DWORD *pdwNumCategories, - DWORD **ppdwEventCategories, - DWORD *pdwLowSeverity, - DWORD *pdwHighSeverity, - DWORD *pdwNumAreas, - LPWSTR **ppszAreaList, - DWORD *pdwNumSources, - LPWSTR **ppszSourceList) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->GetFilter(pdwEventType, - pdwNumCategories, - ppdwEventCategories, - pdwLowSeverity, - pdwHighSeverity, - pdwNumAreas, - ppszAreaList, - pdwNumSources, - ppszSourceList); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// SelectReturnedAttributes -HRESULT COpcUaAeProxySubscription::SelectReturnedAttributes(DWORD dwEventCategory, - DWORD dwCount, - DWORD *dwAttributeIDs) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->SelectReturnedAttributes(dwEventCategory, - dwCount, - dwAttributeIDs); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// GetReturnedAttributes -HRESULT COpcUaAeProxySubscription::GetReturnedAttributes(DWORD dwEventCategory, - DWORD *pdwCount, - DWORD **ppdwAttributeIDs) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->GetReturnedAttributes(dwEventCategory, - pdwCount, - ppdwAttributeIDs); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// Refresh -HRESULT COpcUaAeProxySubscription::Refresh(DWORD dwConnection) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->Refresh(dwConnection); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// CancelRefresh -HRESULT COpcUaAeProxySubscription::CancelRefresh(DWORD dwConnection) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->CancelRefresh(dwConnection); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// GetState -HRESULT COpcUaAeProxySubscription::GetState(BOOL *pbActive, - DWORD *pdwBufferTime, - DWORD *pdwMaxSize, - OPCHANDLE *phClientSubscription) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->GetState(pbActive, - pdwBufferTime, - pdwMaxSize, - phClientSubscription); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// SetState -HRESULT COpcUaAeProxySubscription::SetState(BOOL *pbActive, - DWORD *pdwBufferTime, - DWORD *pdwMaxSize, - OPCHANDLE hClientSubscription, - DWORD *pdwRevisedBufferTime, - DWORD *pdwRevisedMaxSize) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->SetState(pbActive, - pdwBufferTime, - pdwMaxSize, - hClientSubscription, - pdwRevisedBufferTime, - pdwRevisedMaxSize); - - if (SUCCEEDED(hResult)) - { - if (pdwMaxSize) - { - if(*pdwRevisedMaxSize != *pdwMaxSize) - hResult = OPC_S_INVALIDMAXSIZE; - } - - if (pdwBufferTime) - { - if(*pdwRevisedBufferTime != *pdwBufferTime) - hResult = OPC_S_INVALIDBUFFERTIME; - } - } - // release interface. - ipInterface->Release(); - - return hResult; -} - -//========================================================================= -// IOPCEventSubscriptionMgt2 - -// SetKeepAlive -HRESULT COpcUaAeProxySubscription::SetKeepAlive(DWORD dwKeepAliveTime, - DWORD *pdwRevisedKeepAliveTime) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt2* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt2, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->SetKeepAlive( - dwKeepAliveTime, - pdwRevisedKeepAliveTime); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -// GetKeepAlive -HRESULT COpcUaAeProxySubscription::GetKeepAlive(DWORD *pdwKeepAliveTime) -{ - COpcLock cLock(*this); - - // check inner server. - if (m_ipUnknown == NULL || m_pServer == NULL) - { - return E_FAIL; - } - - // fetch required interface. - IOPCEventSubscriptionMgt2* ipInterface = NULL; - - if (FAILED(m_ipUnknown->QueryInterface(IID_IOPCEventSubscriptionMgt2, (void**)&ipInterface))) - { - return E_NOTIMPL; - } - - // invoke method. - HRESULT hResult = ipInterface->GetKeepAlive(pdwKeepAliveTime); - - // release interface. - ipInterface->Release(); - - return hResult; -} - -//============================================================================== -// IOPCEventSink - -// OnEvent -HRESULT COpcUaAeProxySubscription::OnEvent(OPCHANDLE hClientSubscription, - BOOL bRefresh, - BOOL bLastRefresh, - DWORD dwCount, - ONEVENTSTRUCT *pEvents) -{ - // get callback object. - IOPCEventSink* ipCallback = NULL; - - HRESULT hResult = GetCallback(IID_IOPCEventSink, (IUnknown**)&ipCallback); - - if (FAILED(hResult) || ipCallback == NULL) - { - return S_OK; - } - - // fix any conversion issues in variants. - COpcUaProxyUtils::FixupOutputVariants(pEvents->dwNumEventAttrs, pEvents->pEventAttributes); - - // invoke callback. - ipCallback->OnEvent(hClientSubscription, - bRefresh, - bLastRefresh, - dwCount, - pEvents); - - // release callback. - ipCallback->Release(); - - return S_OK; -} diff --git a/ComIOP/Common/Server/Ae/ComAeAreaBrowser.cs b/ComIOP/Common/Server/Ae/ComAeAreaBrowser.cs deleted file mode 100644 index 62c5886ec..000000000 --- a/ComIOP/Common/Server/Ae/ComAeAreaBrowser.cs +++ /dev/null @@ -1,530 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using OpcRcw.Ae; -using OpcRcw.Comn; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server.Ae -{ - /// - /// Implements COM-AE AreaBrowser class - /// - [ComVisible(true)] - public class AreaBrowser : - IOPCEventAreaBrowser - { - /// - /// Initializes the object with the default values - /// - /// The server associated with the browser - /// The session associated with the browser - public AreaBrowser(ComAeProxy server, Session session) - { - m_server = server; - m_session = session; - // ensure browse stack has been initialized. - if (m_browseStack.Count == 0) - { - INode parent = m_session.NodeCache.Find(Objects.Server); - m_browseStack.Push(parent); - } - } - - - #region IOPCEventAreaBrowser Members - - /// - /// 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. - /// - /// OPCAE_BROWSE_UP, OPCAE_BROWSE_DOWN, or OPCAE_BROWSE_TO - /// - /// 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. - /// - 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 szAreas = new List(); - 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 browseStack = new Stack(); - - 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); - } - } - } - - /// - /// Returns whether the specified node allows event notification. (Is the EventNotifier attribute set to SubscribeToEvents?) - /// - /// The NodeId of the node being checked. - private bool IsEventNotificationListAllowed(NodeId nodeId) - { - //only nodes that allow event notification - DataValue value = new DataValue(); - try - { - Node node = m_session.ReadNode(nodeId); - ServiceResult result = node.Read(null, Attributes.EventNotifier, value); - if (result.Code == StatusCodes.BadAttributeIdInvalid) - value.Value = (byte)0; //no EventNotifier attribute found - } - catch (Exception e) - { - //we will assume either no attributes or no EventNotifier attribute - Utils.Trace(e, "Unexpected error in IsEventNotificationListAllowed"); - value.Value = (byte)0; - } - - return System.Convert.ToBoolean((byte)value.Value & EventNotifiers.SubscribeToEvents); - - } - - /// - /// Finds the path to the Node from the Objects folder. - /// - /// - /// The DA proxy exposes only nodes that can be related back to the Objects folder via HierarchicalReferences references. - /// If the client browses to a specific node the proxy must determine if that node has a reference back to the - /// Objects folder. If it does not then it is not a valid node. - /// - private bool FindPathToNode(INode startNode, Stack path) - { - // find all parent nodes. - try - { - foreach (INode node in m_session.NodeCache.Find(startNode.NodeId, ReferenceTypes.HierarchicalReferences, true, true)) - { - // ignore external nodes. - if (node.NodeId.IsAbsolute) - { - continue; - } - - // ignore non-objects/variables. - if ((node.NodeClass & (NodeClass.Object | NodeClass.Variable)) == 0) - { - continue; - } - - // check if server object found. - if (node.NodeId == Objects.Server) - { - path.Push(node); - return true; - } - - // recursively follow parents. - if (FindPathToNode(node, path)) - { - path.Push(node); - return true; - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in FindPathToNode"); - } - // path does not lead to the objects folder. - return false; - } - /// - /// Finds the child node with the specified browse name. - /// - private INode FindChildByName(ExpandedNodeId startId, string browseName) - { - // find all parent nodes. - IList children; - try - { - children = m_session.NodeCache.Find(startId, 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 the namespace when comparing. - if (browseName == child.BrowseName.ToString()) - { - return child; - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in FindChildByName"); - } - // child with specified browse name does not exist. - return null; - } - - /// - /// Return an IEnumString for a list of Areas as determined by the passed parameters. - /// - /// - /// OPC_AREA - returns only areas. - /// OPC_SOURCE - returns only sources. - /// A server specific filter string. A pointer to a NULL string indicates no filtering. - /// Where to save the returned interface pointer. NULL if the HRESULT is other than S_OK or S_FALSE. - 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 names = new List(); - IList 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); - } - } - - private bool IsValidNode(NodeId nodeId, string nodeName, OPCAEBROWSETYPE dwBrowseFilterType) - { - Browser browse = new Browser(m_session); - ReferenceDescriptionCollection references = null; - - try - { - // 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) - if (dwBrowseFilterType == OPCAEBROWSETYPE.OPC_AREA) - { - // if node is 'Server' then the HasNotifier is implicit, so return true - if (nodeName == "Server") - { - return true; - } - - references = browse.Browse(nodeId); - - foreach (ReferenceDescription reference in references) - { - if ((reference.ReferenceTypeId == ReferenceTypes.HasNotifier) || (reference.ReferenceTypeId == ReferenceTypes.HasEventSource)) - { - return IsEventNotificationListAllowed(nodeId); - } - } - } - - // For a node to be a source, it should be the target of the HasEventSource reference - else // Check if this is a source. - { - IList parent = m_session.NodeCache.Find(nodeId, ReferenceTypes.HasEventSource, true, false); - if (parent.Count != 0) - return true; - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in IsValidNode"); - } - - return false; - } - - /// - /// Provides a mechanism to assemble a fully qualified Area name in a hierarchical space. - /// - /// The name of an Area at the current level, obtained from the string enumerator returned by BrowseOPCAreas with a BrowseFilterType of OPC_AREA - /// Where to return the resulting fully qualified area name. - public void GetQualifiedAreaName(string szAreaName, out string pszQualifiedAreaName) - { - pszQualifiedAreaName = String.Empty; - - try - { - pszQualifiedAreaName = szAreaName; - // Make sure the stack is not null - INode parent = m_browseStack.Peek(); - if (parent == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - // And make sure this is avalid Area name at the level - INode child = FindChildByName(parent.NodeId, szAreaName); - if (child == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - pszQualifiedAreaName = ""; - INode[] stack = m_browseStack.ToArray(); - for (int i = stack.Length - 2; i >= 0; i--) - { - // Translate the server namespace index in browsename to the corresponding client namespace index - QualifiedName QName = stack[i].BrowseName; - QualifiedName translatedName = new QualifiedName(QName.Name, (ushort)m_server.ServerMappingTable[QName.NamespaceIndex]); - if (pszQualifiedAreaName.Length != 0) - pszQualifiedAreaName = pszQualifiedAreaName + "/" + translatedName.ToString(); - else - pszQualifiedAreaName = translatedName.ToString(); - } - //Also translate the areaname - QualifiedName QualifiedAreaName = QualifiedName.Parse(szAreaName); - QualifiedName TranslatedAreaName = new QualifiedName(QualifiedAreaName.Name, (ushort)m_server.ServerMappingTable[QualifiedAreaName.NamespaceIndex]); - pszQualifiedAreaName = pszQualifiedAreaName + "/" + TranslatedAreaName.ToString(); - - } - catch (COMException e) - { - throw ComUtils.CreateComException(e); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in GetQualifiedAreaName"); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Provides a mechanism to assemble a fully qualified Source name in a hierarchical space. - /// - /// The name of a Source at the current level, obtained from the string enumerator returned by BrowseOPCAreas with a BrowseFilterType of OPC_SOURCE. - /// Where to return the resulting fully qualified source name. - public void GetQualifiedSourceName(string szSourceName, out string pszQualifiedSourceName) - { - GetQualifiedAreaName(szSourceName, out pszQualifiedSourceName); - } - #endregion - - #region Private Members - private object m_lock = new object(); - private ComAeProxy m_server = null; - private Session m_session = null; - private Stack m_browseStack = new Stack(); - #endregion - } -} diff --git a/ComIOP/Common/Server/Ae/ComAeCondition.cs b/ComIOP/Common/Server/Ae/ComAeCondition.cs deleted file mode 100644 index 94975b3de..000000000 --- a/ComIOP/Common/Server/Ae/ComAeCondition.cs +++ /dev/null @@ -1,881 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -using System.Text; -using OpcRcw.Ae; -using OpcRcw.Da; - -namespace Opc.Ua.Com.Server.Ae -{ - /// - /// Maps ConditionName to instance of OPCCondition class - /// - public class ConditionMap : Dictionary - { - } - - /// - /// Maps event source name to conditionMAP. One instance of SourceMap - /// per process. - /// - public class SourceMap : Dictionary - { - private SourceMap() { } - - /// - /// Accessor for static SourceMap instance - /// - public static SourceMap TheSourceMap - { - get { return theSourceMap; } - } - - private static SourceMap theSourceMap = new SourceMap(); - } - - /// - /// Specialized List which does not permit duplicate entries - /// - /// - public class UniqueList : List - { - /// - /// Adds 'item' to list if item is not already present - /// - /// - public void AddUnique(T item) - { - if (!Contains(item)) - Add(item); - } - } - - /// - /// Specialized Queue which never contains more than one item - /// - /// - public class EventItemQueue : Queue - { - /// - /// Enqueues if empty. - /// - /// The item. - public void EnqueueIfEmpty(T item) - { - if (Count == 0) - base.Enqueue(item); - } - } - - /// - /// Struct representing an OPC Subcondition - /// - public struct OPCSubcondition - { - /// - /// Constructor - /// - /// - public OPCSubcondition(string wszName) - { - m_wsName = wszName; - m_wsMessage = ""; - m_wsDefinition = ""; - m_dwSeverity = 1; - } - - /// - /// Constructor - /// - /// - /// - /// - /// - public OPCSubcondition(string wszName, string wszMessage, string wszDefinition, int dwSeverity) - { - m_wsName = wszName; - m_wsMessage = wszMessage; - m_wsDefinition = wszDefinition; - m_dwSeverity = dwSeverity; - } - - /// - /// Name property - /// - public string Name - { - get { return m_wsName; } - } - - /// - /// Message property - /// - public string Message - { - get { return m_wsMessage; } - } - - /// - /// Subcondition definition property - /// - public string Definition - { - get { return m_wsDefinition; } - } - - /// - /// Subcondition Severity property - /// - public int Severity - { - get { return m_dwSeverity; } - } - - /// - /// Subcondition comparison operator - /// - /// - /// - /// - public static bool operator ==(OPCSubcondition left, OPCSubcondition right) - { - return (left.m_wsName == right.m_wsName); - } - - /// - /// Subcondition comparison operator - /// - /// - /// - /// - public static bool operator !=(OPCSubcondition left, OPCSubcondition right) - { - return (left.m_wsName != right.m_wsName); - } - - /// - /// Required override - /// - /// - public override int GetHashCode() - { - return base.GetHashCode(); - } - - /// - /// Required override - /// - /// - /// - public override bool Equals(Object obj) - { - if (obj == null || GetType() != obj.GetType()) return false; - OPCSubcondition sub = (OPCSubcondition)obj; - return (m_wsName == sub.m_wsName); - } - - - #region Private Members - private string m_wsName; - private string m_wsMessage; - private string m_wsDefinition; - private int m_dwSeverity; - #endregion - } - - /// - /// OPCCondition class definition. Instances of OPCCondition represent a unique source/condition pair - /// and persist within the SourceMap until such time that the condition transitions to acked - /// (if ACK is required) and inactive. OPCCondition class instances are also used to forward Simple and - /// Tracking event information but these instances do not persist within the SourceMap - /// - public class OPCCondition - { - /// - /// Default constructor - /// - public OPCCondition() - { - ClearChangeMask(); - m_EventId = null; - m_dwEventCategory = 0; - m_dwSeverity = 0; - m_dwEventType = 0; - m_dwEventCategory = 0; - m_dwSeverity = 0; - m_bEnabled = true; - m_wNewState = (short)(m_bEnabled ? OpcRcw.Ae.Constants.CONDITION_ENABLED : 0); - m_wQuality = (short)Qualities.OPC_QUALITY_GOOD; - m_bAckRequired = false; - m_dwCookie = m_dwCookieCounter++; - m_wsAckComment = ""; - m_wsActorID = ""; - m_bInitialEnableSet = false; - m_bInitialQualitySet = false; - m_bInitialAckSet = false; - m_bInitialActiveSet = false; - m_bInitialActiveTimeSet = false; - m_ConditionId = null; - m_AcknowledgeMethod = null; - m_bAckPending = false; - m_ftAckPendingStartTime = DateTime.MinValue; - } - - /// - /// ChangeMask Property - /// - public short ChangeMask - { - get { return m_wChangeMask; } - } - - /// - /// EventID Property - /// - public byte[] EventId - { - get { return m_EventId; } - set { m_EventId = value; } - } - - /// - /// NewState property - /// - public short NewState - { - get { return m_wNewState; } - } - - /// - /// Time (of last change) property - /// - public DateTime Time - { - get { return m_ftTime; } - } - - /// - /// Message property - /// - public string Message - { - get { return m_wsMessage; } - } - - /// - /// EventType -- Simple, Tracking, Condition -- property - /// - public int EventType - { - get { return m_dwEventType; } - set { m_dwEventType = value; } - } - - /// - /// Category property - /// - public int EventCategory - { - get { return m_dwEventCategory; } - set { m_dwEventCategory = value; } - } - - /// - /// Severity property - /// - public int Severity - { - get { return m_dwSeverity; } - } - - /// - /// Currently active Subcondition name property - /// - public string SubconditionName - { - get { return m_wsSubconditionName; } - } - - /// - /// Quality property - /// - public short Quality - { - get { return m_wQuality; } - } - - /// - /// AckRequired property - /// - public bool AckRequired - { - get { return m_bAckRequired; } - } - - /// - /// ActiveTime property - /// - public DateTime ActiveTime - { - get { return m_ftActiveTime; } - } - - /// - /// Time of last active subcondition - /// - public DateTime SubconditionTime - { - get { return m_ftSubconditionTime; } - } - - /// - /// Time of last acknowledgement - /// - public DateTime LastAckTime - { - get { return m_ftLastAckTime; } - } - - /// - /// Time the condition transitioned to inactive - /// - public DateTime RTNTime - { - get { return m_ftRTNTime; } - } - - /// - /// Cookie property - /// - public int Cookie - { - get { return m_dwCookie; } - set { m_dwCookie = value; } - } - - /// - /// ActorID property - /// - public string ActorID - { - get { return m_wsActorID; } - set { m_wsActorID = value; } - } - - /// - /// ConditionId - /// - public NodeId ConditionId - { - get { return m_ConditionId; } - set { m_ConditionId = value; } - } - - /// - /// AcknowledgeMethod - /// - public NodeId AcknowledgeMethod - { - get { return m_AcknowledgeMethod; } - set { m_AcknowledgeMethod = value; } - } - - /// - /// AckComment property - /// - public string AckComment - { - get { return m_wsAckComment; } - } - - /// - /// Event attributes property - /// - public Dictionary EventAttributes - { - get { return m_EventAttributes; } - } - - /// - /// Condition is enabled - /// - public bool Enabled - { - get { return m_bEnabled; } - } - - /// - /// Returns list of associated areas associated - /// - public List Areas - { - get { return m_Areas; } - } - - /// - /// Returns list of associated subconditions - /// - public List Subconditions - { - get { return m_Subconditions; } - } - - /// - /// Is the active bit set in NewState ? - /// - /// - public bool IsActive() - { - return ((m_wNewState & OpcRcw.Ae.Constants.CONDITION_ACTIVE) !=0); - } - - /// - /// Called from AckCondition -- includes special handling for the case when - /// The ack has been forwarded to the target UA server but confirmation of the - /// ack has not yet been received. In this case we will want wait for a max - /// period of time ('ftAckWaitTime'), just in case the ack from the target is - /// on its way. dateValue.ToString("hh:mm:ss.fff tt"); - /// - /// - public bool IsAckedOrWaiting(double AckWaitTime) - { - // Utils.Trace("IsAckedOrWaiting (AckWaitTime: {0}) => BEGIN", AckWaitTime); - if ((m_wNewState & OpcRcw.Ae.Constants.CONDITION_ACKED) != 0) - { - // Condition acknowledgement event has been received from the server - // Utils.Trace("IsAckedOrWaiting: Condition is ACKED - return true"); - return true; - } - else if (m_bAckPending == false) - { - // Set a flag indicating that we are waiting for the ack confirmation from the server - m_bAckPending = true; - m_ftAckPendingStartTime = DateTime.Now; - // Utils.Trace("IsAckedOrWaiting: set bAckPending == true, AckPendingStartTime == {0}", m_ftAckPendingStartTime.ToString("hh:mm:ss.fff")); - return false; - } - else - { - DateTime waitUntil = m_ftAckPendingStartTime + new TimeSpan((long)AckWaitTime * TimeSpan.TicksPerMillisecond); - m_bAckPending = false; - // Wait out the remaining "wait for ack confirmation" period - // If we haven't received the condition ack event from the server - // after this period then return false - Utils.Trace("IsAckedOrWaiting: bAckPending is true, waitUntil -> {0}, Now -> {1}", waitUntil.ToString("hh:mm:ss.fff"), DateTime.Now.ToString("hh:mm:ss.fff")); - while (DateTime.Now < waitUntil) - { - System.Threading.Thread.Sleep(100); - if ((m_wNewState & OpcRcw.Ae.Constants.CONDITION_ACKED) != 0) - break; - } - - Utils.Trace("IsAckedOrWaiting: set bAckPending == false, Now -> {0}", DateTime.Now.ToString("hh:mm:ss.fff")); - return ((m_wNewState & OpcRcw.Ae.Constants.CONDITION_ACKED) != 0); - } - } - - /// - /// Is the Acked bit set in NewState ? - /// - /// - public bool IsAcked() - { - return ((m_wNewState & OpcRcw.Ae.Constants.CONDITION_ACKED) != 0); - } - - /// - /// Is the enabled bit set in NewState ? - /// - /// - public bool IsEnabled() - { - return ((m_wNewState & OpcRcw.Ae.Constants.CONDITION_ENABLED) !=0); - } - - /// - /// Number of attributes - /// - /// - public int sizeEventAttributes() - { - return m_EventAttributes.Count; - } - - /// - /// Reset the change mask - /// - public void ClearChangeMask() - { - m_wChangeMask = 0; - } - - /* - public bool IsEffectivelyEnabled(); - public bool AreAreasEffectivelyEnabled(); - public bool UpdateEffectiveState(); - */ - - /// - /// Adjusts the Enable bit of the NewState and ChangeMask - /// - /// - public void SetEnable(bool bEnable) - { - if ((bEnable != IsEnabled()) || !m_bInitialEnableSet) - { - if (bEnable) - m_wNewState |= OpcRcw.Ae.Constants.CONDITION_ENABLED; - else - m_wNewState &= ~OpcRcw.Ae.Constants.CONDITION_ENABLED; - - m_wChangeMask |= OpcRcw.Ae.Constants.CHANGE_ENABLE_STATE; - m_bInitialEnableSet = true; - } - // UpdateEffectiveState(); - } - - /// - /// Adjusts the Active bit of the NewState and ChangeMask - /// - /// - public void SetActive(bool bActive) - { - if ((bActive != IsActive()) || !m_bInitialActiveSet) - { - m_wChangeMask |= OpcRcw.Ae.Constants.CHANGE_ACTIVE_STATE; - - if (bActive) // transitioned into alarm - m_wNewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE; - else // return to normal - m_wNewState &= ~OpcRcw.Ae.Constants.CONDITION_ACTIVE; - - m_bInitialActiveSet = true; - } - } - - /// - /// Adjusts the Acked bit of the NewState and ChangeMask. Unlike method 'Ack' above this method is - /// not called as a direct result of AckCondition. Rather, events received from the target UA server may - /// have become acknowledged out of band (e.g., via acknowledgement from a UA client). - /// - /// - public void SetIsAcked(bool bIsAcked) - { - if ((bIsAcked != IsAcked()) || !m_bInitialAckSet) - { - m_wChangeMask |= OpcRcw.Ae.Constants.CHANGE_ACK_STATE; - - if (bIsAcked) // transitioned into acked - { - m_wNewState |= OpcRcw.Ae.Constants.CONDITION_ACKED; - m_bAckRequired = false; - m_ftLastAckTime = m_ftTime; - m_bAckPending = false; - } - else // return to unacked - m_wNewState &= ~OpcRcw.Ae.Constants.CONDITION_ACKED; - - m_bInitialAckSet = true; - } - } - - - /// - /// Time of last state change - /// - /// - public void SetTime(DateTime ftTime) - { - m_ftTime = ftTime; - if (IsActive() || !m_bInitialActiveTimeSet) - { - if ((m_wChangeMask & OpcRcw.Ae.Constants.CHANGE_ACTIVE_STATE) !=0) - { - m_ftActiveTime = m_ftTime; - m_ftSubconditionTime = m_ftTime; - } - else if ((m_wChangeMask & OpcRcw.Ae.Constants.CHANGE_SUBCONDITION) !=0) - m_ftSubconditionTime = m_ftTime; - - m_bInitialActiveTimeSet = true; - } - else - { - if ((m_wChangeMask & OpcRcw.Ae.Constants.CHANGE_ACTIVE_STATE) !=0) - m_ftRTNTime = m_ftTime; - } - } - - - /// - /// Time of last state change is now - /// - public void SetTime() // time of event is now - { - DateTime ftNow = DateTime.Now; - SetTime(ftNow); - } - - /// - /// Message has changed - /// - /// - public void SetMessage(string wszString) - { - if (m_wsMessage != wszString) - { - m_wsMessage = wszString; - m_wChangeMask |= OpcRcw.Ae.Constants.CHANGE_MESSAGE; - } - } - - /// - /// Set severity and adjust the ChangeMask - /// - /// - public void SetSeverity(int dwSeverity) - { - if (dwSeverity != m_dwSeverity) - { - m_dwSeverity = dwSeverity; - m_wChangeMask |= OpcRcw.Ae.Constants.CHANGE_SEVERITY; - } - } - - /// - /// Set the currently active subcondition name and adjust the ChangeMask - /// - /// - public void SetSubconditionName(string wszSubconditionName) - { - if (m_wsSubconditionName != wszSubconditionName) - { - m_wsSubconditionName = wszSubconditionName; - m_wChangeMask |= OpcRcw.Ae.Constants.CHANGE_SUBCONDITION; - } - } - - - /// - /// Set the quality and adjust the ChangeMask - /// - /// - public void SetQuality(short wQuality) - { - if ((m_wQuality != wQuality) || !m_bInitialQualitySet) - { - m_wQuality = wQuality; - m_wChangeMask |= OpcRcw.Ae.Constants.CHANGE_QUALITY; - m_bInitialQualitySet = true; - } - } - - /// - /// Apply the AckRequired setting when transitioning to Active - /// - /// - public void SetAckRequired(bool bAckReq) - { - m_bAckRequired = bAckReq; - } - - /// - /// Inserts attribute ID/Value pair into the attribute values map - /// - /// - /// - public void push_back_attrval(int dwAttrID, object AnEventAttribute) - { - object value = null; - - if (m_EventAttributes.TryGetValue(dwAttrID, out value)) - { - // TODO: Need to perform a "real" comparison on the attribute value -- - // this just compares pointers and will always evaluate true - if (value != AnEventAttribute) - { - m_EventAttributes[dwAttrID] = AnEventAttribute; - m_wChangeMask |= OpcRcw.Ae.Constants.CHANGE_ATTRIBUTE; - } - } - else - { - m_EventAttributes[dwAttrID] = AnEventAttribute; - m_wChangeMask |= OpcRcw.Ae.Constants.CHANGE_ATTRIBUTE; - } - } - - /// - /// Deletes the contents of the attribute values map - /// - public void clear() - { - m_EventAttributes.Clear(); - } - - /// - /// Inserts an area name into the areas list - /// - /// - public void push_back_area(string sArea) - { - m_Areas.AddUnique(sArea); - } - - /// - /// Insertas a subcondition into the subconditions list - /// - /// - public void push_back_subcondition(OPCSubcondition sub) - { - m_Subconditions.AddUnique(sub); - } - - - #region Private Members - private byte[] m_EventId; - private short m_wChangeMask; - private short m_wNewState; - private DateTime m_ftTime; - private DateTime m_ftLastAckTime; - private string m_wsMessage; - private int m_dwCookie; - private int m_dwEventType; - private int m_dwEventCategory; - private int m_dwSeverity; - private string m_wsSubconditionName; - private short m_wQuality; - private bool m_bAckRequired; - private DateTime m_ftActiveTime; - private DateTime m_ftSubconditionTime; - private DateTime m_ftRTNTime; - private string m_wsActorID; - private string m_wsAckComment; - private bool m_bEnabled; - private bool m_bInitialEnableSet; - private bool m_bInitialQualitySet; - private bool m_bInitialAckSet; - private bool m_bInitialActiveSet; - private bool m_bInitialActiveTimeSet; - private NodeId m_ConditionId; - private NodeId m_AcknowledgeMethod; - private bool m_bAckPending; - private DateTime m_ftAckPendingStartTime; - - /// - /// Simplistics means to generate a unique cookie - /// - static public int m_dwCookieCounter = 0; - - private Dictionary m_EventAttributes = new Dictionary(); - private UniqueList m_Areas = new UniqueList(); - private UniqueList m_Subconditions = new UniqueList(); - #endregion - - } - - /// - /// Holds the contents of one ONEVENTSTRUCT. Instances are pushed into each subscription's - /// pending events queue where the subscription filter applies to the event. - /// - public class OnEventClass - { - /// - /// Constructor -- initializes all members - /// - /// - /// - /// - public OnEventClass(string wszSource, string wszCondition, OPCCondition cond) - { - m_oes.pEventAttributes = IntPtr.Zero; - m_oes.dwNumEventAttrs = 0; - m_oes.wChangeMask = cond.ChangeMask; - m_oes.wNewState = cond.NewState; - m_oes.szSource = wszSource; - m_oes.ftTime = ComUtils.GetFILETIME(cond.Time); - m_oes.szMessage = cond.Message; - m_oes.dwEventType = cond.EventType; - m_oes.dwEventCategory = cond.EventCategory; - m_oes.dwSeverity = cond.Severity; - m_oes.szConditionName = wszCondition; - m_oes.szSubconditionName = cond.SubconditionName; - m_oes.wQuality = cond.Quality; - m_oes.bAckRequired = cond.AckRequired ?1:0; - m_oes.ftActiveTime = ComUtils.GetFILETIME(cond.SubconditionTime); - m_oes.dwCookie = cond.Cookie; - m_oes.szActorID = cond.ActorID; - - m_EventAttributes = (Dictionary) DeepCopy (cond.EventAttributes); - } - - /// - /// Performs a deep copy of the event attributes map/dictionary - /// - /// - /// - private object DeepCopy(object obj) - { - MemoryStream ms = new MemoryStream(); - BinaryFormatter bf = new BinaryFormatter(); - bf.Serialize(ms, obj); - - object newObj; - ms.Seek(0, SeekOrigin.Begin); - newObj = bf.Deserialize(ms); - ms.Close(); - return newObj; - } - - /// - /// Returns the event attributes map - /// - public Dictionary EventAttributes - { - get { return m_EventAttributes; } - } - - /// - /// A COM compatible ONEVENTSTRUCT - /// - public ONEVENTSTRUCT InternalOES - { - get { return m_oes; } - } - - private ONEVENTSTRUCT m_oes; - private Dictionary m_EventAttributes; - - } -} diff --git a/ComIOP/Common/Server/Ae/ComAeEventNotification.cs b/ComIOP/Common/Server/Ae/ComAeEventNotification.cs deleted file mode 100644 index 0dfd17630..000000000 --- a/ComIOP/Common/Server/Ae/ComAeEventNotification.cs +++ /dev/null @@ -1,357 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using System.Threading; -using OpcRcw.Ae; -using OpcRcw.Da; - -namespace Opc.Ua.Com.Server.Ae -{ - /// - /// Processing of events received from the target UA server - /// - public class IncomingEventHandler - { - /// - /// If the event type is CONDITION_EVENT then update any existing record of the condition and adjust - /// state and change mask. - /// - /// - /// - public void ProcessEventNotificationList(EventNotification EventNotification, string[] areas) - { - SourceMap sourceMap = SourceMap.TheSourceMap; - try - { - lock (sourceMap) - { - OPCCondition cond; - if (EventNotification.EventType == OpcRcw.Ae.Constants.CONDITION_EVENT) - { - ConditionMap conditionMap; - if (sourceMap.TryGetValue(EventNotification.SourceID, out conditionMap) == false) - { - conditionMap = new ConditionMap(); - sourceMap.Add(EventNotification.SourceID, conditionMap); - } - - if (conditionMap.TryGetValue(EventNotification.ConditionName, out cond) == false) - { - cond = new OPCCondition(); - cond.EventType = EventNotification.EventType; - conditionMap.Add(EventNotification.ConditionName, cond); - } - - ProcessCondition(EventNotification, areas, cond); - - // When the condition has transitioned to Acked (if ack required) and inactive or disabled - // then remove it from the condition source/condition database - if ((!cond.IsActive() || !cond.IsEnabled()) && (cond.IsAcked() || !cond.AckRequired)) - conditionMap.Remove(EventNotification.ConditionName); - } - else // a tracking or simple event - { - cond = new OPCCondition(); - cond.EventType = EventNotification.EventType; - ProcessCondition(EventNotification, areas, cond); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in ProcessEventNotificationList"); - } - } - - /// - /// Values of existing CONDITION events are updated the forwarded to TheGlobal for further processing - /// per subscription per server instance - /// - /// - /// - /// - private void ProcessCondition(EventNotification EventNotification, string[] areas, OPCCondition newCond) - { - try - { - newCond.ClearChangeMask(); - newCond.SetMessage(EventNotification.Message); - newCond.SetSeverity(EventNotification.Severity); - newCond.SetSubconditionName(EventNotification.SubConditionName); - newCond.SetActive((EventNotification.NewState & OpcRcw.Ae.Constants.CONDITION_ACTIVE) != 0); - - // The UA server generates unique identifiers in the form of guids. how to map these to COM-style cookies? - // For now, just increment a static DWORD counter from the OPCCondition constructor and assign - //newCond.Cookie = EventNotification.Cookie; - - newCond.SetTime(EventNotification.ActiveTime); - newCond.EventId = EventNotification.EventId; - newCond.EventCategory = EventNotification.EventCategory; - newCond.SetQuality((short)EventNotification.Quality); - newCond.ActorID = EventNotification.EventType == OpcRcw.Ae.Constants.TRACKING_EVENT ? EventNotification.ActorID : ""; - newCond.SetEnable((EventNotification.NewState & OpcRcw.Ae.Constants.CONDITION_ENABLED) != 0); - newCond.SetIsAcked((EventNotification.NewState & OpcRcw.Ae.Constants.CONDITION_ACKED) != 0); - newCond.SetAckRequired(EventNotification.AckRequired); - newCond.ConditionId = EventNotification.ConditionId; - newCond.AcknowledgeMethod = EventNotification.AcknowledgeMethod; - - OPCSubcondition subCond = new OPCSubcondition(newCond.SubconditionName, newCond.Message, "", newCond.Severity); - newCond.push_back_subcondition(subCond); - - for (int i = 0; i < areas.Length; i++) - newCond.push_back_area(areas[i]); - - // Insert standard attribute "AckComment" - newCond.push_back_attrval(Global.TheGlobal.StdAttrIds[0], newCond.AckComment); - // Insert standard attribute "Areas" - newCond.push_back_attrval(Global.TheGlobal.StdAttrIds[1], areas); - - foreach (KeyValuePair kvp in EventNotification.EventAttributes) - newCond.push_back_attrval(kvp.Key, kvp.Value); - - if (newCond.IsEnabled()) - { - lock (Global.TheGlobal) - { - Global.TheGlobal.NotifyClients(EventNotification.SourceID, EventNotification.ConditionName, newCond); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in ProcessCondition"); - } - - // Utils.Trace("ProcessCondition - END Source: {0}, condition: {1}, conditionstate: {2}", - // EventNotification.SourceID, EventNotification.ConditionName, newCond.NewState); - } - } - - /// - /// Instances initialized as new "raw" UA events are received from the target UA server - /// - public class EventNotification - { - /// - /// Source name - /// - public byte[] EventId - { - get { return m_eventId; } - set { m_eventId = value; } - } - - /// - /// Source name - /// - public string SourceID - { - get { return m_sourceID; } - set { m_sourceID = value; } - } - - /// - /// Time of event occurance - /// - public DateTime Time - { - get { return m_time; } - set { m_time = value; } - } - - /// - /// Message associated with the event - /// - public string Message - { - get { return m_message; } - set { m_message = value; } - } - - /// - /// Event type -- simple, tracking, condition - /// - public int EventType - { - get { return m_eventType; } - set { m_eventType = value; } - } - - /// - /// Event Category - /// - public int EventCategory - { - get { return m_eventCategory; } - set { m_eventCategory = value; } - } - - /// - /// Event Severity - /// - public int Severity - { - get { return m_severity; } - set { m_severity = value; } - } - - /// - /// Condition name - /// - public string ConditionName - { - get { return m_conditionName; } - set { m_conditionName = value; } - } - - /// - /// Name of last active subcondition - /// - public string SubConditionName - { - get { return m_subConditionName; } - set { m_subConditionName = value; } - } - - /// - /// Change mask - /// - public int ChangeMask - { - get { return m_changeMask; } - set { m_changeMask = value; } - } - - /// - /// New state - /// - public int NewState - { - get { return m_newState; } - set { m_newState = value; } - } - - /// - /// Quality - /// - public short Quality - { - get { return m_quality; } - set { m_quality = value; } - } - - /// - /// Acknowledgement required - /// - public bool AckRequired - { - get { return m_ackRequired; } - set { m_ackRequired = value; } - } - - /// - /// Time of last transition to active - /// - public DateTime ActiveTime - { - get { return m_activeTime; } - set { m_activeTime = value; } - } - - /// - /// Cookie - /// - public int Cookie - { - get { return m_cookie; } - set { m_cookie = value; } - } - - /// - /// Actor ID - /// - public string ActorID - { - get { return m_actorID; } - set { m_actorID = value; } - } - - /// - /// ConditionId - /// - public NodeId ConditionId - { - get { return m_ConditionId; } - set { m_ConditionId = value; } - } - - /// - /// AcknowledgeMethod - /// - public NodeId AcknowledgeMethod - { - get { return m_AcknowledgeMethod; } - set { m_AcknowledgeMethod = value; } - } - - /// - /// Associated event attribute IDs/Values - /// - public Dictionary EventAttributes - { - get { return m_EventAttributes; } - set { m_EventAttributes = value; } - } - - private string m_sourceID = null; - private DateTime m_time = DateTime.MinValue; - private string m_message = null; - private int m_eventType = OpcRcw.Ae.Constants.CONDITION_EVENT; - private int m_eventCategory = 0; - private byte[] m_eventId = null; - private int m_severity = 1; - private string m_conditionName = null; - private string m_subConditionName = null; - private int m_changeMask = 0; - private int m_newState = 0; - private short m_quality = (short)Qualities.OPC_QUALITY_GOOD; - private bool m_ackRequired = false; - private DateTime m_activeTime = DateTime.MinValue; - private int m_cookie = 0; - private string m_actorID = null; - private NodeId m_ConditionId = null; - private NodeId m_AcknowledgeMethod = null; - private Dictionary m_EventAttributes = new Dictionary(); - } - -} diff --git a/ComIOP/Common/Server/Ae/ComAeGlobalStructures.cs b/ComIOP/Common/Server/Ae/ComAeGlobalStructures.cs deleted file mode 100644 index 843712ae8..000000000 --- a/ComIOP/Common/Server/Ae/ComAeGlobalStructures.cs +++ /dev/null @@ -1,141 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using System.Globalization; - -namespace Opc.Ua.Com.Server.Ae -{ - /// - /// Primary purpose is to maintain list of server instances and as a respository for - /// data common to all server instances. - /// - public class Global - { - /// - /// Constructor - /// - public Global() - { - m_StartTime = DateTime.Now; - m_EvServerSet = new List(); - m_lcid = ComUtils.LOCALE_SYSTEM_DEFAULT; - m_StdAttrNames = new string[] { "AckComment", "Areas" }; - m_StdAttrIds = new int[] { 0, 1 }; - } - - /// - /// Called during incoming event processing and as a result of a client-initiated Refresh. - /// Forwards to each server instance for further processing. - /// - /// - /// - /// - public void NotifyClients(string Source, string Condition, OPCCondition cond) - { - OnEventClass OEClass = new OnEventClass(Source, Condition, cond); - - foreach (ComAeProxy s in m_EvServerSet) - { - s.ProcessNewEvent(OEClass); - } - - } - - /// - /// Called from server object constructor to insert server reference into the global list - /// - /// - public void ServerListInsert(ComAeProxy s) - { - m_EvServerSet.Add(s); - } - - /// - /// Called from server object finalizer to remove server reference from the global list - /// - /// - public void ServerListRemove(ComAeProxy s) - { - m_EvServerSet.Remove(s); - } - - /// - /// Start time for this COM proxy - /// - public DateTime StartTime - { - get { return m_StartTime; } - } - - /// - /// Locale ID - /// - public int LCID - { - get { return m_lcid; } - } - - /// - /// Static accessor - /// - public static Global TheGlobal - { - get { return theGlobal; } - } - - /// - /// Standard attribute names - /// - public string[] StdAttrNames - { - get { return m_StdAttrNames; } - } - - /// - /// Standard attribute IDs - /// - public int[] StdAttrIds - { - get { return m_StdAttrIds; } - } - - private readonly string[] m_StdAttrNames; - private readonly int[] m_StdAttrIds; - private static Global theGlobal = new Global(); - private List m_EvServerSet; - private DateTime m_StartTime; - private int m_lcid; - - } - -} diff --git a/ComIOP/Common/Server/Ae/ComAeProxy.cs b/ComIOP/Common/Server/Ae/ComAeProxy.cs deleted file mode 100644 index c2e2fca43..000000000 --- a/ComIOP/Common/Server/Ae/ComAeProxy.cs +++ /dev/null @@ -1,2709 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Xml.Serialization; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Microsoft.Win32; -using Opc.Ua.Client; -using OpcRcw.Ae; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Server.Ae -{ - /// - /// A base class for classes that implement an OPC COM specification. - /// - internal class ComAeProxy2 : ComProxy - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComAeProxy2(SessionCreatedEventHandler callback, ReconnectInProgressEventHandler reconnectCallback) - { - m_mapper = new ComNamespaceMapper(); - m_callback = callback; - m_reconnectCallback = reconnectCallback; - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - // TBD - } - - base.Dispose(disposing); - } - #endregion - - #region Overridden Methods - /// - /// Called when a new session is created. - /// - protected override void OnSessionCreated() - { - lock (Lock) - { - // fetch the configuration. - m_configuration = Endpoint.ParseExtension(null); - - if (m_configuration == null) - { - m_configuration = new ComProxyConfiguration(); - } - - // update the mapping and pass the new session to other objects. - m_mapper.Initialize(Session, m_configuration); - - // save the configuration. - Endpoint.UpdateExtension(null, m_configuration); - SaveConfiguration(); - } - - // invoke callback. - if (m_callback != null) - { - m_callback(Session); - } - } - - /// - /// Called when a session is reconnected. - /// - protected override void OnSessionReconected() - { - if (m_reconnectCallback != null) - { - m_reconnectCallback(Session, 0); - } - } - - /// - /// Called when a session reconnect is scheduled. - /// - protected override void OnReconnectInProgress(int secondsToReconnect) - { - if (m_reconnectCallback != null) - { - m_reconnectCallback(null, secondsToReconnect); - } - } - - /// - /// Called when a session is removed. - /// - protected override void OnSessionRemoved() - { - // TBD - } - #endregion - - #region Private Fields - private ComProxyConfiguration m_configuration; - private ComNamespaceMapper m_mapper; - private SessionCreatedEventHandler m_callback; - private ReconnectInProgressEventHandler m_reconnectCallback; - #endregion - } - - internal delegate void SessionCreatedEventHandler(Session session); - internal delegate void ReconnectInProgressEventHandler(Session session, int secondsToReconnect); - - /// - /// OPC AE Event server. - /// - public class ComAeProxy : - ConnectionPointContainer, - IOPCCommon, - IOPCEventServer, - IOPCEventServer2 - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComAeProxy() - { - RegisterInterface(typeof(OpcRcw.Comn.IOPCShutdown).GUID); - Global.TheGlobal.ServerListInsert(this); - } - - /// - /// Finalizer - /// - ~ComAeProxy() - { - UnregisterInterface(typeof(OpcRcw.Comn.IOPCShutdown).GUID); - Global.TheGlobal.ServerListRemove(this); - } - #endregion - - #region IOPCWrappedServer Members - /// - /// Called when the object is loaded by the COM wrapper process. - /// - public virtual void Load(Guid clsid, ApplicationConfiguration configuration) - { - try - { - // load the configuration if this is the first time. - lock (m_staticLock) - { - if (m_configuration == null) - { - m_configuration = configuration; - m_endpointCache = new ConfiguredEndpointCollection(m_configuration); - m_verifiedEndpoints = new Dictionary(); - m_configuration.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); - } - } - - lock (m_lock) - { - m_startTime = DateTime.UtcNow; - m_lastUpdateTime = DateTime.MinValue; - m_clsid = clsid; - - // create the proxy that manages connections with the server. - m_proxy = new ComAeProxy2(OnSessionCreated, OnSessionReconnect); - m_proxy.Load(clsid, m_configuration); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in Load()."); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Called when a session is created with a server. - /// - private void OnSessionReconnect(Session session, int secondsToReconnect) - { - lock (m_lock) - { - m_session = null; - m_Subscription = null; - m_AreaNodes.Clear(); - } - } - - /// - /// Called when a session is created with a server. - /// - private void OnSessionCreated(Session session) - { - string commonAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); - string configFileName = Utils.Format(@"{0}\OPC Foundation\ComPseudoServers\{1}.internal.xml", commonAppDataPath, m_clsid); - - lock (m_lock) - { - try - { - m_session = null; - m_Subscription = null; - m_AreaNodes.Clear(); - - m_session = session; - - // load the config file. - if (File.Exists(configFileName)) - { - XmlSerializer ser = new XmlSerializer(typeof(Configuration)); - TextReader reader = new StreamReader(configFileName); - m_configFile = (Configuration)ser.Deserialize(reader); - reader.Close(); - - // set the ActualDataType property - for (int ii = 0; ii < m_configFile.Attributes.Length - 1; ii++) - { - NodeId nodeid = new NodeId(m_configFile.Attributes[ii].strDataTypeNodeId); - m_configFile.Attributes[ii].ActualDataType = DataTypes.GetSystemType(nodeid, EncodeableFactory.GlobalFactory); - } - } - else - { - InitConfigInfo(configFileName); - } - - // Obtain the current server table, generate index mapping tables (client->server, server->client) - // and update the client side namespace table if necessary due to server changes - GenerateNamespaceIndexMappings(m_clsid); - - // The client side namespace table may have been updated if the server namespace table - // has changed therefore save the updated client table. - SaveConfigInfo(configFileName); - - // fetch type tree. - m_session.FetchTypeTree(Opc.Ua.ObjectTypeIds.BaseEventType); - m_session.FetchTypeTree(Opc.Ua.ReferenceTypeIds.References); - - //Create UA Event Subscription if none configured in the registry - m_Subscription = new Opc.Ua.Client.Subscription(m_session.DefaultSubscription); - m_Subscription.PublishingEnabled = true; - m_Subscription.PublishingInterval = m_configFile.ProxySubscriptionSettings.PublishingInterval; - m_Subscription.KeepAliveCount = m_configFile.ProxySubscriptionSettings.KeepAliveCount; - m_Subscription.LifetimeCount = m_configFile.ProxySubscriptionSettings.LifetimeCount; - m_Subscription.Priority = m_configFile.ProxySubscriptionSettings.Priority; - m_Subscription.MaxNotificationsPerPublish = m_configFile.ProxySubscriptionSettings.MaxNotificationsPerPublish; - - m_session.AddSubscription(m_Subscription); - m_Subscription.Create(); - m_KeepAliveInterval = (int)(m_Subscription.CurrentPublishingInterval * m_Subscription.CurrentKeepAliveCount); - - // Add Server object as the only monitored item to this subscription - - NodeId nodeId_Server = new NodeId(Opc.Ua.Objects.Server); - - MonitoredItem monitoredItem = CreateMonitoredItemForEvents(nodeId_Server); - m_Subscription.AddItem(monitoredItem); - m_Subscription.ApplyChanges(); - - AreaNode areaNode = new AreaNode(); - areaNode.AreaName = "/"; - ++areaNode.RefCount; - areaNode.MonitoredItem = monitoredItem; - m_notifiers.Add(monitoredItem.ClientHandle, areaNode); - m_AreaNodes.Add("/", areaNode); - - m_Subscription.Session.Call( - Opc.Ua.ObjectTypes.ConditionType, - Methods.ConditionType_ConditionRefresh, - m_Subscription.Id); - } - catch (Exception e) - { - Utils.Trace(e, "Initializing server after create."); - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Saves the proxy configuration file - /// - /// Config filename - /// - private void SaveConfigInfo(string configFileName) - { - try - { - XmlSerializer ser = new XmlSerializer(typeof(Configuration)); - StreamWriter writer = new StreamWriter(configFileName); - ser.Serialize(writer, m_configFile); - writer.Close(); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error saving internal configuration file: {0}", configFileName); - } - } - - - /// - /// compares the new server namespace table with the (saved) table known to the client. Provides a - /// mapping for any namespaces which are new or removed and indices which have changed. - /// - /// - private void GenerateNamespaceIndexMappings(Guid clsid) - { - try - { - StringTable savedStringTable = new StringTable(); - for (int i = 0; i < m_configFile.SavedNamespaceTable.Length; i++) - savedStringTable.Append(m_configFile.SavedNamespaceTable[i]); - - NamespaceTable serverNamespaceTable = m_session.NamespaceUris; - string[] serverNamespaceArray = serverNamespaceTable.ToArray(); - - for (int i = 0; i < serverNamespaceArray.Length; i++) - { - // Generate the serverIndex->clientIndex mapping table. Update the client namespace - // table in the process if new namespaces have been added to the server namespace - m_serverMappingTable.Add(savedStringTable.GetIndexOrAppend(serverNamespaceArray[i])); - } - - m_configFile.SavedNamespaceTable = savedStringTable.ToArray(); - - for (int i = 0; i < m_configFile.SavedNamespaceTable.Length; i++) - { - // Generate the clientIndex->serverIndex mapping table - m_clientmappingTable.Add(serverNamespaceTable.GetIndex(m_configFile.SavedNamespaceTable[i])); - } - - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in InitNamespaceMappingTable"); - } - } - - /// - /// Called when the object is unloaded by the COM wrapper process. - /// - public virtual void Unload() - { - lock (m_lock) - { - Utils.SilentDispose(m_proxy); - m_proxy = null; - m_session = null; - m_Subscription = null; - } - } - #endregion - - #region Initialization Members - /// - /// Initializing the configuration data. (allUsers + @"\Application Data\OPC Foundation\COM Interop\" + remoteServerDlg.PseudoClassID) - /// - private void InitConfigInfo(string configFileName) - { - try - { - Browser browser = new Browser(m_session); - ReferenceDescriptionCollection references = browser.Browse(Opc.Ua.ObjectTypes.BaseEventType); - - if (references == null) - { - throw new Exception("No BaseEventType found in the type hierarchy"); - } - - foreach (ReferenceDescription reference in references) - { - // check for base event types. - if (reference.NodeClass == NodeClass.ObjectType) - { - int cattype = OpcRcw.Ae.Constants.SIMPLE_EVENT; - - if (reference.NodeId == Opc.Ua.ObjectTypes.ConditionType) - { - cattype = OpcRcw.Ae.Constants.CONDITION_EVENT; - } - else if (reference.NodeId == Opc.Ua.ObjectTypes.AuditEventType) - { - cattype = OpcRcw.Ae.Constants.TRACKING_EVENT; - } - - ProcessNodeAsCategory((NodeId)reference.NodeId, cattype); - } - - // check for properties. - else if (reference.NodeClass == NodeClass.Variable) - { - if (reference.TypeDefinition == Opc.Ua.VariableTypeIds.PropertyType) - { - ProcessNodeAsAttribute(Opc.Ua.ObjectTypes.BaseEventType, reference); - } - } - } - - // Add two special attribute for compatibility with AE COM - EventAttribute attr1 = new EventAttribute(); - attr1.AttributeID = Global.TheGlobal.StdAttrIds[1]; - attr1.strNodeId = "Areas"; - attr1.BrowseName = "AECOMAreas"; - attr1.BrowseNameNSIndex = 0; - attr1.AttrDesc = "Areas"; - attr1.strDataTypeNodeId = DataTypes.GetDataTypeId(typeof(string[])).ToString(); - attr1.strEventNodeId = ""; - attr1.IsArray = true; - attr1.ActualDataType = typeof(string[]); - m_EventAttributes.Add(attr1); - - attr1 = new EventAttribute(); - attr1.AttributeID = Global.TheGlobal.StdAttrIds[0]; - attr1.strNodeId = "AckComment"; - attr1.BrowseName = "AECOMAckComment"; - attr1.BrowseNameNSIndex = 0; - attr1.AttrDesc = "AckComment"; - attr1.strDataTypeNodeId = DataTypes.GetDataTypeId(typeof(string)).ToString(); - attr1.strEventNodeId = ""; - attr1.IsArray = false; - attr1.ActualDataType = typeof(string); - m_EventAttributes.Add(attr1); - - m_EventAttributes.Sort(EventAttributeNodeIdCompare); - m_EventCategories.Sort(EventCategoryBrowseNameCompare); - - m_configFile.Categories = m_EventCategories.ToArray(); - m_configFile.Attributes = m_EventAttributes.ToArray(); - m_configFile.LastEventCategoryID = m_catID; - m_configFile.LastEventAttributeID = m_attrID; - - m_configFile.SavedNamespaceTable = m_session.NamespaceUris.ToArray(); - - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in InitConfigInfo"); - } - } - - /// - /// Always accept server certificates. - /// - void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e) - { - e.Accept = true; - } - - /// - /// If this node is not abstract, add it as a category to the EventCategories list - /// and process all nodes beneath it as categories. - /// Also, add all of its atrributes to the EventAttributes list - /// - /// The node being processed - /// The category type id this node will be added as - private void ProcessNodeAsCategory(NodeId nodeId, int CategoryType) - { - try - { - Node node = m_session.ReadNode(nodeId); - EventCategory cat = new EventCategory(); - DataValue value = new DataValue(); - - cat.CategoryID = m_catID++; - cat.strNodeId = node.NodeId.ToString(); - cat.BrowseName = node.BrowseName.ToString(); - cat.EventDesc = node.DisplayName.Text; - cat.EventType = CategoryType; - m_EventCategories.Add(cat); - - Browser browse = new Browser(m_session); - ReferenceDescriptionCollection references = null; - - references = browse.Browse(nodeId); - - foreach (ReferenceDescription reference in references) - { - if (reference.NodeClass == NodeClass.ObjectType) - { - ProcessNodeAsCategory((NodeId)reference.NodeId, CategoryType); - } - else if ((reference.NodeClass == NodeClass.Variable) && (reference.ReferenceTypeId == Opc.Ua.ReferenceTypes.HasProperty)) - { - ProcessNodeAsAttribute(nodeId, reference); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in ProcessNodesAsCategory"); - } - } - - /// - /// Adds a node as an attribute to the EventCategories list - /// - /// The event type node - /// The reference node being added as an attribute - private void ProcessNodeAsAttribute(NodeId EventTypeNodeId, ReferenceDescription AttrRef) - { - try - { - EventAttribute attr = new EventAttribute(); - DataValue value = new DataValue(); - - attr.AttributeID = m_attrID++; - attr.strNodeId = AttrRef.NodeId.ToString(); - attr.BrowseName = AttrRef.BrowseName.Name; - attr.BrowseNameNSIndex = AttrRef.BrowseName.NamespaceIndex; - attr.AttrDesc = AttrRef.DisplayName.Text; - - Node node = m_session.ReadNode((NodeId)AttrRef.NodeId); - node.Read(null, Attributes.DataType, value); - NodeId typenode = (NodeId)value.Value; - attr.strDataTypeNodeId = typenode.ToString(); - attr.ActualDataType = DataTypes.GetSystemType(typenode, EncodeableFactory.GlobalFactory); - attr.strEventNodeId = EventTypeNodeId.ToString(); - - node.Read(null, Attributes.ValueRank, value); - //TODO: Used to be ArraySize. Does ValueRank have the same definition? - if ((int)value.Value >= 0) //TODO: is there a constant that can be used - attr.IsArray = true; - else - attr.IsArray = false; - - m_EventAttributes.Add(attr); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in ProcessNodesAsAttribute"); - } - } - - /// - /// Compare method based off the Attribute NodeId - /// - /// - /// - private static int EventAttributeNodeIdCompare(EventAttribute x, EventAttribute y) - { - return x.strNodeId.CompareTo(y.strNodeId); - } - - /// - /// Compare method based off the BrowseName - /// - /// - /// - private static int EventCategoryBrowseNameCompare(EventCategory x, EventCategory y) - //TODO: should this be a case insensitive compare? - { - return x.BrowseName.ToLower().CompareTo(y.BrowseName.ToLower()); - } - - - #endregion - - #region MonitoredItem Helper Members - /// - /// Creates a new MonitoredItem for events. Applies the standard event filters for condition events - /// and adds the filters necessary to obtain event attributes -- properties of event types/subtypes - /// - /// The node id. - /// - public MonitoredItem CreateMonitoredItemForEvents(NodeId nodeId) - { - MonitoredItem monitoredItem = new MonitoredItem(m_Subscription.DefaultItem); - monitoredItem.AttributeId = Attributes.EventNotifier; - monitoredItem.DisplayName = m_Subscription.Session.NodeCache.GetDisplayText((ExpandedNodeId)nodeId); - monitoredItem.StartNodeId = nodeId; - monitoredItem.NodeClass = NodeClass.Object; - - //get all attribute values from all events - EventFilter filter = new EventFilter(); - - foreach (EventAttribute attr in m_configFile.Attributes) - { - if (attr.strEventNodeId != "") - { - filter.AddSelectClause(new NodeId(attr.strEventNodeId), attr.BrowseName); - // Utils.Trace("AddSelectClause ( {0}: {1}, {2} )", i++, attr.strEventNodeId, attr.BrowseName); - } - } - - // Add Condition-related attributes to the filter so that we have enough info to determine - // Enabled/Disabled, Active/Inactive including time of active transition, Acked/Unacked and active subcondition - - filter.AddSelectClause(Opc.Ua.ObjectTypes.ConditionType, "/EnabledState/Id", Attributes.Value); - filter.AddSelectClause(Opc.Ua.ObjectTypes.ConditionType, "/Quality", Attributes.Value); - - filter.AddSelectClause(Opc.Ua.ObjectTypes.AcknowledgeableConditionType, "/AckedState/Id", Attributes.Value); - filter.AddSelectClause(Opc.Ua.ObjectTypes.AcknowledgeableConditionType, "", Attributes.NodeId); - - filter.AddSelectClause(Opc.Ua.ObjectTypes.AlarmConditionType, "/ActiveState/Id", Attributes.Value); - filter.AddSelectClause(Opc.Ua.ObjectTypes.AlarmConditionType, "/ActiveState/TransitionTime", Attributes.Value); - filter.AddSelectClause(Opc.Ua.ObjectTypes.AlarmConditionType, "/ActiveState/EffectiveDisplayName", Attributes.Value); - - monitoredItem.Filter = filter; - - monitoredItem.Notification += new MonitoredItemNotificationEventHandler(MonitoredItem_Notification); - - return monitoredItem; - - } - #endregion - - #region Subscription Helper methods - - /// - /// Calls the TraslateBrowsePathsToNodeIds service to get the nodeIds for each of the Relative Paths in the list - /// - /// The List of Relative Paths - public BrowsePathResultCollection GetBrowseTargets(List RelativePaths) - { - BrowsePathCollection browsePaths = new BrowsePathCollection(); - NamespaceTable clientUris = null; - try - { - clientUris = new NamespaceTable(m_configFile.SavedNamespaceTable); - } - catch (Exception) - { - return null; - } - - foreach (string relativePath in RelativePaths) - { - BrowsePath browsePath = new BrowsePath(); - browsePath.RelativePath = RelativePath.Parse(relativePath, m_session.TypeTree, clientUris, m_session.NamespaceUris); - browsePath.StartingNode = Objects.Server; - browsePaths.Add(browsePath); - } - - BrowsePathResultCollection results; - DiagnosticInfoCollection diagnosticInfos; - - ResponseHeader responseHeader = m_session.TranslateBrowsePathsToNodeIds( - null, - browsePaths, - out results, - out diagnosticInfos); - - // ensure that the server returned valid results. - Session.ValidateResponse(results, browsePaths); - Session.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); - - return results; - } - - - /// - /// Area filter strings which contain wildcard characters require more processing - /// - public List ProcessWildCardAreaName(string areaName, int wildcardLocation) - { - List areas = new List(); - try - { - // Retrieve substring from the area name up to the wildcard character. - string areaSubstring = areaName.Substring(0, wildcardLocation); - //Scan this string for path elements that are completely specified - BrowsePathTarget target = null; - string path = ""; - int location = areaSubstring.LastIndexOf('/'); - while (location != -1) - { - if (location == 0) // Starts with a slash - break; - // Make sure the '\' is not being treated as a reserved character that is escaped using '&'. - if (String.Compare(areaSubstring.Substring(location - 1, 1), "&") != 0) - break; - // '\'is treated as a special character. Get the next occurance of this character - areaSubstring = areaName.Substring(0, location); - location = areaSubstring.LastIndexOf('/'); - } - if (location != -1) - path = areaName.Substring(0, location); - - if (path.Length != 0) - { - // Get NodeId for this path - List paths = new List(); - paths.Add(path); - BrowsePathResultCollection results = GetBrowseTargets(paths); - if (!StatusCode.IsBad(results[0].StatusCode)) - { - target = results[0].Targets[0]; - } - } - - ExpandedNodeId node = null; - if (location == -1 || target == null) - node = Objects.Server; - else - node = target.TargetId; - - // Browse node for all notifiers below it - IList children = m_session.NodeCache.Find(node, ReferenceTypes.HasEventSource, false, true); - foreach (INode child in children) - { - // match the browsename against the client supplied relative path containing the wildcard character. - // If browsename matches the pattern, add that to the list of areas to be monitored - string pattern = areaName.Substring(location + 1); - if (ComUtils.Match(child.BrowseName.ToString(), pattern, false)) - { - string notifierName = path + '/' + child.BrowseName.ToString(); - areas.Add(notifierName); - } - } - } - catch (Exception ex) - { - Utils.Trace(ex, "Unexpected error in ProcessWildCardAreaName"); - } - return areas; - } - - /// - /// create monitored items for each notifier node identified by the area string(s) added using SetFilter. - /// - /// The List of Area names - public void AddMonitoredItems(List AreaNames) - { - try - { - List szAreas = new List(); - foreach (string areaName in AreaNames) - { - int wildCardLocation = 0; - if ((wildCardLocation = areaName.IndexOfAny(new char[] { '*', '?', '#', '[', ']', '!', '-' })) != -1) - { - // The string contains wildcards - List items = ProcessWildCardAreaName(areaName, wildCardLocation); - if (items.Count == 0) - { - throw ComUtils.CreateComException("AddMonitoredItems", ResultIds.E_INVALIDARG); - } - foreach (string item in items) - { - AreaNode areaNode; - // Check to see if this area was already added to the subscription as a monitored item - if (!m_AreaNodes.TryGetValue(item, out areaNode)) - szAreas.Add(item); - else // increment reference count for this area - ++areaNode.RefCount; - } - } - else - { - // Check to see if this area was already added to the subscription as a monitored item - AreaNode areaNode; - if (!m_AreaNodes.TryGetValue(areaName, out areaNode)) - szAreas.Add(areaName); - else // increment reference count for this area - ++areaNode.RefCount; - } - } - if (szAreas.Count == 0) - return; - - // Translate the fully qualified area names to NodeIds - BrowsePathResultCollection results = GetBrowseTargets(szAreas); - for (int ii = 0; ii < results.Count; ii++) - { - if (StatusCode.IsBad(results[ii].StatusCode)) - { - throw ComUtils.CreateComException("AddMonitoredItems", ResultIds.E_INVALIDARG); - } - // Add monitored item to the subscription - BrowsePathTarget target = results[ii].Targets[0]; - NodeId node; - node = ExpandedNodeId.ToNodeId(target.TargetId, m_session.NamespaceUris); - MonitoredItem monitoredItem = CreateMonitoredItemForEvents(node); - m_Subscription.AddItem(monitoredItem); - m_Subscription.ApplyChanges(); - // Add this area to the AreaNode and then add the AreaNode to the two dictionary elements - AreaNode areaNode = new AreaNode(); - areaNode.AreaName = szAreas[ii]; - ++areaNode.RefCount; - areaNode.MonitoredItem = monitoredItem; - m_notifiers.Add(monitoredItem.ClientHandle, areaNode); - m_AreaNodes.Add(szAreas[ii], areaNode); - } - } - catch (COMException ex) - { - throw ComUtils.CreateComException(ex); - } - catch (Exception ex) - { - Utils.Trace(ex, "Unexpected error in AddMonitoredItems"); - throw ComUtils.CreateComException(ex); - } - } - - /// - /// Remove monitored items from the subscription. - /// - /// The List of fully qulaified area names of nodes to be removed from the subscription - public void RemoveMonitoredItems(List AreaNames) - { - try - { - List removeNodes = new List(); - foreach (string areaName in AreaNames) - { - AreaNode areaNode; - if (m_AreaNodes.TryGetValue(areaName, out areaNode)) - { - // decrement reference count - --areaNode.RefCount; - if (areaNode.RefCount <= 0) - { - // Add item to list of monitored items to be deleted - removeNodes.Add(areaNode.MonitoredItem); - m_AreaNodes.Remove(areaNode.AreaName); - m_notifiers.Remove(areaNode.MonitoredItem.ClientHandle); - } - } - } - if (removeNodes.Count > 0) // remove the monitored items from the subscription - { - m_Subscription.RemoveItems(removeNodes); - m_Subscription.ApplyChanges(); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in RemoveMonitoredItems"); - } - } - - #endregion - - - #region IOPCCommon Members - - /// - /// Sets the Locale ID for the server. - /// - public void SetLocaleID(int dwLcid) - { - lock (m_lock) - { - if (m_session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - try - { - bool localeSupported = false; - - foreach (int locale in m_localeIds) - { - if (dwLcid == locale) - { - if (locale != m_lcid) - { - UpdateLocale(m_session, ComUtils.GetLocale(locale)); - } - - // save the passed locale value. - m_lcid = dwLcid; - localeSupported = true; - break; - } - } - - if (!localeSupported) throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - catch (COMException e) - { - throw ComUtils.CreateComException(e); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in SetLocaleID"); - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Update locale ID for the session. - /// - private void UpdateLocale(Session session, string locale) - { - if (session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - try - { - StringCollection preferredLocales = new StringCollection(); - preferredLocales.Add(locale); - session.ChangePreferredLocales(preferredLocales); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in UpdateLocale"); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Get the local IDs from the server. - /// - internal List GetLocaleIDs() - { - lock (m_lock) - { - string[] locales = null; - List localeList = new List(); - DataValueCollection values = null; - DiagnosticInfoCollection diagnosticInfos = null; - - try - { - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - ReadValueId valueId = new ReadValueId(); - valueId.NodeId = new NodeId(Opc.Ua.Variables.Server_ServerCapabilities_LocaleIdArray); - valueId.AttributeId = Attributes.Value; - nodesToRead.Add(valueId); - - // read values from the UA server. - ResponseHeader responseHeader = m_session.Read( - null, - 0, - TimestampsToReturn.Neither, - nodesToRead, - out values, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(values, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - - locales = ((string[])(values[0].Value)); - - // add the default locale - localeList.Add(ComUtils.LOCALE_SYSTEM_DEFAULT); - localeList.Add(ComUtils.LOCALE_USER_DEFAULT); - - if (locales != null) - { - foreach (string locale in locales) - { - // cache the supported locales. - localeList.Add(ComUtils.GetLocale(locale)); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in GetLocaleIds"); - throw ComUtils.CreateComException(e); - } - - return localeList; - } - } - - /// - /// Gets the available Locale IDs from the server. - /// - public void QueryAvailableLocaleIDs(out int pdwCount, out System.IntPtr pdwLcid) - { - if (m_session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - lock (m_lock) - { - try - { - pdwCount = 0; - pdwLcid = IntPtr.Zero; - - // marshal parameters. - if (m_localeIds != null && m_localeIds.Count > 0) - { - pdwLcid = Marshal.AllocCoTaskMem(m_localeIds.Count * Marshal.SizeOf(typeof(int))); - - int[] lcids = new int[m_localeIds.Count]; - - for (int ii = 0; ii < m_localeIds.Count; ii++) - { - lcids[ii] = m_localeIds[ii]; - } - - Marshal.Copy(lcids, 0, pdwLcid, m_localeIds.Count); - pdwCount = m_localeIds.Count; - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in QueryAvailableLocaleIDs"); - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Gets the current Locale ID from the server. - /// - public void GetLocaleID(out int pdwLcid) - { - lock (m_lock) - { - try - { - pdwLcid = m_lcid; - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in GetLocaleID"); - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Gets the error string from the server. - /// - void OpcRcw.Comn.IOPCCommon.GetErrorString(int dwError, out string ppString) - { - lock (m_lock) - { - try - { - // look up COM errors locally. - ppString = ComUtils.GetSystemMessage(dwError, m_lcid); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in GetErrorString"); - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Sets the name of the client. - /// - public void SetClientName(string szName) - { - lock (m_lock) - { - m_clientName = szName; - } - } - - #endregion - - #region IOPCEventServer Members - - - /// - /// Returns the current status information for the Event server. - /// - /// The structure returning the status infromation. The server allocates the structure. - public void GetStatus(out IntPtr ppEventServerStatus) - { - lock (m_lock) - { - try - { - OpcRcw.Ae.OPCEVENTSERVERSTATUS status = new OPCEVENTSERVERSTATUS(); - - Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; - - status.dwServerState = OPCEVENTSERVERSTATE.OPCAE_STATUS_COMM_FAULT; - status.ftStartTime = ComUtils.GetFILETIME(m_startTime); - status.ftLastUpdateTime = ComUtils.GetFILETIME(m_lastUpdateTime); - status.ftCurrentTime = ComUtils.GetFILETIME(DateTime.UtcNow); - status.wMajorVersion = (short)version.Major; - status.wMinorVersion = (short)version.Minor; - status.wBuildNumber = (short)version.Build; - status.szVendorInfo = "OPC UA COM AE Proxy Server"; - - if (m_session != null) - { - status.dwServerState = OPCEVENTSERVERSTATE.OPCAE_STATUS_RUNNING; - status.szVendorInfo = m_session.ConfiguredEndpoint.ToString(); - } - - ppEventServerStatus = Marshal.AllocCoTaskMem(Marshal.SizeOf(status.GetType())); - Marshal.StructureToPtr(status, ppEventServerStatus, false); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in GetStatus"); - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Add an Event Subscription object to an Event Server - /// - /// FALSE if the Event Subscription is to be created inactive and TRUE if it is to be created as active. - /// The requested buffer time. The buffer time is in milliseconds and tells the server how often to send event notifications. A value of 0 for dwBufferTime means that the server should send event notifications as soon as it gets them. - /// The requested maximum number of events that will be sent in a single IOPCEventSink::OnEvent callback. A value of 0 means that there is no limit to the number of events that will be sent in a single callback. - /// Client provided handle for this event subscription. - /// The type of interface desired - /// Where to store the returned interface pointer. - /// The buffer time that the server is actually providing, which may differ from dwBufferTime. - /// The maximum number of events that the server will actually be sending in a single IOPCEventSink::OnEvent callback, which may differ from dwMaxSize. - public void CreateEventSubscription(int bActive, int dwBufferTime, int dwMaxSize, int hClientSubscription, ref Guid riid, out object ppUnk, out int pdwRevisedBufferTime, out int pdwRevisedMaxSize) - { - ppUnk = IntPtr.Zero; - pdwRevisedBufferTime = 0; - pdwRevisedMaxSize = 0; - IntPtr pbActive = IntPtr.Zero; - IntPtr pdwBufferTime = IntPtr.Zero; - IntPtr pdwMaxSize = IntPtr.Zero; - Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046"); - - try - { - Subscription subscription = new Subscription(this); - if (subscription == null) - throw ComUtils.CreateComException("E_OUTOFMEMORY", ResultIds.E_OUTOFMEMORY); - - SubscriptionListInsert(subscription); - - pbActive = Marshal.AllocHGlobal(Marshal.SizeOf(bActive.GetType())); - pdwBufferTime = Marshal.AllocHGlobal(Marshal.SizeOf(dwBufferTime.GetType())); - pdwMaxSize = Marshal.AllocHGlobal(Marshal.SizeOf(dwMaxSize.GetType())); - - Marshal.WriteInt32(pbActive, bActive); - Marshal.WriteInt32(pdwBufferTime, dwBufferTime); - Marshal.WriteInt32(pdwMaxSize, dwMaxSize); - subscription.SetState(pbActive, pdwBufferTime, pdwMaxSize, hClientSubscription, out pdwRevisedBufferTime, out pdwRevisedMaxSize); - subscription.UaSubscription = m_Subscription; - ppUnk = subscription; - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in CreateEventSubscription"); - throw ComUtils.CreateComException(e); - } - finally - { - if (pbActive != IntPtr.Zero) - Marshal.FreeHGlobal(pbActive); - - if (pdwBufferTime != IntPtr.Zero) - Marshal.FreeHGlobal(pdwBufferTime); - - if (pdwMaxSize != IntPtr.Zero) - Marshal.FreeHGlobal(pdwMaxSize); - } - - } - - /// - /// Gives clients a means of finding out exactly which filter criteria are supported by a given event server. - /// - /// A bit mask which indicates which types of filtering are supported by the server. - public void QueryAvailableFilters(out int pdwFilterMask) - { - try - { - pdwFilterMask = OpcRcw.Ae.Constants.FILTER_BY_EVENT | - OpcRcw.Ae.Constants.FILTER_BY_CATEGORY | - OpcRcw.Ae.Constants.FILTER_BY_SEVERITY | - OpcRcw.Ae.Constants.FILTER_BY_AREA | - OpcRcw.Ae.Constants.FILTER_BY_SOURCE; - } - - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in QueryAvailableFilters"); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Returns the specific categories of events supported by the server. - /// - /// Bit mask specifying which event types are of interest. - /// The number of event categories returned. (This is the size of the EventCategoryID and EventCategoryDesc arrays.) - /// Array of DWORD codes for the vendor specific event categories implemented by the server. - /// Array of strings for the text names or descriptions for each of the event category IDs. - public void QueryEventCategories(int dwEventType, out int pdwCount, out IntPtr ppdwEventCategories, out IntPtr ppszEventCategoryDescs) - { - lock (m_lock) - { - pdwCount = 0; - ppdwEventCategories = IntPtr.Zero; - ppszEventCategoryDescs = IntPtr.Zero; - List Cats = new List(); - - try - { - if (dwEventType == 0 || dwEventType > OpcRcw.Ae.Constants.ALL_EVENTS) - { - throw ComUtils.CreateComException("QueryEventCategories", ResultIds.E_INVALIDARG); - } - - foreach (EventCategory cat in m_configFile.Categories) - { - if ((System.Convert.ToBoolean(dwEventType & OpcRcw.Ae.Constants.SIMPLE_EVENT) && (cat.EventType == OpcRcw.Ae.Constants.SIMPLE_EVENT)) || - (System.Convert.ToBoolean(dwEventType & OpcRcw.Ae.Constants.CONDITION_EVENT) && (cat.EventType == OpcRcw.Ae.Constants.CONDITION_EVENT)) || - (System.Convert.ToBoolean(dwEventType & OpcRcw.Ae.Constants.TRACKING_EVENT) && (cat.EventType == OpcRcw.Ae.Constants.TRACKING_EVENT))) - { - Cats.Add(cat); - } - } - - Cats.Sort(EventCategoryDescriptionCompare); - pdwCount = Cats.Count; - int[] CatIDs = new int[pdwCount]; - string[] CatDescs = new string[pdwCount]; - - for (int i = 0; i < pdwCount; i++) - { - CatIDs[i] = Cats[i].CategoryID; - CatDescs[i] = Cats[i].EventDesc; - } - - ppdwEventCategories = ComUtils.GetInt32s(CatIDs); - ppszEventCategoryDescs = ComUtils.GetUnicodeStrings(CatDescs); - } - catch (COMException e) - { - throw ComUtils.CreateComException(e); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in QueryEventCategories"); - throw ComUtils.CreateComException(e); - } - - } - } - - /// - /// Gives clients a means of finding out the specific condition names which the event server supports for the specified event category. - /// - /// A DWORD event category code, as returned by the QueryEventCategories method. Only the names of conditions within this event category are returned. - /// The number of condition names being returned. - /// Array of strings containing the condition names for the specified event category. - public int QueryConditionNames(int dwEventCategory, out int pdwCount, out IntPtr ppszConditionNames) - { - pdwCount = 0; - ppszConditionNames = IntPtr.Zero; - return ResultIds.E_NOTIMPL; - } - - /// - /// Gives clients a means of finding out the specific sub-condition names which are associated with the specified condition name. - /// - /// A condition name, as returned by the QueryConditionNames method. Only the names of sub-conditions associated with this condition are returned. - /// The number of sub-condition names being returned. - /// Array of strings containing the sub-condition names associated with the specified condition. - public void QuerySubConditionNames(string szConditionName, out int pdwCount, out IntPtr ppszSubConditionNames) - { - pdwCount = 0; - ppszSubConditionNames = IntPtr.Zero; - - throw ComUtils.CreateComException("QuerySubConditionNames", ResultIds.E_NOTIMPL); - } - - /// - /// Gives clients a means of finding out the specific condition names associated with the specified source. - /// - /// A source name, as returned by the IOPCEventAreaBrower::GetQualifiedSourceName method. Only the names of conditions associated with this source are returned. - /// The number of condition names being returned. - /// Array of strings containing the condition names for the specified source. - public void QuerySourceConditions(string szSource, out int pdwCount, out IntPtr ppszConditionNames) - { - if (szSource == string.Empty) - throw ComUtils.CreateComException("QuerySourceConditions", ResultIds.E_INVALIDARG); - - BrowsePathTarget target = null; - List conditionNames = new List(); - List paths = new List(); - - paths.Add(szSource); - BrowsePathResultCollection results = GetBrowseTargets(paths); - - if (StatusCode.IsBad(results[0].StatusCode)) - throw ComUtils.CreateComException("QuerySourceConditions", ResultIds.E_INVALIDARG); - else - target = results[0].Targets[0]; - - ExpandedNodeId node = null; - if (target == null) - throw ComUtils.CreateComException("QuerySourceConditions", ResultIds.E_INVALIDARG); - else - node = target.TargetId; - - IList children = m_session.NodeCache.Find(node, ReferenceTypes.HasComponent, false, true); - foreach (INode child in children) - { - if (m_session.TypeTree.IsTypeOf(child.TypeDefinitionId, Opc.Ua.ObjectTypes.ConditionType)) - { - conditionNames.Add(child.DisplayName.ToString()); - } - - } - - pdwCount = conditionNames.Count; - ppszConditionNames = ComUtils.GetUnicodeStrings(conditionNames.ToArray()); - - } - - /// - /// Using the EventCategories returned by the QueryEventCategories method, client application can invoke the QueryEventAttributes method to get information about the vendor-specific attributes the server can provide as part of an event notification for an event within the specified event category. Simple servers may not support any vendor-specific attributes for some or even all EventCategories. - /// - /// One of the Event Category codes returned from the QueryEventCategories function. - /// The number of event attributes (size of the AttrID, and AttrDescs, and AttrTypes arrays) returned by the function. - /// Array of DWORD codes for vendor-specific event attributes associated with the event category and available from the server. - /// Array of strings for the text names or descriptions for each of the event attribute IDs. This array corresponds to the AttrIDs array. - /// Array of VARTYPES identifying the data type of each of the event attributes. This array corresponds to the AttrIDs array. - public void QueryEventAttributes(int dwEventCategory, out int pdwCount, out IntPtr ppdwAttrIDs, out IntPtr ppszAttrDescs, out IntPtr ppvtAttrTypes) - { - pdwCount = 0; - ppdwAttrIDs = IntPtr.Zero; - ppszAttrDescs = IntPtr.Zero; - ppvtAttrTypes = IntPtr.Zero; - - try - { - // Make sure we are passed a valid dwEventCategory - NodeId catNodeId = FindEventCatNodeId(dwEventCategory); - if (catNodeId == null) - throw ComUtils.CreateComException("QueryEventAttributes", ResultIds.E_INVALIDARG); - List Attrs = GetEventAttributes(dwEventCategory); - Attrs.Sort(EventAttributeDescCompare); - pdwCount = Attrs.Count; - int[] AttrIDs = new int[pdwCount]; - string[] AttrDescs = new string[pdwCount]; - short[] AttrTypes = new short[pdwCount]; - - for (int i = 0; i < pdwCount; i++) - { - AttrIDs[i] = Attrs[i].AttributeID; - AttrDescs[i] = Attrs[i].AttrDesc; - AttrTypes[i] = (short)ComUtils.GetVarType(Attrs[i].ActualDataType); - if ((Attrs[i].ActualDataType != null) & (short)AttrTypes[i] == 0) - { - // any UA types that do not have a corresponding COM type will be set to string - AttrTypes[i] = (short)VarEnum.VT_BSTR; - } - - if (Attrs[i].IsArray) - AttrTypes[i] = (short)((short)VarEnum.VT_ARRAY | AttrTypes[i]); - } - ppdwAttrIDs = ComUtils.GetInt32s(AttrIDs); - ppszAttrDescs = ComUtils.GetUnicodeStrings(AttrDescs); - ppvtAttrTypes = ComUtils.GetInt16s(AttrTypes); - - } - catch (COMException e) - { - throw ComUtils.CreateComException(e); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in QueryEventAttributes"); - throw ComUtils.CreateComException(e); - } - } - - - /// - /// Given an event source, and an array of associated attribute ID codes, return an array of the item ID strings corresponding to each attribute ID. - /// - /// An event source for which to return the item IDs corresponding to each of an array of attribute IDs if they exist. - /// DWORD event category code indicating the category of events for which item IDs are to be returned. - /// The name of a condition within the event category for which item IDs are to be returned. - /// The name of a sub-condition within a multi-state condition. This should be a NULL string for a single state condition. - /// The number of event attribute IDs (size of the AssocAttrIDs array) passed into the function. - /// Array of DWORD IDs of vendor-specific event attributes associated with the generator ID and available from the server for which to return ItemIDs. - /// Array of item ID strings corresponding to each event attribute ID associated with the generator ID. This array is the same length as the AssocAttrIDs array passed into the function. A Null string is returned if no item ID is available for this attribute. - /// Array of network node names of the associated OPC Data Access Servers. A Null string is returned if the OPC Data Access Server is running on the local node. - /// Array of class IDs for the associated OPC Data Access Servers. - public void TranslateToItemIDs(string szSource, int dwEventCategory, string szConditionName, string szSubconditionName, int dwCount, int[] pdwAssocAttrIDs, out IntPtr ppszAttrItemIDs, out IntPtr ppszNodeNames, out IntPtr ppCLSIDs) - { - ppszAttrItemIDs = IntPtr.Zero; - ppszNodeNames = IntPtr.Zero; - ppCLSIDs = IntPtr.Zero; - - throw ComUtils.CreateComException("TranslateToItemIDs", ResultIds.E_NOTIMPL); - - } - - /// - /// Returns the current state information for the condition instance corresponding to the szSource and szConditionName. - /// - /// A source name, as returned by the IOPCEventAreaBrower::GetQualifiedSourceName method. The state of the condition instance associated with this source is returned. - /// A condition name, as returned by the QueryConditionNames method. The state of this condition is returned. - /// The requested number of event attributes to be returned in the OPCCONDITIONSTATE structure. Can be zero if no attributes are desired - /// The array of Attribute IDs indicating which event attributes should be returned in the OPCCONDITIONSTATE structure. - /// Pointer to where the OPCCONDITIONSTATE structure pointer should be returned. The server allocates the structure. - public void GetConditionState(string szSource, string szConditionName, int dwNumEventAttrs, int[] pdwAttributeIDs, out IntPtr ppConditionState) - { - ppConditionState = IntPtr.Zero; - - throw ComUtils.CreateComException("GetConditionState", ResultIds.E_NOTIMPL); - } - - /// - /// Places the specified process areas into the enabled state. Therefore, the server will now generate condition-related events for these conditions as long as the source itself is enabled and no containing area in its hierarchy is disabled. - /// - /// The number of process areas for which conditions are to be enabled. - /// An array of area names, as returned by IOPCEventAreaBrowser::GetQualifiedAreaName. - public void EnableConditionByArea(int dwNumAreas, string[] pszAreas) - { - throw ComUtils.CreateComException("EnableConditionByArea", ResultIds.E_NOTIMPL); - } - - /// - /// Places all conditions for the specified event sources into the enabled state. Therefore, the server will now generate condition-related events for these conditions. - /// - /// The number of event sources for which conditions are to be enabled. - /// An array of source names, as returned by IOPCEventAreaBrowser::GetQualifiedSourceName - public void EnableConditionBySource(int dwNumSources, string[] pszSources) - { - throw ComUtils.CreateComException("EnableConditionBySource", ResultIds.E_NOTIMPL); - } - - /// - /// Places the specified process areas into the disabled state. Therefore, the server will now cease generating condition-related events for these conditions. - /// - /// The number of process areas for which conditions are to be disabled. - /// An array of area names, as returned by IOPCEventAreaBrowser::GetQualifiedAreaName - public void DisableConditionByArea(int dwNumAreas, string[] pszAreas) - { - throw ComUtils.CreateComException("DisableConditionByArea", ResultIds.E_NOTIMPL); - } - - /// - /// Places all conditions for the specified event sources into the disabled state. Therefore, the server will no longer generate condition-related events for these conditions. - /// - /// The number of event sources for which conditions are to be disabled. - /// An array of source names, as returned by IOPCEventAreaBrowser::GetQualifiedSourceName - public void DisableConditionBySource(int dwNumSources, string[] pszSources) - { - throw ComUtils.CreateComException("DisableConditionBySource", ResultIds.E_NOTIMPL); - } - - /// - /// Used to acknowledge one or more conditions in the Event Server. - /// - /// The number of acknowledgments passed with this function. - /// A string passed in by the client, identifying who is acknowledging the conditions. - /// Comment string passed in by the client associated with acknowledging the conditions. A NULL string indicating no comment is allowed. - /// Array of event source strings identifying the source (or owner) of each condition that is being acknowledged. - /// Array of Condition Name strings identifying each condition that is being acknowledged. Condition Names are unique within the scope of the event server. - /// Array of active times corresponding to each Source and ConditionName pair. - /// Array of server supplied �cookies� corresponding to each Source and Condition Name pair, that in addition to the Active Time, uniquely identifies a specific event notification. - /// Array of HRESULTS indicating the success of the individual acknowledgments. - public void AckCondition(int dwCount, string szAcknowledgerID, string szComment, string[] pszSource, string[] pszConditionName, System.Runtime.InteropServices.ComTypes.FILETIME[] pftActiveTime, int[] pdwCookie, out IntPtr ppErrors) - { - if ((dwCount <= 0) || (szAcknowledgerID == string.Empty)) - throw ComUtils.CreateComException("AckCondition", ResultIds.E_INVALIDARG); - - ppErrors = IntPtr.Zero; - int[] errors = new int[dwCount]; - - try - { - // Utils.Trace("AckCondition (count: {0}) => BEGIN", dwCount); - for (int i = 0; i < dwCount; i++) - { - // Utils.Trace("\tCall AckCondition ... (AcknowledgerID:{0}, Source: {1}, condition: {2}, ActiveTime: {3}, Cookie: {4})", - // szAcknowledgerID, pszSource[i], pszConditionName[i], GetDateTime(pftActiveTime[i]), pdwCookie[i]); - - errors[i] = AckCondition(szAcknowledgerID, szComment, pszSource[i], pszConditionName[i], pftActiveTime[i], pdwCookie[i]); - - // Utils.Trace("\tAckCondition return: {0}", errors[i]); - } - - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in AckCondition"); - throw ComUtils.CreateComException(e); - } - - // Utils.Trace("AckCondition (count: {0}) => END", dwCount); - } - - /// - /// Create an OPCEventAreaBrowser object on behalf of this client and return the interface to the Client. - /// - /// The type of interface desired (e.g. IID_IOPCEventAreaBrowser) - /// Where to store the returned interface pointer. - public void CreateAreaBrowser(ref Guid riid, out object ppUnk) - { - Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046"); - - ppUnk = IntPtr.Zero; - - try - { - AreaBrowser brower = new AreaBrowser(this, m_session); - if (brower == null) - throw ComUtils.CreateComException("CreateAreaBrowser", ResultIds.E_OUTOFMEMORY); - - ppUnk = brower; - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in CreateAreaBrowser"); - throw ComUtils.CreateComException(e); - } - } - - #endregion - - #region IOPCEventServer2 Members - - /// - /// Places the specified process areas into the enabled state. Therefore, the server will now generate condition-related events for the sources in these areas as long as the source itself is enabled and no containing area in its hierarchy is disabled. - /// - /// The number of process areas for which conditions are to be enabled. - /// An array of area names, as returned by IOPCEventAreaBrowser::GetQualifiedAreaName. - /// Array of HRESULTS indicating the success of placing all conditions for all sources within a specified process area into the enabled state. The errors correspond to the areas passed into the method. - public void EnableConditionByArea2(int dwNumAreas, string[] pszAreas, out IntPtr ppErrors) - { - ppErrors = IntPtr.Zero; - - throw ComUtils.CreateComException("EnableConditionByArea2", ResultIds.E_NOTIMPL); - } - - /// - /// Places all conditions for the specified event sources into the enabled state. Therefore, the server will now generate condition-related events for these sources. - /// - /// The number of event sources for which conditions are to be enabled. - /// An array of source names, as returned by IOPCEventAreaBrowser::GetQualifiedSourceName - /// Array of HRESULTS indicating the success of placing all conditions for the specified event source into the enabled state. The errors correspond to the sources passed into the method. - public void EnableConditionBySource2(int dwNumSources, string[] pszSources, out IntPtr ppErrors) - { - ppErrors = IntPtr.Zero; - - throw ComUtils.CreateComException("EnableConditionBySource2", ResultIds.E_NOTIMPL); - } - - /// - /// Places the specified process areas into the disabled state. Therefore, the server will now cease generating condition-related events for these conditions. - /// - /// The number of process areas for which conditions are to be disabled. - /// An array of area names, as returned by IOPCEventAreaBrowser::GetQualifiedAreaName - /// Array of HRESULTS indicating the success of placing all conditions for all sources within a specified process area into the disabled state. The errors correspond to the areas passed into the method. - public void DisableConditionByArea2(int dwNumAreas, string[] pszAreas, out IntPtr ppErrors) - { - ppErrors = IntPtr.Zero; - - throw ComUtils.CreateComException("DisableConditionByArea2", ResultIds.E_NOTIMPL); - } - - /// - /// Places all conditions for the specified event sources into the disabled state. Therefore, the server will no longer generate condition-related events for these sources. - /// - /// The number of event sources for which conditions are to be disabled. - /// An array of source names, as returned by IOPCEventAreaBrowser::GetQualifiedSourceName - /// Array of HRESULTS indicating the success of placing all conditions for the specified event source into the disabled state. The errors correspond to the sources passed into the method. - public void DisableConditionBySource2(int dwNumSources, string[] pszSources, out IntPtr ppErrors) - { - ppErrors = IntPtr.Zero; - - throw ComUtils.CreateComException("DisableConditionBySource2", ResultIds.E_NOTIMPL); - } - - /// - /// Returns the current enable state and the effective enable state for each area specified in pszAreas. - /// - /// The number of areas for which the enable state is to be queried. - /// An array of area names, as returned by IOPCEventAreaBrowser::GetQualifiedAreaName - /// Array of BOOL indicating the current enable state of the corresponding area. TRUE if the area is enabled, FALSE if it is disabled. - /// Array of BOOL indicating the effective enable state of the corresponding area. TRUE if the area is enabled and all areas within the hierarchy of its containing areas are enabled. FALSE if the area is disabled or any area within the hierarchy of its containing areas is disabled. - /// Array of HRESULTS indicating the success of retrieving the enable state of the area. The errors correspond to the areas passed into the method. - public void GetEnableStateByArea(int dwNumAreas, string[] pszAreas, out IntPtr pbEnabled, out IntPtr pbEffectivelyEnabled, out IntPtr ppErrors) - { - pbEnabled = IntPtr.Zero; - pbEffectivelyEnabled = IntPtr.Zero; - ppErrors = IntPtr.Zero; - - throw ComUtils.CreateComException("GetEnableStateByArea", ResultIds.E_NOTIMPL); - } - - /// - /// Returns the current enable state and the effective enable state for each source specified in pszSources. - /// - /// The number of event sources for which the enable state is to be queried. - /// An array of source names, as returned by IOPCEventAreaBrowser::GetQualifiedSourceName - /// Array of BOOL indicating the current enable state of the corresponding source. TRUE if the source is enabled, FALSE if it is disabled. - /// Array of BOOL indicating the effective enable state of the corresponding source. TRUE if the source is enabled and all areas within the hierarchy of its containing areas are enabled. FALSE if the source is disabled or any area within the hierarchy of its containing areas is disabled. - /// Array of HRESULTS indicating the success of retrieving the enable state of the source. The errors correspond to the sources passed into the method. - public void GetEnableStateBySource(int dwNumSources, string[] pszSources, out IntPtr pbEnabled, out IntPtr pbEffectivelyEnabled, out IntPtr ppErrors) - { - pbEnabled = IntPtr.Zero; - pbEffectivelyEnabled = IntPtr.Zero; - ppErrors = IntPtr.Zero; - - throw ComUtils.CreateComException("GetEnableStateBySource", ResultIds.E_NOTIMPL); - } - - #endregion - - #region Query Support Members - /// - /// Returns the list of attribute data of the event category specified - /// - /// - public List GetEventAttributes(int dwEventCategory) - { - List Attrs = new List(); - try - { - Boolean BaseObjectTypeProcessed = false; - Browser browseEventTypes = new Browser(m_session); - browseEventTypes.BrowseDirection = BrowseDirection.Inverse; - - Browser browseVars = new Browser(m_session); - browseVars.NodeClassMask = (int)NodeClass.Variable; - browseVars.ReferenceTypeId = Opc.Ua.ReferenceTypes.HasProperty; - - ReferenceDescriptionCollection references = null; - NodeId typeNodeId = FindEventCatNodeId(dwEventCategory); - - while (!BaseObjectTypeProcessed) - { - references = browseVars.Browse(typeNodeId); - foreach (ReferenceDescription reference in references) - { - EventAttribute attribute = FindEventAttrInfo(reference.NodeId.ToString()); - if (attribute != null) - Attrs.Add(attribute); - } - - if (typeNodeId.Equals(Opc.Ua.ObjectTypes.BaseObjectType)) - { - BaseObjectTypeProcessed = true; - break; - } - - if (typeNodeId.Equals(Opc.Ua.ObjectTypes.BaseEventType)) - { - BaseObjectTypeProcessed = true; - Attrs.Add(FindEventAttrInfo("Areas")); - } - else - { - if (typeNodeId.Equals(Opc.Ua.ObjectTypes.ConditionType)) - Attrs.Add(FindEventAttrInfo("AckComment")); - - references = browseEventTypes.Browse(typeNodeId); - foreach (ReferenceDescription refDesc in references) - { - if (refDesc.ReferenceTypeId == ReferenceTypes.HasSubtype) - { - typeNodeId = (NodeId)refDesc.NodeId; //TODO: Can a type have only one parent? - break; - } - } - } - - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in GetEventAttributes"); - } - return Attrs; - } - - /// - /// Returns the event attribute data based off the attribute node ID - /// - /// String version of the Attribute NodeId being searched for - private EventAttribute FindEventAttrInfo(string AttrNodeId) - { - try - { - //The Attributes array is sorted off the strNodeId so we can do a binary search. - int first = 0; - int last = m_configFile.Attributes.Length - 1; - int mid; - while (first <= last) - { - mid = (first + last) / 2; - int compareValue = m_configFile.Attributes[mid].strNodeId.CompareTo(AttrNodeId); - if (compareValue == 0) - return m_configFile.Attributes[mid]; - else if (compareValue > 0) - last = mid - 1; - else - first = mid + 1; - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in FindEventAttrInfo"); - } - return null; - } - - /// - /// Returns the event category NodeId based off the event category ID - /// - /// The event category ID - public NodeId FindEventCatNodeId(int EventCategoryID) - { - NodeId nodeId = null; - try - { - foreach (EventCategory cat in m_configFile.Categories) - if (cat.CategoryID == EventCategoryID) - { - nodeId = new NodeId(cat.strNodeId); - break; - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in FindEventCatNodeId"); - } - return nodeId; - } - - /// - /// Compare method based off the Attribute Description - /// - /// - /// - private static int EventAttributeDescCompare(EventAttribute x, EventAttribute y) - { - int c = x.AttrDesc.ToLower().CompareTo(y.AttrDesc.ToLower()); - if (c != 0) - return c; - else - { - if ((x.ActualDataType != null) && (y.ActualDataType != null)) - return x.ActualDataType.Name.CompareTo(y.ActualDataType.Name); - else - return 0; - } - } - - /// - /// Compare method based off the BrowseName - /// - /// - /// - private static int EventCategoryDescriptionCompare(EventCategory x, EventCategory y) - //TODO: should this be a case insensitive compare? - { - return x.EventDesc.ToLower().CompareTo(y.EventDesc.ToLower()); - } - #endregion - - #region Notification Processing Members - /// - /// Processes a Publish response from the UA server. - /// - /// - /// - void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) - { - try - { - EventFieldList eventFields = e.NotificationValue as EventFieldList; - - if (eventFields == null) - { - return; - } - if (monitoredItem != null) - { - if (monitoredItem.ClientHandle != eventFields.ClientHandle) - { - return; - } - } - INode eventUA = monitoredItem.GetEventType(eventFields); - EventCategory cat = FindEventCatInfo(eventUA.BrowseName.ToString()); - - if (cat == null) return; // The event is not of a category that we recognize. - - if (cat.EventType == OpcRcw.Ae.Constants.CONDITION_EVENT) - { - NodeId branchId = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType, Opc.Ua.BrowseNames.BranchId) as NodeId; - if (!NodeId.IsNull(branchId)) return; // We don't support condition branches in the COM Proxy - } - - EventNotification ev = new EventNotification(); - - ev.EventId = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.EventId)) as byte[]; - ev.SourceID = System.Convert.ToString(monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.SourceName))); - ev.Time = System.Convert.ToDateTime(monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.Time))); - ev.Message = System.Convert.ToString(monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.Message))); - ev.EventType = cat.EventType; - ev.EventCategory = cat.CategoryID; - ev.Severity = System.Convert.ToInt32(monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.Severity))); - - List Attrs = GetEventAttributes(cat.CategoryID); - UniqueList strEventNodeIds = new UniqueList(); - foreach (EventAttribute attr in Attrs) - if (attr.strEventNodeId != "") - strEventNodeIds.AddUnique(attr.strEventNodeId); - - ev.EventAttributes = new Dictionary(); - foreach (EventAttribute attr in m_configFile.Attributes) - { - foreach (string strEventNodeId in strEventNodeIds) - { - if (attr.strEventNodeId == strEventNodeId) - { - object value = monitoredItem.GetFieldValue(eventFields, (NodeId)attr.strEventNodeId, new QualifiedName(attr.BrowseName, attr.BrowseNameNSIndex)); - if (value == null) - { - ev.EventAttributes.Add(attr.AttributeID, ""); - } - else if ((value.GetType() != null) & (short)ComUtils.GetVarType(value) != 0) - { - ev.EventAttributes.Add(attr.AttributeID, value); - } - else - { - // any value with a UA type that does not have a corresponding COM type will be returned as a string - ev.EventAttributes.Add(attr.AttributeID, value.ToString()); - } - } - } - } - - //Condition-Related Event properties - ev.ConditionName = ""; - ev.SubConditionName = ""; - ev.ChangeMask = 0; - ev.NewState = OpcRcw.Ae.Constants.CONDITION_ENABLED | OpcRcw.Ae.Constants.CONDITION_ACKED; - ev.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD; - ev.AckRequired = false; - ev.ActiveTime = DateTime.Now; - ev.Cookie = 0; - - if (ev.EventType == OpcRcw.Ae.Constants.CONDITION_EVENT) - SetConditionEventFields(monitoredItem, eventFields, ev, cat); - - //Tracking Events and for Condition-Related Events which are acknowledgment notifications - if (cat.EventType == OpcRcw.Ae.Constants.TRACKING_EVENT) - ev.ActorID = System.Convert.ToString(monitoredItem.GetFieldValue(eventFields, (NodeId)eventUA.NodeId, new QualifiedName(Opc.Ua.BrowseNames.ClientUserId))); - - IncomingEventHandler eventHandler = new IncomingEventHandler(); - - //extract the area associated with this event. - AreaNode areaNode; - string[] areas = null; - if (m_notifiers.TryGetValue(monitoredItem.ClientHandle, out areaNode)) - { - areas = new string[] { areaNode.AreaName }; - } - eventHandler.ProcessEventNotificationList(ev, areas); - } - catch (Exception ex) - { - Utils.Trace(ex, "Unexpected error in MonitoredItem_Notification"); - } - } - - /// - /// Additional new event processing when the received event maps to a (COM AE) condition event type. We need to extract - /// the condition name, subcondition name, changeMask, newState, Quality, AckRequired, ActiveTime and cookie. - /// - /// - /// - /// - /// - void SetConditionEventFields(MonitoredItem monitoredItem, EventFieldList eventFields, EventNotification ev, EventCategory cat) - { - LocalizedText localText; - String ConditionName; - StatusCode? Status; - DateTime? TimeOfLastTransition; - - try - { - NodeId eventType = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.EventType) as NodeId; - - // UA events are categorized into three subsets. The first of these subsets consists of types and subtypes of ConditionType - // which yields the event condition name, quality and enable/disable status. - if (m_session.TypeTree.IsTypeOf(eventType, Opc.Ua.ObjectTypes.ConditionType)) - { - ConditionName = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType, Opc.Ua.BrowseNames.ConditionName) as String; - if (ConditionName != null) - ev.ConditionName = ConditionName; - else - ev.ConditionName = cat.BrowseName; - - // Set the subcondition name as conditionname for now. If the event of of type AlarmconditionType and a subcondition (UA substate) - // exists then this field will be set accordingly. - ev.SubConditionName = ev.ConditionName; - - bool? enabled = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType, - "/EnabledState/Id", Attributes.Value) as bool?; - - Status = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType, - "/Quality", Attributes.Value) as StatusCode?; - - ev.Quality = MapStatusToQuality(Status); - - if (enabled == true) - ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ENABLED; - else - ev.NewState &= ~OpcRcw.Ae.Constants.CONDITION_ENABLED; - } - - // The second of the three UA event subsets consists of types and subtypes of AcknowledgeableconditionType. - // This categorization yields events which support acknowledgement in addition to enable/disable state - if (m_session.TypeTree.IsTypeOf(eventType, Opc.Ua.ObjectTypes.AcknowledgeableConditionType)) - { - bool? acked = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AcknowledgeableConditionType, - "/AckedState/Id", Attributes.Value) as bool?; - - // Extract the "ConditionId" (nodeId of the condition instance) - ev.ConditionId = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AcknowledgeableConditionType, - "", Attributes.NodeId) as NodeId; - - ev.AcknowledgeMethod = Opc.Ua.Methods.AcknowledgeableConditionType_Acknowledge; - - if (acked == true) - { - ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ACKED; - ev.AckRequired = false; - } - else - { - ev.NewState &= ~OpcRcw.Ae.Constants.CONDITION_ACKED; - ev.AckRequired = true; - } - - } - - // the third of the three UA event subsets consists of types and subtypes of AlarmConditionType. This - // categorization yields events which support the notion of Active/Inactive and also may support substates - // (subconditions). - if (m_session.TypeTree.IsTypeOf(eventType, Opc.Ua.ObjectTypes.AlarmConditionType)) - { - bool? active = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AlarmConditionType, - "/ActiveState/Id", Attributes.Value) as bool?; - - TimeOfLastTransition = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AlarmConditionType, - "/ActiveState/TransitionTime", Attributes.Value) as DateTime?; - - if (active == true) - { - ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE; - ev.ActiveTime = TimeOfLastTransition ?? DateTime.MinValue; - } - - // Active subconditon. - localText = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AlarmConditionType, - "/ActiveState/EffectiveDisplayName", Attributes.Value) as LocalizedText; - if (localText != null && localText.ToString() != "") - ev.SubConditionName = localText.ToString(); - } - else // If this is not an AlarmConditionType (thus no UA active/inactive states apply) default to Active - ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE; - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in SetConditionEventFields"); - } - } - - /// - /// Maps status code returned from the server into corresponding OPC COM Quality. Not all status codes have - /// one-for-one mapping to COM quality therefore as a default, just map qualities 'Bad', 'Uncertain' and 'Good' - /// - /// Status code associated with the event notification - /// Closest match COM quality - short MapStatusToQuality(StatusCode? Status) - { - short mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_BAD; - - if (Status != null) - { - switch (((StatusCode)Status).Code) - { - // Bad status codes - case StatusCodes.BadConfigurationError: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_CONFIG_ERROR; break; - case StatusCodes.BadNotConnected: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_NOT_CONNECTED; break; - case StatusCodes.BadDeviceFailure: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_DEVICE_FAILURE; break; - case StatusCodes.BadSensorFailure: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_SENSOR_FAILURE; break; - case StatusCodes.BadNoCommunication: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_COMM_FAILURE; break; - case StatusCodes.BadOutOfService: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_OUT_OF_SERVICE; break; - - // Uncertain status codes - case StatusCodes.UncertainNoCommunicationLastUsableValue: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_LAST_USABLE; break; - case StatusCodes.UncertainLastUsableValue: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_LAST_USABLE; break; - case StatusCodes.UncertainSensorNotAccurate: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_SENSOR_CAL; break; - case StatusCodes.UncertainEngineeringUnitsExceeded: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_EGU_EXCEEDED; break; - case StatusCodes.UncertainSubNormal: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_SUB_NORMAL; break; - - // Good status codes - case StatusCodes.GoodLocalOverride: mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_LOCAL_OVERRIDE; break; - - // Defaults - default: - if (StatusCode.IsBad((StatusCode)Status)) - mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_BAD; - else if (StatusCode.IsUncertain((StatusCode)Status)) - mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_UNCERTAIN; - else if (StatusCode.IsGood((StatusCode)Status)) - mappedQuality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD; - - break; - } - } - - return mappedQuality; - - } - - /// - /// Somewhat simplistic logic to extract the containing area associated with a received event. Just parse the - /// source path and assume the final token is the unqualified source while the remainder of the string is the area - /// path. - /// - /// - /// - string[] FindEventAreas(EventNotification ev) - { - try - { - QualifiedNameCollection browseNames = SimpleAttributeOperand.Parse(ev.SourceID); - String areaString = "/"; - - if (browseNames.Count > 0) - { - for (int i = 0; i < browseNames.Count - 1; i++) - { - areaString += browseNames[i]; - areaString += "/"; - } - } - return new string[] { areaString }; - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in FindEventAreas"); - return null; - } - } - - /// - /// Processes a Publish response from the UA server for AddressSpace changes. - /// - /// - /// - void AddressSpaceChange_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) - { - try - { - EventFieldList eventFields = e.NotificationValue as EventFieldList; - - if (eventFields == null) - { - return; - } - if (monitoredItem != null) - { - if (monitoredItem.ClientHandle != eventFields.ClientHandle) - { - return; - } - } - INode eventUA = monitoredItem.GetEventType(eventFields); - if (eventUA.NodeId == new NodeId(Opc.Ua.ObjectTypes.BaseModelChangeEventType)) - { - //TODO:if we get this event we know a change was made, but we do not know what so we will beed to get all EventTypes and compare and update our config data - } - else if (eventUA.NodeId != new NodeId(Opc.Ua.ObjectTypes.GeneralModelChangeEventType)) - { - //We are not interested in any other event, so we will return. - //If we can set the where clause on the filter for this item, this else clause can be removed. - return; - } - else - { - object v = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.GeneralModelChangeEventType, new QualifiedName(Opc.Ua.BrowseNames.Changes)); - - //ChangeStructureDataTypeCollection changes = (ChangeStructureDataTypeCollection) monitoredItem.GetFieldValue(eventFields, ObjectTypes.GeneralModelChangeEventType, new QualifiedName(GeneralModelChangeEvent.Names.Changes)); - - - - } - - } - catch (Exception ex) - { - Utils.Trace(ex, "Unexpected error in AddressSpaceChange_Notification"); - } - } - - /// - /// Returns the event category data based off the event category browse name - /// - /// The event category browse name. - public EventCategory FindEventCatInfo(string EventName) - { - try - { - //The Categories array is sorted off the BrowseName so we can do a binary search. - int first = 0; - int last = m_configFile.Categories.Length - 1; - int mid; - while (first <= last) - { - mid = (first + last) / 2; - int compareValue = m_configFile.Categories[mid].BrowseName.CompareTo(EventName); - if (compareValue == 0) - return m_configFile.Categories[mid]; - else if (compareValue > 0) - last = mid - 1; - else - first = mid + 1; - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in FindEventCatInfo"); - } - return null; - } - - /// - /// Give each subscription the oppurtunity to examine the new event and - /// notify clients if appropriate (e.g., filter) - /// - /// - public void ProcessNewEvent(OnEventClass OEClass) - { - lock (m_lock) - { - foreach (Subscription s in m_EvSubMgtSet) - { - s.ProcessNewEvent(OEClass); - } - } - } - #endregion - - #region Condition Acknowledgement Support members - /// - /// AckCondition - /// - /// - /// - /// - /// - /// - /// - /// - public int AckCondition(string szAcknowledgerID, string szComment, string szSource, string szConditionName, System.Runtime.InteropServices.ComTypes.FILETIME ftActiveTime, int dwCookie) - { - OPCCondition cond = FindCondition(szSource, szConditionName); - if (cond == null) - return ResultIds.E_INVALIDARG; - - if (cond.ActiveTime != GetDateTime(ftActiveTime)) - return ResultIds.E_INVALIDTIME; - - if (cond.Cookie != dwCookie) - return ResultIds.E_INVALIDARG; - - if (cond.IsAckedOrWaiting(m_Subscription.CurrentPublishingInterval * 2)) - return ResultIds.S_ALREADYACKED; - try - { - IList args = m_session.Call(cond.ConditionId, cond.AcknowledgeMethod, cond.EventId, new LocalizedText(szComment)); - } - - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in AckCondition"); - return ResultIds.E_FAIL; - } - - return ResultIds.S_OK; - } - - /// - /// Unmarshals a WIN32 FILETIME. - /// - public static DateTime GetDateTime(System.Runtime.InteropServices.ComTypes.FILETIME input) - { - System.Runtime.InteropServices.ComTypes.FILETIME output = new System.Runtime.InteropServices.ComTypes.FILETIME(); - - output.dwLowDateTime = input.dwLowDateTime; - output.dwHighDateTime = input.dwHighDateTime; - - return ComUtils.GetDateTime(output); - } - - /// - /// FindCondition - /// - /// - /// - /// - OPCCondition FindCondition(string szSource, string szCondition) - { - SourceMap sourceMap = SourceMap.TheSourceMap; - lock (sourceMap) - { - OPCCondition cond; - ConditionMap conditionMap; - if (sourceMap.TryGetValue(szSource, out conditionMap) == false) - return null; - - if (conditionMap.TryGetValue(szCondition, out cond) == false) - return null; - else - return cond; - } - - } - #endregion - - #region Subscription Management Members - /// - /// Adds subscription reference to the list - /// - /// - public void SubscriptionListInsert(Subscription s) - { - m_EvSubMgtSet.Add(s); - } - - /// - /// Removes subscription reference from the list - /// - /// - public void SubscriptionListRemove(Subscription s) - { - m_EvSubMgtSet.Remove(s); - } - - /// - /// Time of last subscription callback for this server instance - /// - public DateTime LastUpdateTime - { - get { return m_lastUpdateTime; } - set { m_lastUpdateTime = value; } - } - #endregion - - /// - /// Accessor used when negotiating subscription keepalive time. Client cannot request a keepalive - /// time faster than that of the UA master subscription - /// - public int KeepAliveInterval - { - get { return m_KeepAliveInterval; } - } - - /// - /// Accessor for use by internal subscription to add/remove monitored items. MasterSubscription - /// is the single UA subscription maintained by the proxy - /// - public Opc.Ua.Client.Subscription MasterSubscription - { - get { return m_Subscription; } - } - - /// - /// Accessor used to obtain the Server namespace mapping table (server namespace index to client namespace index) - /// - public List ServerMappingTable - { - get { return m_serverMappingTable; } - } - - /// - /// Accessor used to obtain the Client namespace mapping table (client namespace index to server namespace index) - /// Client indices which cannot be mapped to a server index (i.e., namespace is removed from server) map to -1 - /// - public List ClientMappingTable - { - get { return m_clientmappingTable; } - } - - #region Private Fields - private ComAeProxy2 m_proxy; - private Guid m_clsid; - private int m_KeepAliveInterval = 1000; - private object m_lock = new object(); - private DateTime m_startTime = DateTime.MinValue; - private DateTime m_lastUpdateTime = DateTime.MinValue; - private static object m_staticLock = new object(); - private static ApplicationConfiguration m_configuration; - private static ConfiguredEndpointCollection m_endpointCache; - private static Dictionary m_verifiedEndpoints; - private Session m_session; - private string m_clientName; - private List m_localeIds = null; - private int m_lcid = ComUtils.LOCALE_SYSTEM_DEFAULT; - private List m_EvSubMgtSet = new List(); - private Opc.Ua.Client.Subscription m_Subscription = null; - private List m_serverMappingTable = new List(); - private List m_clientmappingTable = new List(); - - private Configuration m_configFile = new Configuration(); - private List m_EventCategories = new List(); - private List m_EventAttributes = new List(); - - - private int m_catID = 1; - private int m_attrID = 2; //starts with 2 as 0 and 1 are used for the standard attributes 'areas' and 'ackcomment' - private const string AreasAttributeName = "Areas"; - private const string AckCommentAttributeName = "AckComment"; - - /// - /// The DefaultServerUrl - /// - private const string DefaultServerUrl = "http://localhost:51211/UA/SampleServer"; - - //Dictionary of notifier nodes - private Dictionary m_notifiers = new Dictionary(); - private Dictionary m_AreaNodes = new Dictionary(); - #endregion - } - - #region class to store information about COM areas - class AreaNode - { - public AreaNode() - { - m_name = ""; - m_count = 0; - m_monitoredItem = null; - } - public string AreaName - { - get { return m_name; } - set { m_name = value; } - } - - public int RefCount - { - get { return m_count; } - set { m_count = value; } - } - - public MonitoredItem MonitoredItem - { - get { return m_monitoredItem; } - set { m_monitoredItem = value; } - } - - private string m_name; // Fully qualified area name - private int m_count; // Count of subscriptions subscribing to this area - private MonitoredItem m_monitoredItem; // monitored item that represents the area node - }; - #endregion - - #region Configuration File Classes - - /// - /// Configuration data for the event categories and attributess - /// - public class Configuration - { - /// - /// SubscriptionSettings accessor - /// - public SubscriptionSettings ProxySubscriptionSettings - { - get { return m_proxySubscriptionSettings; } - set { m_proxySubscriptionSettings = value; } - } - - /// - /// SavedNamespaceTable accessor - /// - public string[] SavedNamespaceTable - { - get { return m_savedNamespaceTable; } - set { m_savedNamespaceTable = value; } - } - - /// - /// Categories accessor - /// - public EventCategory[] Categories - { - get { return m_Categories; } - set { m_Categories = value; } - } - - /// - /// Attributes accessor - /// - public EventAttribute[] Attributes - { - get { return m_Attributes; } - set { m_Attributes = value; } - } - - /// - /// LastEventCategoryID accessor - /// - public int LastEventCategoryID - { - get { return m_LastEventCategoryID; } - set { m_LastEventCategoryID = value; } - } - - /// - /// LastEventAttributeID accessor - /// - public int LastEventAttributeID - { - get { return m_LastEventAttributeID; } - set { m_LastEventAttributeID = value; } - } - - #region Private Fields - private string[] m_savedNamespaceTable; - private EventCategory[] m_Categories; - private EventAttribute[] m_Attributes; - private int m_LastEventCategoryID; - private int m_LastEventAttributeID; - private SubscriptionSettings m_proxySubscriptionSettings = new SubscriptionSettings(); - #endregion - - } - - /// - /// UA Subscription configuration settings. - /// - public class SubscriptionSettings - { - /// - /// MaxNotificationsPerPublish accessor - /// - public uint MaxNotificationsPerPublish - { - get { return m_maxNotificationsPerPublish; } - set { m_maxNotificationsPerPublish = value; } - } - - /// - /// KeepAliveCount accessor - /// - public uint KeepAliveCount - { - get { return m_keepAliveCount; } - set { m_keepAliveCount = value; } - } - - /// - /// LifetimeCount accessor - /// - public uint LifetimeCount - { - get { return m_lifetimeCount; } - set { m_lifetimeCount = value; } - } - - /// - /// PublishingInterval accessor - /// - public int PublishingInterval - { - get { return m_publishingInterval; } - set { m_publishingInterval = value; } - } - - /// - /// Priority accessor - /// - public byte Priority - { - get { return m_priority; } - set { m_priority = value; } - } - - #region Private Fields - private uint m_maxNotificationsPerPublish = 0; - private uint m_keepAliveCount = 10; - private uint m_lifetimeCount = 1000; - private int m_publishingInterval = 0; - private byte m_priority = 0; - #endregion - } - - - /// - /// Event category data - /// - public class EventCategory - { - /// - /// CategoryID accessor - /// - [XmlAttribute] - public int CategoryID - { - get { return m_CategoryID; } - set { m_CategoryID = value; } - } - - /// - /// strNodeId accessor - /// - [XmlAttribute] - public string strNodeId - { - get { return m_strNodeId; } - set { m_strNodeId = value; } - } - - /// - /// BrowseName accessor - /// - [XmlAttribute] - public string BrowseName - { - get { return m_BrowseName; } - set { m_BrowseName = value; } - } - - /// - /// EventDesc accessor - /// - [XmlAttribute] - public string EventDesc - { - get { return m_EventDesc; } - set { m_EventDesc = value; } - } - - /// - /// EventType accessor - /// - [XmlAttribute] - public int EventType - { - get { return m_EventType; } - set { m_EventType = value; } - } - - #region Private Fields - private int m_CategoryID; //Event Category ID number - private string m_strNodeId; //NodeId of the event type - private string m_BrowseName; - private string m_EventDesc; - private int m_EventType; - #endregion - } - /// - /// Event attribute data - /// - public class EventAttribute - { - /// - /// AttributeID accessor - /// - [XmlAttribute] - public int AttributeID - { - get { return m_AttributeID; } - set { m_AttributeID = value; } - } - - /// - /// strNodeId accessor - /// - [XmlAttribute] - public string strNodeId - { - get { return m_strNodeId; } - set { m_strNodeId = value; } - } - - /// - /// BrowseName accessor - /// - [XmlAttribute] - public string BrowseName - { - get { return m_BrowseName; } - set { m_BrowseName = value; } - } - - /// - /// BrowseNameNSIndex accessor - /// - [XmlAttribute] - public ushort BrowseNameNSIndex - { - get { return m_BrowseNameNSIndex; } - set { m_BrowseNameNSIndex = value; } - } - - /// - /// AttrDesc accessor - /// - [XmlAttribute] - public string AttrDesc - { - get { return m_AttrDesc; } - set { m_AttrDesc = value; } - } - - /// - /// strEventNodeId accessor - /// - [XmlAttribute] - public string strEventNodeId - { - get { return m_strEventNodeId; } - set { m_strEventNodeId = value; } - } - - /// - /// strDataTypeNodeId accessor - /// - [XmlAttribute] - public string strDataTypeNodeId - { - get { return m_strDataTypeNodeId; } - set { m_strDataTypeNodeId = value; } - } - - /// - /// IsArray accessor - /// - [XmlAttribute] - public bool IsArray - { - get { return m_IsArray; } - set { m_IsArray = value; } - } - - /// - /// ActualDataType accessor - /// - [XmlIgnoreAttribute] - public Type ActualDataType - { - get { return m_ActualDataType; } - set { m_ActualDataType = value; } - } - - - - #region Private Fields - private int m_AttributeID; //Attribute ID number - private string m_strNodeId; //NodeId of the attribute - private string m_BrowseName; - private ushort m_BrowseNameNSIndex; // namespace index - private string m_AttrDesc; - private string m_strEventNodeId; // NodeId of the Event Type where this attribute is defined - private string m_strDataTypeNodeId; // NodeId of the DataType - private bool m_IsArray; - private Type m_ActualDataType; - #endregion - - } - #endregion -} diff --git a/ComIOP/Common/Server/Ae/ComAeSubscription.cs b/ComIOP/Common/Server/Ae/ComAeSubscription.cs deleted file mode 100644 index 0f3acf868..000000000 --- a/ComIOP/Common/Server/Ae/ComAeSubscription.cs +++ /dev/null @@ -1,967 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using System.Threading; -using OpcRcw.Ae; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Server.Ae -{ - /// - /// Implements COM-AE Subscription class - /// - public class Subscription : - ConnectionPointContainer, - IDisposable, - IOPCEventSubscriptionMgt, - IOPCEventSubscriptionMgt2 - { - /// - /// Initializes the object with the default values - /// - /// - public Subscription(ComAeProxy server) - { - RegisterInterface(typeof(OpcRcw.Ae.IOPCEventSink).GUID); - - m_server = server; - m_bCancelRefresh = false; - m_ftLastUpdate = DateTime.Now; - m_bActive = false; - m_dwBufferTime = DefaultBufferTime; - m_dwMaxSize = DefaultMaxCallbackSize; - m_hClientSubscription = 0; - m_dwEventType = Constants.ALL_EVENTS; - m_dwLowSeverity = 1; - m_dwHighSeverity = 1000; - m_bCancelRefresh = false; - m_subscription = null; - m_MinimumKeepAliveTime = server.KeepAliveInterval; - } - - #region IDisposable Members - /// - /// The finializer implementation. - /// - ~Subscription() - { - Dispose(false); - } - - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - UnregisterInterface(typeof(OpcRcw.Ae.IOPCEventSink).GUID); - - // Remove monitored items added for this subscription - if (m_AreaVector.Count > 0) - m_server.RemoveMonitoredItems(m_AreaVector); - - if (m_server != null) - { - m_server.SubscriptionListRemove(this); - } - - if (m_server != null) - { - ComUtils.ReleaseServer(m_server); - m_server = null; - } - } - #endregion - - #region IOPCEventSubscriptionMgt Members - - /// - /// Sets the filtering criteria to be used for the event subscription. - /// - /// Bit mask specifying which event types are of interest - /// Length of array of event categories. A length of 0 indicates all categories should be included in the filter. - /// Array of event categories of interest. - /// Lowest severity of interest (inclusive). - /// Highest severity of interest (inclusive). - /// Length of array of areas. A length of 0 indicates all areas should be included in the filter. - /// Array of process area strings of interest - only events or conditions in these areas will be reported. - /// Length of array of event sources. A length of 0 indicates all sources should be included in the filter. - /// Array of event sources of interest - only events from these sources will be reported. - 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 szAreas = new List(); - for (int i = 0; i < dwNumAreas; i++) - { - szAreas.Add(pszAreaList[i]); - } - if (szAreas.Count > 0) - m_server.AddMonitoredItems(szAreas); - } - - if (dwNumSources != 0) - { - List szSources = new List(); - for (int i = 0; i < dwNumSources; i++) - { - int wildCardLocation = 0; - if ((wildCardLocation = pszSourceList[i].IndexOfAny(new char[] { '*', '?', '#', '[', ']', '!', '-' })) != -1) - { - // The string contains wildcards - List 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); - } - } - - /// - /// Returns the filter currently in use for event subscriptions. - /// - /// Bit map specifying which event types are of allowed through the filter - /// Length of the event category array returned. - /// Array of event categories for the filter. - /// Lowest severity allowed through filter. - /// Highest severity allowed through filter. - /// Length of the area list array returned. - /// List of process areas for the filter. - /// Length of the event source list returned. - /// List of sources for the filter. - public void GetFilter(out int pdwEventType, out int pdwNumCategories, out IntPtr ppdwEventCategories, out int pdwLowSeverity, out int pdwHighSeverity, out int pdwNumAreas, out IntPtr ppszAreaList, out int pdwNumSources, out IntPtr ppszSourceList) - { - pdwEventType = 0; - pdwNumCategories = 0; - ppdwEventCategories = IntPtr.Zero; - pdwLowSeverity = 0; - pdwHighSeverity = 0; - pdwNumAreas = 0; - ppszAreaList = IntPtr.Zero; - pdwNumSources = 0; - ppszSourceList = IntPtr.Zero; - - try - { - pdwEventType = m_dwEventType; - pdwLowSeverity = m_dwLowSeverity; - pdwHighSeverity = m_dwHighSeverity; - if (m_EventCategoryVector.Count != 0) - { - int[] EventCategoryIDs = m_EventCategoryVector.ToArray(); - pdwNumCategories = m_EventCategoryVector.Count; - ppdwEventCategories = ComUtils.GetInt32s(EventCategoryIDs); - } - if (m_AreaVector.Count != 0) - { - string[] Areas = m_AreaVector.ToArray(); - pdwNumAreas = m_AreaVector.Count; - ppszAreaList = ComUtils.GetUnicodeStrings(Areas); - } - if (m_SourceVector.Count != 0) - { - string[] Sources = m_SourceVector.ToArray(); - pdwNumSources = m_SourceVector.Count; - ppszSourceList = ComUtils.GetUnicodeStrings(Sources); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in GetFilter"); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Sets the attributes to be returned with event notifications in the IOPCEventSink::OnEvent callback. - /// - /// The specific event category for which the list of attributes applies. - /// The size of the attribute IDs array. - /// The list IDs of the attributes to return with event notifications for the event type and event category specified. - public void SelectReturnedAttributes(int dwEventCategory, int dwCount, int[] dwAttributeIDs) - { - try - { - - if (dwCount < 0) - { - throw ComUtils.CreateComException("SelectReturnedAttributes", ResultIds.E_INVALIDARG); - } - - // Make sure we are passed a valid dwEventCategory - NodeId catNodeId = m_server.FindEventCatNodeId(dwEventCategory); - if (catNodeId == null) - throw ComUtils.CreateComException("SelectReturnedAttributes", ResultIds.E_INVALIDARG); - - // Check for valid attributeIds - List attrs = m_server.GetEventAttributes(dwEventCategory); - - for (int i = 0; i < dwCount; i++) - { - if (!CompareAttribID(attrs,dwAttributeIDs[i])) - throw ComUtils.CreateComException("SelectReturnedAttributes", ResultIds.E_INVALIDARG); ; - - } - lock (m_csData) - { - ReturnedAttributeList ras = new ReturnedAttributeList(); - - for (int i = 0; i < dwCount; i++) - ras.AddUnique(dwAttributeIDs[i]); - - m_ReturnedAttributes[dwEventCategory] = ras; - } - } - catch (COMException e) - { - throw ComUtils.CreateComException(e); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in SelectReturnedAttributes"); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Retrieves the attributes which are currently specified to be returned with event notifications in the IOPCEventSink::OnEvent callback. - /// - /// The specific event category for which to retrieve the list of attributes. - /// The size of the attribute IDs array which is being returned. Is set to zero if no attributes are currently specified. - /// The list IDs of the attributes which are currently specified to be returned with event notifications for the event type and event category specified. - public void GetReturnedAttributes(int dwEventCategory, out int pdwCount, out IntPtr ppdwAttributeIDs) - { - pdwCount = 0; - ppdwAttributeIDs = IntPtr.Zero; - - try - { - // Make sure we are passed a valid dwEventCategory - NodeId catNodeId = m_server.FindEventCatNodeId(dwEventCategory); - if (catNodeId == null) - throw ComUtils.CreateComException("SetFilter", ResultIds.E_INVALIDARG); - - lock (m_csData) - { - ReturnedAttributeList ras; - if (m_ReturnedAttributes.TryGetValue(dwEventCategory, out ras)) - { - pdwCount = ras.Count; - int[] attrIDs = ras.ToArray(); - - ppdwAttributeIDs = ComUtils.GetInt32s(attrIDs); - } - } - } - catch (COMException e) - { - throw ComUtils.CreateComException(e); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in GetReturnedAttributes"); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Force a refresh for all active conditions and inactive, unacknowledged conditions whose event notifications match the filter of the event subscription. - /// - /// The OLE Connection number returned from IConnectionPoint::Advise. This is passed to help the server determine which OPC event sink to call when the request completes. - public void Refresh(int dwConnection) - { - try - { - if (m_RefreshID != 0 || m_RefreshQ.Count != 0) - throw ComUtils.CreateComException("Refresh", ResultIds.E_BUSY); - - m_RefreshID = dwConnection; - - // Foe each source walk through all associated conditions. If the condition is "refreshable", i.e. Active or - // inactive/unacknowledged, then create an event and push it on to the subscription's refresh queue - SourceMap sourceMap = SourceMap.TheSourceMap; - foreach (KeyValuePair kvp in sourceMap) - { - string sourceName = kvp.Key; - ConditionMap conditionMap = kvp.Value; - foreach (KeyValuePair kvpCond in conditionMap) - { - string conditionName = kvpCond.Key; - OPCCondition cond = kvpCond.Value; - - if (cond.IsEnabled() && (cond.IsActive() || !cond.IsAcked())) - { - OnEventClass OEClass = new OnEventClass(sourceName, conditionName, cond); - if (MatchesFilter(OEClass)) - m_RefreshQ.Enqueue(OEClass); - } - - } - } - - if (m_RefreshQ.Count > 0) - { - ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork), null); - } - else - { - CancelRefresh(dwConnection); - } - - - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in Refresh"); - throw ComUtils.CreateComException(e); - } - } - - - /// - /// Cancels a refresh in progress for the event subscription. - /// - /// The OLE Connection number returned from IConnectionPoint::Advise. This is passed to help the server determine which OPC event sink to call when the request completes. - public void CancelRefresh(int dwConnection) - { - if (dwConnection == 0) - { - throw ComUtils.CreateComException("CancelRefresh", ResultIds.E_INVALIDARG); - } - - if (dwConnection != m_RefreshID) - { - throw ComUtils.CreateComException("CancelRefresh", ResultIds.E_FAIL); - } - - m_bCancelRefresh = true; - ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork), null); - } - - /// - /// Get the current state of the subscription. - /// - /// The current active state of the subscription. - /// The current buffer time configured for event notification. - /// The current max number of events that will be sent in a single IOPCEventSink::OnEvent callback. - /// The client supplied subscription handle - public void GetState(out int pbActive, out int pdwBufferTime, out int pdwMaxSize, out int phClientSubscription) - { - pbActive = 0; - pdwBufferTime = 0; - pdwMaxSize = 0; - phClientSubscription = 0; - - try - { - pbActive = m_bActive ? 1 : 0; - pdwBufferTime = m_dwBufferTime; - pdwMaxSize = m_dwMaxSize; - phClientSubscription = m_hClientSubscription; - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in GetState"); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Client can set various properties of the event subscription. - /// - /// TRUE (non-zero) to activate the subscription. FALSE (0) to deactivate the subscription. - /// New buffer time requested for the subscription by the client. - /// New maximum number of event notifications to send with a single IOPCEventSink::OnEvent callback. - /// Client supplied handle for the subscription. - /// The buffer time that the server is actually providing, which may differ from dwBufferTime. - /// The maximum number of events that the server will actually be sending in a single IOPCEventSink::OnEvent callback, which may differ from dwMaxSize. - public void SetState( - IntPtr pbActive, - IntPtr pdwBufferTime, - IntPtr pdwMaxSize, - int hClientSubscription, - out int pdwRevisedBufferTime, - out int pdwRevisedMaxSize) - { - pdwRevisedBufferTime = m_dwBufferTime; - pdwRevisedMaxSize = m_dwMaxSize; - - try - { - int dwBufferTime = 0; - int dwMaxSize = 0; - - if (pbActive != IntPtr.Zero) - m_bActive = Marshal.ReadInt32(pbActive) == 0 ? false : true; - - m_hClientSubscription = hClientSubscription; - - // Set revised max size to the smaller of (1)requested size or (2)default max - if (pdwMaxSize != IntPtr.Zero) - { - dwMaxSize = Marshal.ReadInt32(pdwMaxSize); - dwMaxSize = dwMaxSize > 0 ? dwMaxSize : DefaultMaxCallbackSize; - m_dwMaxSize = (dwMaxSize < DefaultMaxCallbackSize ? dwMaxSize : DefaultMaxCallbackSize); - pdwRevisedMaxSize = m_dwMaxSize; - } - - // Set revised buffer time to the larger of (1)requested time or (2) default time - if (pdwBufferTime != IntPtr.Zero) - { - dwBufferTime = Marshal.ReadInt32(pdwBufferTime); - dwBufferTime = dwBufferTime > 0 ? dwBufferTime : DefaultBufferTime; - m_dwBufferTime = (dwBufferTime > DefaultBufferTime ? dwBufferTime : DefaultBufferTime); - pdwRevisedBufferTime = m_dwBufferTime; - } - - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in SetState"); - throw ComUtils.CreateComException(e); - } - - } - - - #endregion - - #region IOPCEventSubscriptionMgt2 Members - /// - /// Returns the currently active keep-alive time for the subscription. - /// - public void GetKeepAlive(out int pdwKeepAliveTime) - { - pdwKeepAliveTime = 0; - lock (m_csData) - { - try - { - pdwKeepAliveTime = m_KeepAliveTime; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Sets the keep-alive time for a subscription to cause the server to provide - /// client callbacks on the subscription when there are no new events to report. - /// - /// The maximum amount of time (in milliseconds) the client expects to receive a new subscription callback since the last subscription callback. A value of zero indicates the client does not wish to receive any keep-alive callbacks. - /// The KeepAliveTime the server is actually providing. - public void SetKeepAlive( - int dwKeepAliveTime, - out int pdwRevisedKeepAliveTime) - { - pdwRevisedKeepAliveTime = 0; - - lock (m_csData) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - if (dwKeepAliveTime == 0) - return; - - lock (m_csData) - { - try - { - // The only keep alive interval supported is that of the underlying UA subscription - m_KeepAliveTime = m_MinimumKeepAliveTime; - pdwRevisedKeepAliveTime = m_KeepAliveTime; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - } - #endregion - - /// - /// Determines whether the newly received event matches the filter applied to this - /// subscription. - /// - /// - /// - private bool MatchesFilter(OnEventClass pOnEventClass) - { - bool FilterMatches = true; - - try - { - if (System.Convert.ToBoolean(m_dwEventType & pOnEventClass.InternalOES.dwEventType) == false) - FilterMatches = false; - - if (m_EventCategoryVector.Count != 0) - if (m_EventCategoryVector.Contains(pOnEventClass.InternalOES.dwEventCategory) == false) - FilterMatches = false; - - if (pOnEventClass.InternalOES.dwSeverity < m_dwLowSeverity | pOnEventClass.InternalOES.dwSeverity > m_dwHighSeverity) - FilterMatches = false; - - if (m_AreaVector.Count != 0) - { - if (pOnEventClass.EventAttributes.Count > 0) - { - string[] areas = (string[])pOnEventClass.EventAttributes[1]; - foreach (string area in areas) - { - if (m_AreaVector.Contains(area) == true) - { - FilterMatches = true; - break; - } - FilterMatches = false; - } - } - } - - if (m_SourceVector.Count != 0) - if (m_SourceVector.Contains(pOnEventClass.InternalOES.szSource) == false) - FilterMatches = false; - - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in MatchesFilter"); - FilterMatches = false; - } - return FilterMatches; - } - - /// - /// If the subscription filter allows the event then enqueue the event - /// and assign a threadpool worker to handle the subscription callback - /// - /// - public void ProcessNewEvent(OnEventClass pOnEventClass) - { - lock (m_csData) - { - try - { - if (m_bActive == true) - { - // compare to my filter, if it matches - if (MatchesFilter(pOnEventClass)) - m_OnEventQ.Enqueue(pOnEventClass); - - // Just a keep-alive event? - else if ((pOnEventClass.InternalOES.szSource == null) && (pOnEventClass.InternalOES.szConditionName == null)) - m_KeepAliveQ.EnqueueIfEmpty(pOnEventClass); - - // Even if this event was filtered out, check to see if it - // is time to send anything that is already in my queue. - if (m_OnEventQ.Count > 0) - { - TimeSpan bufferTime = TimeSpan.FromMilliseconds(m_dwBufferTime); - DateTime lastUpdate = m_LastUpdateTime; - DateTime nextUpdate = lastUpdate + bufferTime; - - if (m_OnEventQ.Count >= m_dwMaxSize || nextUpdate <= DateTime.Now) - ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork), null); - } - - // No "real events" to send ... is it time to send a keep alive (keepalive of 0 means disabled) ? - else if ((m_KeepAliveQ.Count > 0) && (m_KeepAliveTime != 0)) - { - TimeSpan bufferTime = TimeSpan.FromMilliseconds(m_KeepAliveTime); - DateTime lastUpdate = m_LastUpdateTime; - if (DateTime.Now >= (lastUpdate + bufferTime)) - ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork), null); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in ProcessNewEvent"); - } - } - } - - /// - /// Initializes a COM-patible ONEVENTSTRUCT ready to be sent to subscribing clients - /// - /// - /// - private void CopyToOnEventStruct(ref ONEVENTSTRUCT oes, OnEventClass pOnEventClass) - { - try - { - oes = pOnEventClass.InternalOES; - - ReturnedAttributeList attrIds; - if (m_ReturnedAttributes.TryGetValue(oes.dwEventCategory, out attrIds) == true) - { - int retAttrCount = attrIds.Count; - int i = 0; - object[] attrVals = new object[retAttrCount]; - - foreach (int attrId in attrIds) - attrVals[i++] = pOnEventClass.EventAttributes[attrId]; - - oes.dwNumEventAttrs = retAttrCount; - oes.pEventAttributes = ComUtils.GetVARIANTs(attrVals, false); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in CopyToOnEventStruct"); - } - } - - /// - /// Called on a threadpool thread, SendEvents pops waiting event notifications from the - /// subscription queue (subject to MaxSize) and invokes the client callback - /// - /// - /// - /// - public void SendEvents(EventItemQueue q, bool bRefresh, bool bKeepAlive) - { - int dwCount = 0; - int hClientSubscription = 0; - bool bLastRefresh = false; - ONEVENTSTRUCT[] events; - - lock (m_csData) - { - hClientSubscription = m_hClientSubscription; - dwCount = Math.Min(q.Count, m_dwMaxSize); - bLastRefresh = (dwCount == q.Count) && bRefresh; - events = new ONEVENTSTRUCT[dwCount]; - - for (int i = 0; i < dwCount; i++) - CopyToOnEventStruct(ref events[i], q.Dequeue()); - - } - - bool bUpdated = false; - - try - { - lock (m_lock) - { - object callback = GetCallback(typeof(IOPCEventSink).GUID); - - if (callback == null) - { - return; - } - - if (dwCount > 0) // don't update time for a keep alive callback - { - m_LastUpdateTime = DateTime.Now; - bUpdated = true; - } - - if (bRefresh && bLastRefresh) - m_RefreshID = 0; - - ((IOPCEventSink)callback).OnEvent( - hClientSubscription, - bRefresh ? 1 : 0, - bLastRefresh ? 1 : 0, - bKeepAlive ? 0 : dwCount, - events); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in OnEvent callback."); - } - finally - { - for (int i = 0; i < dwCount; i++) - Marshal.FreeCoTaskMem(events[i].pEventAttributes); - } - - if (m_server != null && bUpdated) - m_server.LastUpdateTime = m_LastUpdateTime; - } - - /// - /// Clears the refresh related state from the subscription and generates a callback - /// where bRefresh==true and bLastRefresh==true - /// - private void SendCancelRefresh() - { - lock (m_csData) - { - m_RefreshQ.Clear(); - m_bCancelRefresh = false; - m_RefreshID = 0; - } - - // Create an empty event -- dwCount will be set to zero anyway - ONEVENTSTRUCT[] emptyEvent = new ONEVENTSTRUCT[1]; - CopyToOnEventStruct(ref emptyEvent[0], new OnEventClass(null, null, new OPCCondition())); - - try - { - lock (m_lock) - { - object callback = GetCallback(typeof(IOPCEventSink).GUID); - - if (callback == null) - { - return; - } - - ((IOPCEventSink)callback).OnEvent(m_hClientSubscription, 1, 1, 0, emptyEvent); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error in OnEvent callback."); - } - finally - { - Marshal.FreeCoTaskMem(emptyEvent[0].pEventAttributes); - } - - } - - /// - /// Called from threadpool worker, ThreadWork examines the subscription's queues and - /// initiates callback processing where events are queued and waiting. ThreadWork - /// also services Refresh cancel requests - /// - /// - public void ThreadWork(object obj) - { - bool bCancelRefresh = false; - int dwRefreshQSize = 0; - int dwEventQSize = 0; - - lock (m_csData) - { - dwEventQSize = m_OnEventQ.Count; - - bCancelRefresh = m_bCancelRefresh; - dwRefreshQSize = m_RefreshQ.Count; - } - - // new events have priority over refresh events. - - if (bCancelRefresh) - SendCancelRefresh(); - - if (dwEventQSize > 0) - SendEvents(m_OnEventQ, false, false); - - if (dwRefreshQSize > 0) - SendEvents(m_RefreshQ, true, false); - - if (!bCancelRefresh && dwEventQSize == 0 && dwRefreshQSize == 0) - SendEvents(m_KeepAliveQ, false, true); // keep-alive callback - - lock (m_csData) - { - if (m_OnEventQ.Count > 0 || m_RefreshQ.Count > 0) - ThreadPool.QueueUserWorkItem(ThreadWork); - } - } - - /// - /// Subscription is active - /// - public bool Active - { - get { return m_bActive; } - } - - /// - /// Access/assign the UA subscription - /// - public Opc.Ua.Client.Subscription UaSubscription - { - get { return m_subscription; } - set { m_subscription = value; } - } - - /// - /// iterates through the list of attributes and returns true when a matching attribute is found - /// Caller: SelectReturnedAttributes() - /// - private bool CompareAttribID(List attrs, int id1) - { - foreach (EventAttribute attrib in attrs) - { - if (attrib.AttributeID == id1) - return true; - } - return false; - } - - #region Private Member - private object m_lock = new object(); - private object m_csData = new object(); - private ComAeProxy m_server = null; - private bool m_bActive; - private int m_dwBufferTime; - private int m_dwMaxSize; - private int m_hClientSubscription; - private int m_KeepAliveTime = 0; // Initially disabled - private int m_MinimumKeepAliveTime = 1000; - private DateTime m_LastUpdateTime = DateTime.MinValue; - private const int DefaultMaxCallbackSize = 1000; - private const int DefaultBufferTime = 1000; - - private EventItemQueue m_OnEventQ = new EventItemQueue(); - private EventItemQueue m_RefreshQ = new EventItemQueue(); - private EventItemQueue m_KeepAliveQ = new EventItemQueue(); - private DateTime m_ftLastUpdate; - - // data members for Set/Get Filter - private int m_dwEventType; - private UniqueList m_EventCategoryVector = new UniqueList(); - private UniqueList m_AreaVector = new UniqueList(); - private UniqueList m_SourceVector = new UniqueList(); - private int m_dwLowSeverity; - private int m_dwHighSeverity; - - // data member for SelectReturnAttributes() - private Dictionary m_ReturnedAttributes = new Dictionary(); - - // data member flag for Refresh/CancelRefresh; - private bool m_bCancelRefresh; - private int m_RefreshID = 0; - - private Opc.Ua.Client.Subscription m_subscription; - #endregion - } - - /// - /// List containing the client requested set of attribute IDs for any one event category - /// - public class ReturnedAttributeList : UniqueList - { - } - - -} diff --git a/ComIOP/Common/Server/Ae/ComConnectionPointContainer.cs b/ComIOP/Common/Server/Ae/ComConnectionPointContainer.cs deleted file mode 100644 index baba7c0bf..000000000 --- a/ComIOP/Common/Server/Ae/ComConnectionPointContainer.cs +++ /dev/null @@ -1,432 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections; -using System.Text; -using System.Runtime.InteropServices; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Server.Ae -{ - /// - /// A class that implements the COM-DA interfaces. - /// - public class ConnectionPointContainer : OpcRcw.Comn.IConnectionPointContainer - { - #region Public Members - /// - /// Called when a IConnectionPoint.Advise is called. - /// - public virtual void OnAdvise(Guid riid) - { - // does nothing. - } - - /// - /// Called when a IConnectionPoint.Unadvise is called. - /// - public virtual void OnUnadvise(Guid riid) - { - // does nothing. - } - #endregion - - #region Protected Members - /// - /// Initializes the object with default values. - /// - protected ConnectionPointContainer() - { - // does nothing. - } - - /// - /// Registers an interface as a connection point. - /// - protected void RegisterInterface(Guid iid) - { - m_connectionPoints[iid] = new ConnectionPoint(iid, this); - } - - /// - /// Unregisters an interface as a connection point. - /// - protected void UnregisterInterface(Guid iid) - { - m_connectionPoints.Remove(iid); - } - - /// - /// Returns the callback interface for the connection point (if currently connected). - /// - protected object GetCallback(Guid iid) - { - ConnectionPoint connectionPoint = (ConnectionPoint)m_connectionPoints[iid]; - - if (connectionPoint != null) - { - return connectionPoint.Callback; - } - - return null; - } - - /// - /// Whether a client has connected to the specified connection point. - /// - protected bool IsConnected(Guid iid) - { - ConnectionPoint connectionPoint = (ConnectionPoint)m_connectionPoints[iid]; - - if (connectionPoint != null) - { - return connectionPoint.IsConnected; - } - - return false; - } - #endregion - - #region IConnectionPointContainer Members - /// - public void EnumConnectionPoints(out OpcRcw.Comn.IEnumConnectionPoints ppenum) - { - lock (m_lock) - { - try - { - ppenum = new EnumConnectionPoints(m_connectionPoints.Values); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void FindConnectionPoint(ref Guid riid, out OpcRcw.Comn.IConnectionPoint ppCP) - { - lock (m_lock) - { - try - { - ppCP = null; - - ConnectionPoint connectionPoint = (ConnectionPoint)m_connectionPoints[riid]; - - if (connectionPoint == null) - { - throw new ExternalException("CONNECT_E_NOCONNECTION", ResultIds.CONNECT_E_NOCONNECTION); - } - - ppCP = connectionPoint as IConnectionPoint; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - #region Private Members - private object m_lock = new object(); - private Hashtable m_connectionPoints = new Hashtable(); - #endregion - } - - /// - /// A class that implements the COM-DA interfaces. - /// - public class ConnectionPoint : OpcRcw.Comn.IConnectionPoint - { - /// - /// Creates a connection point for the specified interface and container. - /// - public ConnectionPoint(Guid iid, ConnectionPointContainer container) - { - m_interface = iid; - m_container = container; - } - - /// - /// The current callback object. - /// - public object Callback - { - get { return m_callback; } - } - - /// - /// Whether the client has connected to the connection point. - /// - public bool IsConnected - { - get { return m_callback != null; } - } - - #region IConnectionPoint Members - - /// - public void GetConnectionInterface(out Guid pIID) - { - lock (m_lock) - { - try - { - pIID = m_interface; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void GetConnectionPointContainer(out OpcRcw.Comn.IConnectionPointContainer ppCPC) - { - lock (m_lock) - { - try - { - ppCPC = m_container; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Advise(object pUnkSink, out int pdwCookie) - { - lock (m_lock) - { - try - { - if (pUnkSink == null) - { - throw new ExternalException("E_POINTER", ResultIds.E_POINTER); - } - - pdwCookie = 0; - - // check if an callback already exists. - if (m_callback != null) - { - throw new ExternalException("CONNECT_E_ADVISELIMIT", ResultIds.CONNECT_E_ADVISELIMIT); - } - - m_callback = pUnkSink; - pdwCookie = ++m_cookie; - - // notify container. - m_container.OnAdvise(m_interface); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Unadvise(int dwCookie) - { - lock (m_lock) - { - try - { - // not a valid connection id. - if (m_cookie != dwCookie || m_callback == null) - { - throw new ExternalException("CONNECT_E_NOCONNECTION", ResultIds.CONNECT_E_NOCONNECTION); - } - - // clear the callback. - Marshal.ReleaseComObject(m_callback); - m_callback = null; - - // notify container. - m_container.OnUnadvise(m_interface); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void EnumConnections(out OpcRcw.Comn.IEnumConnections ppenum) - { - throw new ExternalException("E_NOTIMPL", ResultIds.E_NOTIMPL); - } - #endregion - - #region Private Members - private object m_lock = new object(); - private Guid m_interface = Guid.Empty; - private ConnectionPointContainer m_container = null; - private object m_callback = null; - private int m_cookie = 0; - #endregion - } - - /// - /// A class that implements the COM-DA interfaces. - /// - public class EnumConnectionPoints : OpcRcw.Comn.IEnumConnectionPoints - { - /// - /// Initializes the object with a set of connection points. - /// - internal EnumConnectionPoints(ICollection connectionPoints) - { - if (connectionPoints != null) - { - foreach (OpcRcw.Comn.IConnectionPoint connectionPoint in connectionPoints) - { - m_connectionPoints.Add(connectionPoint); - } - } - } - - #region IEnumConnectionPoints Members - /// - public void Skip(int cConnections) - { - lock (m_lock) - { - try - { - m_index += cConnections; - - if (m_index > m_connectionPoints.Count) - { - m_index = m_connectionPoints.Count; - } - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Clone(out OpcRcw.Comn.IEnumConnectionPoints ppenum) - { - lock (m_lock) - { - try - { - ppenum = new EnumConnectionPoints(m_connectionPoints); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Reset() - { - lock (m_lock) - { - try - { - m_index = 0; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void RemoteNext(int cConnections, IntPtr ppCP, out int pceltFetched) - { - lock (m_lock) - { - try - { - if (ppCP == IntPtr.Zero) - { - throw new ExternalException("E_INVALIDARG", ResultIds.E_INVALIDARG); - } - - pceltFetched = 0; - - if (m_index >= m_connectionPoints.Count) - { - return; - } - - object[] unknowns = new object[cConnections]; - - for (int ii = 0; ii < m_connectionPoints.Count - m_index && ii < cConnections; ii++) - { - unknowns[ii] = (OpcRcw.Comn.IConnectionPoint)m_connectionPoints[m_index + ii]; - pceltFetched++; - } - - m_index += pceltFetched; - - IntPtr[] pointers = new IntPtr[pceltFetched]; - Marshal.Copy(ppCP, pointers, 0, pceltFetched); - - for (int ii = 0; ii < pceltFetched; ii++) - { - pointers[ii] = Marshal.GetIUnknownForObject(unknowns[ii]); - } - - Marshal.Copy(pointers, 0, ppCP, pceltFetched); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - #region Private Members - private object m_lock = new object(); - private ArrayList m_connectionPoints = new ArrayList(); - private int m_index = 0; - #endregion - } -} diff --git a/ComIOP/Common/Server/Ae/ComEnumerator.cs b/ComIOP/Common/Server/Ae/ComEnumerator.cs deleted file mode 100644 index 5335cd53b..000000000 --- a/ComIOP/Common/Server/Ae/ComEnumerator.cs +++ /dev/null @@ -1,286 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections; -using System.Text; -using System.Runtime.InteropServices; - -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Server.Ae -{ - /// - /// A class that implements the COM-DA interfaces. - /// - public class EnumUnknown : IEnumUnknown - { - /// - /// Initializes the object with a set of interface pointers. - /// - internal EnumUnknown(ICollection unknowns) - { - if (unknowns != null) - { - foreach (object unknown in unknowns) - { - m_unknowns.Add(unknown); - } - } - } - - #region EnumUnknown Members - /// - public void Skip(int celt) - { - lock (m_lock) - { - try - { - m_index += celt; - - if (m_index > m_unknowns.Count) - { - m_index = m_unknowns.Count; - } - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Clone(out IEnumUnknown ppenum) - { - lock (m_lock) - { - try - { - ppenum = new EnumUnknown(m_unknowns); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Reset() - { - lock (m_lock) - { - try - { - m_index = 0; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void RemoteNext(int celt, IntPtr rgelt, out int pceltFetched) - { - lock (m_lock) - { - try - { - pceltFetched = 0; - - if (m_index >= m_unknowns.Count) - { - return; - } - - object[] unknowns = new object[celt]; - - for (int ii = 0; ii < m_unknowns.Count - m_index && ii < unknowns.Length; ii++) - { - unknowns[ii] = m_unknowns[m_index+ii]; - pceltFetched++; - } - - IntPtr[] pointers = new IntPtr[pceltFetched]; - Marshal.Copy(rgelt, pointers, 0, pceltFetched); - - for (int ii = 0; ii < pceltFetched; ii++) - { - pointers[ii] = Marshal.GetIUnknownForObject(unknowns[ii]); - } - - Marshal.Copy(pointers, 0, rgelt, pceltFetched); - - m_index += pceltFetched; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - #region Private Members - private object m_lock = new object(); - private ArrayList m_unknowns = new ArrayList(); - private int m_index = 0; - #endregion - } - - /// - /// A class that implements the COM-DA interfaces. - /// - public class EnumString : OpcRcw.Comn.IEnumString - { - /// - /// Initializes the object with a set of interface pointers. - /// - internal EnumString(ICollection strings) - { - if (strings != null) - { - foreach (object instance in strings) - { - m_strings.Add(instance); - } - } - } - - #region EnumString Members - /// - public void Skip(int celt) - { - lock (m_lock) - { - try - { - m_index += celt; - - if (m_index > m_strings.Count) - { - m_index = m_strings.Count; - } - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Clone(out OpcRcw.Comn.IEnumString ppenum) - { - lock (m_lock) - { - try - { - ppenum = new EnumString(m_strings); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Reset() - { - lock (m_lock) - { - try - { - m_index = 0; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public int RemoteNext(int celt, IntPtr rgelt, out int pceltFetched) - { - pceltFetched = 0; - - lock (m_lock) - { - try - { - pceltFetched = 0; - - if (m_index >= m_strings.Count) - { - return ResultIds.S_FALSE; - } - - string [] strings = new string[celt]; - - for (int ii = 0; ii < m_strings.Count - m_index && ii < strings.Length; ii++) - { - strings[ii] = (string)m_strings[m_index+ii]; - pceltFetched++; - } - - IntPtr[] pointers = new IntPtr[pceltFetched]; - Marshal.Copy(rgelt, pointers, 0, pceltFetched); - - for (int ii = 0; ii < pceltFetched; ii++) - { - pointers[ii] = Marshal.StringToCoTaskMemUni(strings[ii]); - } - - Marshal.Copy(pointers, 0, rgelt, pceltFetched); - - m_index += pceltFetched; - - return ResultIds.S_OK; - } - catch (Exception) - { - return ResultIds.E_FAIL; - } - } - } - #endregion - - #region Private Members - private object m_lock = new object(); - private ArrayList m_strings = new ArrayList(); - private int m_index = 0; - #endregion - } -} diff --git a/ComIOP/Common/Server/Ae2/AeConditionManager.cs b/ComIOP/Common/Server/Ae2/AeConditionManager.cs deleted file mode 100644 index ec39bda53..000000000 --- a/ComIOP/Common/Server/Ae2/AeConditionManager.cs +++ /dev/null @@ -1,295 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Manages conditions requring acknowledgement. - /// - public class AeConditionManager - { - #region Public Methods - /// - /// Initializes the manager. - /// - public void Initialize() - { - lock (m_lock) - { - m_cookies = new Dictionary(); - m_events = new Dictionary(); - } - } - - /// - /// Processes an event (assigns a cookie if acknowledgment is required). - /// - public void ProcessEvent(AeEvent e) - { - if (NodeId.IsNull(e.ConditionId)) - { - return; - } - - lock (m_lock) - { - string conditionId = GetConditionId(e); - - // assign a cookie to the condition/branch. - int cookie = 0; - - if (!m_cookies.TryGetValue(conditionId, out cookie)) - { - cookie = ++m_counter; - m_cookies[conditionId] = cookie; - } - - // remove acked events. - if (e.AckedState) - { - m_events.Remove(cookie); - m_cookies.Remove(conditionId); - } - - // save event for acking. - else - { - m_events[cookie] = e; - e.Cookie = cookie; - } - } - } - - /// - /// Acknowledges one or more events. - /// - 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; - } - #endregion - - #region Private Method - /// - /// Combines the condition id/branch id in a unique identifier. - /// - private string GetConditionId(AeEvent e) - { - StringBuilder buffer = new StringBuilder(); - buffer.Append(e.ConditionId); - - if (NodeId.IsNull(e.BranchId)) - { - buffer.Append(e.BranchId); - } - - return buffer.ToString(); - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private int m_counter; - private Dictionary m_events; - private Dictionary m_cookies; - #endregion - } - - /// - /// Stores a request to acknowledge an event. - /// - public class AeAcknowledgeRequest - { - /// - /// The source of the condition. - /// - public string SourceName { get; set; } - - /// - /// The name of the condition. - /// - public string ConditionName { get; set; } - - /// - /// The active time. - /// - public DateTime ActiveTime { get; set; } - - /// - /// The cookie. - /// - public int Cookie { get; set; } - } -} diff --git a/ComIOP/Common/Server/Ae2/AeEvent.cs b/ComIOP/Common/Server/Ae2/AeEvent.cs deleted file mode 100644 index fa364784e..000000000 --- a/ComIOP/Common/Server/Ae2/AeEvent.cs +++ /dev/null @@ -1,174 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores an event received from the UA server. - /// - public class AeEvent - { - /// - /// A number assigned by the proxy to the event when it arrives. - /// - public int Cookie { get; set; } - - /// - /// The event id. - /// - public byte[] EventId { get; set; } - - /// - /// The event type. - /// - public NodeId EventType { get; set; } - - /// - /// The event source. - /// - public string SourceName { get; set; } - - /// - /// The event time. - /// - public DateTime Time { get; set; } - - /// - /// The event message. - /// - public LocalizedText Message { get; set; } - - /// - /// The event severity. - /// - public ushort Severity { get; set; } - - /// - /// The user that triggered the audit event. - /// - public string AuditUserId { get; set; } - - /// - /// The NodeId of the condition (used for acknowledging). - /// - public NodeId ConditionId { get; set; } - - /// - /// The condition branch which the event belongs to. - /// - public NodeId BranchId { get; set; } - - /// - /// The name of the condition. - /// - public string ConditionName { get; set; } - - /// - /// The last comment. - /// - public LocalizedText Comment { get; set; } - - /// - /// The user that added the comment. - /// - public string CommentUserId { get; set; } - - /// - /// The qualilty of the underlying data source. - /// - public StatusCode Quality { get; set; } - - /// - /// The current Enabled state (Conditions). - /// - public bool EnabledState { get; set; } - - /// - /// The current Acknowledged state (Conditions). - /// - public bool AckedState { get; set; } - - /// - /// The current Active state (Alarms). - /// - public bool ActiveState { get; set; } - - /// - /// When the condition transitioned into the Active state (Alarms). - /// - public DateTime ActiveTime { get; set; } - - /// - /// The current Limit state (ExclusiveLimitConditions). - /// - public LocalizedText LimitState { get; set; } - - /// - /// The current HighHigh state (NonExclusiveLimitConditions). - /// - public LocalizedText HighHighState { get; set; } - - /// - /// The current High state (NonExclusiveLimitConditions). - /// - public LocalizedText HighState { get; set; } - - /// - /// The current Low state (NonExclusiveLimitConditions). - /// - public LocalizedText LowState { get; set; } - - /// - /// The current LowLow state (NonExclusiveLimitConditions). - /// - public LocalizedText LowLowState { get; set; } - - /// - /// The category for the event type. - /// - public AeEventCategory Category { get; set; } - - /// - /// The attribute values requested for the category. - /// - public object[] AttributeValues { get; set; } - } -} diff --git a/ComIOP/Common/Server/Ae2/AeEventAttribute.cs b/ComIOP/Common/Server/Ae2/AeEventAttribute.cs deleted file mode 100644 index fc7cbea20..000000000 --- a/ComIOP/Common/Server/Ae2/AeEventAttribute.cs +++ /dev/null @@ -1,129 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores an instance declaration fetched from the server. - /// - public class AeEventAttribute - { - /// - /// The proxy assigned identifier for the attribute. - /// - public uint LocalId; - - /// - /// The type that the declaration belongs to. - /// - public NodeId RootTypeId { get; set; } - - /// - /// The browse path to the instance declaration. - /// - public QualifiedNameCollection BrowsePath { get; set; } - - /// - /// The browse path to the instance declaration. - /// - public string BrowsePathDisplayText { get; set; } - - /// - /// A localized path to the instance declaration. - /// - public string DisplayPath { get; set; } - - /// - /// The node id for the instance declaration. - /// - public NodeId NodeId { get; set; } - - /// - /// The node class of the instance declaration. - /// - public NodeClass NodeClass { get; set; } - - /// - /// The browse name for the instance declaration. - /// - public QualifiedName BrowseName { get; set; } - - /// - /// The display name for the instance declaration. - /// - public string DisplayName { get; set; } - - /// - /// The description for the instance declaration. - /// - public string Description { get; set; } - - /// - /// The modelling rule for the instance declaration (i.e. Mandatory or Optional). - /// - public NodeId ModellingRule { get; set; } - - /// - /// The data type for the instance declaration. - /// - public NodeId DataType { get; set; } - - /// - /// The value rank for the instance declaration. - /// - public int ValueRank { get; set; } - - /// - /// The built-in type parent for the data type. - /// - public BuiltInType BuiltInType { get; set; } - - /// - /// An instance declaration that has been overridden by the current instance. - /// - public AeEventAttribute OverriddenDeclaration { get; set; } - - /// - /// The attribute is not visible to clients. - /// - public bool Hidden { get; set; } - } -} diff --git a/ComIOP/Common/Server/Ae2/AeEventCategory.cs b/ComIOP/Common/Server/Ae2/AeEventCategory.cs deleted file mode 100644 index c78cf9bc3..000000000 --- a/ComIOP/Common/Server/Ae2/AeEventCategory.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores a type declaration retrieved from a server. - /// - public class AeEventCategory - { - /// - /// The AE event type that the category belongs to. - /// - public int EventType { get; set; } - - /// - /// The proxy assigned category id for the event type. - /// - public uint LocalId; - - /// - /// The UA event type node id for the category. - /// - public NodeId TypeId { get; set; } - - /// - /// The UA event type node id for the supertype. - /// - public NodeId SuperTypeId { get; set; } - - /// - /// A description for the event type. - /// - public string Description { get; set; } - - /// - /// The fully inhierited list of instance declarations for the UA event type. - /// - public List Attributes { get; set; } - } - -} diff --git a/ComIOP/Common/Server/Ae2/AeEventFilter.cs b/ComIOP/Common/Server/Ae2/AeEventFilter.cs deleted file mode 100644 index 2908f0343..000000000 --- a/ComIOP/Common/Server/Ae2/AeEventFilter.cs +++ /dev/null @@ -1,677 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// A declararion of an event filter. - /// - public class AeEventFilter - { - #region Constructors - /// - /// Creates a new instance of an AeEventFilter. - /// - public AeEventFilter(ComAeNamespaceMapper mapper) - { - m_mapper = mapper; - } - #endregion - - #region Public Members - /// - /// The event types requested by the client. - /// - public int EventTypes { get; private set; } - - /// - /// The minimum severity for events to report. - /// - public ushort LowSeverity { get; private set; } - - /// - /// The maxnimum severity for events to report. - /// - public ushort HighSeverity { get; private set; } - - /// - /// The category ids requested by the client. - /// - public uint[] RequestedCategoryIds { get; private set; } - - /// - /// The category ids requested by the client. - /// - public Dictionary RequestedAttributeIds { get; private set; } - - /// - /// The optimized list of category ids (duplicates removed). - /// - public List RevisedCategories { get; set; } - - /// - /// The sources selected. - /// - public List SelectedSources { get; set; } - - /// - /// The optimized list of attributes ids (duplicates removed). - /// - public List SelectedAttributes { get; set; } - - /// - /// Sets the categories. - /// - public void SetFilter(int eventTypes, ushort lowSeverity, ushort highSeverity, uint[] categoryIds, List sources) - { - RevisedCategories = new List(); - - // update list of sources. - SelectedSources = new List(); - - if (sources != null) - { - SelectedSources.AddRange(sources); - } - - for (int ii = 0; categoryIds != null && ii < categoryIds.Length; ii++) - { - AeEventCategory category = m_mapper.GetCategory(categoryIds[ii]); - - // ignore unknown categories. - if (category == null) - { - continue; - } - - // ignore categories if the event types mask filters them out. - if ((category.EventType & eventTypes) == 0) - { - continue; - } - - // add category. - RevisedCategories.Add(category); - } - - // save the original ids. - EventTypes = eventTypes; - LowSeverity = lowSeverity; - HighSeverity = highSeverity; - RequestedCategoryIds = categoryIds; - - // update selected attributes. - UpdatedSelectAttributes(); - } - - /// - /// Selects the attributes for the category. - /// - public bool SelectAttributes(uint categoryId, uint[] attributeIds) - { - // validate category. - if (m_mapper.GetCategory(categoryId) == null) - { - return false; - } - - // validate attributes. - if (attributeIds != null) - { - for (int ii = 0; ii < attributeIds.Length; ii++) - { - if (m_mapper.GetAttribute(attributeIds[ii]) == null) - { - return false; - } - } - } - - // update list. - if (RequestedAttributeIds == null) - { - RequestedAttributeIds = new Dictionary(); - } - - if (attributeIds == null || attributeIds.Length == 0) - { - RequestedAttributeIds.Remove(categoryId); - } - else - { - RequestedAttributeIds[categoryId] = attributeIds; - } - - UpdatedSelectAttributes(); - return true; - } - - /// - /// Returns the event filter defined by the filter declaration. - /// - public EventFilter GetFilter() - { - EventFilter filter = new EventFilter(); - filter.SelectClauses = GetSelectClause(); - filter.WhereClause = GetWhereClause(); - return filter; - } - - /// - /// Translates an event notification in an AE event. - /// - public AeEvent TranslateNotification(Session session, EventFieldList e) - { - AeEvent e2 = new AeEvent(); - - // extract the required event fields. - int index = 0; - - e2.EventId = ExtractField(e, index++, null); - e2.EventType = ExtractField(e, index++, null); - e2.SourceName = ExtractField(e, index++, null); - e2.Time = ExtractField(e, index++, DateTime.MinValue); - e2.Message = ExtractField(e, index++, null); - e2.Severity = ExtractField(e, index++, 0); - - if ((EventTypes & OpcRcw.Ae.Constants.TRACKING_EVENT) != 0) - { - e2.AuditUserId = ExtractField(e, index++, null); - } - - if ((EventTypes & OpcRcw.Ae.Constants.CONDITION_EVENT) != 0) - { - e2.BranchId = ExtractField(e, index++, null); - e2.ConditionName = ExtractField(e, index++, null); - e2.Quality = ExtractField(e, index++, StatusCodes.Good); - e2.Comment = ExtractField(e, index++, null); - e2.CommentUserId = ExtractField(e, index++, null); - e2.EnabledState = ExtractField(e, index++, false); - e2.AckedState = ExtractField(e, index++, false); - e2.ActiveState = ExtractField(e, index++, false); - e2.ActiveTime = ExtractField(e, index++, DateTime.MinValue); - e2.LimitState = ExtractField(e, index++, null); - e2.HighHighState = ExtractField(e, index++, null); - e2.HighState = ExtractField(e, index++, null); - e2.LowState = ExtractField(e, index++, null); - e2.LowLowState = ExtractField(e, index++, null); - - // condition id is always last. - e2.ConditionId = ExtractField(e, e.EventFields.Count - 1, null); - } - - // find the category for the event. - e2.Category = FindCategory(session, e2); - - // extract any additional attributes. - if (RequestedAttributeIds != null) - { - uint[] attributeIds = null; - - if (!RequestedAttributeIds.TryGetValue(e2.Category.LocalId, out attributeIds)) - { - return e2; - } - - // nothing more to do. - if (attributeIds == null || attributeIds.Length == 0) - { - return e2; - } - - // search for the requested attributes. - object[] values = new object[attributeIds.Length]; - - for (int ii = 0; ii < attributeIds.Length; ii++) - { - // look for matching attribute. - for (int jj = 0; jj < SelectedAttributes.Count; jj++) - { - if (jj >= e.EventFields.Count) - { - break; - } - - AeEventAttribute attribute = SelectedAttributes[jj]; - - if (attribute == null || attribute.LocalId != attributeIds[ii]) - { - continue; - } - - values[ii] = GetLocalAttributeValue(e.EventFields[jj], attribute); - } - } - - e2.AttributeValues = values; - } - - return e2; - } - - /// - /// Converts an event field to a locally useable attribute value. - /// - private object GetLocalAttributeValue(Variant fieldValue, AeEventAttribute attribute) - { - // check for null. - if (fieldValue == Variant.Null) - { - return null; - } - - // check that the data type is what is expected. - TypeInfo typeInfo = fieldValue.TypeInfo; - - if (typeInfo == null) - { - typeInfo = TypeInfo.Construct(fieldValue); - } - - if (attribute.BuiltInType != BuiltInType.Variant && typeInfo.BuiltInType != attribute.BuiltInType) - { - return null; - } - - // check for expected array dimension. - if (attribute.ValueRank >= 0 && typeInfo.ValueRank == ValueRanks.Scalar) - { - return null; - } - - if (typeInfo.ValueRank != ValueRanks.Scalar) - { - if (attribute.ValueRank == ValueRanks.ScalarOrOneDimension && typeInfo.ValueRank != 1) - { - return null; - } - - if (attribute.ValueRank != ValueRanks.Any && attribute.ValueRank != typeInfo.ValueRank) - { - return null; - } - } - - // map to local value. - return m_mapper.GetLocalValue(fieldValue); - } - - /// - /// Finds the category for the event. - /// - private AeEventCategory FindCategory(Session session, AeEvent e) - { - AeEventCategory category = m_mapper.GetCategory(e.EventType); - - NodeId subTypeId = e.EventType; - NodeId superTypeId = null; - - // follow the type tree if type not recognized. - while (category == null) - { - superTypeId = session.NodeCache.FindSuperType(subTypeId); - - if (!NodeId.IsNull(superTypeId)) - { - category = m_mapper.GetCategory(superTypeId); - - if (category != null) - { - return category; - } - } - - subTypeId = superTypeId; - } - - // default to base event type. - if (category == null) - { - category = m_mapper.GetCategory(Opc.Ua.ObjectTypeIds.BaseEventType); - } - - return category; - } - - /// - /// Extracts a field value from an incoming event. - /// - private T ExtractField(EventFieldList e, int index, T defaultValue) - { - if (e == null || index >= e.EventFields.Count || index < 0) - { - return defaultValue; - } - - Variant value = e.EventFields[index]; - - if (!typeof(T).IsInstanceOfType(value.Value)) - { - return defaultValue; - } - - return (T)value.Value; - } - #endregion - - #region Private Methods - /// - /// Updates the selected attributes for the current filters. - /// - private void UpdatedSelectAttributes() - { - SelectedAttributes = new List(); - - // add attributes which always requested. - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.BaseEventType, Opc.Ua.BrowseNames.EventId)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.BaseEventType, Opc.Ua.BrowseNames.EventType)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.BaseEventType, Opc.Ua.BrowseNames.SourceName)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.BaseEventType, Opc.Ua.BrowseNames.Time)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.BaseEventType, Opc.Ua.BrowseNames.Message)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.BaseEventType, Opc.Ua.BrowseNames.Severity)); - - // add tracking event attributes. - if ((EventTypes & OpcRcw.Ae.Constants.TRACKING_EVENT) != 0) - { - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.AuditEventType, Opc.Ua.BrowseNames.ClientUserId)); - } - - // add condition event attributes. - if ((EventTypes & OpcRcw.Ae.Constants.CONDITION_EVENT) != 0) - { - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.ConditionType, Opc.Ua.BrowseNames.BranchId)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.ConditionType, Opc.Ua.BrowseNames.ConditionName)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.ConditionType, Opc.Ua.BrowseNames.Quality)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.ConditionType, Opc.Ua.BrowseNames.Comment)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.ConditionType, Opc.Ua.BrowseNames.ClientUserId)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.ConditionType, Opc.Ua.BrowseNames.EnabledState, Opc.Ua.BrowseNames.Id)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.AcknowledgeableConditionType, Opc.Ua.BrowseNames.AckedState, Opc.Ua.BrowseNames.Id)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.AlarmConditionType, Opc.Ua.BrowseNames.ActiveState, Opc.Ua.BrowseNames.Id)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.AlarmConditionType, Opc.Ua.BrowseNames.ActiveState, Opc.Ua.BrowseNames.TransitionTime)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.ExclusiveLimitAlarmType, Opc.Ua.BrowseNames.LimitState, Opc.Ua.BrowseNames.CurrentState)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.NonExclusiveLimitAlarmType, Opc.Ua.BrowseNames.HighHighState)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.NonExclusiveLimitAlarmType, Opc.Ua.BrowseNames.HighState)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.NonExclusiveLimitAlarmType, Opc.Ua.BrowseNames.LowState)); - SelectedAttributes.Add(m_mapper.GetAttribute(Opc.Ua.ObjectTypeIds.NonExclusiveLimitAlarmType, Opc.Ua.BrowseNames.LowLowState)); - } - - if (RequestedAttributeIds != null) - { - // update list for all requested attributes. - foreach (KeyValuePair pair in RequestedAttributeIds) - { - for (int ii = 0; ii < pair.Value.Length; ii++) - { - // check if already in list. - bool found = false; - - for (int jj = 0; jj < SelectedAttributes.Count; jj++) - { - if (SelectedAttributes[jj] != null && SelectedAttributes[jj].LocalId == pair.Value[ii]) - { - found = true; - break; - } - } - - if (found) - { - continue; - } - - // verify that it exists. - AeEventAttribute attribute = m_mapper.GetAttribute(pair.Value[ii]); - - if (attribute != null) - { - SelectedAttributes.Add(attribute); - } - } - } - } - } - - /// - /// Checks if a supertype was already selected. - /// - private bool IsSuperTypeSelected(AeEventCategory category, uint[] categoryIds) - { - AeEventCategory subType = category; - AeEventCategory superType = null; - - while (subType != null) - { - superType = m_mapper.GetCategory(subType.SuperTypeId); - - if (superType == null) - { - return false; - } - - for (int ii = 0; ii < categoryIds.Length; ii++) - { - if (categoryIds[ii] == superType.LocalId) - { - return true; - } - } - - subType = superType; - } - - return false; - } - - /// - /// Returns the select clause defined by the filter declaration. - /// - private SimpleAttributeOperandCollection GetSelectClause() - { - SimpleAttributeOperandCollection selectClause = new SimpleAttributeOperandCollection(); - - // add the explicitly selected attributes. - foreach (AeEventAttribute attribute in SelectedAttributes) - { - if (attribute != null) - { - SimpleAttributeOperand operand = new SimpleAttributeOperand(); - operand.TypeDefinitionId = attribute.RootTypeId; - operand.AttributeId = (attribute.NodeClass == NodeClass.Object) ? Attributes.NodeId : Attributes.Value; - operand.BrowsePath = attribute.BrowsePath; - selectClause.Add(operand); - } - } - - // need to request the condition id if condition events selected. - if ((EventTypes & OpcRcw.Ae.Constants.CONDITION_EVENT) != 0) - { - SimpleAttributeOperand operand = new SimpleAttributeOperand(); - operand.TypeDefinitionId = Opc.Ua.ObjectTypeIds.ConditionType; - operand.AttributeId = Attributes.NodeId; - operand.BrowsePath.Clear(); - selectClause.Add(operand); - } - - return selectClause; - } - - /// - /// Returns the where clause defined by the filter declaration. - /// - private ContentFilter GetWhereClause() - { - ContentFilter whereClause = new ContentFilter(); - - ContentFilterElement element1 = null; - - // filter by source. - if (SelectedSources != null && SelectedSources.Count > 0) - { - SimpleAttributeOperand operand1 = new SimpleAttributeOperand(); - operand1.TypeDefinitionId = Opc.Ua.ObjectTypeIds.BaseEventType; - operand1.AttributeId = Attributes.Value; - operand1.BrowsePath.Add(new QualifiedName(Opc.Ua.BrowseNames.SourceNode)); - - for (int ii = 0; ii < SelectedSources.Count; ii++) - { - LiteralOperand operand2 = new LiteralOperand(); - operand2.Value = SelectedSources[ii]; - ContentFilterElement element2 = whereClause.Push(FilterOperator.Equals, operand1, operand2); - element1 = (element1 != null)?whereClause.Push(FilterOperator.Or, element1, element2):element2; - } - } - - // add condition/tracking categories if no other categories selected. - if (RevisedCategories == null || RevisedCategories.Count == 0) - { - if (EventTypes == (OpcRcw.Ae.Constants.SIMPLE_EVENT | OpcRcw.Ae.Constants.TRACKING_EVENT)) - { - ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.ConditionType); - ContentFilterElement element3 = whereClause.Push(FilterOperator.Not, element2); - - element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element3) : element3; - } - - else if (EventTypes == (OpcRcw.Ae.Constants.SIMPLE_EVENT | OpcRcw.Ae.Constants.CONDITION_EVENT)) - { - ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.AuditEventType); - ContentFilterElement element3 = whereClause.Push(FilterOperator.Not, element2); - ContentFilterElement element4 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.TransitionEventType); - ContentFilterElement element5 = whereClause.Push(FilterOperator.Not, element4); - ContentFilterElement element6 = whereClause.Push(FilterOperator.Or, element3, element5); - - element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element6) : element6; - } - - else if (EventTypes == (OpcRcw.Ae.Constants.TRACKING_EVENT | OpcRcw.Ae.Constants.CONDITION_EVENT)) - { - ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.AuditEventType); - ContentFilterElement element3 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.TransitionEventType); - ContentFilterElement element4 = whereClause.Push(FilterOperator.Or, element2, element3); - ContentFilterElement element5 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.ConditionType); - ContentFilterElement element6 = whereClause.Push(FilterOperator.Or, element4, element5); - - element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element6) : element6; - } - - else if (EventTypes == OpcRcw.Ae.Constants.TRACKING_EVENT) - { - ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.AuditEventType); - ContentFilterElement element3 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.TransitionEventType); - ContentFilterElement element4 = whereClause.Push(FilterOperator.Or, element2, element3); - - element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element4) : element4; - } - - else if (EventTypes == OpcRcw.Ae.Constants.CONDITION_EVENT) - { - ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.ConditionType); - - element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element2) : element2; - } - - else if (EventTypes == OpcRcw.Ae.Constants.SIMPLE_EVENT) - { - ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.AuditEventType); - ContentFilterElement element3 = whereClause.Push(FilterOperator.Not, element2); - ContentFilterElement element4 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.TransitionEventType); - ContentFilterElement element5 = whereClause.Push(FilterOperator.Not, element4); - ContentFilterElement element6 = whereClause.Push(FilterOperator.Or, element3, element5); - ContentFilterElement element7 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.ConditionType); - ContentFilterElement element8 = whereClause.Push(FilterOperator.Not, element7); - - element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element8) : element8; - } - } - - // filter by event type. - if (RevisedCategories.Count > 0) - { - SimpleAttributeOperand operand1 = new SimpleAttributeOperand(); - operand1.TypeDefinitionId = Opc.Ua.ObjectTypeIds.BaseEventType; - operand1.AttributeId = Attributes.Value; - operand1.BrowsePath.Add(new QualifiedName(Opc.Ua.BrowseNames.EventType)); - - ContentFilterElement element3 = null; - - for (int ii = 0; ii < RevisedCategories.Count; ii++) - { - ContentFilterElement element2 = whereClause.Push(FilterOperator.Equals, operand1, RevisedCategories[ii].TypeId); - element3 = (element3 != null) ? whereClause.Push(FilterOperator.Or, element2, element3) : element2; - } - - element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element3) : element3; - } - - // filter by severity. - if (LowSeverity > 1 || HighSeverity < 1000) - { - SimpleAttributeOperand operand1 = new SimpleAttributeOperand(); - operand1.TypeDefinitionId = Opc.Ua.ObjectTypeIds.BaseEventType; - operand1.AttributeId = Attributes.Value; - operand1.BrowsePath.Add(new QualifiedName(Opc.Ua.BrowseNames.Severity)); - - if (LowSeverity > 1) - { - LiteralOperand operand2 = new LiteralOperand(); - operand2.Value = LowSeverity; - ContentFilterElement element2 = whereClause.Push(FilterOperator.GreaterThanOrEqual, operand1, operand2); - element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element2) : element2; - } - - if (HighSeverity < 1000) - { - LiteralOperand operand2 = new LiteralOperand(); - operand2.Value = HighSeverity; - ContentFilterElement element2 = whereClause.Push(FilterOperator.LessThanOrEqual, operand1, operand2); - element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element2) : element2; - } - } - - return whereClause; - } - #endregion - - #region Private Fields - private ComAeNamespaceMapper m_mapper; - #endregion - } -} diff --git a/ComIOP/Common/Server/Ae2/ComAeBrowser.cs b/ComIOP/Common/Server/Ae2/ComAeBrowser.cs deleted file mode 100644 index 97efff41f..000000000 --- a/ComIOP/Common/Server/Ae2/ComAeBrowser.cs +++ /dev/null @@ -1,855 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// A base class for classes that implement an OPC COM specification. - /// - public class ComAe2Browser : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComAe2Browser(ComAe2Proxy server, ComAe2ProxyConfiguration configuration, ComAeNamespaceMapper mapper) - { - m_server = server; - m_configuration = configuration; - m_mapper = mapper; - - m_cache = new Dictionary(); - - AeBrowseElement root = new AeBrowseElement(); - root.NodeId = Opc.Ua.ObjectIds.Server; - root.ItemId = String.Empty; - root.BrowseText = String.Empty; - root.IsArea = true; - root.Duplicated = false; - - m_cache[String.Empty] = root; - m_position = root; - } - #endregion - - #region IDisposable Members - /// - /// The finializer implementation. - /// - ~ComAe2Browser() - { - Dispose(false); - } - - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - m_disposed = true; - } - - /// - /// Throws if disposed. - /// - private void ThrowIfDisposed() - { - if (m_disposed) - { - throw new ObjectDisposedException(GetType().Name); - } - } - #endregion - - #region Public Members - /// - /// Gets or sets the handle. - /// - /// The handle. - public IntPtr Handle - { - get { return m_handle; } - set { m_handle = value; } - } - - /// - /// Moves the current browse position up. - /// - public void BrowseUp() - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - // determine the parent id. - string parentId = String.Empty; - - lock (m_lock) - { - // can't browse up from root. - if (String.IsNullOrEmpty(m_position.ItemId)) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - // get parent id. - int index = m_position.ItemId.LastIndexOf('/'); - - if (index != -1) - { - parentId = m_position.ItemId.Substring(0, index); - } - } - - // browse to the parent. - BrowseTo(parentId); - } - - /// - /// Moves the current browse position down. - /// - public void BrowseDown(string targetName) - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - lock (m_lock) - { - // check if this is the first access. - if (m_position.Areas == null) - { - Browse(true, String.Empty); - } - - // find the area. - if (m_position.Areas != null) - { - for (int ii = 0; ii < m_position.Areas.Count; ii++) - { - if (m_position.Areas[ii].BrowseText == targetName) - { - m_position = m_position.Areas[ii]; - return; - } - } - } - - throw ComUtils.CreateComException(ResultIds.E_INVALIDBRANCHNAME); - } - } - - /// - /// Moves the current browse position to the specified item. - /// - 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 names = new Stack(); - 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; - } - } - - /// - /// Gets the qualified name. - /// - public string GetQualifiedName(string targetName, bool isArea) - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - lock (m_lock) - { - List elements = null; - - // check if this is the first access. - if (isArea) - { - if (m_position.Areas == null) - { - Browse(true, String.Empty); - } - - elements = m_position.Areas; - } - else - { - if (m_position.Sources == null) - { - Browse(false, String.Empty); - } - - elements = m_position.Sources; - } - - // find the target. - for (int ii = 0; ii < elements.Count; ii++) - { - if (elements[ii].BrowseText == targetName) - { - return elements[ii].ItemId; - } - } - - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - } - - /// - /// Browses the current branch. - /// - /// - /// The list of names that meet the criteria. - /// - public IList Browse(bool isArea, string filter) - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - lock (m_lock) - { - // fetch the children. - List children = Browse(session, m_position, filter, isArea); - - // create list of names. - List names = new List(children.Count); - - for (int ii = 0; ii < children.Count; ii++) - { - names.Add(children[ii].BrowseText); - } - - return names; - } - } - - /// - /// Finds the children that match the pattern (updates cache if required). - /// - private List Browse(Session session, AeBrowseElement start, string pattern, bool isArea) - { - // check cache. - List targets = (isArea)?start.Areas:start.Sources; - - if (targets == null) - { - // fetch from server. - targets = Browse(session, start, isArea); - - // update cache. - if (isArea) - { - start.Areas = targets; - } - else - { - start.Sources = targets; - } - } - - // check if all matched. - if (String.IsNullOrEmpty(pattern) || pattern == "*") - { - return targets; - } - - // apply filter. - List hits = new List(); - - for (int ii = 0; ii < targets.Count; ii++) - { - if (ComUtils.Match(targets[ii].BrowseText, pattern, false)) - { - hits.Add(targets[ii]); - } - } - - return hits; - } - - /// - /// Fetches the children from the server. - /// - private List 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 hits = new List(); - - 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; - } - - /// - /// Checks if the item id identified by the is a valid area or source. - /// - public bool IsValidQualifiedName(string itemId, bool isArea) - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - lock (m_lock) - { - // find the root. - Stack names = new Stack(); - AeBrowseElement root = FindRoot(itemId, names); - - // find the target. - AeBrowseElement target = Find(session, itemId, root, names, isArea); - - if (target == null) - { - return false; - } - - return true; - } - } - - /// - /// Returns the areas or sources that meet search pattern. - /// - public List SearchByQualifiedName(string pattern, bool isArea) - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - List hits = new List(); - - // 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 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; - } - - /// - /// Finds the area/source with the specified identifier. - /// - private AeBrowseElement Find(Session session, string itemId, bool isArea) - { - // check if it has been cached. - AeBrowseElement target = null; - - if (m_cache.TryGetValue(itemId, out target)) - { - if (target.IsArea == isArea) - { - return target; - } - - return null; - } - - // find the first parent that is already cached. - Stack names = new Stack(); - AeBrowseElement root = FindRoot(itemId, names); - - // browse for the node in the server. - try - { - return Find(session, itemId, root, names, isArea); - } - catch - { - return null; - } - } - - private static readonly char[] s_WildcardChars = "*?#[".ToCharArray(); - - /// - /// Returns true if char is one of the special chars that must be escaped. - /// - private static bool IsWildcardChar(char ch) - { - for (int ii = 0; ii < s_WildcardChars.Length; ii++) - { - if (s_WildcardChars[ii] == ch) - { - return true; - } - } - - return false; - } - #endregion - - #region AeBrowseElement Class - /// - /// Stores metadata about a browse element. - /// - private class AeBrowseElement - { - public AeBrowseElement Parent { get; set; } - public NodeId NodeId { get; set; } - public string ItemId { get; set; } - public string BrowseText { get; set; } - public bool IsArea { get; set; } - public bool Duplicated { get; set; } - public List Areas { get; set; } - public List Sources { get; set; } - } - #endregion - - #region Private Methods - /// - /// Parses the item if looking for a known root element. - /// - private AeBrowseElement FindRoot(string itemId, Stack names) - { - // parse the item id looking for a known parent. - 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; - } - - if (root == null) - { - root = m_cache[String.Empty]; - } - - return root; - } - - /// - /// Finds an element identified by the path from the root. - /// - private AeBrowseElement Find(Session session, string itemId, AeBrowseElement root, Stack names, bool isArea) - { - string browseText = null; - - BrowsePath browsePath = new BrowsePath(); - browsePath.StartingNode = root.NodeId; - - while (names.Count > 0) - { - RelativePathElement path = new RelativePathElement(); - - path.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasNotifier; - path.IsInverse = false; - path.IncludeSubtypes = true; - - // final hop can be HasEventSource for sources. - if (!isArea && names.Count == 1) - { - path.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasEventSource; - } - - browseText = names.Pop(); - path.TargetName = m_mapper.GetRemoteBrowseName(browseText); - browsePath.RelativePath.Elements.Add(path); - } - - BrowsePathCollection browsePaths = new BrowsePathCollection(); - browsePaths.Add(browsePath); - - // make the call to the server. - BrowsePathResultCollection results; - DiagnosticInfoCollection diagnosticInfos; - - ResponseHeader responseHeader = session.TranslateBrowsePathsToNodeIds( - null, - browsePaths, - out results, - out diagnosticInfos); - - // ensure that the server returned valid results. - Session.ValidateResponse(results, browsePaths); - Session.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); - - // check if the start node actually exists. - if (StatusCode.IsBad(results[0].StatusCode)) - { - return null; - } - - // must be exact one target. - if (results[0].Targets.Count != 1) - { - return null; - } - - // can't be an external reference. - BrowsePathTarget target = results[0].Targets[0]; - - if (target.RemainingPathIndex != UInt32.MaxValue) - { - return null; - } - - // need to check if at the end of the tree. - BrowseDescription nodeToBrowse = new BrowseDescription(); - nodeToBrowse.NodeId = (NodeId)target.TargetId; - nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasEventSource; - nodeToBrowse.BrowseDirection = BrowseDirection.Forward; - nodeToBrowse.IncludeSubtypes = true; - - ReferenceDescriptionCollection children = ComAeUtils.Browse(session, nodeToBrowse, false); - - if (!isArea) - { - if (children != null && children.Count > 0) - { - return null; - } - } - else - { - if (children == null || children.Count == 0) - { - return null; - } - } - - // construct the element. - AeBrowseElement element = new AeBrowseElement(); - element.NodeId = (NodeId)target.TargetId; - element.ItemId = itemId; - element.BrowseText = browseText; - element.IsArea = isArea; - - return element; - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private bool m_disposed; - private IntPtr m_handle; - private ComAe2Proxy m_server; - private ComAe2ProxyConfiguration m_configuration; - private ComAeNamespaceMapper m_mapper; - private AeBrowseElement m_position; - private Dictionary m_cache; - #endregion - } -} diff --git a/ComIOP/Common/Server/Ae2/ComAeNamespaceMapper.cs b/ComIOP/Common/Server/Ae2/ComAeNamespaceMapper.cs deleted file mode 100644 index 403cb0375..000000000 --- a/ComIOP/Common/Server/Ae2/ComAeNamespaceMapper.cs +++ /dev/null @@ -1,679 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Maps the UA type model to a local - /// - public class ComAeNamespaceMapper : ComNamespaceMapper - { - /// - /// Initializes the mapper. - /// - public void Initialize(Session session, ComAe2ProxyConfiguration configuration) - { - base.Initialize(session, configuration); - - m_session = session; - - // discard the table. - m_eventTypes = new NodeIdDictionary(); - m_categories = new Dictionary(); - m_attributes = new Dictionary(); - - // load the well known types from an embedded resource. - IndexWellKnownTypes(); - - // browse the server for additional types. - if (!configuration.UseOnlyBuiltInTypes) - { - IndexTypesFromServer(Opc.Ua.ObjectTypeIds.BaseEventType, OpcRcw.Ae.Constants.SIMPLE_EVENT); - } - - // check for existing category mapping. - NodeIdMappingSet mappingSet = configuration.GetMappingSet("EventCategories"); - - // update mappings. - UpdateEventTypeMappings(mappingSet); - - // update configuration. - configuration.ReplaceMappingSet(mappingSet); - - // check for existing attribute mapping. - mappingSet = configuration.GetMappingSet("EventAttributes"); - - // update mappings. - UpdateEventAttributeMappings(mappingSet); - - // update configuration. - configuration.ReplaceMappingSet(mappingSet); - } - - /// - /// Gets the list of categories for the specified event types. - /// - public List GetCategories(int eventType) - { - List categories = new List(); - - foreach (AeEventCategory category in m_categories.Values) - { - if ((category.EventType & eventType) != 0) - { - categories.Add(category); - } - } - - categories.Sort(CompareCategories); - return categories; - } - - /// - /// Returns the category with the specified category id. - /// - public AeEventCategory GetCategory(uint categoryId) - { - AeEventCategory category = null; - - if (!m_categories.TryGetValue(categoryId, out category)) - { - return null; - } - - return category; - } - - /// - /// Returns the category with the specified event type id. - /// - public AeEventCategory GetCategory(NodeId typeId) - { - AeEventCategory category = null; - - if (!this.m_eventTypes.TryGetValue(typeId, out category)) - { - return null; - } - - return category; - } - - /// - /// Returns the attribute with the specified attribute id. - /// - public AeEventAttribute GetAttribute(uint attributeId) - { - AeEventAttribute attribute = null; - - if (!m_attributes.TryGetValue(attributeId, out attribute)) - { - return null; - } - - return attribute; - } - - /// - /// Returns the attribute with the specified event type id and browse path. - /// - public AeEventAttribute GetAttribute(NodeId typeId, params string[] browseNames) - { - AeEventCategory category = null; - - if (!this.m_eventTypes.TryGetValue(typeId, out category)) - { - return null; - } - - StringBuilder buffer = new StringBuilder(); - - if (browseNames != null) - { - for (int ii = 0; ii < browseNames.Length; ii++) - { - if (buffer.Length > 0) - { - buffer.Append('/'); - } - - buffer.Append(browseNames[ii]); - } - } - - string targetPath = buffer.ToString(); - - if (!String.IsNullOrEmpty(targetPath)) - { - for (int ii = 0; ii < category.Attributes.Count; ii++) - { - if (category.Attributes[ii].BrowsePathDisplayText == targetPath) - { - return category.Attributes[ii]; - } - } - } - - return null; - } - - /// - /// Gets the list of categories for the specified event types. - /// - public List GetAttributes(uint categoryId) - { - AeEventCategory category = null; - - if (!m_categories.TryGetValue(categoryId, out category)) - { - return null; - } - - List attributes = new List(); - - AeEventCategory subType = category; - - while (subType != null) - { - for (int ii = 0; ii < subType.Attributes.Count; ii++) - { - AeEventAttribute attribute = subType.Attributes[ii]; - - if (attribute.OverriddenDeclaration == null) - { - if (!attribute.Hidden) - { - attributes.Add(attribute); - } - } - } - - AeEventCategory superType = null; - - if (!m_eventTypes.TryGetValue(subType.SuperTypeId, out superType)) - { - break; - } - - subType = superType; - } - - attributes.Sort(CompareAttributes); - return attributes; - } - - #region Private Methods - /// - /// Uses the description to compare two categories. - /// - private static int CompareCategories(AeEventCategory x, AeEventCategory y) - { - if (Object.ReferenceEquals(x, y)) - { - return 0; - } - - if (Object.ReferenceEquals(x, null)) - { - return (Object.ReferenceEquals(y, null))?0:-1; - } - - return x.Description.CompareTo(y.Description); - } - - /// - /// Uses the BrowsePathDisplayText to compare two attributes. - /// - private static int CompareAttributes(AeEventAttribute x, AeEventAttribute y) - { - if (Object.ReferenceEquals(x, y)) - { - return 0; - } - - if (Object.ReferenceEquals(x, null)) - { - return (Object.ReferenceEquals(y, null)) ? 0 : -1; - } - - return x.BrowsePathDisplayText.CompareTo(y.BrowsePathDisplayText); - } - - /// - /// Indexes the well known subtypes. - /// - private void IndexWellKnownTypes() - { - SystemContext context = new SystemContext(); - context.EncodeableFactory = m_session.MessageContext.Factory; - context.NamespaceUris = m_session.NamespaceUris; - context.ServerUris = m_session.ServerUris; - - NodeStateCollection predefinedNodes = new NodeStateCollection(); - predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.Stack.Generated.Opc.Ua.PredefinedNodes.uanodes", typeof(NodeState).Assembly, true); - - NodeIdDictionary types = new NodeIdDictionary(); - - // collect the instance declarations for all types. - for (int ii = 0; ii < predefinedNodes.Count; ii++) - { - BaseTypeState type = predefinedNodes[ii] as BaseTypeState; - - if (type != null) - { - types.Add(type.NodeId, type); - } - } - - // index only those types which are subtypes of BaseEventType. - foreach (BaseTypeState type in types.Values) - { - BaseTypeState subType = type; - BaseTypeState superType = null; - - int eventType = 0; - - while (subType != null) - { - if (subType.NodeId == Opc.Ua.ObjectTypeIds.ConditionType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.ConditionType) - { - eventType = OpcRcw.Ae.Constants.CONDITION_EVENT; - } - - else if (subType.NodeId == Opc.Ua.ObjectTypeIds.AuditEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.AuditEventType) - { - eventType = OpcRcw.Ae.Constants.TRACKING_EVENT; - } - - else if (subType.NodeId == Opc.Ua.ObjectTypeIds.BaseEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.BaseEventType) - { - eventType = OpcRcw.Ae.Constants.SIMPLE_EVENT; - } - - // found an event, collect the attribute and index it. - if (eventType != 0) - { - List declarations = new List(); - Dictionary map = new Dictionary(); - - ComAeUtils.CollectInstanceDeclarations( - m_session, - this, - type, - null, - declarations, - map); - - AeEventCategory declaration = new AeEventCategory(); - declaration.TypeId = type.NodeId; - declaration.SuperTypeId = type.SuperTypeId; - declaration.EventType = eventType; - declaration.Description = (LocalizedText.IsNullOrEmpty(type.DisplayName))?type.BrowseName.Name:type.DisplayName.Text; - declaration.Attributes = declarations; - m_eventTypes[declaration.TypeId] = declaration; - break; - } - - // follow the tree to the parent. - if (!types.TryGetValue(subType.SuperTypeId, out superType)) - { - break; - } - - subType = superType; - } - } - - // hide the built in attributes. - AeEventCategory category = GetCategory(Opc.Ua.ObjectTypeIds.BaseEventType); - - if (category != null) - { - for (int ii = 0; ii < category.Attributes.Count; ii++) - { - switch (category.Attributes[ii].BrowsePathDisplayText) - { - case Opc.Ua.BrowseNames.Message: - case Opc.Ua.BrowseNames.Severity: - case Opc.Ua.BrowseNames.SourceName: - case Opc.Ua.BrowseNames.Time: - case Opc.Ua.BrowseNames.ReceiveTime: - case Opc.Ua.BrowseNames.LocalTime: - { - category.Attributes[ii].Hidden = true; - break; - } - } - } - } - } - - /// - /// Recursively populates the event types table. - /// - private void IndexTypesFromServer(NodeId baseTypeId, int eventType) - { - // check if event type needs to be revised. - if (baseTypeId == Opc.Ua.ObjectTypeIds.ConditionType) - { - eventType = OpcRcw.Ae.Constants.CONDITION_EVENT; - } - - else if (baseTypeId == Opc.Ua.ObjectTypeIds.AuditEventType) - { - eventType = OpcRcw.Ae.Constants.TRACKING_EVENT; - } - - else if (baseTypeId == Opc.Ua.ObjectTypeIds.BaseEventType) - { - eventType = OpcRcw.Ae.Constants.SIMPLE_EVENT; - } - - // browse for subtypes. - BrowseDescription nodeToBrowse = new BrowseDescription(); - nodeToBrowse.NodeId = baseTypeId; - nodeToBrowse.BrowseDirection = BrowseDirection.Forward; - nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasSubtype; - nodeToBrowse.IncludeSubtypes = false; - nodeToBrowse.NodeClassMask = (uint)NodeClass.ObjectType; - nodeToBrowse.ResultMask = (uint)(BrowseResultMask.BrowseName | BrowseResultMask.DisplayName | BrowseResultMask.NodeClass); - - ReferenceDescriptionCollection references = ComAeUtils.Browse( - m_session, - nodeToBrowse, - false); - - for (int ii = 0; ii < references.Count; ii++) - { - // these types have t - if (references[ii].NodeId.IsAbsolute) - { - continue; - } - - NodeId typeId = (NodeId)references[ii].NodeId; - - if (!m_eventTypes.ContainsKey(typeId)) - { - // collection the instances declared by the type. - List declarations = new List(); - Dictionary map = new Dictionary(); - - ComAeUtils.CollectInstanceDeclarations( - m_session, - this, - (NodeId)references[ii].NodeId, - null, - declarations, - map); - - AeEventCategory declaration = new AeEventCategory(); - declaration.TypeId = (NodeId)references[ii].NodeId; - declaration.SuperTypeId = baseTypeId; - declaration.EventType = eventType; - declaration.Description = (LocalizedText.IsNullOrEmpty(references[ii].DisplayName)) ? references[ii].BrowseName.Name : references[ii].DisplayName.Text; - declaration.Attributes = declarations; - m_eventTypes[declaration.TypeId] = declaration; - } - - // recursively look for subtypes. - IndexTypesFromServer(typeId, eventType); - } - } - - /// - /// Assigns a locally unique numeric id to each event type. - /// - private void UpdateEventTypeMappings(NodeIdMappingSet mappingSet) - { - NodeIdMappingCollection mappingsToKeep = new NodeIdMappingCollection(); - Dictionary categories = new Dictionary(); - - for (int ii = 0; ii < mappingSet.Mappings.Count; ii++) - { - NodeIdMapping mapping = mappingSet.Mappings[ii]; - - try - { - // need to convert the cached type id to a remote id. - NodeId localId = NodeId.Parse(mapping.NodeId); - NodeId remoteId = this.GetRemoteNodeId(localId); - - AeEventCategory eventType = null; - - if (m_eventTypes.TryGetValue(remoteId, out eventType)) - { - // check if the event already has an id. - if (eventType.LocalId == 0) - { - // must update the saved integer id. - if (!categories.ContainsKey(mapping.IntegerId)) - { - eventType.LocalId = mapping.IntegerId; - categories[eventType.LocalId] = eventType; - mappingsToKeep.Add(mapping); - } - - // must assign a new one if a duplicate found. - else - { - eventType.LocalId = 0; - } - } - } - } - catch (Exception) - { - // discard invalid mappings. - } - } - - // assign ids to any types which do not have mappings. - uint nextId = 1; - - foreach (AeEventCategory eventType in m_eventTypes.Values) - { - if (eventType.LocalId == 0) - { - // find a unique id. - while (categories.ContainsKey(nextId)) nextId++; - - // assign the id. - eventType.LocalId = nextId; - categories[eventType.LocalId] = eventType; - - // save the mapping. - NodeIdMapping mapping = new NodeIdMapping(); - mapping.IntegerId = nextId; - mapping.NodeId = this.GetLocalNodeId(eventType.TypeId).ToString(); - - mappingsToKeep.Add(mapping); - } - } - - // update mappings. - mappingSet.Mappings = mappingsToKeep; - m_categories = categories; - } - - /// - /// Assigns a locally unique numeric id to each event type. - /// - private void UpdateEventAttributeMappings(NodeIdMappingSet mappingSet) - { - NodeIdMappingCollection mappingsToKeep = new NodeIdMappingCollection(); - - // collect all unique declarations. - List list = new List(); - - foreach (AeEventCategory type in m_eventTypes.Values) - { - for (int ii = 0; ii < type.Attributes.Count; ii++) - { - AeEventAttribute declaration = type.Attributes[ii]; - - // only variables can be attributes. - if (declaration.NodeClass != NodeClass.Variable) - { - continue; - } - - // need to link attributes to any attributes that they override. - AeEventCategory subType = type; - AeEventCategory superType = null; - - while (subType != null) - { - if (NodeId.IsNull(subType.SuperTypeId) || subType.TypeId == subType.SuperTypeId || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.BaseObjectType) - { - list.Add(declaration); - break; - } - - if (!m_eventTypes.TryGetValue(subType.SuperTypeId, out superType)) - { - break; - } - - for (int jj = 0; jj < superType.Attributes.Count; jj++) - { - if (superType.Attributes[jj].BrowsePathDisplayText == declaration.BrowsePathDisplayText) - { - declaration.OverriddenDeclaration = superType.Attributes[jj]; - declaration = declaration.OverriddenDeclaration; - break; - } - } - - subType = superType; - } - } - } - - // look up ids for all attributes in master list. - Dictionary attributes = new Dictionary(); - - for (int ii = 0; ii < list.Count; ii++) - { - AeEventAttribute declaration = list[ii]; - - for (int jj = 0; jj < mappingSet.Mappings.Count; jj++) - { - NodeIdMapping mapping = mappingSet.Mappings[jj]; - - try - { - // browse display paths always use local namespa indexes. - if (declaration.BrowsePathDisplayText != mapping.BrowePath) - { - continue; - } - - // need to convert the cached type id to a remote id. - NodeId localId = NodeId.Parse(mapping.NodeId); - NodeId remoteId = this.GetRemoteNodeId(localId); - - if (declaration.RootTypeId != remoteId) - { - continue; - } - - // must update the saved integer id. - if (!attributes.ContainsKey(mapping.IntegerId)) - { - declaration.LocalId = mapping.IntegerId; - attributes[declaration.LocalId] = declaration; - mappingsToKeep.Add(mapping); - } - - // must assign a new one if a duplicate found. - else - { - declaration.LocalId = 0; - } - } - catch (Exception) - { - // ignore invalid mappings. - } - } - } - - // assign new ids. - uint nextId = 1; - - for (int ii = 0; ii < list.Count; ii++) - { - AeEventAttribute declaration = list[ii]; - - if (declaration.LocalId == 0) - { - // find a unique id. - while (attributes.ContainsKey(nextId)) nextId++; - - // assign the id. - declaration.LocalId = nextId; - attributes[declaration.LocalId] = declaration; - - // save the mapping. - NodeIdMapping mapping = new NodeIdMapping(); - mapping.IntegerId = nextId; - mapping.NodeId = this.GetLocalNodeId(declaration.RootTypeId).ToString(); - mapping.BrowePath = declaration.BrowsePathDisplayText; - - mappingsToKeep.Add(mapping); - } - } - - // update mapping set. - mappingSet.Mappings = mappingsToKeep; - m_attributes = attributes; - } - #endregion - - #region Private Fields - private Session m_session; - private NodeIdDictionary m_eventTypes; - private Dictionary m_categories; - private Dictionary m_attributes; - #endregion - } -} diff --git a/ComIOP/Common/Server/Ae2/ComAeProxy.cs b/ComIOP/Common/Server/Ae2/ComAeProxy.cs deleted file mode 100644 index 8cc22f117..000000000 --- a/ComIOP/Common/Server/Ae2/ComAeProxy.cs +++ /dev/null @@ -1,262 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// A base class for classes that implement an OPC COM specification. - /// - public class ComAe2Proxy : ComProxy - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComAe2Proxy() - { - m_mapper = new ComAeNamespaceMapper(); - m_subscriptions = new List(); - m_conditionManager = new AeConditionManager(); - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (!m_disposed) - { - if (disposing) - { - lock (m_subscriptions) - { - for (int ii = 0; ii < m_subscriptions.Count; ii++) - { - m_subscriptions[ii].Dispose(); - } - - m_subscriptions.Clear(); - } - - if (m_browser != null) - { - m_browser.Dispose(); - m_browser = null; - } - - m_mapper = null; - } - - m_disposed = true; - } - - base.Dispose(disposing); - } - - private bool m_disposed = false; - #endregion - - #region Overridden Methods - /// - /// Called when a new session is created. - /// - protected override void OnSessionCreated() - { - lock (Lock) - { - // fetch the configuration. - m_configuration = Endpoint.ParseExtension(null); - - if (m_configuration == null) - { - m_configuration = new ComAe2ProxyConfiguration(); - } - - Session session = Session; - - // update the mapping and pass the new session to other objects. - m_mapper.Initialize(session, m_configuration); - - // save the configuration. - Endpoint.UpdateExtension(null, m_configuration); - SaveConfiguration(); - - // create the browser. - m_browser = new ComAe2Browser(this, m_configuration, m_mapper); - m_conditionManager.Initialize(); - } - } - - /// - /// Called when a session is reconnected. - /// - protected override void OnSessionReconected() - { - lock (m_subscriptions) - { - for (int ii = 0; ii < m_subscriptions.Count; ii++) - { - m_subscriptions[ii].OnSessionReconected(Session); - } - } - } - #endregion - - /// - /// Gets the last update time. - /// - public DateTime LastUpdateTime - { - get - { - DateTime latest = DateTime.MinValue; - - lock (m_subscriptions) - { - for (int ii = 0; ii < m_subscriptions.Count; ii++) - { - DateTime time = m_subscriptions[ii].LastUpdateTime; - - if (time > latest) - { - latest = time; - } - } - } - - return latest; - } - } - - /// - /// Gets the supported event categories. - /// - public List QueryEventCategories(int eventType) - { - ThrowIfNotConnected(); - return m_mapper.GetCategories(eventType); - } - - /// - /// Gets the supported event attributes. - /// - public List QueryEventAttributes(uint categoryId) - { - ThrowIfNotConnected(); - return m_mapper.GetAttributes(categoryId); - } - - /// - /// Creates a new area browser. - /// - public ComAe2Browser CreateBrowser() - { - ThrowIfNotConnected(); - return new ComAe2Browser(this, m_configuration, m_mapper); - } - - /// - /// Creates a new event subscription. - /// - public ComAe2Subscription CreateSubscription() - { - ThrowIfNotConnected(); - - ComAe2Subscription subscription = new ComAe2Subscription(this, m_configuration, m_mapper, m_browser, m_conditionManager); - - lock (m_subscriptions) - { - m_subscriptions.Add(subscription); - } - - return subscription; - } - - /// - /// Called when a subscription is deleted. - /// - public void SubscriptionDeleted(ComAe2Subscription subscription) - { - lock (m_subscriptions) - { - for (int ii = 0; ii < m_subscriptions.Count; ii++) - { - if (Object.ReferenceEquals(subscription, m_subscriptions[ii])) - { - m_subscriptions.RemoveAt(ii); - break; - } - } - } - } - - /// - /// Checks that the source node exists. - /// - public bool IsSourceValid(string sourceId) - { - ThrowIfNotConnected(); - return m_browser.IsValidQualifiedName(sourceId, false); - } - - /// - /// Acknowledges one or more events. - /// - public int[] AcknowledgeEvents( - string comment, - string acknowledgerId, - AeAcknowledgeRequest[] requests) - { - ThrowIfNotConnected(); - return m_conditionManager.AcknowledgeEvents(Session, comment, acknowledgerId, requests); - } - - #region Private Fields - private ComAe2ProxyConfiguration m_configuration; - private ComAeNamespaceMapper m_mapper; - private List m_subscriptions; - private ComAe2Browser m_browser; - private AeConditionManager m_conditionManager; - #endregion - } -} diff --git a/ComIOP/Common/Server/Ae2/ComAeProxyConfiguration.cs b/ComIOP/Common/Server/Ae2/ComAeProxyConfiguration.cs deleted file mode 100644 index 12adae4e1..000000000 --- a/ComIOP/Common/Server/Ae2/ComAeProxyConfiguration.cs +++ /dev/null @@ -1,79 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.ServiceModel; -using System.Runtime.Serialization; -using System.Collections.Generic; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores the configuration for UA that wraps a COM server. - /// - [DataContract(Namespace = Namespaces.ComInterop)] - public class ComAe2ProxyConfiguration : ComProxyConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public ComAe2ProxyConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - UseOnlyBuiltInTypes = false; - } - #endregion - - #region Public Properties - /// - /// Gets or sets a flag indicating that only built in types should be used. - /// - [DataMember(Order = 1)] - public bool UseOnlyBuiltInTypes { get; set; } - #endregion - } -} diff --git a/ComIOP/Common/Server/Ae2/ComAeSubscription.cs b/ComIOP/Common/Server/Ae2/ComAeSubscription.cs deleted file mode 100644 index 2a5d21079..000000000 --- a/ComIOP/Common/Server/Ae2/ComAeSubscription.cs +++ /dev/null @@ -1,1116 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Ae; - -namespace Opc.Ua.Com.Server -{ - /// - /// A base class for classes that implement an OPC COM specification. - /// - public class ComAe2Subscription : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComAe2Subscription( - ComAe2Proxy server, - ComAe2ProxyConfiguration configuration, - ComAeNamespaceMapper mapper, - ComAe2Browser browser, - AeConditionManager conditionManager) - { - m_server = server; - m_configuration = configuration; - m_mapper = mapper; - m_browser = browser; - m_conditionManager = conditionManager; - m_filter = new AeEventFilter(m_mapper); - m_queue = new Queue(); - m_notifiers = new NodeIdDictionary(); - m_sourceNodes = new List(); - - // set a default filters. - m_filter.SetFilter(Constants.ALL_EVENTS, 0, UInt16.MaxValue, null, null); - UpdateAreaFilter(null); - UpdateSourceFilter(null); - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (!m_disposed) - { - if (disposing) - { - lock (m_lock) - { - if (m_subscription != null) - { - m_subscription.Dispose(); - m_subscription = null; - } - - if (m_callbackTimer != null) - { - m_callbackTimer.Dispose(); - m_callbackTimer = null; - } - } - - m_notifiers = null; - m_browser = null; - m_mapper = null; - m_callback = null; - m_server = null; - } - - m_disposed = true; - } - } - - /// - /// Throws if disposed. - /// - private void ThrowIfDisposed() - { - if (m_disposed) - { - throw new ObjectDisposedException(GetType().Name); - } - } - #endregion - - #region Public Members - /// - /// Gets or sets the handle. - /// - /// The handle. - public IntPtr Handle - { - get { return m_handle; } - set { m_handle = value; } - } - - /// - /// Gets the current active state. - /// - public bool Active { get; set; } - - /// - /// Gets the maximum callback size. - /// - public uint MaxSize { get; set; } - - /// - /// Gets the buffer time. - /// - public uint BufferTime { get; set; } - - /// - /// Gets the client handle. - /// - public uint ClientHandle { get; set; } - - /// - /// Gets the keep alive. - /// - public uint KeepAlive { get; private set; } - - /// - /// Gets the last update time. - /// - public DateTime LastUpdateTime - { - get - { - DateTime lastUpdateTime; - - lock (m_lock) - { - lastUpdateTime = m_lastUpdateTime; - } - - return lastUpdateTime; - } - } - - /// - /// Gets the actual maximum callback size. - /// - public uint ActualMaxSize - { - get - { - if (m_subscription != null) - { - return m_subscription.MaxNotificationsPerPublish; - } - - return MaxSize; - } - } - - /// - /// Gets the actual buffer time. - /// - public uint ActualBufferTime - { - get - { - if (m_subscription != null) - { - return (uint)m_subscription.CurrentPublishingInterval; - } - - return (uint)Math.Max(BufferTime, 1000); - } - } - - /// - /// Sets the keep alive rate. - /// - public uint SetKeepAlive(uint keepAlive) - { - lock (m_lock) - { - if (keepAlive > 0) - { - uint sampleTime = ActualBufferTime; - uint ratio = (uint)Math.Truncate(((double)keepAlive)/sampleTime); - keepAlive = Math.Max(sampleTime*ratio, sampleTime); - } - - KeepAlive = keepAlive; - m_keepAliveCount = 1; - } - - return KeepAlive; - } - - /// - /// Sets the callback. - /// - /// The callback. - public void SetCallback(IComAeEventCallback callback) - { - ThrowIfDisposed(); - - lock (m_lock) - { - if (m_callback != null) - { - m_callback.Dispose(); - m_callback = null; - } - - m_callback = callback; - } - } - - /// - /// Applies any changes to the subscription. - /// - public void ApplyChanges() - { - ThrowIfDisposed(); - - lock (m_lock) - { - if (m_subscription == null) - { - CreateSubscription(); - } - else - { - ModifySubscription(); - } - - if (m_callbackTimer != null) - { - m_callbackTimer.Dispose(); - m_callbackTimer = null; - } - - if (Active) - { - // adjust keep alive to reflect current settings. - SetKeepAlive(KeepAlive); - - // start a callabck thread. - m_callbackTimer = new Timer(DoProcessQueue, null, 0, (long)ActualBufferTime); - } - } - } - - /// - /// Updates the object after a reconnect. - /// - public void OnSessionReconected(Session session) - { - ThrowIfDisposed(); - - lock (m_lock) - { - foreach (Subscription subscription in session.Subscriptions) - { - if (Object.ReferenceEquals(this, subscription.Handle)) - { - m_subscription = subscription; - m_notifiers = new NodeIdDictionary(); - - foreach (MonitoredItem monitoredItem in subscription.MonitoredItems) - { - m_notifiers[monitoredItem.StartNodeId] = monitoredItem; - } - - break; - } - } - } - } - - /// - /// Sets the event filter. - /// - 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 areasToUse = new List(); - - if (areas != null) - { - for (int ii = 0; ii < areas.Length; ii++) - { - List areaIds = m_browser.SearchByQualifiedName(areas[ii], true); - - if (areaIds.Count == 0) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - areasToUse.AddRange(areaIds); - } - } - - // validate sources. - List sourcesToUse = new List(); - - if (sources != null) - { - for (int ii = 0; ii < sources.Length; ii++) - { - List 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); - } - } - - /// - /// Updates the list of area filters. - /// - private void UpdateAreaFilter(List areas) - { - // check if monitoring all events. - if (areas == null || areas.Count == 0) - { - MonitoredItem monitoredItem = null; - - if (!m_notifiers.TryGetValue(Opc.Ua.ObjectIds.Server, out monitoredItem)) - { - monitoredItem = CreateMonitoredItem(Opc.Ua.ObjectIds.Server); - } - - m_notifiers.Clear(); - m_notifiers[Opc.Ua.ObjectIds.Server] = monitoredItem; - return; - } - - // build table of areas to monitor. - NodeIdDictionary notifiers = new NodeIdDictionary(); - - // map all of the area search strings onto NodeIds for notifiers. - for (int ii = 0; ii < areas.Count; ii++) - { - NodeId areaId = areas[ii]; - - // check for existing item. - MonitoredItem monitoredItem = null; - - if (m_notifiers.TryGetValue(areaId, out monitoredItem)) - { - notifiers[areaId] = monitoredItem; - continue; - } - - // check for new item. - if (!notifiers.ContainsKey(areaId)) - { - notifiers[areaId] = CreateMonitoredItem(areaId); - } - } - - // mark unused items for deletion. - foreach (MonitoredItem monitoredItem in m_notifiers.Values) - { - if (!notifiers.ContainsKey(monitoredItem.StartNodeId)) - { - m_subscription.RemoveItem(monitoredItem); - } - } - - m_notifiers = notifiers; - } - - /// - /// Updates the list of source filters. - /// - private void UpdateSourceFilter(List sources) - { - m_sourceNodes.Clear(); - - if (sources != null && sources.Count > 0) - { - for (int ii = 0; ii < sources.Count; ii++) - { - NodeId sourceId = sources[ii]; - - if (!m_sourceNodes.Contains(sourceId)) - { - m_sourceNodes.Add(sourceId); - } - } - } - } - - /// - /// Creates a new monitored item and adds it to the subscription. - /// - private MonitoredItem CreateMonitoredItem(NodeId notifierId) - { - MonitoredItem monitoredItem = new MonitoredItem(); - - monitoredItem.DisplayName = null; - monitoredItem.StartNodeId = notifierId; - monitoredItem.RelativePath = null; - monitoredItem.NodeClass = NodeClass.Object; - monitoredItem.AttributeId = Attributes.EventNotifier; - monitoredItem.IndexRange = null; - monitoredItem.Encoding = null; - monitoredItem.MonitoringMode = MonitoringMode.Reporting; - monitoredItem.SamplingInterval = 0; - monitoredItem.QueueSize = UInt32.MaxValue; - monitoredItem.DiscardOldest = true; - - return monitoredItem; - } - - /// - /// Get the event filter parameters. - /// - public void GetFilter( - out int eventTypes, - out ushort lowSeverity, - out ushort highSeverity, - out uint[] categoryIds, - out string[] areas, - out string[] sources) - { - ThrowIfDisposed(); - - lock (m_lock) - { - eventTypes = m_filter.EventTypes; - lowSeverity = m_filter.LowSeverity; - highSeverity = m_filter.HighSeverity; - categoryIds = m_filter.RequestedCategoryIds; - areas = m_areas; - sources = m_sources; - } - } - - /// - /// Selects the attributes for the event category. - /// - public void SelectAttributes( - uint categoryId, - uint[] attributeIds) - { - ThrowIfDisposed(); - - lock (m_lock) - { - if (!m_filter.SelectAttributes(categoryId, attributeIds)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - } - } - - /// - /// Returns the currently selected attributes. - /// - public uint[] GetSelectedAttributes(uint categoryId) - { - ThrowIfDisposed(); - - lock (m_lock) - { - if (m_mapper.GetCategory(categoryId) == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - uint[] attributeIds = null; - - if (m_filter.RequestedAttributeIds != null) - { - m_filter.RequestedAttributeIds.TryGetValue(categoryId, out attributeIds); - } - - return attributeIds; - } - } - - /// - /// Initiates of refresh of all conditions. - /// - public void Refresh() - { - ThrowIfDisposed(); - - lock (m_lock) - { - if (m_refreshQueue != null) - { - throw ComUtils.CreateComException(ResultIds.E_BUSY); - } - - m_refreshQueue = new Queue(); - - // turn on publishing first. - if (!Active) - { - m_subscription.SetPublishingMode(true); - List itemsToUpdate = new List(m_notifiers.Values); - m_subscription.SetMonitoringMode(MonitoringMode.Reporting, itemsToUpdate); - } - - m_subscription.ConditionRefresh(); - } - } - - /// - /// Cancels a previous refresh. - /// - public void CancelRefresh() - { - ThrowIfDisposed(); - - lock (m_lock) - { - if (m_refreshQueue == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - m_refreshQueue = null; - - // send an empty callback. - ThreadPool.QueueUserWorkItem(DoRefresh, null); - - // turn off publishing when done. - if (!Active) - { - m_subscription.SetPublishingMode(false); - List itemsToUpdate = new List(m_notifiers.Values); - m_subscription.SetMonitoringMode(MonitoringMode.Disabled, itemsToUpdate); - } - } - } - #endregion - - #region Private Methods - /// - /// Creates the subscription. - /// - private void CreateSubscription() - { - if (m_subscription != null) - { - m_subscription.Dispose(); - m_subscription = null; - } - - // get the current session. - Session session = m_server.Session; - - if (session == null) - { - return; - } - - // create the subscription. - m_subscription = new Subscription(); - m_subscription.PublishingEnabled = Active; - m_subscription.PublishingInterval = (int)Math.Max(BufferTime, 1000); - m_subscription.KeepAliveCount = (uint)Math.Max(Math.Ceiling(((double)KeepAlive)/m_subscription.PublishingInterval), 10); - m_subscription.LifetimeCount = m_subscription.KeepAliveCount*3; - m_subscription.MaxNotificationsPerPublish = MaxSize; - m_subscription.TimestampsToReturn = TimestampsToReturn.Neither; - m_subscription.Priority = 0; - m_subscription.FastEventCallback = OnEventNotification; - m_subscription.DisableMonitoredItemCache = true; - - session.AddSubscription(m_subscription); - m_subscription.Create(); - - // update the monitored items. - EventFilter filter = m_filter.GetFilter(); - MonitoringMode monitoringMode = (Active)?MonitoringMode.Reporting:MonitoringMode.Disabled; - - foreach (MonitoredItem monitoredItem in m_notifiers.Values) - { - monitoredItem.Filter = filter; - monitoredItem.MonitoringMode = monitoringMode; - m_subscription.AddItem(monitoredItem); - } - - m_subscription.ApplyChanges(); - } - - /// - /// Modifies a subscription. - /// - private void ModifySubscription() - { - // turn off publishing first. - if (!Active && m_subscription.CurrentPublishingEnabled) - { - m_subscription.SetPublishingMode(false); - } - - m_subscription.PublishingInterval = (int)Math.Max(BufferTime, 1000); - m_subscription.KeepAliveCount = (uint)Math.Max(Math.Ceiling(((double)KeepAlive)/m_subscription.PublishingInterval), 10); - m_subscription.LifetimeCount = m_subscription.KeepAliveCount * 3; - m_subscription.MaxNotificationsPerPublish = MaxSize; - m_subscription.TimestampsToReturn = TimestampsToReturn.Neither; - m_subscription.Priority = 0; - m_subscription.Modify(); - - // update the monitored items. - EventFilter filter = m_filter.GetFilter(); - MonitoringMode monitoringMode = (Active)?MonitoringMode.Reporting:MonitoringMode.Disabled; - - List itemsToUpdate = new List(); - - foreach (MonitoredItem monitoredItem in m_notifiers.Values) - { - monitoredItem.Filter = filter; - - if (!monitoredItem.Created) - { - monitoredItem.MonitoringMode = monitoringMode; - m_subscription.AddItem(monitoredItem); - } - else - { - if (monitoredItem.MonitoringMode != monitoringMode) - { - itemsToUpdate.Add(monitoredItem); - } - } - } - - m_subscription.ApplyChanges(); - m_subscription.SetMonitoringMode(monitoringMode, itemsToUpdate); - - // turn on publishing last. - if (Active && !m_subscription.CurrentPublishingEnabled) - { - m_subscription.SetPublishingMode(true); - } - } - - private void OnEventNotification(Subscription subscription, EventNotificationList notification, IList stringTable) - { - try - { - // check if disposed. - if (m_disposed) - { - return; - } - - // check if session still active. - Session session = m_server.Session; - - if (session == null || !session.Connected) - { - return; - } - - // check if events are being reported. - if (m_callback == null) - { - return; - } - - lock (m_lock) - { - foreach (EventFieldList e in notification.Events) - { - // translate the notification and send the response. - AeEvent e2 = m_filter.TranslateNotification(m_server.Session, e); - - if (e2 != null) - { - // check if refresh has started. - if (e2.EventType == Opc.Ua.ObjectTypeIds.RefreshStartEventType) - { - m_refreshInProgress = true; - continue; - } - - // check if refresh has ended. - if (e2.EventType == Opc.Ua.ObjectTypeIds.RefreshEndEventType) - { - m_refreshInProgress = false; - - // turn off publishing if the subscription is not active, - if (!Active) - { - m_subscription.SetPublishingMode(false); - List itemsToUpdate = new List(m_notifiers.Values); - m_subscription.SetMonitoringMode(MonitoringMode.Disabled, itemsToUpdate); - } - - if (m_refreshQueue != null) - { - ThreadPool.QueueUserWorkItem(DoRefresh, m_refreshQueue); - } - - continue; - } - - // cache any conditions requiring acknowledgement. - m_conditionManager.ProcessEvent(e2); - - // queue on refresh. - if (m_refreshInProgress) - { - if (m_refreshQueue != null) - { - m_refreshQueue.Enqueue(e2); - } - - continue; - } - - // queue the event. - if (Active) - { - lock (m_queue) - { - m_queue.Enqueue(e2); - } - } - } - } - } - } - catch (Exception exception) - { - Utils.Trace(exception, "Error processing event callback."); - } - } - - /// - /// Sends the queued events in blocks. - /// - private void SendInBlocks(IComAeEventCallback callback, Queue events, uint blockSize, bool refreshFlag) - { - if (callback == null) - { - return; - } - - if (blockSize == 0) - { - blockSize = (uint)events.Count; - } - - while (events.Count > 0) - { - List eventsInBlock = new List(); - - try - { - for (int ii = 0; ii < blockSize && events.Count > 0; ii++) - { - // warning - Translate() allocates unmanaged memory that is deleted in the finally block. - eventsInBlock.Add(Translate(events.Dequeue())); - } - - // invoke callback. - callback.OnEvent( - ClientHandle, - refreshFlag, - (refreshFlag)?events.Count == 0:false, - eventsInBlock.ToArray()); - } - finally - { - // must deallocate attributes on exit. - for (int ii = 0; ii < eventsInBlock.Count; ii++) - { - IntPtr pAttributes = eventsInBlock[ii].pEventAttributes; - ComUtils.GetVARIANTs(ref pAttributes, eventsInBlock[ii].dwNumEventAttrs, true); - } - } - } - } - - /// - /// Cslled to send refresh events to client. - /// - private void DoRefresh(object state) - { - try - { - // check if disposed. - if (m_disposed) - { - return; - } - - // send a dummy callback after a cancel. - if (state == null) - { - IComAeEventCallback callback = m_callback; - - if (callback != null) - { - callback.OnEvent( - ClientHandle, - true, - true, - null); - } - - return; - } - - Queue eventsToSend = null; - - lock (m_lock) - { - // check if refresh has been cancelled. - if (!Object.ReferenceEquals(state, m_refreshQueue)) - { - return; - } - - // clear the queue to indicate operation is complete. - eventsToSend = m_refreshQueue; - m_refreshQueue = null; - } - - // send the events to client. - SendInBlocks(m_callback, eventsToSend, MaxSize, true); - } - catch (Exception exception) - { - Utils.Trace(exception, "Error processing refresh callback."); - } - } - - /// - /// Called send events to client. - /// - private void DoProcessQueue(object state) - { - Queue events = new Queue(); - - try - { - // check if disposed. - if (m_disposed) - { - return; - } - - // process the queue. - lock (m_queue) - { - while (m_queue.Count > 0) - { - events.Enqueue(m_queue.Dequeue()); - } - } - - // check if time for a keep alive. - lock (m_lock) - { - // check if time for keep alive. - if (events.Count == 0) - { - if (KeepAlive == 0 || m_lastUpdateTime.AddMilliseconds(KeepAlive*m_keepAliveCount) > DateTime.UtcNow) - { - return; - } - } - - // no keep alives if not active. - if (!Active) - { - return; - } - - // update counters. - if (events.Count > 0) - { - m_lastUpdateTime = DateTime.UtcNow; - m_keepAliveCount = 1; - } - else - { - m_keepAliveCount++; - } - } - - // send a keep alive callback. - if (events.Count == 0) - { - IComAeEventCallback callback = m_callback; - - if (callback != null) - { - callback.OnEvent( - ClientHandle, - false, - false, - null); - } - - return; - } - - // send the events to client. - SendInBlocks(m_callback, events, MaxSize, false); - } - catch (Exception exception) - { - Utils.Trace(exception, "Error processing event callback."); - } - } - - /// - /// Marshals an event for return to the client. - /// - 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; - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private bool m_disposed; - private IntPtr m_handle; - private ComAe2Proxy m_server; - private ComAe2ProxyConfiguration m_configuration; - private ComAeNamespaceMapper m_mapper; - private ComAe2Browser m_browser; - private AeConditionManager m_conditionManager; - private IComAeEventCallback m_callback; - private AeEventFilter m_filter; - private string[] m_areas; - private string[] m_sources; - private NodeIdDictionary m_notifiers; - private List m_sourceNodes; - private Subscription m_subscription; - private Queue m_queue; - private bool m_refreshInProgress; - private Queue m_refreshQueue; - private Timer m_callbackTimer; - private DateTime m_lastUpdateTime; - private uint m_keepAliveCount; - #endregion - } -} diff --git a/ComIOP/Common/Server/Ae2/ComAeUtils.cs b/ComIOP/Common/Server/Ae2/ComAeUtils.cs deleted file mode 100644 index 51c31f262..000000000 --- a/ComIOP/Common/Server/Ae2/ComAeUtils.cs +++ /dev/null @@ -1,813 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Defines numerous functions used to browse the UA server event mode. - /// - public static class ComAeUtils - { - /// - /// Browses the address space and returns the references found. - /// - /// The session. - /// The set of browse operations to perform. - /// if set to true a exception will be thrown on an error. - /// - /// The references found. Null if an error occurred. - /// - public static ReferenceDescriptionCollection Browse(Session session, BrowseDescriptionCollection nodesToBrowse, bool throwOnError) - { - try - { - ReferenceDescriptionCollection references = new ReferenceDescriptionCollection(); - BrowseDescriptionCollection unprocessedOperations = new BrowseDescriptionCollection(); - - while (nodesToBrowse.Count > 0) - { - // start the browse operation. - BrowseResultCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.Browse( - null, - null, - 0, - nodesToBrowse, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, nodesToBrowse); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); - - ByteStringCollection continuationPoints = new ByteStringCollection(); - - for (int ii = 0; ii < nodesToBrowse.Count; ii++) - { - // check for error. - if (StatusCode.IsBad(results[ii].StatusCode)) - { - // this error indicates that the server does not have enough simultaneously active - // continuation points. This request will need to be resent after the other operations - // have been completed and their continuation points released. - if (results[ii].StatusCode == StatusCodes.BadNoContinuationPoints) - { - unprocessedOperations.Add(nodesToBrowse[ii]); - } - - continue; - } - - // check if all references have been fetched. - if (results[ii].References.Count == 0) - { - continue; - } - - // save results. - references.AddRange(results[ii].References); - - // check for continuation point. - if (results[ii].ContinuationPoint != null) - { - continuationPoints.Add(results[ii].ContinuationPoint); - } - } - - // process continuation points. - ByteStringCollection revisedContinuationPoints = new ByteStringCollection(); - - while (continuationPoints.Count > 0) - { - // continue browse operation. - session.BrowseNext( - null, - false, - continuationPoints, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, continuationPoints); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); - - for (int ii = 0; ii < continuationPoints.Count; ii++) - { - // check for error. - if (StatusCode.IsBad(results[ii].StatusCode)) - { - continue; - } - - // check if all references have been fetched. - if (results[ii].References.Count == 0) - { - continue; - } - - // save results. - references.AddRange(results[ii].References); - - // check for continuation point. - if (results[ii].ContinuationPoint != null) - { - revisedContinuationPoints.Add(results[ii].ContinuationPoint); - } - } - - // check if browsing must continue; - continuationPoints = revisedContinuationPoints; - } - - // check if unprocessed results exist. - nodesToBrowse = unprocessedOperations; - } - - // return complete list. - return references; - } - catch (Exception exception) - { - if (throwOnError) - { - throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); - } - - return null; - } - } - - /// - /// Browses the address space and returns the references found. - /// - /// The session. - /// The NodeId for the starting node. - /// if set to true a exception will be thrown on an error. - /// - /// The references found. Null if an error occurred. - /// - public static ReferenceDescriptionCollection Browse(Session session, BrowseDescription nodeToBrowse, bool throwOnError) - { - try - { - ReferenceDescriptionCollection references = new ReferenceDescriptionCollection(); - - // construct browse request. - BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); - nodesToBrowse.Add(nodeToBrowse); - - // start the browse operation. - BrowseResultCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.Browse( - null, - null, - 0, - nodesToBrowse, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, nodesToBrowse); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); - - do - { - // check for error. - if (StatusCode.IsBad(results[0].StatusCode)) - { - throw new ServiceResultException(results[0].StatusCode); - } - - // process results. - for (int ii = 0; ii < results[0].References.Count; ii++) - { - references.Add(results[0].References[ii]); - } - - // check if all references have been fetched. - if (results[0].References.Count == 0 || results[0].ContinuationPoint == null) - { - break; - } - - // continue browse operation. - ByteStringCollection continuationPoints = new ByteStringCollection(); - continuationPoints.Add(results[0].ContinuationPoint); - - session.BrowseNext( - null, - false, - continuationPoints, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, continuationPoints); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); - } - while (true); - - //return complete list. - return references; - } - catch (Exception exception) - { - if (throwOnError) - { - throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); - } - - return null; - } - } - - /// - /// Browses the address space and returns all of the supertypes of the specified type node. - /// - /// The session. - /// The NodeId for a type node in the address space. - /// if set to true a exception will be thrown on an error. - /// - /// The references found. Null if an error occurred. - /// - public static ReferenceDescriptionCollection BrowseSuperTypes(Session session, NodeId typeId, bool throwOnError) - { - ReferenceDescriptionCollection supertypes = new ReferenceDescriptionCollection(); - - try - { - // find all of the children of the field. - BrowseDescription nodeToBrowse = new BrowseDescription(); - - nodeToBrowse.NodeId = typeId; - nodeToBrowse.BrowseDirection = BrowseDirection.Inverse; - nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.HasSubtype; - nodeToBrowse.IncludeSubtypes = false; // more efficient to use IncludeSubtypes=False when possible. - nodeToBrowse.NodeClassMask = 0; // the HasSubtype reference already restricts the targets to Types. - nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; - - ReferenceDescriptionCollection references = Browse(session, nodeToBrowse, throwOnError); - - while (references != null && references.Count > 0) - { - // should never be more than one supertype. - supertypes.Add(references[0]); - - // only follow references within this server. - if (references[0].NodeId.IsAbsolute) - { - break; - } - - // get the references for the next level up. - nodeToBrowse.NodeId = (NodeId)references[0].NodeId; - references = Browse(session, nodeToBrowse, throwOnError); - } - - // return complete list. - return supertypes; - } - catch (Exception exception) - { - if (throwOnError) - { - throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); - } - - return null; - } - } - - /// - /// Returns the node ids for a set of relative paths. - /// - /// An open session with the server to use. - /// The starting node for the relative paths. - /// The namespace URIs referenced by the relative paths. - /// The relative paths. - /// A collection of local nodes. - public static List TranslateBrowsePaths( - Session session, - NodeId startNodeId, - NamespaceTable namespacesUris, - params string[] relativePaths) - { - // build the list of browse paths to follow by parsing the relative paths. - BrowsePathCollection browsePaths = new BrowsePathCollection(); - - if (relativePaths != null) - { - for (int ii = 0; ii < relativePaths.Length; ii++) - { - BrowsePath browsePath = new BrowsePath(); - - // The relative paths used indexes in the namespacesUris table. These must be - // converted to indexes used by the server. An error occurs if the relative path - // refers to a namespaceUri that the server does not recognize. - - // The relative paths may refer to ReferenceType by their BrowseName. The TypeTree object - // allows the parser to look up the server's NodeId for the ReferenceType. - - browsePath.RelativePath = RelativePath.Parse( - relativePaths[ii], - session.TypeTree, - namespacesUris, - session.NamespaceUris); - - browsePath.StartingNode = startNodeId; - - browsePaths.Add(browsePath); - } - } - - // make the call to the server. - BrowsePathResultCollection results; - DiagnosticInfoCollection diagnosticInfos; - - ResponseHeader responseHeader = session.TranslateBrowsePathsToNodeIds( - null, - browsePaths, - out results, - out diagnosticInfos); - - // ensure that the server returned valid results. - Session.ValidateResponse(results, browsePaths); - Session.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); - - // collect the list of node ids found. - List nodes = new List(); - - for (int ii = 0; ii < results.Count; ii++) - { - // check if the start node actually exists. - if (StatusCode.IsBad(results[ii].StatusCode)) - { - nodes.Add(null); - continue; - } - - // an empty list is returned if no node was found. - if (results[ii].Targets.Count == 0) - { - nodes.Add(null); - continue; - } - - // Multiple matches are possible, however, the node that matches the type model is the - // one we are interested in here. The rest can be ignored. - BrowsePathTarget target = results[ii].Targets[0]; - - if (target.RemainingPathIndex != UInt32.MaxValue) - { - nodes.Add(null); - continue; - } - - // The targetId is an ExpandedNodeId because it could be node in another server. - // The ToNodeId function is used to convert a local NodeId stored in a ExpandedNodeId to a NodeId. - nodes.Add(ExpandedNodeId.ToNodeId(target.TargetId, session.NamespaceUris)); - } - - // return whatever was found. - return nodes; - } - - /// - /// Collects instance declarations nodes from with a type. - /// - public static void CollectInstanceDeclarations( - Session session, - ComNamespaceMapper mapper, - NodeId typeId, - AeEventAttribute parent, - List instances, - IDictionary map) - { - // find the children. - BrowseDescription nodeToBrowse = new BrowseDescription(); - - if (parent == null) - { - nodeToBrowse.NodeId = typeId; - } - else - { - nodeToBrowse.NodeId = parent.NodeId; - } - - nodeToBrowse.BrowseDirection = BrowseDirection.Forward; - nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.HasChild; - nodeToBrowse.IncludeSubtypes = true; - nodeToBrowse.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable); - nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; - - // ignore any browsing errors. - ReferenceDescriptionCollection references = Browse(session, nodeToBrowse, false); - - if (references == null) - { - return; - } - - // process the children. - List nodeIds = new List(); - List children = new List(); - - for (int ii = 0; ii < references.Count; ii++) - { - ReferenceDescription reference = references[ii]; - - if (reference.NodeId.IsAbsolute) - { - continue; - } - - // create a new declaration. - AeEventAttribute child = new AeEventAttribute(); - - child.RootTypeId = typeId; - child.NodeId = (NodeId)reference.NodeId; - child.BrowseName = reference.BrowseName; - child.NodeClass = reference.NodeClass; - - if (!LocalizedText.IsNullOrEmpty(reference.DisplayName)) - { - child.DisplayName = reference.DisplayName.Text; - } - else - { - child.DisplayName = reference.BrowseName.Name; - } - - if (parent != null) - { - child.BrowsePath = new QualifiedNameCollection(parent.BrowsePath); - child.BrowsePathDisplayText = Utils.Format("{0}/{1}", parent.BrowsePathDisplayText, mapper.GetLocalBrowseName(reference.BrowseName)); - child.DisplayPath = Utils.Format("{0}/{1}", parent.DisplayPath, reference.DisplayName); - } - else - { - child.BrowsePath = new QualifiedNameCollection(); - child.BrowsePathDisplayText = Utils.Format("{0}", reference.BrowseName); - child.DisplayPath = Utils.Format("{0}", reference.DisplayName); - } - - child.BrowsePath.Add(reference.BrowseName); - - // check if reading an overridden declaration. - AeEventAttribute overriden = null; - - if (map.TryGetValue(child.BrowsePathDisplayText, out overriden)) - { - child.OverriddenDeclaration = overriden; - } - - map[child.BrowsePathDisplayText] = child; - - // add to list. - children.Add(child); - nodeIds.Add(child.NodeId); - } - - // check if nothing more to do. - if (children.Count == 0) - { - return; - } - - // find the modelling rules. - List modellingRules = FindTargetOfReference(session, nodeIds, Opc.Ua.ReferenceTypeIds.HasModellingRule, false); - - if (modellingRules != null) - { - for (int ii = 0; ii < nodeIds.Count; ii++) - { - children[ii].ModellingRule = modellingRules[ii]; - - // if the modelling rule is null then the instance is not part of the type declaration. - if (NodeId.IsNull(modellingRules[ii])) - { - map.Remove(children[ii].BrowsePathDisplayText); - } - } - } - - // update the descriptions. - UpdateInstanceDescriptions(session, children, false); - - // recusively collect instance declarations for the tree below. - for (int ii = 0; ii < children.Count; ii++) - { - if (!NodeId.IsNull(children[ii].ModellingRule)) - { - instances.Add(children[ii]); - CollectInstanceDeclarations(session, mapper, typeId, children[ii], instances, map); - } - } - } - - /// - /// Collects instance declarations nodes from with a type. - /// - public static void CollectInstanceDeclarations( - Session session, - ComNamespaceMapper mapper, - NodeState node, - AeEventAttribute parent, - List instances, - IDictionary map) - { - List children = new List(); - node.GetChildren(session.SystemContext, children); - - if (children.Count == 0) - { - return; - } - - // process the children. - for (int ii = 0; ii < children.Count; ii++) - { - BaseInstanceState instance = children[ii]; - - // only interested in objects and variables. - if (instance.NodeClass != NodeClass.Object && instance.NodeClass != NodeClass.Variable) - { - return; - } - - // ignore instances without a modelling rule. - if (NodeId.IsNull(instance.ModellingRuleId)) - { - return; - } - - // create a new declaration. - AeEventAttribute declaration = new AeEventAttribute(); - - declaration.RootTypeId = (parent != null)?parent.RootTypeId:node.NodeId; - declaration.NodeId = (NodeId)instance.NodeId; - declaration.BrowseName = instance.BrowseName; - declaration.NodeClass = instance.NodeClass; - declaration.Description = (instance.Description != null)?instance.Description.ToString():null; - - // get data type information. - BaseVariableState variable = instance as BaseVariableState; - - if (variable != null) - { - declaration.DataType = variable.DataType; - declaration.ValueRank = variable.ValueRank; - - if (!NodeId.IsNull(variable.DataType)) - { - declaration.BuiltInType = DataTypes.GetBuiltInType(declaration.DataType, session.TypeTree); - } - } - - if (!LocalizedText.IsNullOrEmpty(instance.DisplayName)) - { - declaration.DisplayName = instance.DisplayName.Text; - } - else - { - declaration.DisplayName = instance.BrowseName.Name; - } - - if (parent != null) - { - declaration.BrowsePath = new QualifiedNameCollection(parent.BrowsePath); - declaration.BrowsePathDisplayText = Utils.Format("{0}/{1}", parent.BrowsePathDisplayText, mapper.GetLocalBrowseName(instance.BrowseName)); - declaration.DisplayPath = Utils.Format("{0}/{1}", parent.DisplayPath, instance.DisplayName); - } - else - { - declaration.BrowsePath = new QualifiedNameCollection(); - declaration.BrowsePathDisplayText = Utils.Format("{0}", instance.BrowseName); - declaration.DisplayPath = Utils.Format("{0}", instance.DisplayName); - } - - declaration.BrowsePath.Add(instance.BrowseName); - - // check if reading an overridden declaration. - AeEventAttribute overriden = null; - - if (map.TryGetValue(declaration.BrowsePathDisplayText, out overriden)) - { - declaration.OverriddenDeclaration = overriden; - } - - map[declaration.BrowsePathDisplayText] = declaration; - - // only interested in variables. - if (instance.NodeClass == NodeClass.Variable) - { - instances.Add(declaration); - } - - // recusively build tree. - CollectInstanceDeclarations(session, mapper, instance, declaration, instances, map); - } - } - - /// - /// Finds the targets for the specified reference. - /// - private static List FindTargetOfReference(Session session, List nodeIds, NodeId referenceTypeId, bool throwOnError) - { - try - { - // construct browse request. - BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); - - for (int ii = 0; ii < nodeIds.Count; ii++) - { - BrowseDescription nodeToBrowse = new BrowseDescription(); - nodeToBrowse.NodeId = nodeIds[ii]; - nodeToBrowse.BrowseDirection = BrowseDirection.Forward; - nodeToBrowse.ReferenceTypeId = referenceTypeId; - nodeToBrowse.IncludeSubtypes = false; - nodeToBrowse.NodeClassMask = 0; - nodeToBrowse.ResultMask = (uint)BrowseResultMask.None; - nodesToBrowse.Add(nodeToBrowse); - } - - // start the browse operation. - BrowseResultCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.Browse( - null, - null, - 1, - nodesToBrowse, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, nodesToBrowse); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); - - List targetIds = new List(); - ByteStringCollection continuationPoints = new ByteStringCollection(); - - for (int ii = 0; ii < nodeIds.Count; ii++) - { - targetIds.Add(null); - - // check for error. - if (StatusCode.IsBad(results[ii].StatusCode)) - { - continue; - } - - // check for continuation point. - if (results[ii].ContinuationPoint != null && results[ii].ContinuationPoint.Length > 0) - { - continuationPoints.Add(results[ii].ContinuationPoint); - } - - // get the node id. - if (results[ii].References.Count > 0) - { - if (NodeId.IsNull(results[ii].References[0].NodeId) || results[ii].References[0].NodeId.IsAbsolute) - { - continue; - } - - targetIds[ii] = (NodeId)results[ii].References[0].NodeId; - } - } - - // release continuation points. - if (continuationPoints.Count > 0) - { - session.BrowseNext( - null, - true, - continuationPoints, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, nodesToBrowse); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); - } - - //return complete list. - return targetIds; - } - catch (Exception exception) - { - if (throwOnError) - { - throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); - } - - return null; - } - } - - /// - /// Finds the targets for the specified reference. - /// - private static void UpdateInstanceDescriptions(Session session, List instances, bool throwOnError) - { - try - { - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - - for (int ii = 0; ii < instances.Count; ii++) - { - ReadValueId nodeToRead = new ReadValueId(); - nodeToRead.NodeId = instances[ii].NodeId; - nodeToRead.AttributeId = Attributes.Description; - nodesToRead.Add(nodeToRead); - - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = instances[ii].NodeId; - nodeToRead.AttributeId = Attributes.DataType; - nodesToRead.Add(nodeToRead); - - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = instances[ii].NodeId; - nodeToRead.AttributeId = Attributes.ValueRank; - nodesToRead.Add(nodeToRead); - } - - // start the browse operation. - DataValueCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.Read( - null, - 0, - TimestampsToReturn.Neither, - nodesToRead, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - - // update the instances. - for (int ii = 0; ii < nodesToRead.Count; ii += 3) - { - AeEventAttribute instance = instances[ii / 3]; - - instance.Description = results[ii].GetValue(LocalizedText.Null).Text; - instance.DataType = results[ii+1].GetValue(NodeId.Null); - instance.ValueRank = results[ii+2].GetValue(ValueRanks.Any); - - if (!NodeId.IsNull(instance.DataType)) - { - instance.BuiltInType = DataTypes.GetBuiltInType(instance.DataType, session.TypeTree); - } - } - } - catch (Exception exception) - { - if (throwOnError) - { - throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); - } - } - } - } -} diff --git a/ComIOP/Common/Server/Ae2/IComAeEventCallback.cs b/ComIOP/Common/Server/Ae2/IComAeEventCallback.cs deleted file mode 100644 index 83a47c458..000000000 --- a/ComIOP/Common/Server/Ae2/IComAeEventCallback.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using OpcRcw.Ae; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// Specifies the parameters for an async request. - /// - public interface IComAeEventCallback : IDisposable - { - /// - /// Called - /// - void OnEvent( - uint hClientSubscription, - bool bRefresh, - bool bLastRefresh, - ONEVENTSTRUCT[] pEvents); - } -} diff --git a/ComIOP/Common/Server/ComNamespaceMapper.cs b/ComIOP/Common/Server/ComNamespaceMapper.cs deleted file mode 100644 index 11bb90dfc..000000000 --- a/ComIOP/Common/Server/ComNamespaceMapper.cs +++ /dev/null @@ -1,1347 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// A class that manages the mapping between the local and remote namespace indexes. - /// - public class ComNamespaceMapper - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComNamespaceMapper() - { - } - #endregion - - #region Generic Mapping Methods - /// - /// Initializes the namespace mappings and updates the proxy configuration. - /// - /// The session. - /// The configuration. - public virtual void Initialize(Session session, ComProxyConfiguration configuration) - { - lock (m_lock) - { - m_typeTable = session.TypeTree; - - // index namspace uris. - if (configuration.NamespaceUris == null) - { - configuration.NamespaceUris = new StringCollection(); - } - - m_namespaceUris = new StringTableMapping(); - m_namespaceUris.Initialize(configuration.NamespaceUris, session.NamespaceUris); - - // index server uris. - if (configuration.ServerUris == null) - { - configuration.ServerUris = new StringCollection(); - } - - m_serverUris = new StringTableMapping(); - m_serverUris.Initialize(configuration.ServerUris, session.ServerUris); - - // create message context. - ServiceMessageContext context = new ServiceMessageContext(); - - context.MaxArrayLength = session.MessageContext.MaxArrayLength; - context.MaxByteStringLength = session.MessageContext.MaxByteStringLength; - context.MaxMessageSize = session.MessageContext.MaxMessageSize; - context.MaxStringLength = session.MessageContext.MaxStringLength; - context.Factory = session.MessageContext.Factory; - context.NamespaceUris = new NamespaceTable(); - context.ServerUris = new StringTable(); - - // copy namespace uris. - context.NamespaceUris.Append(session.NamespaceUris.GetString(1)); - - for (int ii = 0; ii < configuration.NamespaceUris.Count; ii++) - { - context.NamespaceUris.Append(configuration.NamespaceUris[ii]); - } - - // copy server uris. - context.ServerUris.Append(session.ServerUris.GetString(0)); - - for (int ii = 0; ii < configuration.ServerUris.Count; ii++) - { - context.ServerUris.Append(configuration.ServerUris[ii]); - } - - m_localMessageContext = context; - - // index mapping sets by the name assigned. - if (configuration.MappingSets != null) - { - m_mappingSets = new Dictionary(); - - for (int ii = 0; ii < configuration.MappingSets.Count; ii++) - { - UpdateMappingSet(configuration.MappingSets[ii]); - } - } - } - } - - /// - /// Updates an integer id mapping set. - /// - public void UpdateMappingSet(NodeIdMappingSet mappingSet) - { - lock (m_lock) - { - if (m_mappingSets == null) - { - m_mappingSets = new Dictionary(); - } - - string mappingType = mappingSet.MappingType; - - if (mappingType == null) - { - mappingType = String.Empty; - } - - m_mappingSets[mappingType] = mappingSet; - } - } - - /// - /// Gets the remote node id associated with an integer id. - /// - /// Type of the mapping. - /// The integer id. - /// The mapping; null if not found. - public NodeId GetRemoteIntegerIdMapping(string mappingType, uint integerId) - { - lock (m_lock) - { - // check if no mappings defined. - if (m_mappingSets == null) - { - return null; - } - - if (mappingType == null) - { - mappingType = String.Empty; - } - - // check for an existing mapping. - NodeIdMappingSet mappingSet = null; - - if (!m_mappingSets.TryGetValue(mappingType, out mappingSet)) - { - return null; - } - - // search for a existing integer id. - if (mappingSet.Mappings != null) - { - for (int ii = 0; ii < mappingSet.Mappings.Count; ii++) - { - NodeIdMapping mapping = mappingSet.Mappings[ii]; - - if (integerId == mapping.IntegerId) - { - return GetRemoteNodeId(mapping.NodeId); - } - } - } - - // not found. - return null; - } - } - - /// - /// Gets the integer mapping for a remote node id. - /// - /// Type of the mapping. - /// The remote node id. - /// The mapping; 0 if not found. - public uint GetLocalIntegerIdMapping(string mappingType, NodeId remoteId) - { - lock (m_lock) - { - // check if no mappings defined. - if (m_mappingSets == null) - { - return 0; - } - - if (mappingType == null) - { - mappingType = String.Empty; - } - - // check for an existing mapping. - NodeIdMappingSet mappingSet = null; - - if (!m_mappingSets.TryGetValue(mappingType, out mappingSet)) - { - return 0; - } - - // search for a existing integer id. - NodeId localId = GetLocalNodeId(remoteId); - - if (mappingSet.Mappings != null) - { - for (int ii = 0; ii < mappingSet.Mappings.Count; ii++) - { - NodeIdMapping mapping = mappingSet.Mappings[ii]; - - if (localId == mapping.NodeId) - { - return mapping.IntegerId; - } - } - } - - // not found. - return 0; - } - } - - /// - /// Gets the remote index for the local namespace index. - /// - /// The local namespace index. - /// The remote namespace index; UInt16.MaxValue if no mapping exists. - public ushort GetRemoteNamespaceIndex(ushort localIndex) - { - if (localIndex < 2) - { - return localIndex; - } - - lock (m_lock) - { - int remoteIndex = m_namespaceUris.LocalToRemote[localIndex]; - - if (remoteIndex < 0) - { - return UInt16.MaxValue; - } - - return (ushort)remoteIndex; - } - } - - /// - /// Gets the remote index for the local server index. - /// - /// The local server index. - /// The remote server index; UInt32.MaxValue if no mapping exists. - public uint GetRemoteServerIndex(uint localIndex) - { - if (localIndex < 2) - { - return localIndex; - } - - lock (m_lock) - { - int remoteIndex = m_serverUris.LocalToRemote[localIndex]; - - if (remoteIndex < 0) - { - return UInt32.MaxValue; - } - - return (uint)remoteIndex; - } - } - - /// - /// Gets the local index for the remote namespace index. - /// - /// The remote namespace index. - /// The remote namespace index; UInt16.MaxValue if no mapping exists. - public ushort GetLocalNamespaceIndex(ushort remoteIndex) - { - if (remoteIndex < 2) - { - return remoteIndex; - } - - lock (m_lock) - { - int localIndex = m_namespaceUris.RemoteToLocal[remoteIndex]; - - if (localIndex < 0) - { - return UInt16.MaxValue; - } - - return (ushort)localIndex; - } - } - - /// - /// Gets the local index for the remote server index. - /// - /// The remote server index. - /// The remote namespace index; UInt16.MaxValue if no mapping exists. - public uint GetLocalServerIndex(ushort remoteIndex) - { - if (remoteIndex < 1) - { - return remoteIndex; - } - - lock (m_lock) - { - int localIndex = m_serverUris.RemoteToLocal[remoteIndex]; - - if (localIndex < 0) - { - return UInt32.MaxValue; - } - - return (uint)localIndex; - } - } - - /// - /// Gets the remote node id. - /// - /// The local id. - /// The remote node id. - public NodeId GetRemoteNodeId(NodeId localId) - { - if (localId == null || localId.NamespaceIndex == 0) - { - return localId; - } - - ushort remoteIndex = GetRemoteNamespaceIndex(localId.NamespaceIndex); - - if (remoteIndex == localId.NamespaceIndex) - { - return localId; - } - - return new NodeId(localId.Identifier, remoteIndex); - } - - /// - /// Gets the local node id. - /// - /// The remote id. - /// The local node id. - public NodeId GetLocalNodeId(NodeId remoteId) - { - if (remoteId == null || remoteId.NamespaceIndex == 0) - { - return remoteId; - } - - ushort localIndex = GetLocalNamespaceIndex(remoteId.NamespaceIndex); - - if (localIndex == remoteId.NamespaceIndex) - { - return remoteId; - } - - return new NodeId(remoteId.Identifier, localIndex); - } - - /// - /// Gets the remote node id. - /// - /// The local id. - /// The remote node id. - public ExpandedNodeId GetRemoteExpandedNodeId(ExpandedNodeId localId) - { - if (localId == null) - { - return localId; - } - - ushort localNamespaceIndex = localId.NamespaceIndex; - uint localServerIndex = localId.ServerIndex; - - ushort remoteNamespaceIndex = GetRemoteNamespaceIndex(localNamespaceIndex); - uint remoteServerIndex = GetRemoteServerIndex(localServerIndex); - - if (localNamespaceIndex == remoteNamespaceIndex && localServerIndex == remoteServerIndex) - { - return localId; - } - - return new ExpandedNodeId(localId.Identifier, remoteNamespaceIndex, localId.NamespaceUri, remoteServerIndex); - } - - /// - /// Gets the local node id. - /// - /// The remote id. - /// The local node id. - public ExpandedNodeId GetLocaleExpandedNodeId(ExpandedNodeId remoteId) - { - if (remoteId == null) - { - return remoteId; - } - - ushort remoteNamespaceIndex = remoteId.NamespaceIndex; - uint remoteServerIndex = remoteId.ServerIndex; - - ushort localNamespaceIndex = GetRemoteNamespaceIndex(remoteNamespaceIndex); - uint localServerIndex = GetRemoteServerIndex(remoteServerIndex); - - if (localNamespaceIndex == remoteNamespaceIndex && localServerIndex == remoteServerIndex) - { - return remoteId; - } - - return new ExpandedNodeId(remoteId.Identifier, localNamespaceIndex, remoteId.NamespaceUri, localServerIndex); - } - - /// - /// Gets the remote qualified name. - /// - /// The local qualified name. - /// The remote qualified name. - public QualifiedName GetRemoteQualifiedName(QualifiedName localName) - { - if (localName == null || localName.NamespaceIndex == 0) - { - return localName; - } - - ushort remoteIndex = GetRemoteNamespaceIndex(localName.NamespaceIndex); - - if (remoteIndex == localName.NamespaceIndex) - { - return localName; - } - - return new QualifiedName(localName.Name, remoteIndex); - } - - /// - /// Gets the c qualified name. - /// - /// Name of the local. - /// The remote qualified name. - public QualifiedName GetLocalQualifiedName(QualifiedName localName) - { - if (localName == null || localName.NamespaceIndex == 0) - { - return localName; - } - - ushort remoteIndex = GetRemoteNamespaceIndex(localName.NamespaceIndex); - - if (remoteIndex == localName.NamespaceIndex) - { - return localName; - } - - return new QualifiedName(localName.Name, remoteIndex); - } - - /// - /// Returns a list of remote browse paths for a list of local relative paths. - /// - public BrowsePathCollection GetRemoteBrowsePaths(NodeId localNodeId, params string[] relativePaths) - { - BrowsePathCollection browsePaths = new BrowsePathCollection(); - - if (relativePaths != null) - { - for (int ii = 0; ii < relativePaths.Length; ii++) - { - BrowsePath browsePath = new BrowsePath(); - - browsePath.RelativePath = RelativePath.Parse(relativePaths[ii], this.m_typeTable); - browsePath.StartingNode = GetRemoteNodeId(localNodeId); - - for (int jj = 0; jj < browsePath.RelativePath.Elements.Count; jj++) - { - QualifiedName targetName = browsePath.RelativePath.Elements[jj].TargetName; - targetName = GetRemoteQualifiedName(targetName); - browsePath.RelativePath.Elements[jj].TargetName = targetName; - - NodeId referenceTypeId = browsePath.RelativePath.Elements[jj].ReferenceTypeId; - referenceTypeId = GetRemoteNodeId(referenceTypeId); - browsePath.RelativePath.Elements[jj].ReferenceTypeId = referenceTypeId; - } - - browsePaths.Add(browsePath); - } - } - - return browsePaths; - } - #endregion - - #region COM DA Specific Mapping Methods - /// - /// Gets the local data value. - /// - /// The remote value. - /// The local data value. - public DaValue GetLocalDataValue(DataValue remoteValue) - { - DaValue localValue = new DaValue(); - - localValue.Error = ComDaProxy.MapReadStatusToErrorCode(remoteValue.StatusCode); - - if (localValue.Error >= 0) - { - localValue.HdaQuality = ComUtils.GetHdaQualityCode(remoteValue.StatusCode); - localValue.Timestamp = remoteValue.SourceTimestamp; - localValue.Error = ResultIds.S_OK; - - if (localValue.Timestamp == DateTime.MinValue) - { - localValue.Timestamp = remoteValue.ServerTimestamp; - } - - try - { - localValue.Value = GetLocalValue(remoteValue.WrappedValue); - } - catch - { - localValue.Error = ResultIds.E_BADTYPE; - } - } - - return localValue; - } - - /// - /// Gets the remote data value. - /// - /// The local value. - /// The remote data type. - /// The remote data value. - /// Thrown if a conversion error occurs. - public DataValue GetRemoteDataValue(DaValue localValue, TypeInfo remoteType) - { - DataValue remoteValue = new DataValue(); - remoteValue.SourceTimestamp = localValue.Timestamp; - - if (localValue.Error < 0) - { - throw ComUtils.CreateComException(localValue.Error); - } - - remoteValue.StatusCode = ComUtils.GetHdaQualityCode(localValue.HdaQuality); - - try - { - remoteValue.WrappedValue = GetRemoteValue(new Variant(localValue.Value), remoteType); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e, ResultIds.E_BADTYPE); - } - - return remoteValue; - } - - /// - /// Converts a remote variant value to a local variant value. - /// - /// The remote value. - /// The local value. - public object GetLocalValue(Variant remoteValue) - { - TypeInfo remoteType = remoteValue.TypeInfo; - - if (remoteType == null) - { - remoteType = TypeInfo.Construct(remoteValue.Value); - } - - TypeInfo localType = GetLocalTypeInfo(remoteType); - - // check for array conversions. - Array remoteArray = remoteValue.Value as Array; - - if (remoteArray != null && remoteType.ValueRank != ValueRanks.Scalar) - { - Array localArray = null; - - // convert byte[] arrays to object[] arrays. - if (remoteType.BuiltInType == BuiltInType.ByteString || remoteType.BuiltInType == BuiltInType.ExtensionObject) - { - localArray = TypeInfo.CastArray(remoteArray, remoteType.BuiltInType, BuiltInType.Null, null); - return localArray; - } - - // convert Variant[] arrays to object[] arrays. - if (localType.BuiltInType == BuiltInType.Variant) - { - localArray = TypeInfo.CastArray(remoteArray, remoteType.BuiltInType, BuiltInType.Null, ConvertRemoteToLocal); - return localArray; - } - - // convert all other types of arrays. - localArray = TypeInfo.CastArray(remoteArray, remoteType.BuiltInType, localType.BuiltInType, ConvertRemoteToLocal); - return localArray; - } - - object localValue = ConvertRemoteToLocal(remoteValue.Value, remoteType.BuiltInType, localType.BuiltInType); - return localValue; - } - - /// - /// Converts a local variant value to a remote variant value. - /// - /// The local value. - /// The expected type for the remote value. - /// The remote value. - public Variant GetRemoteValue(Variant localeValue, TypeInfo remoteType) - { - TypeInfo localType = localeValue.TypeInfo; - - if (localType == null) - { - localType = TypeInfo.Construct(localeValue.Value); - } - - if (localType.BuiltInType == remoteType.BuiltInType || remoteType.BuiltInType == BuiltInType.Variant) - { - return localeValue; - } - - if (localType.BuiltInType == BuiltInType.ByteString && (remoteType.BuiltInType == BuiltInType.Byte && remoteType.ValueRank != ValueRanks.Scalar)) - { - return localeValue; - } - - Array localArray = localeValue.Value as Array; - - if (localArray != null && !typeof(byte[]).IsInstanceOfType(localArray)) - { - Array remoteArray = TypeInfo.CastArray(localArray, localType.BuiltInType, remoteType.BuiltInType, ConvertLocalToRemote); - return new Variant(remoteArray, remoteType); - } - - object remoteValue = ConvertLocalToRemote(localeValue.Value, localType.BuiltInType, remoteType.BuiltInType); - return new Variant(remoteValue, remoteType); - } - - private static readonly char[] s_SpecialChars = new char[] { '/', '%' }; - - /// - /// Gets the local name for the qualified name, - /// - /// The remote qualified name. - /// - public string GetLocalBrowseName(QualifiedName browseName) - { - if (QualifiedName.IsNull(browseName)) - { - return String.Empty; - } - - ushort namespaceIndex = GetLocalNamespaceIndex(browseName.NamespaceIndex); - string name = browseName.Name; - - int index = name.IndexOfAny(s_BrowseNameEscapedChars); - - if (index != -1) - { - StringBuilder buffer = new StringBuilder(name.Length); - buffer.Append(namespaceIndex); - buffer.Append(':'); - - for (int ii = 0; ii < name.Length; ii++) - { - if (IsEscapedChar(name[ii])) - { - buffer.AppendFormat("{0:X2}", (int)name[ii]); - } - else - { - buffer.Append(name[ii]); - } - } - - return buffer.ToString(); - } - - // check if the namespace index changed. - if (browseName.NamespaceIndex != namespaceIndex) - { - browseName = new QualifiedName(browseName.Name, namespaceIndex); - } - - return browseName.ToString(); - } - - private static readonly char[] s_BrowseNameEscapedChars = "/*?#[%".ToCharArray(); - - /// - /// Returns true if char is one of the special chars that must be escaped. - /// - private static bool IsEscapedChar(char ch) - { - for (int ii = 0; ii < s_BrowseNameEscapedChars.Length; ii++) - { - if (Char.IsControl(ch) || s_BrowseNameEscapedChars[ii] == ch) - { - return true; - } - } - - return false; - } - - private static readonly char[] s_HexChars = "0123456789ABCDFEF".ToCharArray(); - - /// - /// Converts to char to a hex number. Returns -1 if char is invalid. - /// - private static int ToHexDigit(char ch) - { - ch = Char.ToUpperInvariant(ch); - - for (int ii = 0; ii < s_HexChars.Length; ii++) - { - if (s_HexChars[ii] == ch) - { - return ii; - } - } - - return -1; - } - - /// - /// Gets the remote qualified name for the local name. - /// - /// The local qualified name. - /// The remote qualified name. - public QualifiedName GetRemoteBrowseName(string browseName) - { - // check for null. - if (String.IsNullOrEmpty(browseName)) - { - return QualifiedName.Null; - } - - // parse the browse name. - QualifiedName qname = QualifiedName.Parse(browseName); - - // construct the qualified name with the remote index. - ushort namespaceIndex = GetRemoteNamespaceIndex(qname.NamespaceIndex); - - // unescape any special characters in name. - string name = qname.Name; - int index = name.IndexOf('%'); - - if (index != -1) - { - StringBuilder buffer = new StringBuilder(name.Length); - - for (int ii = 0; ii < name.Length; ii++) - { - if (name[ii] == '%') - { - int code = 0; - - if (ii < name.Length-2) - { - int ch = ToHexDigit(name[ii+1]); - - if (ch > 0) - { - code = ch * 16; - ch = ToHexDigit(name[ii+2]); - - if (ch > 0) - { - code += ch; - buffer.Append((char)code); - continue; - } - } - } - } - - buffer.Append(name[ii]); - } - - return new QualifiedName(buffer.ToString(), namespaceIndex); - } - - // check if no translation required. - if (qname.NamespaceIndex == namespaceIndex) - { - return qname; - } - - // return a new name. - return new QualifiedName(qname.Name, namespaceIndex); - } - - /// - /// Constructs a node id from an item id. - /// - /// The item id. - /// The node id, null if an error occurred. - public NodeId GetRemoteNodeId(string itemId) - { - try - { - // root is the objects folder. - if (String.IsNullOrEmpty(itemId)) - { - return ObjectIds.ObjectsFolder; - } - - // must remove ';' from item id since the CTT does not like them. - #if !NO_CTT_HACK - StringBuilder buffer = new StringBuilder(itemId.Length+2); - - for (int ii = 0; ii < itemId.Length; ii++) - { - char ch = itemId[ii]; - - if (ch == '*') - { - if (ii < itemId.Length-1 && itemId[ii+1] == '*') - { - buffer.Append('*'); - ii++; - continue; - } - - buffer.Append('='); - continue; - } - - buffer.Append(ch); - } - - itemId = buffer.ToString(); - #endif - - - // parse the item id. - NodeId nodeId = NodeId.Parse(itemId); - - // get the remote index. - ushort namespaceIndex = GetRemoteNamespaceIndex(nodeId.NamespaceIndex); - - // nothing more to do if they are the same. - if (namespaceIndex == nodeId.NamespaceIndex) - { - return nodeId; - } - - // create a new node id. - if (namespaceIndex != UInt16.MaxValue) - { - return new NodeId(nodeId.Identifier, namespaceIndex); - } - - return null; - } - catch (Exception) - { - // oops. could not parse the item id. - return null; - } - } - - /// - /// Constructs an item id from a node id. - /// - /// The node id. - /// The item id, null if an error occurred. - public string GetLocalItemId(NodeId nodeId) - { - try - { - // check for null. - if (NodeId.IsNull(nodeId)) - { - return null; - } - - // check for the objects folder (use knowledge of the target to avoid calling the less efficient Equals() method). - if (nodeId.IdType == IdType.Numeric && nodeId.NamespaceIndex == 0) - { - if ((uint)nodeId.Identifier == Objects.ObjectsFolder) - { - return String.Empty; - } - } - - // get the lcoal index. - ushort namespaceIndex = GetLocalNamespaceIndex(nodeId.NamespaceIndex); - - // check if a mapping is required. - if (namespaceIndex != nodeId.NamespaceIndex) - { - // could happen if the server updates it namespace table. - if (namespaceIndex == UInt16.MaxValue) - { - return null; - } - - nodeId = new NodeId(nodeId.Identifier, namespaceIndex); - } - - // convert the node id to a string. - string itemId = nodeId.ToString(); - - // must remove ';' from item id since the CTT does not like them. - #if !NO_CTT_HACK - StringBuilder buffer = new StringBuilder(itemId.Length+2); - - for (int ii = 0; ii < itemId.Length; ii++) - { - char ch = itemId[ii]; - - if (ch == '=') - { - buffer.Append('*'); - continue; - } - - if (ch == '*') - { - buffer.Append('*'); - continue; - } - - buffer.Append(ch); - } - - itemId = buffer.ToString(); - #endif - - return itemId; - } - catch (Exception) - { - // oops. probably a programming error. - return null; - } - } - #endregion - - #region Private Methods - /// - /// Gets the local type info. - /// - /// The remote type info. - /// The local type info. - private TypeInfo GetLocalTypeInfo(TypeInfo remoteType) - { - BuiltInType localBuiltInType = BuiltInType.Null; - - switch (remoteType.BuiltInType) - { - case BuiltInType.Guid: - case BuiltInType.XmlElement: - case BuiltInType.NodeId: - case BuiltInType.ExpandedNodeId: - case BuiltInType.QualifiedName: - case BuiltInType.LocalizedText: - { - localBuiltInType = BuiltInType.String; - break; - } - - case BuiltInType.StatusCode: - { - localBuiltInType = BuiltInType.UInt32; - break; - } - - case BuiltInType.ExtensionObject: - { - localBuiltInType = BuiltInType.ByteString; - break; - } - - default: - { - localBuiltInType = remoteType.BuiltInType; - break; - } - } - - return new TypeInfo(localBuiltInType, remoteType.ValueRank); - } - - /// - /// Converts a remote value to a local value. - /// - /// The remote value. - /// The data type of the remote value. - /// The data type of the local value. - /// The local value. - 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; - } - - /// - /// Converts a local value to a remote value. - /// - /// The local value. - /// The data type of the local value. - /// The data type of the remote value. - /// The remote value. - 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; - } - #endregion - - #region StringTableMapping Class - /// - /// Stores the mapping between two string tables. - /// - private class StringTableMapping - { - #region Public Members - /// - /// Gets the mapping from a local index to a remote index. - /// - /// The local to remote mapping. - public int[] LocalToRemote - { - get { return m_localToRemote; } - } - - /// - /// Gets the mapping from a remote index to a local index. - /// - /// The remote to local mapping. - public int[] RemoteToLocal - { - get { return m_remoteToLocal; } - } - - /// - /// Initializes the mapping between the tables. - /// - /// The local table. - /// The remote table. - /// The local table is updates with missing URIs from the remote table. - public void Initialize(List localTable, StringTable remoteTable) - { - m_remoteToLocal = InitializeRemoteToLocalMapping(localTable, remoteTable); - m_localToRemote = InitializeLocalToRemoteMapping(localTable, remoteTable); - } - #endregion - - #region Private Methods - /// - /// Initializes the local to remote mapping for a pair of string tables. - /// - /// The local table. - /// The remote table. - /// The mapping. - private int[] InitializeLocalToRemoteMapping(List localTable, StringTable remoteTable) - { - List indexes = new List(); - indexes.Add(0); - - if (remoteTable is NamespaceTable) - { - indexes.Add(1); - } - - for (int ii = 0; ii < localTable.Count; ii++) - { - int index = remoteTable.GetIndex(localTable[ii]); - indexes.Add(index); - } - - return indexes.ToArray(); - } - - /// - /// Initializes the remote to local mapping for a pair of string tables. - /// - /// The local table. - /// The remote table. - /// The mapping. - private int[] InitializeRemoteToLocalMapping(List localTable, StringTable remoteTable) - { - List indexes = new List(); - indexes.Add(0); - - if (remoteTable is NamespaceTable) - { - indexes.Add(1); - } - - int start = indexes.Count; - - for (int ii = start; ii < remoteTable.Count; ii++) - { - string uri = remoteTable.GetString((uint)ii); - - // look for the matching local index. - bool found = false; - - for (int jj = 0; jj < localTable.Count; jj++) - { - if (localTable[jj] == uri) - { - found = true; - indexes.Add(jj+start); - break; - } - } - - // not found. - if (!found) - { - localTable.Add(uri); - indexes.Add(localTable.Count-1+start); - } - } - - // return the indexes. - return indexes.ToArray(); - } - #endregion - - #region Private Fields - private int[] m_remoteToLocal; - private int[] m_localToRemote; - #endregion - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private ITypeTable m_typeTable; - private ServiceMessageContext m_localMessageContext; - private StringTableMapping m_namespaceUris; - private StringTableMapping m_serverUris; - private Dictionary m_mappingSets; - #endregion - } -} diff --git a/ComIOP/Common/Server/ComProxy.cs b/ComIOP/Common/Server/ComProxy.cs deleted file mode 100644 index 7831c7853..000000000 --- a/ComIOP/Common/Server/ComProxy.cs +++ /dev/null @@ -1,760 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Globalization; -using Opc.Ua.Client; -using System.Threading.Tasks; - -namespace Opc.Ua.Com.Server -{ - /// - /// A base class for classes that implement an OPC COM specification. - /// - public class ComProxy : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComProxy() - { - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (!m_disposed) - { - if (disposing) - { - lock (m_lock) - { - m_running = false; - - if (m_reconnectTimer != null) - { - m_reconnectTimer.Dispose(); - m_reconnectTimer = null; - } - - if (m_session != null) - { - m_session.Dispose(); - m_session = null; - } - } - } - - m_disposed = true; - } - } - - private bool m_disposed; - #endregion - - #region Initialization - /// - /// Gets the endpoint. - /// - /// The endpoint. - public ConfiguredEndpoint Endpoint - { - get { return m_endpoint; } - } - - /// - /// Gets a value indicating whether this is connected. - /// - /// true if connected; otherwise, false. - public bool Connected - { - get - { - lock (m_lock) - { - if (m_session == null) - { - return false; - } - - return m_session.Connected; - } - } - } - - /// - /// Called when the object is loaded by the COM process. - /// - /// The CLSID used to activate the server. - /// The application configuration for the COM process. - public virtual void Load(Guid clsid, ApplicationConfiguration configuration) - { - lock (m_lock) - { - // save the application configuration. - m_configuration = configuration; - - // set the start time. - m_startTime = DateTime.UtcNow; - - // look up default time zone. - DateTime now = DateTime.Now; - - m_timebias = (int)-TimeZone.CurrentTimeZone.GetUtcOffset(now).TotalMinutes; - - if (TimeZone.CurrentTimeZone.IsDaylightSavingTime(now)) - { - m_timebias += 60; - } - - // load endpoint information. - m_endpoint = LoadConfiguredEndpoint(clsid); - - // create a dummy endpoint so the COM client receives an indication of the problem. - if (m_endpoint == null) - { - ApplicationDescription server = new ApplicationDescription(); - - server.ApplicationName = "(Missing Configuration File)"; - server.ApplicationType = ApplicationType.Server; - server.ApplicationUri = clsid.ToString(); - - m_endpoint = new ConfiguredEndpoint(server, null); - } - - m_clsid = clsid; - m_running = true; - - // connect to the server. - OnCreateSession(null); - } - } - - /// - /// Unloads this instance. - /// - public virtual void Unload() - { - lock (m_lock) - { - if (m_session != null) - { - m_session.Close(5000); - } - } - - Dispose(); - } - - /// - /// Returns the available locales. - /// - public int[] GetAvailableLocaleIds() - { - ThrowIfNotConnected(); - - List localeIds = new List(); - localeIds.Add(ComUtils.LOCALE_SYSTEM_DEFAULT); - - try - { - lock (m_lock) - { - DataValue value = m_session.ReadValue(Opc.Ua.VariableIds.Server_ServerCapabilities_LocaleIdArray); - string[] locales = value.GetValue(null); - - for (int ii = 0; ii < locales.Length; ii++) - { - try - { - CultureInfo culture = CultureInfo.GetCultureInfo(locales[ii]); - - if (culture != null) - { - localeIds.Add(culture.LCID); - } - } - catch (Exception) - { - // ignore invalid locales. - } - } - } - } - catch (Exception) - { - // ignore network errors. - } - - return localeIds.ToArray(); - } - - /// - /// Sets the current locale. - /// - public void SetLocaleId(int localeId) - { - ThrowIfNotConnected(); - - try - { - StringCollection preferredLocales = new StringCollection(); - - if (localeId != 0 && localeId != ComUtils.LOCALE_SYSTEM_DEFAULT) - { - CultureInfo culture = CultureInfo.GetCultureInfo(localeId); - - if (culture != null) - { - preferredLocales.Add(culture.Name); - } - } - - m_session.ChangePreferredLocales(preferredLocales); - } - catch (Exception) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - } - - /// - /// Gets the current locale. - /// - public int GetLocaleId() - { - ThrowIfNotConnected(); - - try - { - if (m_session.PreferredLocales.Count == 0) - { - return ComUtils.LOCALE_SYSTEM_DEFAULT; - } - - string locale = m_session.PreferredLocales[0]; - - CultureInfo culture = CultureInfo.GetCultureInfo(locale); - - if (culture != null) - { - return culture.LCID; - } - - return ComUtils.LOCALE_SYSTEM_DEFAULT; - } - catch (Exception) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - } - #endregion - - #region Public Properties - /// - /// Gets the current session. - /// - /// The session. - public Opc.Ua.Client.Session Session - { - get { return m_session; } - } - #endregion - - #region Protected Properties - /// - /// Gets the lock. - /// - /// The lock. - protected object Lock - { - get { return m_lock; } - } - - /// - /// Gets the configuration. - /// - /// The configuration. - protected ApplicationConfiguration Configuration - { - get { return m_configuration; } - } - - /// - /// Gets a value indicating whether this is running. - /// - /// true if running; otherwise, false. - protected bool Running - { - get { return m_running; } - } - - /// - /// Gets the start time. - /// - /// The start time. - protected DateTime StartTime - { - get { return m_startTime; } - } - - /// - /// Gets the timebias. - /// - /// The timebias. - protected int Timebias - { - get { return m_timebias; } - } - - /// - /// Called when a new session is created. - /// - protected virtual void OnSessionCreated() - { - } - - /// - /// Called when a session is reconnected. - /// - protected virtual void OnSessionReconected() - { - } - - /// - /// Called when a session reconnect is scheduled. - /// - protected virtual void OnReconnectInProgress(int secondsToReconnect) - { - } - - /// - /// Called when a session is removed. - /// - protected virtual void OnSessionRemoved() - { - } - - /// - /// Saves the current endpoint configuration. - /// - protected void SaveConfiguration() - { - SaveConfiguredEndpoint(m_clsid, m_endpoint); - } - - /// - /// Throws if disposed or not connected. - /// - protected Session ThrowIfNotConnected() - { - if (m_disposed) - { - throw new ObjectDisposedException(GetType().Name); - } - - if (m_session == null || !m_session.Connected) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_session; - } - #endregion - - #region Private Methods - /// - /// Creates a session with the server. - /// - /// The state. - private async void OnCreateSession(object state) - { - // check if nothing to do. - lock (m_lock) - { - if (!m_running || m_session != null) - { - return; - } - - // stop the reconnect timer. - if (m_reconnectTimer != null) - { - m_reconnectTimer.Dispose(); - m_reconnectTimer = null; - } - } - - // create the session. - try - { - Session session = await Connect(m_clsid); - session.KeepAlive += new KeepAliveEventHandler(Session_KeepAlive); - - lock (m_lock) - { - // discard unneeded session. - if (m_session != null) - { - session.Dispose(); - return; - } - - // update the session. - m_session = session; - } - - OnSessionCreated(); - } - catch (Exception e) - { - Utils.Trace(e, "Could not create a Session with the UA Server."); - - // schedule a reconnect. - lock (m_lock) - { - m_reconnectTimer = new Timer(OnCreateSession, null, 20000, Timeout.Infinite); - Utils.Trace("Calling OnCreateSession in 20000ms."); - OnReconnectInProgress(20); - } - } - } - - /// - /// Creates a session with the server. - /// - /// The state. - private void OnReconnectSession(object state) - { - // get the CLSID of the COM server. - Session session = state as Session; - - if (session == null) - { - return; - } - - // check if nothing to do. - lock (m_lock) - { - if (!m_running || !Object.ReferenceEquals(m_session, session)) - { - return; - } - - // stop the reconnect timer. - if (m_reconnectTimer != null) - { - m_reconnectTimer.Dispose(); - m_reconnectTimer = null; - } - } - - // reconnect the session. - try - { - session.Reconnect(); - - lock (m_lock) - { - if (!m_running || !Object.ReferenceEquals(m_session, session)) - { - session.Dispose(); - return; - } - } - - OnSessionReconected(); - } - catch (Exception e) - { - Utils.Trace("Unexpected reconnecting a Session with the UA Server. {0}", e.Message); - - // schedule a reconnect. - lock (m_lock) - { - // check if session has been replaced. - if (!m_running || !Object.ReferenceEquals(m_session, session)) - { - session.Dispose(); - return; - } - - // check if the session has been closed. - ServiceResultException sre = e as ServiceResultException; - - if (sre == null || sre.StatusCode != StatusCodes.BadSessionClosed) - { - m_session = null; - session.Dispose(); - OnSessionRemoved(); - ThreadPool.QueueUserWorkItem(OnCreateSession, null); - Utils.Trace("Calling OnCreateSession NOW."); - return; - } - - // check if reconnecting is still an option. - if (m_lastKeepAliveTime.AddMilliseconds(session.SessionTimeout) > DateTime.UtcNow) - { - m_reconnectTimer = new Timer(OnReconnectSession, session, 20000, Timeout.Infinite); - Utils.Trace("Calling OnReconnectSession in 20000ms."); - OnReconnectInProgress(20); - return; - } - - // give up and re-create the session. - m_session = null; - session.Dispose(); - OnSessionRemoved(); - m_reconnectTimer = new Timer(OnCreateSession, null, 20000, Timeout.Infinite); - Utils.Trace("Calling OnCreateSession in 20000ms."); - OnReconnectInProgress(20); - } - } - } - - /// - /// The session the keep alive handler. - /// - /// The session. - /// The instance containing the event data. - private void Session_KeepAlive(ISession session, KeepAliveEventArgs e) - { - int missedKeepAlives = 0; - - lock (m_lock) - { - // check if the session is closed. - if (!m_running || !Object.ReferenceEquals(m_session, session)) - { - return; - } - - // check if everything is ok. - if (ServiceResult.IsGood(e.Status)) - { - m_missedKeepAlives = 0; - m_lastKeepAliveTime = DateTime.UtcNow; - return; - } - - // increment miss count. - missedKeepAlives = ++m_missedKeepAlives; - } - - // attempt to reconnect after two misses. - if (missedKeepAlives == 2) - { - ThreadPool.QueueUserWorkItem(OnReconnectSession, session); - Utils.Trace("Calling OnReconnectSession NOW."); - } - } - - /// - /// Connects to the UA server identfied by the CLSID. - /// - /// The CLSID. - /// The UA server. - private async Task Connect(Guid clsid) - { - // load the endpoint information. - ConfiguredEndpoint endpoint = m_endpoint = LoadConfiguredEndpoint(clsid); - - if (endpoint == null) - { - throw new ServiceResultException(StatusCodes.BadConfigurationError); - } - - // update security information. - if (endpoint.UpdateBeforeConnect) - { - endpoint.UpdateFromServer(); - - // check if halted while waiting for a response. - if (!m_running) - { - throw new ServiceResultException(StatusCodes.BadServerHalted); - } - } - - // look up the client certificate. - X509Certificate2 clientCertificate = await m_configuration.SecurityConfiguration.ApplicationCertificate.Find(true); - - // create a message context to use with the channel. - ServiceMessageContext messageContext = m_configuration.CreateMessageContext(); - - // create the channel. - ITransportChannel channel = SessionChannel.Create( - m_configuration, - endpoint.Description, - endpoint.Configuration, - clientCertificate, - messageContext); - - // create the session. - Session session = new Session(channel, m_configuration, endpoint, clientCertificate); - - // create a session name that is useful for debugging. - string sessionName = Utils.Format("COM Client ({0})", System.Net.Dns.GetHostName()); - - // open the session. - Opc.Ua.UserIdentity identity = null; - - if (endpoint.UserIdentity != null) - { - // need to decode password. - UserNameIdentityToken userNameToken = endpoint.UserIdentity as UserNameIdentityToken; - - if (userNameToken != null) - { - UserNameIdentityToken copy = new UserNameIdentityToken(); - copy.PolicyId = userNameToken.PolicyId; - copy.DecryptedPassword = new UTF8Encoding().GetString(userNameToken.Password); - copy.UserName = userNameToken.UserName; - copy.EncryptionAlgorithm = userNameToken.EncryptionAlgorithm; - identity = new Opc.Ua.UserIdentity(copy); - } - - // create the identity object. - else - { - identity = new Opc.Ua.UserIdentity(endpoint.UserIdentity); - } - } - - session.Open(sessionName, identity); - - // return the new session. - return session; - } - - /// - /// Reads the UA endpoint information associated the CLSID - /// - /// The CLSID used to activate the COM server. - /// The endpoint. - protected ConfiguredEndpoint LoadConfiguredEndpoint(Guid clsid) - { - try - { - string relativePath = Utils.Format("%CommonApplicationData%\\OPC Foundation\\ComPseudoServers\\{0}.xml", clsid); - string absolutePath = Utils.GetAbsoluteFilePath(relativePath, false, false, false); - - // oops - nothing found. - if (absolutePath == null) - { - return null; - } - - // open the file. - using (FileStream istrm = File.Open(absolutePath, FileMode.Open, FileAccess.Read)) - { - using (XmlTextReader reader = new XmlTextReader(istrm)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(ConfiguredEndpoint)); - return (ConfiguredEndpoint)serializer.ReadObject(reader, false); - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error loading endpoint configuration for COM Proxy with CLSID={0}.", clsid); - return null; - } - } - - /// - /// Saves the UA endpoint information associated the CLSID. - /// - /// The CLSID used to activate the COM server. - /// The endpoint. - protected void SaveConfiguredEndpoint(Guid clsid, ConfiguredEndpoint endpoint) - { - try - { - string relativePath = Utils.Format("%CommonApplicationData%\\OPC Foundation\\ComPseudoServers\\{0}.xml", clsid); - string absolutePath = Utils.GetAbsoluteFilePath(relativePath, false, false, true); - - // oops - nothing found. - if (absolutePath == null) - { - absolutePath = Utils.GetAbsoluteFilePath(relativePath, true, false, true); - } - - // open the file. - FileStream ostrm = File.Open(absolutePath, FileMode.Create, FileAccess.ReadWrite); - - using (XmlTextWriter writer = new XmlTextWriter(ostrm, System.Text.Encoding.UTF8)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(ConfiguredEndpoint)); - serializer.WriteObject(writer, endpoint); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error saving endpoint configuration for COM Proxy with CLSID={0}.", clsid); - } - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private Guid m_clsid; - private ApplicationConfiguration m_configuration; - private ConfiguredEndpoint m_endpoint; - private bool m_running; - private DateTime m_startTime; - private int m_timebias; - private Timer m_reconnectTimer; - private int m_missedKeepAlives; - private DateTime m_lastKeepAliveTime; - private Opc.Ua.Client.Session m_session; - #endregion - } -} diff --git a/ComIOP/Common/Server/ComProxyConfiguration.cs b/ComIOP/Common/Server/ComProxyConfiguration.cs deleted file mode 100644 index 3e7d5b730..000000000 --- a/ComIOP/Common/Server/ComProxyConfiguration.cs +++ /dev/null @@ -1,437 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.ServiceModel; -using System.Runtime.Serialization; -using System.Collections.Generic; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores the configuration for UA that wraps a COM server. - /// - [DataContract(Namespace = Namespaces.ComInterop)] - public class ComProxyConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public ComProxyConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - } - #endregion - - #region Public Properties - /// - /// Gets or sets the namespace uris known to the server. - /// - /// The namespace uris. - /// - /// This list starts with index 1. - /// This list ensures the indexes used to create browse names/node ids do not - /// change even if the server tables change. - /// - [DataMember(Order = 1, EmitDefaultValue = false)] - public StringCollection NamespaceUris { get; set; } - - /// - /// Gets or sets the server uris known to the server. - /// - /// The server uris. - /// - /// This list starts with index 2. - /// This list ensures the indexes used to create browse names/node ids do not - /// change even if the server tables change. - /// - [DataMember(Order = 2, EmitDefaultValue = false)] - public StringCollection ServerUris { get; set; } - - /// - /// Gets or sets the size of the blocks to use when browsing. - /// - /// The size of the block. - [DataMember(Order=3)] - public int BrowseBlockSize { get; set; } - - /// - /// Gets or sets the sets of mappings for node ids. - /// - /// The sets of mappings for node ids. - [DataMember(Order = 4, EmitDefaultValue = false)] - public NodeIdMappingSetCollection MappingSets { get; set; } - #endregion - - /// - /// Returns the mapping set. Creates an empty one if it does not exist. - /// - public NodeIdMappingSet GetMappingSet(string mappingType) - { - NodeIdMappingSet mappingSet = new NodeIdMappingSet(); - mappingSet.MappingType = mappingType; - - if (this.MappingSets != null) - { - for (int ii = 0; ii < this.MappingSets.Count; ii++) - { - if (this.MappingSets[ii].MappingType == mappingType) - { - mappingSet.Mappings = this.MappingSets[ii].Mappings; - return mappingSet; - } - } - } - - mappingSet.Mappings = new NodeIdMappingCollection(); - return mappingSet; - } - - /// - /// Replaces the mapping set. Adds it if it does not exist. - /// - public void ReplaceMappingSet(NodeIdMappingSet mappingSet) - { - if (this.MappingSets != null) - { - for (int ii = 0; ii < this.MappingSets.Count; ii++) - { - if (this.MappingSets[ii].MappingType == mappingSet.MappingType) - { - this.MappingSets[ii] = mappingSet; - return; - } - } - } - - if (this.MappingSets == null) - { - this.MappingSets = new NodeIdMappingSetCollection(); - } - - this.MappingSets.Add(mappingSet); - } - } - - #region NodeIdMappingSet Class - /// - /// Stores an integer mapping assigned to a NodeId. - /// - [DataContract(Namespace = Namespaces.ComInterop)] - public class NodeIdMappingSet - { - #region Constructors - /// - /// The default constructor. - /// - public NodeIdMappingSet() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - } - #endregion - - #region Public Properties - /// - /// Gets or sets the type of the mapping. - /// - /// The type of the mapping. - [DataMember(Order=1)] - public string MappingType - { - get { return m_mappingType; } - set { m_mappingType = value; } - } - - /// - /// Gets or sets the mappings. - /// - /// The mappings. - [DataMember(Order=2)] - public NodeIdMappingCollection Mappings - { - get { return m_mappings; } - set { m_mappings = value; } - } - #endregion - - #region Private Members - private string m_mappingType; - private NodeIdMappingCollection m_mappings; - #endregion - } - #endregion - - #region NodeIdMappingSetCollection Class - /// - /// A collection of NodeIdMapping values. - /// - /// - /// A strongly-typed collection of NodeIdMapping values. - /// - [CollectionDataContract(Name="ListOfNodeIdMappingSet", Namespace=Namespaces.ComInterop, ItemName="NodeIdMappingSet")] - public class NodeIdMappingSetCollection : List, ICloneable - { - /// - /// Initializes an empty collection. - /// - /// - /// Initializes an empty collection. - /// - public NodeIdMappingSetCollection() { } - - /// - /// Initializes the collection with the specified capacity. - /// - /// - /// Initializes the collection with the specified capacity. - /// - /// Max capacity of collection - public NodeIdMappingSetCollection(int capacity) : base(capacity) { } - - /// - /// Initializes the collection from another collection. - /// - /// - /// Initializes the collection from another collection. - /// - /// A collection of NodeIdMappingSets to add to this collection - public NodeIdMappingSetCollection(IEnumerable collection) : base(collection) { } - - /// - /// Converts an array to a collection. - /// - /// - /// Converts an array to a collection. - /// - /// A collection of NodeIdMappingSets to add to this collection - public static NodeIdMappingSetCollection ToNodeIdMappingSetCollection(NodeIdMappingSet[] values) - { - if (values != null) - { - return new NodeIdMappingSetCollection(values); - } - - return new NodeIdMappingSetCollection(); - } - - /// - /// Converts an array to a collection. - /// - /// - /// Converts an array to a collection. - /// - /// A collection of NodeIdMappingSets to add to this collection - public static implicit operator NodeIdMappingSetCollection(NodeIdMappingSet[] values) - { - return ToNodeIdMappingSetCollection(values); - } - - /// - /// Creates a deep copy of the collection. - /// - /// - /// Creates a deep copy of the collection. - /// - public object Clone() - { - return new NodeIdMappingSetCollection(this); - } - } - #endregion - - #region NodeIdMapping Class - /// - /// Stores an integer mapping assigned to a NodeId. - /// - [DataContract(Namespace = Namespaces.ComInterop)] - public class NodeIdMapping - { - #region Constructors - /// - /// The default constructor. - /// - public NodeIdMapping() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - } - #endregion - - #region Public Properties - /// - /// Gets or sets the integer id. - /// - /// The integer id. - [DataMember(Order = 1, EmitDefaultValue = false)] - public uint IntegerId { get; set; } - - /// - /// Gets or sets the node id. - /// - /// The node id. - [DataMember(Order = 2, EmitDefaultValue = false)] - public string NodeId { get; set; } - - /// - /// Gets or sets the browse patj. - /// - /// The node id. - [DataMember(Order = 3, EmitDefaultValue = false)] - public string BrowePath { get; set; } - #endregion - } - #endregion - - #region NodeIdMappingCollection Class - /// - /// A collection of NodeIdMapping values. - /// - /// - /// A strongly-typed collection of NodeIdMapping values. - /// - [CollectionDataContract(Name="ListOfNodeIdMapping", Namespace=Namespaces.ComInterop, ItemName="NodeIdMapping")] - public class NodeIdMappingCollection : List, ICloneable - { - /// - /// Initializes an empty collection. - /// - /// - /// Initializes an empty collection. - /// - public NodeIdMappingCollection() { } - - /// - /// Initializes the collection with the specified capacity. - /// - /// - /// Initializes the collection with the specified capacity. - /// - /// Max capacity of collection - public NodeIdMappingCollection(int capacity) : base(capacity) { } - - /// - /// Initializes the collection from another collection. - /// - /// - /// Initializes the collection from another collection. - /// - /// A collection of NodeIdMappings to add to this collection - public NodeIdMappingCollection(IEnumerable collection) : base(collection) { } - - /// - /// Converts an array to a collection. - /// - /// - /// Converts an array to a collection. - /// - /// A collection of NodeIdMappings to add to this collection - public static NodeIdMappingCollection ToNodeIdMappingCollection(NodeIdMapping[] values) - { - if (values != null) - { - return new NodeIdMappingCollection(values); - } - - return new NodeIdMappingCollection(); - } - - /// - /// Converts an array to a collection. - /// - /// - /// Converts an array to a collection. - /// - /// A collection of NodeIdMappings to add to this collection - public static implicit operator NodeIdMappingCollection(NodeIdMapping[] values) - { - return ToNodeIdMappingCollection(values); - } - - /// - /// Creates a deep copy of the collection. - /// - /// - /// Creates a deep copy of the collection. - /// - public object Clone() - { - return new NodeIdMappingCollection(this); - } - } - #endregion -} diff --git a/ComIOP/Common/Server/Da/Com.Da.EnumItemAttributes.cs b/ComIOP/Common/Server/Da/Com.Da.EnumItemAttributes.cs deleted file mode 100644 index fc12645c9..000000000 --- a/ComIOP/Common/Server/Da/Com.Da.EnumItemAttributes.cs +++ /dev/null @@ -1,217 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections; -using System.Text; -using System.Runtime.InteropServices; - -using OpcRcw.Da; -using OpcRcw.Comn; - -namespace Opc.Ua.Com.Server.Da -{ - /// - /// A class that implements the COM-DA interfaces. - /// - public class EnumOPCItemAttributes : IEnumOPCItemAttributes - { - /// - public class ItemAttributes - { - /// - public string ItemID = null; - /// - public string AccessPath = null; - /// - public int ClientHandle = -1; - /// - public int ServerHandle = -1; - /// - public bool Active = false; - /// - public VarEnum CanonicalDataType = VarEnum.VT_EMPTY; - /// - public VarEnum RequestedDataType = VarEnum.VT_EMPTY; - /// - public int AccessRights = Constants.OPC_READABLE | Constants.OPC_WRITEABLE; - /// - public OPCEUTYPE EuType = OPCEUTYPE.OPC_NOENUM; - /// - public double MaxValue = 0; - /// - public double MinValue = 0; - /// - public string[] EuInfo = null; - } - - /// - /// Initializes the object with a set of connection points. - /// - internal EnumOPCItemAttributes(ICollection items) - { - if (items != null) - { - foreach (ItemAttributes item in items) - { - m_items.Add(item); - } - } - } - - #region IEnumOPCItemAttributes Members - /// - public void Skip(int celt) - { - lock (m_lock) - { - try - { - m_index += celt; - - if (m_index > m_items.Count) - { - m_index = m_items.Count; - } - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Clone(out IEnumOPCItemAttributes ppEnumItemAttributes) - { - lock (m_lock) - { - try - { - ppEnumItemAttributes = new EnumOPCItemAttributes(m_items); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Reset() - { - lock (m_lock) - { - try - { - m_index = 0; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - public void Next(int celt, out System.IntPtr ppItemArray, out int pceltFetched) - { - lock (m_lock) - { - try - { - pceltFetched = 0; - ppItemArray = IntPtr.Zero; - - if (m_index >= m_items.Count) - { - return; - } - - // determine how many items to return. - pceltFetched = m_items.Count - m_index; - - if (pceltFetched > celt) - { - pceltFetched = celt; - } - - // allocate return array. - ppItemArray = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OPCITEMATTRIBUTES))*pceltFetched); - - // marshal items to return. - IntPtr pos = ppItemArray; - - for (int ii = 0; ii < pceltFetched; ii++) - { - ItemAttributes item = (ItemAttributes)m_items[m_index+ii]; - - OPCITEMATTRIBUTES copy = new OPCITEMATTRIBUTES(); - - copy.szItemID = item.ItemID; - copy.szAccessPath = item.AccessPath; - copy.hClient = item.ClientHandle; - copy.hServer = item.ServerHandle; - copy.bActive = (item.Active)?1:0; - copy.vtCanonicalDataType = (short)item.CanonicalDataType; - copy.vtRequestedDataType = (short)item.RequestedDataType; - copy.dwAccessRights = item.AccessRights; - copy.dwBlobSize = 0; - copy.pBlob = IntPtr.Zero; - copy.dwEUType = item.EuType; - copy.vEUInfo = null; - - switch (item.EuType) - { - case OPCEUTYPE.OPC_ANALOG: { copy.vEUInfo = new double[] { item.MinValue, item.MaxValue }; break; } - case OPCEUTYPE.OPC_ENUMERATED: { copy.vEUInfo = item.EuInfo; break; } - } - - Marshal.StructureToPtr(copy, pos, false); - pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMATTRIBUTES))); - } - - // update index. - m_index += pceltFetched; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - #region Private Members - private object m_lock = new object(); - private ArrayList m_items = new ArrayList(); - private int m_index = 0; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/Com.Da.Group.cs b/ComIOP/Common/Server/Da/Com.Da.Group.cs deleted file mode 100644 index 6cf5e67a6..000000000 --- a/ComIOP/Common/Server/Da/Com.Da.Group.cs +++ /dev/null @@ -1,4337 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using System.Diagnostics; -using System.Threading; - -using OpcRcw.Da; -using OpcRcw.Comn; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server.Da -{ - /// - /// A class that implements the COM-DA interfaces. - /// - public class Group : - ConnectionPointContainer, - IDisposable, - IOPCItemMgt, - IOPCSyncIO, - IOPCSyncIO2, - IOPCAsyncIO2, - IOPCAsyncIO3, - IOPCGroupStateMgt, - IOPCGroupStateMgt2, - IOPCItemDeadbandMgt, - IOPCItemSamplingMgt - { - /// - /// Initializes the object with the default values. - /// - public Group( - Server server, - object serverLock, - string name, - int serverHandle, - int clientHandle, - int updateRate, - bool active, - float deadband, - int lcid, - int timebias, - Subscription subscription, - NodeIdDictionary cache) - { - // register interface for a group object as a connection point. - RegisterInterface(typeof(OpcRcw.Da.IOPCDataCallback).GUID); - - // all the groups use the same lock as the server object. - // this is necessary because the session/subscription objects are not thread safe. - m_lock = serverLock; - - // set default values. - m_server = server; - m_subscription = subscription; - m_session = subscription.Session; - m_name = name; - m_serverHandle = serverHandle; - m_clientHandle = clientHandle; - m_updateRate = updateRate; - m_active = false; - m_deadband = deadband; - m_lcid = lcid; - m_timebias = timebias; - m_enabled = true; - m_advised = false; - m_cache = cache; - m_defaultKeepAliveCount = subscription.KeepAliveCount; - - this.PublishStateChanged(active, null); - } - - #region Public Properties - /// - /// The unique server assigned handle for the group. - /// - public int ServerHandle - { - get { return m_serverHandle; } - } - #endregion - - #region IDisposable Members - /// - /// Frees the group and all of its resources. - /// - public void Dispose() - { - lock (m_lock) - { - // delete the subscription with supressing an exception - (true). - m_subscription.Delete(true); - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// - #region IOPCItemMgt Members - /// - /// IOPCItemMgt::SetActiveState - Sets one or more items in a group to active or inactive state. - /// - public void SetActiveState( - int dwCount, - int[] phServer, - int bActive, - out System.IntPtr ppErrors) - { - // validate arguments. - if (dwCount == 0 || phServer == null || dwCount != phServer.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - Item[] itemsToModify = new Item[dwCount]; - - List monitoredItems = new List(); - MonitoringMode monitoringMode = (bActive != 0)?MonitoringMode.Reporting:MonitoringMode.Disabled; - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // update locally cached client handle. - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - monitoredItems.Add(itemToModify.MonitoredItem); - - itemsToModify[ii] = itemToModify; - errors[ii] = ResultIds.S_OK; - } - - // update items. - if (monitoredItems.Count > 0) - { - m_subscription.SetMonitoringMode(monitoringMode, monitoredItems); - } - - // check for any errors. - for (int ii = 0; ii < itemsToModify.Length; ii++) - { - Item itemToModify = itemsToModify[ii]; - - if (itemToModify == null) - { - continue; - } - - // note that the old sampling rate may no longer work if an error occurred here. - if (ServiceResult.IsBad(itemToModify.MonitoredItem.Status.Error)) - { - // restore monitoring mode. - itemToModify.MonitoredItem.MonitoringMode = (itemToModify.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled; - errors[ii] = ResultIds.E_FAIL; - continue; - } - - itemToModify.Active = bActive != 0; - itemToModify.MonitoredItem.DequeueValues(); - - if (!itemToModify.Active) - { - itemToModify.LastQualitySent = OpcRcw.Da.Qualities.OPC_QUALITY_OUT_OF_SERVICE; - } - } - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - - /// - /// IOPCItemMgt::AddItems - Adds one or more items to a group. - /// - public void AddItems( - int dwCount, - OPCITEMDEF[] pItemArray, - out System.IntPtr ppAddResults, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || pItemArray == null || dwCount != pItemArray.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - // compile set of item modifications. - int[] errors = new int[dwCount]; - OPCITEMRESULT[] results = new OPCITEMRESULT[dwCount]; - - List itemsToAdd = new List(); - - for (int ii = 0; ii < dwCount; ii++) - { - OPCITEMDEF itemToAdd = pItemArray[ii]; - - // initialize result structure. - results[ii].hServer = 0; - results[ii].dwBlobSize = 0; - results[ii].pBlob = IntPtr.Zero; - results[ii].vtCanonicalDataType = (short)VarEnum.VT_EMPTY; - results[ii].dwAccessRights = 0; - results[ii].wReserved = 0; - - // parse node id. - NodeId nodeId = Server.ItemIdToNodeId(itemToAdd.szItemID); - - if (nodeId == null) - { - errors[ii] = ResultIds.E_INVALIDITEMID; - continue; - } - - // find node. - VariableNode variable = m_session.NodeCache.Find(nodeId) as VariableNode; - - if (variable == null) - { - errors[ii] = ResultIds.E_INVALIDITEMID; - continue; - } - - // validated the requested datatype. - if (itemToAdd.vtRequestedDataType != 0) - { - if (ComUtils.GetSystemType(itemToAdd.vtRequestedDataType) == null) - { - errors[ii] = ResultIds.E_BADTYPE; - continue; - } - } - - // fill in metadata. - results[ii].vtCanonicalDataType = (short)m_server.DataTypeToVarType(variable.DataType, variable.ValueRank); - results[ii].dwAccessRights = ComUtils.GetAccessRights(variable.AccessLevel); - - if (results[ii].vtCanonicalDataType == (short)VarEnum.VT_VARIANT) - { - results[ii].vtCanonicalDataType = (short)VarEnum.VT_EMPTY; - } - - // create an item. - Item item = new Item(); - - item.ItemId = itemToAdd.szItemID; - item.ClientHandle = itemToAdd.hClient; - item.ServerHandle = ii; // save this temporarily to correlate response to request list. - item.Active = itemToAdd.bActive != 0; - item.ReqType = (VarEnum)itemToAdd.vtRequestedDataType; - item.Variable = variable; - - // check if the item supports deadband. - INode euRange = m_session.NodeCache.Find(nodeId, ReferenceTypeIds.HasProperty, false, true, Opc.Ua.BrowseNames.EURange); - - if (euRange != null) - { - item.DeadbandSupported = true; - } - - // create a monitored item. - MonitoredItem monitoredItem = new MonitoredItem(); - - monitoredItem.StartNodeId = nodeId; - monitoredItem.AttributeId = Attributes.Value; - monitoredItem.MonitoringMode = (item.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled; - monitoredItem.SamplingInterval = m_updateRate; - monitoredItem.QueueSize = 0; - monitoredItem.DiscardOldest = true; - monitoredItem.Encoding = null; - monitoredItem.Filter = null; - monitoredItem.IndexRange = null; - - if (m_deadband != 0 && item.DeadbandSupported) - { - DataChangeFilter filter = new DataChangeFilter(); - - filter.DeadbandType = (uint)(int)DeadbandType.Percent; - filter.DeadbandValue = m_deadband; - filter.Trigger = DataChangeTrigger.StatusValue; - - monitoredItem.Filter = filter; - } - - item.MonitoredItem = monitoredItem; - itemsToAdd.Add(item); - - // update the subscription. - m_subscription.AddItem(monitoredItem); - } - - if (itemsToAdd.Count > 0) - { - // create monitored items on the UA server. - m_subscription.ApplyChanges(); - - foreach (Item item in itemsToAdd) - { - // check for error during add. - int index = item.ServerHandle; - MonitoredItem monitoredItem = item.MonitoredItem; - - if (ServiceResult.IsBad(monitoredItem.Status.Error)) - { - errors[index] = Server.MapReadStatusToErrorCode(monitoredItem.Status.Error.StatusCode); - m_subscription.RemoveItem(monitoredItem); - continue; - } - - // save server handle. - results[index].hServer = item.ServerHandle = Utils.ToInt32(monitoredItem.ClientHandle); - - // add an entry in the cache. - CreateCacheEntry(item); - - // index item. - m_items[item.ServerHandle] = item; - } - } - - // marshal the results. - ppAddResults = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OPCITEMRESULT))*dwCount); - IntPtr pos = ppAddResults; - - for (int ii = 0; ii < dwCount; ii++) - { - Marshal.StructureToPtr(results[ii], pos, false); - pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMRESULT))); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemMgt::SetClientHandles - Changes the client handle for one or more items in a group. - /// - public void SetClientHandles( - int dwCount, - int[] phServer, - int[] phClient, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || phClient == null || dwCount != phServer.Length || dwCount != phClient.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - - // update locally cached client handle. - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - itemToModify.ClientHandle = phClient[ii]; - errors[ii] = ResultIds.S_OK; - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemMgt::SetDatatypes - Changes the requested data type for one or more items in a group. - /// - public void SetDatatypes( - int dwCount, - int[] phServer, - short[] pRequestedDatatypes, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || pRequestedDatatypes == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - - // update locally cached client handle. - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // validate the requested datatype. - if (pRequestedDatatypes[ii] != 0) - { - if (ComUtils.GetSystemType(pRequestedDatatypes[ii]) == null) - { - errors[ii] = ResultIds.E_BADTYPE; - continue; - } - } - - itemToModify.ReqType = (VarEnum)pRequestedDatatypes[ii]; - errors[ii] = ResultIds.S_OK; - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemMgt::ValidateItems - Determines if an item is valid. - /// Also returns information about the item such as canonical datatype, etc. - /// - public void ValidateItems( - int dwCount, - OPCITEMDEF[] pItemArray, - int bBlobUpdate, - out System.IntPtr ppValidationResults, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || pItemArray == null || dwCount != pItemArray.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - OPCITEMRESULT[] results = new OPCITEMRESULT[dwCount]; - - for (int ii = 0; ii < dwCount; ii++) - { - results[ii].hServer = 0; - results[ii].dwBlobSize = 0; - results[ii].pBlob = IntPtr.Zero; - results[ii].vtCanonicalDataType = (short)VarEnum.VT_EMPTY; - results[ii].dwAccessRights = 0; - results[ii].wReserved = 0; - - // parse node id. - NodeId nodeId = Server.ItemIdToNodeId(pItemArray[ii].szItemID); - - if (nodeId == null) - { - errors[ii] = ResultIds.E_INVALIDITEMID; - continue; - } - - // find node. - VariableNode variable = m_session.NodeCache.Find(nodeId) as VariableNode; - - if (variable == null) - { - errors[ii] = ResultIds.E_INVALIDITEMID; - continue; - } - - // validated the requested datatype. - if (pItemArray[ii].vtRequestedDataType != 0) - { - if (ComUtils.GetSystemType(pItemArray[ii].vtRequestedDataType) == null) - { - errors[ii] = ResultIds.E_BADTYPE; - continue; - } - } - - // fill in metadata. - results[ii].vtCanonicalDataType = (short)m_server.DataTypeToVarType(variable.DataType, variable.ValueRank); - results[ii].dwAccessRights = ComUtils.GetAccessRights(variable.AccessLevel); - - if (results[ii].vtCanonicalDataType == (short)VarEnum.VT_VARIANT) - { - results[ii].vtCanonicalDataType = (short)VarEnum.VT_EMPTY; - } - - errors[ii] = ResultIds.S_OK; - } - - // marshal the results. - ppValidationResults = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OPCITEMRESULT))*dwCount); - IntPtr pos = ppValidationResults; - - for (int ii = 0; ii < dwCount; ii++) - { - Marshal.StructureToPtr(results[ii], pos, false); - pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMRESULT))); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemMgt::CreateEnumerator - Creates an enumerator for the items in the group. - /// - public void CreateEnumerator(ref Guid riid, out object ppUnk) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - if (riid != typeof(OpcRcw.Da.IEnumOPCItemAttributes).GUID) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - - List itemsToEnumerate = new List(); - - foreach (Item item in m_items.Values) - { - EnumOPCItemAttributes.ItemAttributes attributes = new EnumOPCItemAttributes.ItemAttributes(); - - attributes.ItemID = item.ItemId; - attributes.AccessPath = String.Empty; - attributes.ClientHandle = item.ClientHandle; - attributes.ServerHandle = item.ServerHandle; - attributes.Active = item.Active; - attributes.RequestedDataType = item.ReqType; - attributes.AccessRights = ComUtils.GetAccessRights(item.Variable.AccessLevel); - attributes.CanonicalDataType = m_server.DataTypeToVarType(item.Variable.DataType, item.Variable.ValueRank); - attributes.EuType = OpcRcw.Da.OPCEUTYPE.OPC_NOENUM; - attributes.MaxValue = 0; - attributes.MinValue = 0; - attributes.EuInfo = null; - - if (attributes.CanonicalDataType == VarEnum.VT_VARIANT) - { - attributes.CanonicalDataType = VarEnum.VT_EMPTY; - } - - // find euRange. - VariableNode euRange = m_session.NodeCache.Find( - item.Variable.NodeId, - ReferenceTypeIds.HasProperty, - false, - true, - Opc.Ua.BrowseNames.EURange) as VariableNode; - - if (euRange != null) - { - attributes.EuType = OpcRcw.Da.OPCEUTYPE.OPC_ANALOG; - - Range range = ExtensionObject.ToEncodeable(euRange.Value.Value as ExtensionObject) as Range; - - if (range != null) - { - attributes.MaxValue = range.High; - attributes.MinValue = range.Low; - } - } - - // find enumStrings. - VariableNode enumStrings = m_session.NodeCache.Find( - item.Variable.NodeId, - ReferenceTypeIds.HasProperty, - false, - true, - Opc.Ua.BrowseNames.EnumStrings) as VariableNode; - - if (enumStrings != null) - { - attributes.EuType = OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED; - - LocalizedText[] strings = enumStrings.Value.Value as LocalizedText[]; - - if (strings != null) - { - attributes.EuInfo = new string[strings.Length]; - - for (int ii = 0; ii < strings.Length; ii++) - { - attributes.EuInfo[ii] = strings[ii].Text; - } - } - } - - // add item - itemsToEnumerate.Add(attributes); - } - - // create enumerator. - ppUnk = new EnumOPCItemAttributes(itemsToEnumerate); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemMgt::RemoveItems - Removes/Deletes one or more items from a group. - /// - public void RemoveItems( - int dwCount, - int[] phServer, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - // validate arguments. - if (dwCount == 0 || phServer == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - - // get list of items to delete. - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToDelete = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToDelete)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // release entry in the cache. - DeleteCacheEntry(itemToDelete); - - m_subscription.RemoveItem(itemToDelete.MonitoredItem); - errors[ii] = ResultIds.S_OK; - } - - // apply changes. - m_subscription.ApplyChanges(); - - // update local state. - for (int ii = 0; ii < dwCount; ii++) - { - m_items.Remove(phServer[ii]); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// - #region IOPCSyncIO Members - /// - /// IOPCSyncIO::Read - Reads the value, quality and timestamp information for one or more items in a group - /// - public void Read( - OpcRcw.Da.OPCDATASOURCE dwSource, - int dwCount, - int[] phServer, - out System.IntPtr ppItemValues, - out System.IntPtr ppErrors) - { - // validate arguments. - if (dwCount == 0 || phServer == null || dwCount != phServer.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - OpcRcw.Da.OPCITEMSTATE[] results = new OpcRcw.Da.OPCITEMSTATE[dwCount]; - int[] errors = new int[dwCount]; - VarEnum[] reqTypes = new VarEnum[dwCount]; - - // use the minimum max age for all items. - int maxAge = (dwSource == OPCDATASOURCE.OPC_DS_CACHE)?Int32.MaxValue:0; - - // build list of values to read. - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - List itemsToRead = new List(); - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - for (int ii = 0; ii < dwCount; ii++) - { - results[ii].hClient = 0; - results[ii].vDataValue = null; - results[ii].wQuality = OpcRcw.Da.Qualities.OPC_QUALITY_BAD; - results[ii].ftTimeStamp = ComUtils.GetFILETIME(DateTime.MinValue); - results[ii].wReserved = 0; - - Item itemToRead = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToRead)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - results[ii].hClient = itemToRead.ClientHandle; - - // check if reading from the cache. - if (dwSource == OPCDATASOURCE.OPC_DS_CACHE) - { - // read the value from cache. - DataValue cachedValue = ReadCachedValue(itemToRead, Int32.MaxValue); - - if (cachedValue != null) - { - // get value from the cache. - object value = null; - short quality = Qualities.OPC_QUALITY_BAD; - DateTime timestamp = DateTime.MinValue; - - errors[ii] = ProcessReadResult( - phServer[ii], - itemToRead.ReqType, - cachedValue, - out value, - out quality, - out timestamp); - - // all done if a suitable value is in the cache. - if (!m_active || !itemToRead.Active) - { - quality = Qualities.OPC_QUALITY_OUT_OF_SERVICE; - } - - results[ii].vDataValue = value; - results[ii].wQuality = quality; - results[ii].ftTimeStamp = ComUtils.GetFILETIME(timestamp); - continue; - } - } - - // save the requested data type. - reqTypes[ii] = itemToRead.ReqType; - - ReadValueId nodeToRead = new ReadValueId(); - - nodeToRead.NodeId = itemToRead.MonitoredItem.ResolvedNodeId; - nodeToRead.AttributeId = Attributes.Value; - - // needed to correlate results to input. - nodeToRead.Handle = ii; - - nodesToRead.Add(nodeToRead); - itemsToRead.Add(itemToRead); - } - } - - // read values from server. - DataValueCollection values = null; - DiagnosticInfoCollection diagnosticInfos = null; - - if (nodesToRead.Count > 0) - { - m_session.Read( - null, - maxAge, - TimestampsToReturn.Both, - nodesToRead, - out values, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(values, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - } - - for (int ii = 0; ii < nodesToRead.Count; ii++) - { - // get index in original array. - int index = (int)nodesToRead[ii].Handle; - - // process the read result. - object value = null; - short quality = Qualities.OPC_QUALITY_BAD; - DateTime timestamp = DateTime.MinValue; - - int error = ProcessReadResult( - phServer[index], - reqTypes[index], - values[ii], - out value, - out quality, - out timestamp); - - // update the cache. - UpdateCachedValue(itemsToRead[ii], values[ii]); - - // check for error. - if (error < 0) - { - errors[index] = error; - continue; - } - - // update response. - results[index].vDataValue = value; - results[index].wQuality = quality; - results[index].ftTimeStamp = ComUtils.GetFILETIME(timestamp); - - errors[index] = ResultIds.S_OK; - } - - // marshal the results. - ppItemValues = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OPCITEMSTATE))*dwCount); - IntPtr pos = ppItemValues; - - for (int ii = 0; ii < dwCount; ii++) - { - Marshal.StructureToPtr(results[ii], pos, false); - pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMSTATE))); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - Utils.Trace(e, "Error reading items."); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Processes a value read from the server. - /// - private int ProcessReadResult( - int serverHandle, - VarEnum reqType, - DataValue dataValue, - out object value, - out short quality, - out DateTime timestamp) - { - value = null; - quality = Qualities.OPC_QUALITY_BAD; - timestamp = DateTime.MinValue; - - // check for invalid response from server. - if (dataValue == null) - { - return ResultIds.E_FAIL; - } - - // check for error. - int error = Server.MapReadStatusToErrorCode(dataValue.StatusCode); - - if (error < 0) - { - return error; - } - - // convert UA value to VARIANT value. - value = ComUtils.GetVARIANT(dataValue.Value); - quality = ComUtils.GetQualityCode(dataValue.StatusCode); - timestamp = dataValue.SourceTimestamp; - - // do any data conversion. - if (dataValue.Value != null && reqType != VarEnum.VT_EMPTY) - { - object changedValue = null; - error = ComUtils.ChangeTypeForCOM(value, reqType, out changedValue); - - if (error < 0) - { - value = null; - quality = OpcRcw.Da.Qualities.OPC_QUALITY_BAD; - return error; - } - - value = changedValue; - } - - return ResultIds.S_OK; - } - - /// - /// IOPCSyncIO::Write - Writes values to one or more items in a group. - /// - public void Write( - int dwCount, - int[] phServer, - object[] pItemValues, - out System.IntPtr ppErrors) - { - // validate arguments. - if (dwCount == 0 || phServer == null || pItemValues == null || dwCount != phServer.Length || dwCount != pItemValues.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - - // build list of values to write. - WriteValueCollection valuesToWrite = new WriteValueCollection(); - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToWrite = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToWrite)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - VariableNode variable = itemToWrite.Variable; - - WriteValue valueToWrite = new WriteValue(); - - valueToWrite.NodeId = variable.NodeId; - valueToWrite.IndexRange = null; - valueToWrite.AttributeId = Attributes.Value; - - DataValue value = new DataValue(); - - int error = 0; - value.Value = m_server.VariantValueToValue(variable, pItemValues[ii], out error); - - if (error != ResultIds.S_OK) - { - errors[ii] = error; - continue; - } - - valueToWrite.Value = value; - - // needed to correlate results to input. - valueToWrite.Handle = ii; - - valuesToWrite.Add(valueToWrite); - } - } - - // write values from server. - StatusCodeCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - if (valuesToWrite.Count > 0) - { - m_session.Write( - null, - valuesToWrite, - out results, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(results, valuesToWrite); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToWrite); - - //Utils.Trace( - // "SyncWrite: GroupHandle={0}, ServerHandle={1}, Value={2}", - // m_clientHandle, - // phServer[0], - // valuesToWrite[0].Value.WrappedValue); - } - - for (int ii = 0; ii < valuesToWrite.Count; ii++) - { - // get index in original array. - int index = (int)valuesToWrite[ii].Handle; - - // map UA code to DA code. - errors[index] = Server.MapWriteStatusToErrorCode(results[ii]); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - Utils.Trace(e, "Error writing items."); - throw ComUtils.CreateComException(e); - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// - #region IOPCSyncIO2 Members - /// - /// IOPCSyncIO2::ReadMaxAge - Reads one or more values, qualities and timestamps for the items specified. - /// - public void ReadMaxAge( - int dwCount, - int[] phServer, - int[] pdwMaxAge, - out System.IntPtr ppvValues, - out System.IntPtr ppwQualities, - out System.IntPtr ppftTimeStamps, - out System.IntPtr ppErrors) - { - // validate arguments. - if (dwCount == 0 || phServer == null || pdwMaxAge == null || dwCount != phServer.Length || dwCount != pdwMaxAge.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - object[] values = new object[dwCount]; - short[] qualities = new short[dwCount]; - DateTime[] timestamps = new DateTime[dwCount]; - int[] errors = new int[dwCount]; - VarEnum[] reqTypes = new VarEnum[dwCount]; - - // use the minimum max age for all items. - int maxAge = Int32.MaxValue; - - // build list of values to read. - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - List itemsToRead = new List(); - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - for (int ii = 0; ii < dwCount; ii++) - { - values[ii] = null; - qualities[ii] = OpcRcw.Da.Qualities.OPC_QUALITY_BAD; - timestamps[ii] = DateTime.MinValue; - - Item itemToRead = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToRead)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // check if reading from the cache. - if (pdwMaxAge[ii] > 0) - { - DataValue cachedValue = ReadCachedValue(itemToRead, pdwMaxAge[ii]); - - if (cachedValue != null) - { - // get value from the cache. - object value = null; - short quality = Qualities.OPC_QUALITY_BAD; - DateTime timestamp = DateTime.MinValue; - - errors[ii] = ProcessReadResult( - phServer[ii], - itemToRead.ReqType, - cachedValue, - out value, - out quality, - out timestamp); - - // all done if a suitable value is in the cache. - if (!m_active || !itemToRead.Active) - { - quality = Qualities.OPC_QUALITY_OUT_OF_SERVICE; - } - - values[ii] = value; - qualities[ii] = quality; - timestamps[ii] = timestamp; - continue; - } - } - - ReadValueId nodeToRead = new ReadValueId(); - - nodeToRead.NodeId = itemToRead.Variable.NodeId; - nodeToRead.AttributeId = Attributes.Value; - - // save the requested data type. - reqTypes[ii] = itemToRead.ReqType; - - // needed to correlate results to input. - nodeToRead.Handle = ii; - - nodesToRead.Add(nodeToRead); - itemsToRead.Add(itemToRead); - - // calculate max age. - if (maxAge > pdwMaxAge[ii]) - { - maxAge = pdwMaxAge[ii]; - } - } - } - - // read values from server. - DataValueCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - if (nodesToRead.Count > 0) - { - m_session.Read( - null, - maxAge, - TimestampsToReturn.Both, - nodesToRead, - out results, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(results, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - } - - for (int ii = 0; ii < nodesToRead.Count; ii++) - { - // get index in original array. - int index = (int)nodesToRead[ii].Handle; - - // process the read result. - object value = null; - short quality = Qualities.OPC_QUALITY_BAD; - DateTime timestamp = DateTime.MinValue; - - int error = ProcessReadResult( - phServer[index], - reqTypes[index], - results[ii], - out value, - out quality, - out timestamp); - - // update the read cache. - UpdateCachedValue(itemsToRead[ii], results[ii]); - - // check for error. - if (error < 0) - { - errors[index] = error; - continue; - } - - // update response. - values[index] = value; - qualities[index] = quality; - timestamps[index] = timestamp; - - errors[index] = ResultIds.S_OK; - } - - // marshal results. - ppvValues = ComUtils.GetVARIANTs(values, false); - ppwQualities = ComUtils.GetInt16s(qualities); - ppftTimeStamps = ComUtils.GetFILETIMEs(timestamps); - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - - /// - /// IOPCSyncIO2::WriteVQT - Writes one or more values, qualities and timestamps for the items specified. - /// - public void WriteVQT( - int dwCount, - int[] phServer, - OPCITEMVQT[] pItemVQT, - out System.IntPtr ppErrors) - { - // validate arguments. - if (dwCount == 0 || phServer == null || pItemVQT == null || dwCount != phServer.Length || dwCount != pItemVQT.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - - // build list of values to write. - WriteValueCollection valuesToWrite = new WriteValueCollection(); - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToWrite = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToWrite)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - WriteValue valueToWrite = new WriteValue(); - - valueToWrite.NodeId = itemToWrite.Variable.NodeId; - valueToWrite.IndexRange = null; - valueToWrite.AttributeId = Attributes.Value; - - DataValue value = new DataValue(); - - int error = 0; - value.Value = m_server.VariantValueToValue(itemToWrite.Variable, pItemVQT[ii].vDataValue, out error); - - if (error != ResultIds.S_OK) - { - errors[ii] = error; - continue; - } - - if (pItemVQT[ii].bQualitySpecified != 0) - { - value.StatusCode = ComUtils.GetQualityCode(pItemVQT[ii].wQuality); - } - - if (pItemVQT[ii].bTimeStampSpecified != 0) - { - value.SourceTimestamp = ComUtils.GetDateTime(pItemVQT[ii].ftTimeStamp); - } - - valueToWrite.Value = value; - - // needed to correlate results to input. - valueToWrite.Handle = ii; - - valuesToWrite.Add(valueToWrite); - } - } - - // write values from server. - StatusCodeCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - if (valuesToWrite.Count > 0) - { - m_session.Write( - null, - valuesToWrite, - out results, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(results, valuesToWrite); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToWrite); - } - - for (int ii = 0; ii < valuesToWrite.Count; ii++) - { - // get index in original array. - int index = (int)valuesToWrite[ii].Handle; - - // map UA code to DA code. - errors[index] = Server.MapWriteStatusToErrorCode(results[ii]); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv// - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// - #region IOPCAsyncIO2 Members - /// - /// IOPCAsyncIO2::Read - Read one or more items in a group. The results are returned via the client�s - /// IOPCDataCallback connection established through the server�s IConnectionPointContainer. - /// - public void Read( - int dwCount, - int[] phServer, - int dwTransactionID, - out int pdwCancelID, - out System.IntPtr ppErrors) - { - pdwCancelID = 0; - - // validate arguments. - if (dwCount == 0 || phServer == null || dwCount != phServer.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // get callback object - nothing more to do if missing. - IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID); - - if (callback == null) - { - throw ComUtils.CreateComException(ResultIds.CONNECT_E_NOCONNECTION); - } - - try - { - int[] errors = new int[dwCount]; - - // build list of values to read. - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToRead = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToRead)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - ReadValueId nodeToRead = new ReadValueId(); - - nodeToRead.NodeId = itemToRead.MonitoredItem.ResolvedNodeId; - nodeToRead.AttributeId = Attributes.Value; - - // needed to correlate results to input. - nodeToRead.Handle = itemToRead; - - nodesToRead.Add(nodeToRead); - } - - // create a transaction. - if (nodesToRead.Count > 0) - { - pdwCancelID = Utils.IncrementIdentifier(ref m_nextHandle); - m_transactions[pdwCancelID] = new AsyncReadTransaction(dwTransactionID, nodesToRead, false); - } - } - - // read values from server. - if (nodesToRead.Count > 0) - { - m_session.BeginRead( - null, - 0, - TimestampsToReturn.Both, - nodesToRead, - new AsyncCallback(OnReadComplete), - pdwCancelID); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - Utils.Trace(e, "Error reading items."); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Called when an asynchronous read operation completes. - /// - private void OnReadComplete(IAsyncResult result) - { - AsyncReadTransaction transaction = null; - - lock (m_lock) - { - // complete the operation. - DataValueCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - int serviceError = ResultIds.S_OK; - - try - { - m_session.EndRead( - result, - out results, - out diagnosticInfos); - } - catch (Exception) - { - serviceError = ResultIds.E_FAIL; - } - - try - { - // check if transaction has been cancelled. - int cancelId = (int)result.AsyncState; - - Transaction transaction2 = null; - - if (!m_transactions.TryGetValue(cancelId, out transaction2)) - { - return; - } - - transaction = (AsyncReadTransaction)transaction2; - m_transactions.Remove(cancelId); - - // get callback object - nothing more to do if missing. - IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID); - - if (callback == null) - { - return; - } - - // process results. - ReadValueIdCollection nodesToRead = transaction.NodesToRead; - - List callbackValues = new List(); - - for (int ii = 0; ii < nodesToRead.Count; ii++) - { - // get item in originally read. - Item itemToRead = (Item)nodesToRead[ii].Handle; - - // process the read result. - object value = null; - short quality = Qualities.OPC_QUALITY_BAD; - DateTime timestamp = DateTime.MinValue; - int error = serviceError; - - if (serviceError >= 0) - { - error = ProcessReadResult( - itemToRead.ServerHandle, - itemToRead.ReqType, - results[ii], - out value, - out quality, - out timestamp); - - // update the cache. - UpdateCachedValue(itemToRead, results[ii]); - } - - CallbackValue callbackValue = new CallbackValue(); - - callbackValue.ClientHandle = itemToRead.ClientHandle; - callbackValue.Value = value; - callbackValue.Quality = quality; - callbackValue.Timestamp = timestamp; - callbackValue.Error = error; - - callbackValues.Add(callbackValue); - } - - // queue the callback. - CallbackRequest request = new CallbackRequest(); - - request.CallbackType = (transaction.IsRefresh)?CallbackType.DataChange:CallbackType.Read; - request.Callback = callback; - request.TransactionId = transaction.TransactionId; - request.GroupHandle = m_clientHandle; - request.ServerHandle = m_serverHandle; - request.Values = callbackValues; - - QueueCallbackRequest(request); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing asynchronous read callback."); - } - } - } - - /// - /// IOPCAsyncIO2::Write - Write one or more items in a group. The results are returned via the client�s - /// IOPCDataCallback connection established through the server�s IConnectionPointContainer. - /// - public void Write( - int dwCount, - int[] phServer, - object[] pItemValues, - int dwTransactionID, - out int pdwCancelID, - out System.IntPtr ppErrors) - { - pdwCancelID = 0; - - // validate arguments. - if (dwCount == 0 || phServer == null || pItemValues == null || dwCount != phServer.Length || dwCount != pItemValues.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // get callback object - nothing more to do if missing. - IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID); - - if (callback == null) - { - throw ComUtils.CreateComException(ResultIds.CONNECT_E_NOCONNECTION); - } - - try - { - int[] errors = new int[dwCount]; - - // build list of values to write. - WriteValueCollection valuesToWrite = new WriteValueCollection(); - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - CallbackValue[] conversionErrors = null; - - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToWrite = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToWrite)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - VariableNode variable = itemToWrite.Variable; - - WriteValue valueToWrite = new WriteValue(); - - valueToWrite.NodeId = variable.NodeId; - valueToWrite.IndexRange = null; - valueToWrite.AttributeId = Attributes.Value; - - DataValue value = new DataValue(); - - int error = 0; - value.Value = m_server.VariantValueToValue(variable, pItemValues[ii], out error); - - if (error != ResultIds.S_OK) - { - // only allocate this array when it is needed. - if (conversionErrors == null) - { - conversionErrors = new CallbackValue[dwCount]; - } - - // create the callback item. - CallbackValue conversionError = new CallbackValue(); - - conversionError.ClientHandle = itemToWrite.ClientHandle; - conversionError.Error = error; - - conversionErrors[ii] = conversionError; - - errors[ii] = error; - continue; - } - - valueToWrite.Value = value; - - // needed to correlate results to input. - valueToWrite.Handle = itemToWrite; - - valuesToWrite.Add(valueToWrite); - } - - // create transaction. - if (valuesToWrite.Count > 0 || conversionErrors != null) - { - pdwCancelID = Utils.IncrementIdentifier(ref m_nextHandle); - m_transactions[pdwCancelID] = new AsyncWriteTransaction(dwTransactionID, valuesToWrite); - } - - // send conversion errors in the callback if no valid items available (CTT bug workaround). - if (valuesToWrite.Count == 0 && conversionErrors != null) - { - // must return S_OK from this function if sending the errors in the callback. - List errorsToSend = new List(); - - for (int ii = 0; ii < conversionErrors.Length; ii++) - { - if (conversionErrors[ii] != null) - { - errors[ii] = ResultIds.S_OK; - errorsToSend.Add(conversionErrors[ii]); - } - } - - // queue the request. - CallbackRequest request = new CallbackRequest(); - - request.CallbackType = CallbackType.Write; - request.Callback = callback; - request.TransactionId = dwTransactionID; - request.GroupHandle = m_clientHandle; - request.ServerHandle = m_serverHandle; - request.Values = errorsToSend; - - QueueCallbackRequest(request); - } - } - - // write values to server. - if (valuesToWrite.Count > 0) - { - m_session.BeginWrite( - null, - valuesToWrite, - new AsyncCallback(OnWriteComplete), - pdwCancelID); - - // Utils.Trace( - // "AsyncWrite: GroupHandle={0}, ServerHandle={1}, Value={2}, CancelID={3}", - // m_clientHandle, - // phServer[0], - // valuesToWrite[0].Value.WrappedValue, - // pdwCancelID); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - Utils.Trace(e, "Error writing items."); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Called when an asynchronous write operation completes. - /// - private void OnWriteComplete(IAsyncResult result) - { - AsyncWriteTransaction transaction = null; - - lock (m_lock) - { - // complete the write operation. - StatusCodeCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - int serviceError = ResultIds.S_OK; - - try - { - m_session.EndWrite( - result, - out results, - out diagnosticInfos); - } - catch (Exception) - { - serviceError = ResultIds.E_FAIL; - } - - try - { - // check if transaction has been cancelled. - int cancelId = (int)result.AsyncState; - - Transaction transaction2 = null; - - if (!m_transactions.TryGetValue(cancelId, out transaction2)) - { - return; - } - - transaction = (AsyncWriteTransaction)transaction2; - m_transactions.Remove(cancelId); - - // get callback object - nothing more to do if missing. - IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID); - - if (callback == null) - { - return; - } - - // process results. - WriteValueCollection valuesToWrite = transaction.ValuesToWrite; - - List callbackValues = new List(); - - for (int ii = 0; ii < valuesToWrite.Count; ii++) - { - // get item originally written. - Item itemToWrite = (Item)valuesToWrite[ii].Handle; - - int error = serviceError; - - // get for operation level error. - if (serviceError >= 0) - { - error = Server.MapWriteStatusToErrorCode(results[ii]); - } - - CallbackValue callbackValue = new CallbackValue(); - - callbackValue.ClientHandle = itemToWrite.ClientHandle; - callbackValue.Error = error; - - callbackValues.Add(callbackValue); - } - - // queue the callback. - CallbackRequest request = new CallbackRequest(); - - request.CallbackType = CallbackType.Write; - request.Callback = callback; - request.TransactionId = transaction.TransactionId; - request.GroupHandle = m_clientHandle; - request.ServerHandle = m_serverHandle; - request.Values = callbackValues; - - QueueCallbackRequest(request); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing asynchronous write callback."); - } - } - } - - /// - /// IOPCAsyncIO2::Cancel2 - Request that the server cancel an outstanding transaction. - /// - public void Cancel2(int dwCancelID) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // get callback object - error if missing. - IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID); - - if (callback == null) - { - throw ComUtils.CreateComException(ResultIds.CONNECT_E_NOCONNECTION); - } - - try - { - // see if transaction has already completed. - Transaction transaction = null; - - if (!m_transactions.TryGetValue(dwCancelID, out transaction)) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - // remove transaction - results will be discarded. - m_transactions.Remove(dwCancelID); - - // Utils.Trace( - // "AsyncCancel: GroupHandle={0}, CancelID={1}", - // m_clientHandle, - // dwCancelID); - - // queue the callback. - CallbackRequest request = new CallbackRequest(); - - request.CallbackType = CallbackType.Cancel; - request.Callback = callback; - request.TransactionId = transaction.TransactionId; - request.GroupHandle = m_clientHandle; - request.ServerHandle = m_serverHandle; - - QueueCallbackRequest(request); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCAsyncIO2::Refresh2 - Forces a callback to IOPCDataCallback::OnDataChange for all active items - /// in the group (whether they have changed or not). Inactive items are not included in the callback. - /// - public void Refresh2( - OpcRcw.Da.OPCDATASOURCE dwSource, - int dwTransactionID, - out int pdwCancelID) - { - // calculate max age. - int maxAge = (dwSource == OPCDATASOURCE.OPC_DS_DEVICE)?0:Int32.MaxValue; - - // call refresh. - RefreshMaxAge(maxAge, dwTransactionID, out pdwCancelID); - } - - /// - /// IOPCAsyncIO2::GetEnable - Retrieves the last Callback Enable value set with SetEnable. - /// - public void GetEnable(out int pbEnable) - { - lock (m_lock) - { - // check for callback. - if (!IsConnected(typeof(IOPCDataCallback).GUID)) - { - throw ComUtils.CreateComException(ResultIds.CONNECT_E_NOCONNECTION); - } - - try - { - pbEnable = (m_enabled)?1:0; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCAsyncIO2::SetEnable - Controls the operation of OnDataChange. - /// Setting Enable to FALSE will disable any OnDataChange callbacks with - /// a transaction ID of 0 (those which are not the result of a Refresh). - /// - public void SetEnable(int bEnable) - { - // check for callback. - if (!IsConnected(typeof(IOPCDataCallback).GUID)) - { - throw ComUtils.CreateComException(ResultIds.CONNECT_E_NOCONNECTION); - } - - try - { - PublishStateChanged(null, (bEnable != 0)); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - - /// - /// Updates publishing mode after the enabled or active state changed. - /// - private void PublishStateChanged(bool? active, bool? enabled) - { - bool stateChanged = false; - bool publishingEnabled = false; - - lock (m_lock) - { - bool wasPublishing = m_active; - - if (active != null) - { - m_active = active.Value; - } - - if (enabled != null) - { - m_enabled = enabled.Value; - } - - publishingEnabled = m_active; - stateChanged = publishingEnabled != wasPublishing; - - if (stateChanged) - { - // flag the items as out of service. - if (!m_active) - { - foreach (Item item in m_items.Values) - { - item.LastQualitySent = OpcRcw.Da.Qualities.OPC_QUALITY_OUT_OF_SERVICE; - } - } - - //Utils.Trace( - // "PublishStateChange: GroupHandle={0}, Active {1}, Enabled {2}, Advised {3}", - // m_clientHandle, - // m_active, - // m_enabled, - // m_advised); - - // must always send an update immidiately. - if (publishingEnabled) - { - QueueDataChange(true); - } - - // schedule the next update. - m_nextUpdate = DateTime.UtcNow.Ticks + m_updateRate*TimeSpan.TicksPerMillisecond; - } - } - - // enable publishing. - if (stateChanged) - { - m_subscription.SetPublishingMode(publishingEnabled); - } - } - - /// - /// Called when the client adds the callback. - /// - public override void OnAdvise(Guid riid) - { - base.OnAdvise(riid); - - if (riid == typeof(IOPCDataCallback).GUID) - { - lock (m_lock) - { - if (!m_advised && m_active) - { - QueueDataChange(true); - } - - m_advised = true; - } - } - } - - /// - /// Called when the client removes the callback. - /// - public override void OnUnadvise(Guid riid) - { - base.OnAdvise(riid); - - if (riid == typeof(IOPCDataCallback).GUID) - { - m_advised = false; - } - } - - /// - /// Processes a Publish repsonse from the server. - /// - public void Update(long ticks) - { - lock (m_lock) - { - // check if it is time for the next update. - if (m_nextUpdate > ticks) - { - return; - } - - // Utils.Trace( - // "Checking For Updates: Group={0}, Rate={1}, Delta={2}", - // m_clientHandle, - // m_updateRate, - // (ticks - m_nextUpdate)/TimeSpan.TicksPerMillisecond); - - // queue a data channge. - QueueDataChange(false); - - // schedule the next update. - m_nextUpdate = DateTime.UtcNow.Ticks + m_updateRate*TimeSpan.TicksPerMillisecond; - } - } - - /// - /// Queues a datachange. - /// - private void QueueDataChange(bool sendAll) - { - // dequeue values from monitored item caches. - List changes = new List(); - - foreach (Item item in this.m_items.Values) - { - IList values = item.MonitoredItem.DequeueValues(); - - // send the cached value if an update must be sent. - if (sendAll && values.Count == 0) - { - values = new DataValue[1]; - - // look of value in the publishing cache. - DataValue dataValue = ReadCachedValue(item, Int32.MaxValue); - - // create a dummy value if nothing in the cache. - if (dataValue == null) - { - dataValue = new DataValue(); - dataValue.ServerTimestamp = DateTime.UtcNow; - dataValue.StatusCode = StatusCodes.BadWaitingForInitialData; - } - - values[0] = dataValue; - } - - //Utils.Trace( - // "Values Found: Group={0}, Changes={1}", - // m_clientHandle, - // values.Count); - - for (int ii = 0; ii < values.Count; ii++) - { - // apply any type conversions. - object value; - short quality; - DateTime timestamp; - - int error = ProcessReadResult( - item.ServerHandle, - item.ReqType, - values[ii], - out value, - out quality, - out timestamp); - - item.LastValueSent = value; - item.LastQualitySent = quality; - item.LastTimestampSent = timestamp; - - // update value in cache. - UpdateCachedValue(item, values[ii]); - - // create callback value for active items - if (item.Active && m_active && m_enabled) - { - CallbackValue change = new CallbackValue(); - - change.ServerHandle = item.ServerHandle; - change.ClientHandle = item.ClientHandle; - change.Value = value; - change.Quality = quality; - change.Timestamp = timestamp; - change.Error = error; - - changes.Add(change); - } - } - } - - // get callback object - do nothing if missing. - IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID); - - if (callback == null) - { - return; - } - - // check if there are changes to send. - if (changes.Count > 0) - { - CallbackRequest request = new CallbackRequest(); - - request.CallbackType = CallbackType.DataChange; - request.Callback = callback; - request.GroupHandle = m_clientHandle; - request.ServerHandle = m_serverHandle; - request.Values = changes; - - //Utils.Trace( - // "Callback Queued: Group={0}, Changes={1}, Value[0]={2}", - // m_clientHandle, - // changes.Count, - // changes[0].Value); - - QueueCallbackRequest(request); - } - } - - #region CallbackType Enumeration - /// - /// The type of callback to send. - /// - private enum CallbackType - { - /// - /// A data change callback. - /// - DataChange, - - /// - /// A read operation complete callback. - /// - Read, - - /// - /// A write operation complete callback. - /// - Write, - - /// - /// A cancel operation complete callback. - /// - Cancel - } - #endregion - - #region CallbackValue Class - /// - /// A value to send in the callback. - /// - private class CallbackValue - { - /// - /// The handle assigned by the server to the associated item. - /// - public int ServerHandle; - - /// - /// The handle assigned by the client to the associated item. - /// - public int ClientHandle; - - /// - /// The value in a COM VARIANT compatible form. - /// - public object Value; - - /// - /// The COM-DA quality code. - /// - public short Quality; - - /// - /// The source timestamp. - /// - public DateTime Timestamp; - - /// - /// The COM error code associated with the value or operation. - /// - public int Error; - } - #endregion - - #region CallbackValue Class - /// - /// A request to send a callback to the client. - /// - private class CallbackRequest - { - /// - /// The type of callback, - /// - public CallbackType CallbackType; - - /// - /// The callback interface to use. - /// - public IOPCDataCallback Callback; - - /// - /// The handle assigned by the server to the group. - /// - public int ServerHandle; - - /// - /// The handle assigned by the client to the group. - /// - public int GroupHandle; - - /// - /// The transaction id assigned by the client to the operation. - /// - public int TransactionId; - - /// - /// The set of values or error codes to send to the client. - /// - public IList Values; - } - #endregion - - /// - /// Queues a callback request. Assigns a worker thread if one is not already assigned. - /// - private void QueueCallbackRequest(CallbackRequest callback) - { - lock (m_callbacks) - { - if (m_callbacks.Count == 0) - { - ThreadPool.QueueUserWorkItem(OnCallback); - } - - m_callbacks.Enqueue(callback); - } - } - - /// - /// Sends all callbacks in the queue and then exits. - /// - private void OnCallback(object state) - { - try - { - while (true) - { - CallbackRequest callback = null; - - lock (m_callbacks) - { - // exit the thread if nothing to send. - if (m_callbacks.Count == 0) - { - return; - } - - // dob't extract the callback yet - we don't want other threads starting until after this callback is sent. - callback = m_callbacks.Peek(); - } - - // send the callback. - try - { - switch (callback.CallbackType) - { - case CallbackType.DataChange: - case CallbackType.Read: - { - SendReadCallback(callback); - break; - } - - case CallbackType.Write: - { - SendWriteCallback(callback); - break; - } - - case CallbackType.Cancel: - { - SendCancelCallback(callback); - break; - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error sending callback."); - } - - lock (m_callbacks) - { - // remove the callback that was just sent. - m_callbacks.Dequeue(); - - // exit the thread if nothing to send. - if (m_callbacks.Count == 0) - { - return; - } - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error processing callback queue."); - } - } - - /// - /// Sends a read or datachange callback to the client. - /// - private void SendReadCallback(CallbackRequest callback) - { - int count = callback.Values.Count; - - int masterError = ResultIds.S_OK; - int masterQuality = ResultIds.S_OK; - - int[] clientHandles = new int[count]; - object[] values = new object[count]; - short[] qualities = new short[count]; - System.Runtime.InteropServices.ComTypes.FILETIME[] timestamps = new System.Runtime.InteropServices.ComTypes.FILETIME[count]; - int[] errors = new int[count]; - - for (int ii = 0; ii < callback.Values.Count; ii++) - { - CallbackValue change = callback.Values[ii]; - - clientHandles[ii] = change.ClientHandle; - values[ii] = change.Value; - qualities[ii] = change.Quality; - timestamps[ii] = ComUtils.GetFILETIME(change.Timestamp); - errors[ii] = change.Error; - - // check error. - if (change.Error < 0) - { - masterError = ResultIds.S_FALSE; - continue; - } - - // set the master quality if any bad qualities are found. - if ((change.Quality & Qualities.OPC_QUALITY_GOOD) != Qualities.OPC_QUALITY_GOOD) - { - masterQuality = ResultIds.S_FALSE; - } - } - - //Utils.Trace( - // "DataChange: GroupHandle={0}, Count={1}, ServerHandle={2}, Value={3}", - // callback.ServerHandle, - // callback.Values.Count, - // callback.Values[0].ServerHandle, - // callback.Values[0].Value); - - if (callback.CallbackType == CallbackType.DataChange) - { - callback.Callback.OnDataChange( - callback.TransactionId, - callback.GroupHandle, - masterQuality, - masterError, - count, - clientHandles, - values, - qualities, - timestamps, - errors); - - m_server.SetLastUpdate(); - } - else - { - callback.Callback.OnReadComplete( - callback.TransactionId, - callback.GroupHandle, - masterQuality, - masterError, - count, - clientHandles, - values, - qualities, - timestamps, - errors); - } - } - - /// - /// Sends a write callback to the client. - /// - private void SendWriteCallback(CallbackRequest callback) - { - int count = callback.Values.Count; - - int masterError = ResultIds.S_OK; - - int[] clientHandles = new int[count]; - int[] errors = new int[count]; - - for (int ii = 0; ii < callback.Values.Count; ii++) - { - CallbackValue result = callback.Values[ii]; - - clientHandles[ii] = result.ClientHandle; - errors[ii] = result.Error; - - if (result.Error < 0) - { - masterError = ResultIds.S_FALSE; - } - } - - // Utils.Trace( - // "WriteComplete: GroupHandle={0}, ServerHandle={1}, Error={2}", - // callback.GroupHandle, - // callback.Values[0].ClientHandle, - // callback.Values[0].Error); - - callback.Callback.OnWriteComplete( - callback.TransactionId, - callback.GroupHandle, - masterError, - count, - clientHandles, - errors); - } - - /// - /// Sends a cancel callback to the client. - /// - private void SendCancelCallback(CallbackRequest callback) - { - // Utils.Trace( - // "CancelComplete: GroupHandle={0}, TransactionId={1}", - // callback.GroupHandle, - // callback.TransactionId); - - callback.Callback.OnCancelComplete(callback.TransactionId, callback.GroupHandle); - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// - #region IOPCAsyncIO3 Members - /// - /// IOPCAsyncIO3::ReadMaxAge - Reads one or more values, qualities and timestamps for the items specified. - /// This is functionally similar to the OPCSyncIO::Read method except it is asynchronous - /// and no source is specified (DEVICE or CACHE). - /// - public void ReadMaxAge( - int dwCount, - int[] phServer, - int[] pdwMaxAge, - int dwTransactionID, - out int pdwCancelID, - out System.IntPtr ppErrors) - { - pdwCancelID = 0; - - // validate arguments. - if (dwCount == 0 || phServer == null || pdwMaxAge == null || dwCount != phServer.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // get callback object - error if missing. - IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID); - - if (callback == null) - { - throw ComUtils.CreateComException(ResultIds.CONNECT_E_NOCONNECTION); - } - - try - { - int[] errors = new int[dwCount]; - - // build list of values to read. - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - - // use the minimum max age for all items. - int maxAge = Int32.MaxValue; - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToRead = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToRead)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - ReadValueId nodeToRead = new ReadValueId(); - - nodeToRead.NodeId = itemToRead.MonitoredItem.ResolvedNodeId; - nodeToRead.AttributeId = Attributes.Value; - - // needed to correlate results to input. - nodeToRead.Handle = itemToRead; - - nodesToRead.Add(nodeToRead); - - // update max age. - if (maxAge > pdwMaxAge[ii]) - { - maxAge = pdwMaxAge[ii]; - } - } - - // create transaction. - if (nodesToRead.Count > 0) - { - pdwCancelID = Utils.IncrementIdentifier(ref m_nextHandle); - m_transactions[pdwCancelID] = new AsyncReadTransaction(dwTransactionID, nodesToRead, false); - } - } - - // read values from server. - if (nodesToRead.Count > 0) - { - m_session.BeginRead( - null, - maxAge, - TimestampsToReturn.Both, - nodesToRead, - new AsyncCallback(OnReadComplete), - pdwCancelID); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - Utils.Trace(e, "Error reading items."); - throw ComUtils.CreateComException(e); - } - } - - /// - /// IOPCAsyncIO3::WriteVQT - Writes one or more values, qualities and timestamps for the items specified. - /// The results are returned via the client�s IOPCDataCallback connection established - /// through the server�s IConnectionPointContainer. - /// - public void WriteVQT( - int dwCount, - int[] phServer, - OPCITEMVQT[] pItemVQT, - int dwTransactionID, - out int pdwCancelID, - out System.IntPtr ppErrors) - { - pdwCancelID = 0; - - // validate arguments. - if (dwCount == 0 || phServer == null || pItemVQT == null || dwCount != phServer.Length || dwCount != pItemVQT.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // get callback object - nothing more to do if missing. - IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID); - - if (callback == null) - { - throw ComUtils.CreateComException(ResultIds.CONNECT_E_NOCONNECTION); - } - - try - { - int[] errors = new int[dwCount]; - - // build list of values to write. - WriteValueCollection valuesToWrite = new WriteValueCollection(); - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - CallbackValue[] conversionErrors = null; - - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToWrite = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToWrite)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - VariableNode variable = itemToWrite.Variable; - - WriteValue valueToWrite = new WriteValue(); - - valueToWrite.NodeId = variable.NodeId; - valueToWrite.IndexRange = null; - valueToWrite.AttributeId = Attributes.Value; - - DataValue value = new DataValue(); - - int error = 0; - value.Value = m_server.VariantValueToValue(variable, pItemVQT[ii].vDataValue, out error); - - if (error != ResultIds.S_OK) - { - // only allocate this array when it is needed. - if (conversionErrors == null) - { - conversionErrors = new CallbackValue[dwCount]; - } - - // create the callback item. - CallbackValue conversionError = new CallbackValue(); - - conversionError.ClientHandle = itemToWrite.ClientHandle; - conversionError.Error = error; - - conversionErrors[ii] = conversionError; - - errors[ii] = error; - continue; - } - - valueToWrite.Value = value; - - if (pItemVQT[ii].bQualitySpecified != 0) - { - value.StatusCode = ComUtils.GetQualityCode(pItemVQT[ii].wQuality); - } - - if (pItemVQT[ii].bTimeStampSpecified != 0) - { - value.SourceTimestamp = ComUtils.GetDateTime(pItemVQT[ii].ftTimeStamp); - } - - // needed to correlate results to input. - valueToWrite.Handle = itemToWrite; - - valuesToWrite.Add(valueToWrite); - } - - // create transaction. - if (valuesToWrite.Count > 0 || conversionErrors != null) - { - pdwCancelID = Utils.IncrementIdentifier(ref m_nextHandle); - m_transactions[pdwCancelID] = new AsyncWriteTransaction(dwTransactionID, valuesToWrite); - } - - // send conversion errors in the callback if no valid items available (CTT bug workaround). - if (valuesToWrite.Count == 0 && conversionErrors != null) - { - // must return S_OK from this function if sending the errors in the callback. - List errorsToSend = new List(); - - for (int ii = 0; ii < conversionErrors.Length; ii++) - { - if (conversionErrors[ii] != null) - { - errors[ii] = ResultIds.S_OK; - errorsToSend.Add(conversionErrors[ii]); - } - } - - // queue the request. - CallbackRequest request = new CallbackRequest(); - - request.CallbackType = CallbackType.Write; - request.Callback = callback; - request.TransactionId = dwTransactionID; - request.GroupHandle = m_clientHandle; - request.ServerHandle = m_serverHandle; - request.Values = errorsToSend; - - QueueCallbackRequest(request); - } - } - - // write values from server. - if (valuesToWrite.Count > 0) - { - m_session.BeginWrite( - null, - valuesToWrite, - new AsyncCallback(OnWriteComplete), - pdwCancelID); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - Utils.Trace(e, "Error writing items."); - throw ComUtils.CreateComException(e); - } - } - - /// - /// IOPCAsyncIO3::RefreshMaxAge - Force a callback to IOPCDataCallback::OnDataChange for all active items in the group - /// (whether they have changed or not). Inactive items are not included in the callback. - /// - public void RefreshMaxAge( - int dwMaxAge, - int dwTransactionID, - out int pdwCancelID) - { - pdwCancelID = 0; - - // get callback object - error if missing. - IOPCDataCallback callback = (IOPCDataCallback)GetCallback(typeof(IOPCDataCallback).GUID); - - if (callback == null) - { - throw ComUtils.CreateComException(ResultIds.CONNECT_E_NOCONNECTION); - } - - try - { - // build list of values to read. - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - foreach (Item itemToRead in m_items.Values) - { - // check if active. - if (!m_active || !itemToRead.Active) - { - continue; - } - - ReadValueId nodeToRead = new ReadValueId(); - - nodeToRead.NodeId = itemToRead.MonitoredItem.ResolvedNodeId; - nodeToRead.AttributeId = Attributes.Value; - - // needed to correlate results to input. - nodeToRead.Handle = itemToRead; - - nodesToRead.Add(nodeToRead); - } - - // check if nothing to read. - if (nodesToRead.Count == 0) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - // read values from server. - pdwCancelID = Utils.IncrementIdentifier(ref m_nextHandle); - m_transactions[pdwCancelID] = new AsyncReadTransaction(dwTransactionID, nodesToRead, true); - } - - m_session.BeginRead( - null, - dwMaxAge, - TimestampsToReturn.Both, - nodesToRead, - new AsyncCallback(OnReadComplete), - pdwCancelID); - } - catch (Exception e) - { - Utils.Trace(e, "Error refreshing group."); - throw ComUtils.CreateComException(e); - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// - #region IOPCGroupStateMgt Members - /// - /// IOPCGroupStateMgt::GetState - Gets the current state of the group. - /// - public void GetState( - out int pUpdateRate, - out int pActive, - out string ppName, - out int pTimeBias, - out float pPercentDeadband, - out int pLCID, - out int phClientGroup, - out int phServerGroup) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // get the state info. - try - { - pUpdateRate = m_updateRate; - pActive = (m_active)?1:0; - ppName = m_name; - pTimeBias = m_timebias; - pPercentDeadband = m_deadband; - pLCID = m_lcid; - phClientGroup = m_clientHandle; - phServerGroup = m_serverHandle; - } - catch (Exception e) - { - Utils.Trace(e, "Error reading group state."); - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCGroupStateMgt::CloneGroup - Creates a second copy of a group with a unique name. - /// - public void CloneGroup( - string szName, - ref Guid riid, - out object ppUnk) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - Group group = null; - - try - { - // create new group. - int serverHandle = 0; - int revisedUpdateRate = 0; - - group = m_server.CreateGroup( - szName, - m_clientHandle, - m_updateRate, - false, - m_deadband, - m_lcid, - m_timebias, - out serverHandle, - out revisedUpdateRate); - - // copy items. - group.CloneItems(m_items.Values); - - // return new group - ppUnk = group; - } - catch (Exception e) - { - // remove new group on error. - if (group != null) - { - try { m_server.RemoveGroup((int)group.ServerHandle, 0); } - catch {} - } - - Utils.Trace(e, "Error cloning group."); - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Adds the items to group. - /// - private void CloneItems(IEnumerable itemsToClone) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - List itemsToAdd = new List(); - - foreach (Item itemToClone in itemsToClone) - { - // create an item. - Item item = new Item(); - - item.ItemId = itemToClone.ItemId; - item.ClientHandle = itemToClone.ClientHandle; - item.ServerHandle = 0; - item.Active = itemToClone.Active; - item.ReqType = itemToClone.ReqType; - item.Variable = itemToClone.Variable; - item.SamplingRate = itemToClone.SamplingRate; - item.SamplingRateSpecified = itemToClone.SamplingRateSpecified; - item.DeadbandSupported = itemToClone.DeadbandSupported; - item.Deadband = itemToClone.Deadband; - item.DeadbandSpecified = itemToClone.DeadbandSpecified; - item.EnableBuffering = itemToClone.EnableBuffering; - - // create a monitored item. - MonitoredItem monitoredItem = new MonitoredItem(); - - monitoredItem.StartNodeId = item.Variable.NodeId; - monitoredItem.AttributeId = Attributes.Value; - monitoredItem.MonitoringMode = (item.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled; - monitoredItem.SamplingInterval = (item.SamplingRateSpecified)?item.SamplingRate:m_updateRate; - monitoredItem.QueueSize = 0; - monitoredItem.DiscardOldest = true; - monitoredItem.Encoding = null; - monitoredItem.Filter = null; - monitoredItem.IndexRange = null; - - if (item.DeadbandSupported) - { - float deadband = (item.DeadbandSpecified)?item.Deadband:m_deadband; - - DataChangeFilter filter = null; - - if (deadband > 0) - { - filter = new DataChangeFilter(); - - filter.DeadbandType = (uint)(int)DeadbandType.Percent; - filter.DeadbandValue = m_deadband; - filter.Trigger = DataChangeTrigger.StatusValue; - } - - monitoredItem.Filter = filter; - } - - item.MonitoredItem = monitoredItem; - itemsToAdd.Add(item); - - // update the subscription. - m_subscription.AddItem(monitoredItem); - } - - if (itemsToAdd.Count > 0) - { - // create monitored items on the UA server. - m_subscription.ApplyChanges(); - - foreach (Item item in itemsToAdd) - { - // check for error during add. - int index = item.ServerHandle; - MonitoredItem monitoredItem = item.MonitoredItem; - - if (ServiceResult.IsBad(monitoredItem.Status.Error)) - { - m_subscription.RemoveItem(monitoredItem); - continue; - } - - // save server handle. - item.ServerHandle = Utils.ToInt32(monitoredItem.ClientHandle); - - // add an entry in the cache. - CreateCacheEntry(item); - - // index item. - m_items[item.ServerHandle] = item; - } - } - } - } - - /// - /// IOPCGroupStateMgt::SetName - Changes the name of a private group. The name must be unique. - /// - public void SetName(string szName) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate argument. - if (szName == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - // check the name. - int error = m_server.SetGroupName(this.m_name, szName); - - if (error < 0) - { - throw ComUtils.CreateComException(error); - } - - // update name if successful. - this.m_name = szName; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCGroupStateMgt::SetState - Sets various properties of the group. - /// - public void SetState( - System.IntPtr pRequestedUpdateRate, - out int pRevisedUpdateRate, - System.IntPtr pActive, - System.IntPtr pTimeBias, - System.IntPtr pPercentDeadband, - System.IntPtr pLCID, - System.IntPtr phClientGroup) - { - int updateRate = 0; - uint keepAliveCount = 0; - float deadband = 0; - int lcid = 0; - int timebias = 0; - bool updateRateChanged; - - try - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate update rate. - if (pRequestedUpdateRate != IntPtr.Zero) - { - updateRate = Marshal.ReadInt32(pRequestedUpdateRate); - - // throttle the publishing rate. - if (updateRate < 100) - { - updateRate = 100; - } - - // calculate the new keep alive count based on the previous setting. - keepAliveCount = m_defaultKeepAliveCount; - - if (m_keepAliveTime != 0) - { - keepAliveCount = (uint)((m_keepAliveTime/(uint)updateRate)+1); - } - - // check if it is changing. - updateRateChanged = updateRate != m_updateRate; - } - - // validate deadband. - if (pPercentDeadband != IntPtr.Zero) - { - float[] buffer = new float[1]; - Marshal.Copy(pPercentDeadband, buffer, 0, 1); - deadband = buffer[0]; - - if (deadband < 0 || deadband > 100) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - } - - // validate locale. - if (pLCID != IntPtr.Zero) - { - lcid = Marshal.ReadInt32(pLCID); - - if (lcid != 0 && !m_server.IsLocaleSupported(lcid)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - } - - // validate time bias. - if (pTimeBias != IntPtr.Zero) - { - timebias = Marshal.ReadInt32(pTimeBias); - } - - // apply update rate. - if (pRequestedUpdateRate != IntPtr.Zero) - { - m_subscription.PublishingInterval = updateRate; - - // calculate the new keep alive count based on the previous setting. - if (keepAliveCount != 0) - { - m_subscription.KeepAliveCount = keepAliveCount; - } - - // must update the individual items. - foreach (Item item in m_items.Values) - { - if (!item.SamplingRateSpecified) - { - item.MonitoredItem.SamplingInterval = updateRate; - } - } - } - - // apply time bias. - if (pTimeBias != IntPtr.Zero) - { - m_timebias = timebias; - } - - // apply deadband. - if (pPercentDeadband != IntPtr.Zero) - { - m_deadband = deadband; - - DataChangeFilter filter = new DataChangeFilter(); - - filter.DeadbandType = (uint)(int)DeadbandType.Percent; - filter.DeadbandValue = m_deadband; - filter.Trigger = DataChangeTrigger.StatusValue; - - // must update the individual items. - foreach (Item item in m_items.Values) - { - if (item.DeadbandSupported) - { - if (m_deadband > 0) - { - item.MonitoredItem.Filter = filter; - } - } - } - } - - // apply locale. - if (pLCID != IntPtr.Zero) - { - m_lcid = lcid; - } - - // apply client handle. - if (phClientGroup != IntPtr.Zero) - { - m_clientHandle = Marshal.ReadInt32(phClientGroup); - } - - // modify subscription. - m_subscription.Modify(); - - // apply changes to items. - m_subscription.ApplyChanges(); - - // update keep alive time if it changed. - if (keepAliveCount != 0) - { - m_keepAliveTime = (int)(m_subscription.CurrentPublishingInterval*m_subscription.CurrentKeepAliveCount); - } - - // return the actual update rate. - pRevisedUpdateRate = m_updateRate = (int)m_subscription.CurrentPublishingInterval; - - // reset the update counter. - m_nextUpdate = DateTime.UtcNow.Ticks + m_updateRate*TimeSpan.TicksPerMillisecond; - - // Utils.Trace( - // "SetState: GroupHandle={0}, UpdateRate={1}, Active={2}", - // m_clientHandle, - // m_updateRate, - // m_active); - - } - - // apply active. - if (pActive != IntPtr.Zero) - { - bool active = Marshal.ReadInt32(pActive) != 0; - PublishStateChanged(active, null); - } - } - catch (Exception e) - { - Utils.Trace(e, "Error setting group state."); - throw ComUtils.CreateComException(e); - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// - #region IOPCGroupStateMgt2 Members - /// - /// IOPCGroupStateMgt2::GetKeepAlive - Returns the currently active keep-alive time for the subscription. - /// - public void GetKeepAlive(out int pdwKeepAliveTime) - { - lock (m_lock) - { - try - { - pdwKeepAliveTime = m_keepAliveTime; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCGroupStateMgt2::SetKeepAlive - Sets the keep-alive time for a subscription to cause the server to provide - /// client callbacks on the subscription when there are no new events to report. - /// - public void SetKeepAlive( - int dwKeepAliveTime, - out int pdwRevisedKeepAliveTime) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - try - { - // re-calculate keepalive based on update rate. - uint keepAliveCount = (uint)((dwKeepAliveTime/(uint)m_updateRate)+1); - - // update subscription. - m_subscription.KeepAliveCount = keepAliveCount; - m_subscription.Modify(); - - // return the actual keep alive rate. - pdwRevisedKeepAliveTime = m_keepAliveTime = (int)(m_subscription.CurrentPublishingInterval*m_subscription.CurrentKeepAliveCount); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// - #region IOPCItemDeadbandMgt Members - /// - /// IOPCItemDeadbandMgt::SetItemDeadband - Overrides the deadband specified for the group for each requested item. - /// - public void SetItemDeadband( - int dwCount, - int[] phServer, - float[] pPercentDeadband, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || pPercentDeadband == null || dwCount != phServer.Length || dwCount != pPercentDeadband.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - Item[] itemsToModify = new Item[dwCount]; - - // update items. - for (int ii = 0; ii < dwCount; ii++) - { - // find the item. - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // check if deadbands are supported. - if (!itemToModify.DeadbandSupported) - { - errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED; - continue; - } - - // validate the deadband. - float deadband = pPercentDeadband[ii]; - - if (deadband < 0 || deadband > 100) - { - errors[ii] = ResultIds.E_INVALIDARG; - continue; - } - - // change filter. - SetDataChangeFilter(itemToModify.MonitoredItem, deadband); - - itemsToModify[ii] = itemToModify; - errors[ii] = ResultIds.S_OK; - } - - // update the subscription. - m_subscription.ApplyChanges(); - - // check for any errors. - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToModify = itemsToModify[ii]; - - if (itemToModify == null) - { - continue; - } - - // note that the old deadband may no longer work if an error occurred here. - if (ServiceResult.IsBad(itemToModify.MonitoredItem.Status.Error)) - { - // restore deadband. - SetDataChangeFilter(itemToModify.MonitoredItem, (itemToModify.DeadbandSpecified)?itemToModify.Deadband:m_deadband); - - errors[ii] = ResultIds.E_FAIL; - continue; - } - - itemToModify.Deadband = pPercentDeadband[ii]; - itemToModify.DeadbandSpecified = true; - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Sets the data change filter for the monitored item. - /// - private void SetDataChangeFilter(MonitoredItem item, float deadband) - { - // construct filter. - DataChangeFilter filter = null; - - if (deadband > 0) - { - filter = new DataChangeFilter(); - - filter.DeadbandType = (uint)DeadbandType.Percent; - filter.DeadbandValue = deadband; - filter.Trigger = DataChangeTrigger.StatusValue; - } - - item.Filter = filter; - } - - /// - /// IOPCItemDeadbandMgt::GetItemDeadband - Gets the deadband values for each of the requested items. - /// - public void GetItemDeadband( - int dwCount, - int[] phServer, - out System.IntPtr ppPercentDeadband, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || dwCount != phServer.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - // read information from cached item objects. - float[] deadbands = new float[dwCount]; - int[] errors = new int[dwCount]; - - // update items. - for (int ii = 0; ii < dwCount; ii++) - { - // find the item. - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // check if deadbands are supported. - if (!itemToModify.DeadbandSupported) - { - errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED; - continue; - } - - // check if deadband was set - if (!itemToModify.DeadbandSpecified) - { - errors[ii] = ResultIds.E_DEADBANDNOTSET; - continue; - } - - deadbands[ii] = itemToModify.Deadband; - errors[ii] = ResultIds.S_OK; - } - - // marshal deadbands. - ppPercentDeadband = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(float))*dwCount); - Marshal.Copy(deadbands, 0, ppPercentDeadband, dwCount); - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemDeadbandMgt::ClearItemDeadband - Clears the individual item deadband set for the item, - /// sets thems back to the deadband value of the group. - /// - public void ClearItemDeadband( - int dwCount, - int[] phServer, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || dwCount != phServer.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - Item[] itemsToModify = new Item[dwCount]; - - // update items. - for (int ii = 0; ii < dwCount; ii++) - { - // find the item. - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // check if deadbands are supported. - if (!itemToModify.DeadbandSupported) - { - errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED; - continue; - } - - // check if deadband was set - if (!itemToModify.DeadbandSpecified) - { - errors[ii] = ResultIds.E_DEADBANDNOTSET; - continue; - } - - // change filter. - SetDataChangeFilter(itemToModify.MonitoredItem, m_deadband); - - itemsToModify[ii] = itemToModify; - errors[ii] = ResultIds.S_OK; - } - - // update the subscription. - m_subscription.ApplyChanges(); - - // check for any errors. - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToModify = itemsToModify[ii]; - - if (itemToModify == null) - { - continue; - } - - // note that the old deadband may no longer work if an error occurred here. - if (ServiceResult.IsBad(itemToModify.MonitoredItem.Status.Error)) - { - // restore filter. - SetDataChangeFilter(itemToModify.MonitoredItem, itemToModify.Deadband); - - errors[ii] = ResultIds.E_FAIL; - continue; - } - - itemToModify.Deadband = 0; - itemToModify.DeadbandSpecified = false; - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// - #region IOPCItemSamplingMgt Members - - /// - /// IOPCItemSamplingMgt::SetItemSamplingRate - Sets sampling rate on individual items. - /// - public void SetItemSamplingRate( - int dwCount, - int[] phServer, - int[] pdwRequestedSamplingRate, - out System.IntPtr ppdwRevisedSamplingRate, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || pdwRequestedSamplingRate == null || dwCount != phServer.Length || dwCount != pdwRequestedSamplingRate.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - int[] revisedSamplingRates = new int[dwCount]; - Item[] itemsToModify = new Item[dwCount]; - - // update items. - for (int ii = 0; ii < dwCount; ii++) - { - // find the item. - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // update sampling rate. - ChangeSamplingInterval(itemToModify.MonitoredItem, pdwRequestedSamplingRate[ii], itemToModify.EnableBuffering); - - itemsToModify[ii] = itemToModify; - errors[ii] = ResultIds.S_OK; - } - - // update the subscription. - m_subscription.ApplyChanges(); - - // check for any errors. - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToModify = itemsToModify[ii]; - - if (itemToModify == null) - { - continue; - } - - // note that the old sampling rate may no longer work if an error occurred here. - if (ServiceResult.IsBad(itemToModify.MonitoredItem.Status.Error)) - { - // restore sampling interval. - ChangeSamplingInterval(itemToModify.MonitoredItem, itemToModify.SamplingRate, itemToModify.EnableBuffering); - - errors[ii] = ResultIds.E_FAIL; - continue; - } - - // update item on success. - itemToModify.SamplingRate = revisedSamplingRates[ii] = (int)itemToModify.MonitoredItem.Status.SamplingInterval; - itemToModify.SamplingRateSpecified = true; - } - - // marshal error codes. - ppdwRevisedSamplingRate = ComUtils.GetInt32s(revisedSamplingRates); - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Updates the sampling interval and queue size. - /// - private void ChangeSamplingInterval(MonitoredItem monitoredItem, int samplingInterval, bool bufferEnabled) - { - // update sampling interval. - if (samplingInterval < 0) - { - monitoredItem.SamplingInterval = m_updateRate; - } - else - { - monitoredItem.SamplingInterval = samplingInterval; - } - - // update the queue size if buffering is enabled. - if (bufferEnabled) - { - if (monitoredItem.SamplingInterval > 0) - { - monitoredItem.QueueSize = (uint)(m_updateRate/monitoredItem.SamplingInterval); - } - else - { - monitoredItem.QueueSize = 100; - } - } - else - { - monitoredItem.QueueSize = 1; - } - } - - /// - /// IOPCItemSamplingMgt:: GetItemSamplingRate - Gets the sampling rate on individual items, - /// which was previously set with SetItemSamplingRate. - /// - public void GetItemSamplingRate( - int dwCount, - int[] phServer, - out System.IntPtr ppdwSamplingRate, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || dwCount != phServer.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] samplingRates = new int[dwCount]; - int[] errors = new int[dwCount]; - - // update items. - for (int ii = 0; ii < dwCount; ii++) - { - // find the item. - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // check if sampling rate was set - if (!itemToModify.SamplingRateSpecified) - { - errors[ii] = ResultIds.E_RATENOTSET; - continue; - } - - samplingRates[ii] = itemToModify.SamplingRate; - errors[ii] = ResultIds.S_OK; - } - - // marshal results. - ppdwSamplingRate = ComUtils.GetInt32s(samplingRates); - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemSamplingMgt:: ClearItemSamplingRate - Clears the sampling rate on individual items, - /// which was previously set with SetItemSamplingRate. - /// - public void ClearItemSamplingRate( - int dwCount, - int[] phServer, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || dwCount != phServer.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - Item[] itemsToModify = new Item[dwCount]; - - // update items. - for (int ii = 0; ii < dwCount; ii++) - { - // find the item. - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // check if sampling rate was set - if (!itemToModify.SamplingRateSpecified) - { - errors[ii] = ResultIds.E_RATENOTSET; - continue; - } - - // update sampling rate. - ChangeSamplingInterval(itemToModify.MonitoredItem, -1, itemToModify.EnableBuffering); - - itemsToModify[ii] = itemToModify; - errors[ii] = ResultIds.S_OK; - } - - // update the subscription. - m_subscription.ApplyChanges(); - - // check for any errors. - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToModify = itemsToModify[ii]; - - if (itemToModify == null) - { - continue; - } - - // note that the old sampling rate may no longer work if an error occurred here. - if (ServiceResult.IsBad(itemToModify.MonitoredItem.Status.Error)) - { - // restore sampling rate. - ChangeSamplingInterval(itemToModify.MonitoredItem, itemToModify.SamplingRate, itemToModify.EnableBuffering); - - errors[ii] = ResultIds.E_FAIL; - continue; - } - - // update item on success. - itemToModify.SamplingRate = -1; - itemToModify.SamplingRateSpecified = false; - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemSamplingMgt:: SetItemBufferEnable - Requests that the server turns on/off the buffering of data for requested items. - /// - public void SetItemBufferEnable( - int dwCount, - int[] phServer, - int[] pbEnable, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || pbEnable == null || dwCount != phServer.Length || dwCount != pbEnable.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - - int[] errors = new int[dwCount]; - Item[] itemsToModify = new Item[dwCount]; - - // update items. - for (int ii = 0; ii < dwCount; ii++) - { - // find the item. - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // change queue size based on the sampling interval. - ChangeSamplingInterval( - itemToModify.MonitoredItem, - (itemToModify.SamplingRateSpecified)?itemToModify.SamplingRate:-1, - true); - - itemsToModify[ii] = itemToModify; - errors[ii] = ResultIds.S_OK; - } - - // update the subscription. - m_subscription.ApplyChanges(); - - // check for any errors. - for (int ii = 0; ii < dwCount; ii++) - { - Item itemToModify = itemsToModify[ii]; - - if (itemToModify == null) - { - continue; - } - - // note that the old sampling rate may no longer work if an error occurred here. - if (ServiceResult.IsBad(itemToModify.MonitoredItem.Status.Error)) - { - // restore queue size based on the sampling interval. - ChangeSamplingInterval( - itemToModify.MonitoredItem, - (itemToModify.SamplingRateSpecified)?itemToModify.SamplingRate:-1, - false); - - errors[ii] = ResultIds.E_FAIL; - continue; - } - - // update item on success. - itemToModify.EnableBuffering = true; - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemSamplingMgt:: GetItemBufferEnable - Queries the current state of the servers buffering for requested items. - /// - public void GetItemBufferEnable( - int dwCount, - int[] phServer, - out System.IntPtr ppbEnable, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || phServer == null || dwCount != phServer.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - // read information from cached item objects. - int[] enableBuffering = new int[dwCount]; - int[] errors = new int[dwCount]; - - // update items. - for (int ii = 0; ii < dwCount; ii++) - { - // find the item. - Item itemToModify = null; - - if (!m_items.TryGetValue(phServer[ii], out itemToModify)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - enableBuffering[ii] = (itemToModify.EnableBuffering)?1:0; - errors[ii] = ResultIds.S_OK; - } - - // marshal results. - ppbEnable = ComUtils.GetInt32s(enableBuffering); - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - #region Transaction Class - /// - /// Holds the state for an asynchronous operation. - /// - private class Transaction - { - public int TransactionId; - } - - /// - /// Holds the state for an asynchronous read operation. - /// - private class AsyncReadTransaction : Transaction - { - public ReadValueIdCollection NodesToRead; - public bool IsRefresh; - - public AsyncReadTransaction(int transactionId, ReadValueIdCollection nodesToRead, bool isRefresh) - { - TransactionId = transactionId; - NodesToRead = nodesToRead; - IsRefresh = isRefresh; - } - } - - /// - /// Holds the state for an asynchronous write operation. - /// - private class AsyncWriteTransaction : Transaction - { - public WriteValueCollection ValuesToWrite; - - public AsyncWriteTransaction(int transactionId, WriteValueCollection valuesToWrite) - { - TransactionId = transactionId; - ValuesToWrite = valuesToWrite; - } - } - #endregion - - #region Item Cache Functions - /// - /// Adds a cache entry for the item. - /// - private void CreateCacheEntry(Item item) - { - lock (m_cache) - { - CachedValue cachedValue = null; - - if (!m_cache.TryGetValue(item.Variable.NodeId, out cachedValue)) - { - m_cache[item.Variable.NodeId] = cachedValue = new CachedValue(item.Variable.NodeId); - } - - cachedValue.AddRef(); - item.CachedValue = cachedValue; - } - } - - /// - /// Deletes the cache entry for the item. - /// - private void DeleteCacheEntry(Item item) - { - lock (m_cache) - { - if (item.CachedValue.Release() == 0) - { - m_cache.Remove(item.CachedValue.NodeId); - } - } - } - - /// - /// Reads a value from the cache. - /// - private DataValue ReadCachedValue(Item item, int maxAge) - { - lock (m_cache) - { - if (DateTime.UtcNow.AddMilliseconds(maxAge) >= item.CachedValue.Timestamp) - { - return item.CachedValue.LastValue; - } - - return null; - } - } - - /// - /// Updates a value in the cache. - /// - private void UpdateCachedValue(Item item, DataValue value) - { - lock (m_cache) - { - if (value != null) - { - item.CachedValue.Update(value); - } - } - } - #endregion - - #region Private Members - private object m_lock = new object(); - private Server m_server = null; - private Session m_session; - private Subscription m_subscription; - private int m_serverHandle = 0; - private int m_clientHandle = 0; - private int m_updateRate = 0; - private float m_deadband = 0; - private string m_name = null; - private int m_timebias = 0; - private int m_lcid = ComUtils.LOCALE_SYSTEM_DEFAULT; - private int m_keepAliveTime = 0; - private bool m_active; - private bool m_enabled; - private bool m_advised; - private long m_nextUpdate; - private NodeIdDictionary m_cache; - private uint m_defaultKeepAliveCount = 10; - - private SortedDictionary m_items = new SortedDictionary(); - private Dictionary m_transactions = new Dictionary(); - private Queue m_callbacks = new Queue(); - - private int m_nextHandle = 1000; - #endregion - - #region Private Member Functions - #endregion - } - - #region Item Class - /// - /// Describes how an item in the server address space should be accessed. - /// - public class Item - { - #region Properties - /// - /// The identifier for the item. - /// - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// The variable which the item is connected to. - /// - public VariableNode Variable - { - get { return m_variable; } - set { m_variable = value; } - } - - /// - /// The server handle assigned to the item - /// - public int ServerHandle - { - get { return m_serverHandle; } - set { m_serverHandle = value; } - } - - /// - /// The client handle assigned to the item - /// - public int ClientHandle - { - get { return m_clientHandle; } - set { m_clientHandle = value; } - } - - /// - /// The data type to use when returning the item value. - /// - public VarEnum ReqType - { - get { return m_reqType; } - set { m_reqType = value; } - } - - /// - /// Whether the server should send data change updates. - /// - public bool Active - { - get { return m_active; } - set { m_active = value; } - } - - /// - /// The minimum percentage change required to trigger a data update for an item. - /// - public float Deadband - { - get { return m_deadband; } - set { m_deadband = value; } - } - - /// - /// Whether the Deadband is specified. - /// - public bool DeadbandSpecified - { - get { return m_deadbandSpecified; } - set { m_deadbandSpecified = value; } - } - - /// - /// Whether the Deadband is supported. - /// - public bool DeadbandSupported - { - get { return m_deadbandSupported; } - set { m_deadbandSupported = value; } - } - - /// - /// How frequently the server should sample the item value. - /// - public int SamplingRate - { - get { return m_samplingRate; } - set { m_samplingRate = value; } - } - - /// - /// Whether the Sampling Rate is specified. - /// - public bool SamplingRateSpecified - { - get { return m_samplingRateSpecified; } - set { m_samplingRateSpecified = value; } - } - - /// - /// Whether the server should buffer multiple data changes between data updates. - /// - public bool EnableBuffering - { - get { return m_enableBuffering; } - set { m_enableBuffering = value; } - } - - /// - /// Monitored Item. - /// - public MonitoredItem MonitoredItem - { - get { return m_monitoredItem; } - set { m_monitoredItem = value; } - } - - /// - /// The last value cached for the item. - /// - public CachedValue CachedValue - { - get { return m_cachedValue; } - set { m_cachedValue = value; } - } - - /// - /// The last data change sent. - /// - public object LastValueSent - { - get { return m_lastValueSent; } - set { m_lastValueSent = value; } - } - - /// - /// The last data quality sent. - /// - public short LastQualitySent - { - get { return m_lastQualitySent; } - set { m_lastQualitySent = value; } - } - - /// - /// The last data timestamp sent. - /// - public DateTime LastTimestampSent - { - get { return m_lastTimestampSent; } - set { m_lastTimestampSent = value; } - } - #endregion - - #region Constructors - /// - /// Initializes the object with default values. - /// - public Item() {} - - /// - /// Initializes object with the specified ItemIdentifier object. - /// - public Item(string itemId) - { - m_itemId = itemId; - } - - /// - /// Initializes object with the specified Item object. - /// - public Item(Item item) - { - if (item != null) - { - ItemId = item.ItemId; - ServerHandle = item.ServerHandle; - ClientHandle = item.ClientHandle; - ReqType = item.ReqType; - Active = item.Active; - Deadband = item.Deadband; - DeadbandSpecified = item.DeadbandSpecified; - SamplingRate = item.SamplingRate; - SamplingRateSpecified = item.SamplingRateSpecified; - EnableBuffering = item.EnableBuffering; - } - } - #endregion - - #region Private Members - private string m_itemId = null; - private VariableNode m_variable = null; - private int m_serverHandle = 0; - private int m_clientHandle = 0; - private VarEnum m_reqType = VarEnum.VT_EMPTY; - private bool m_active = true; - private float m_deadband = 0; - private bool m_deadbandSpecified = false; - private bool m_deadbandSupported = false; - private int m_samplingRate = 0; - private bool m_samplingRateSpecified = false; - private bool m_enableBuffering = false; - private MonitoredItem m_monitoredItem = null; - private CachedValue m_cachedValue; - private object m_lastValueSent; - private short m_lastQualitySent; - private DateTime m_lastTimestampSent; - #endregion - } - #endregion -} diff --git a/ComIOP/Common/Server/Da/Com.Da.Server.cs b/ComIOP/Common/Server/Da/Com.Da.Server.cs deleted file mode 100644 index 0f88bb044..000000000 --- a/ComIOP/Common/Server/Da/Com.Da.Server.cs +++ /dev/null @@ -1,4668 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Xml; -using System.Net; -using System.IO; -using System.Threading; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.Resources; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Diagnostics; -using System.Runtime.Serialization; -using System.Configuration; -using System.Text; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Win32; - -using OpcRcw.Da; -using OpcRcw.Comn; - -using Opc.Ua.Client; -using Opc.Ua; -using Opc.Ua.Bindings; - -namespace Opc.Ua.Com.Server.Da -{ - /// - /// A class that implements the COM-DA interfaces. - /// - [ComVisible(true)] - [Guid(Server.DaProxyGuid)] - [ProgId("OpcUa.DaProxy")] - public class Server : - ConnectionPointContainer, - IOPCCommon, - IOPCServer, - IOPCBrowseServerAddressSpace, - IOPCItemProperties, - IOPCBrowse, - IOPCItemIO, - IOPCWrappedServer - { - #region Construction and Initialization - /// - /// Initializes the object with the default values. - /// - protected Server() - { - RegisterInterface(typeof(OpcRcw.Comn.IOPCShutdown).GUID); - } - - /// - /// The GUID - /// - private const string DaProxyGuid = "25501B7C-2E39-4fd8-BA5A-FAB081375498"; - - /// - /// The DefaultServerUrl - /// - private const string DefaultServerUrl = "http://localhost:51211/UA/SampleServer"; - - /// - /// Creates a new session. - /// - private Session CreateSession(Guid clsid) - { - // lookup the cached configuration information. - ConfiguredEndpoint endpoint = null; - bool previouslyConnected = true; - - if (!m_verifiedEndpoints.TryGetValue(clsid, out endpoint)) - { - endpoint = LoadConfiguredEndpoint(clsid); - - if (endpoint != null) - { - Utils.Trace("Loaded endpoint with URL: {0}", endpoint.EndpointUrl); - previouslyConnected = false; - } - } - - if (endpoint == null) - { - endpoint = m_endpointCache.Create(DefaultServerUrl); - } - - // Initialize the client configuration. - // Fetch the current configuration information by connecting to the server's discovery endpoint. - // This method assumes that the discovery endpoint can be constructed by appending "/discovery" to the URL. - if (endpoint.UpdateBeforeConnect && !previouslyConnected) - { - endpoint.UpdateFromServer(BindingFactory.Default); - Utils.Trace("Updated endpoint from server: {0}", endpoint.EndpointUrl); - } - - // Need to specify that the server is trusted by the client application. - if (!previouslyConnected) - { - m_configuration.SecurityConfiguration.AddTrustedPeer(endpoint.Description.ServerCertificate); - } - - // Set the session keep alive to 600 seconds. - m_configuration.ClientConfiguration.DefaultSessionTimeout = 600000; - - ServiceMessageContext messageContext = m_configuration.CreateMessageContext(); - - // Initialize the channel which will be created with the server. - ITransportChannel channel = SessionChannel.Create( - m_configuration, - endpoint.Description, - endpoint.Configuration, - m_configuration.SecurityConfiguration.ApplicationCertificate.Find(true), - messageContext); - - // Wrap the channel with the session object. - Session session = new Session(channel, m_configuration, endpoint, null); - session.ReturnDiagnostics = DiagnosticsMasks.SymbolicId; - - // The user login credentials must be provided when opening a session. - IUserIdentity identity = null; - - if (endpoint.UserIdentity != null) - { - identity = new Opc.Ua.UserIdentity(endpoint.UserIdentity); - } - - // Create the session. This actually connects to the server. - session.Open("COM Client Session", identity); - - // need to fetch the references in order use the node cache. - session.FetchTypeTree(ReferenceTypeIds.References); - - // save the updated information. - if (!previouslyConnected) - { - try - { - SaveConfiguredEndpoint(clsid, endpoint); - } - catch (Exception e) - { - Utils.Trace(e, "Could not save SaveConfiguredEndpoint in registry."); - } - - m_verifiedEndpoints.Add(clsid, endpoint); - } - - return session; - } - - /// - /// Always accept server certificates. - /// - void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e) - { - e.Accept = true; - } - - /// - /// Called when the object is loaded by the COM wrapper process. - /// - public virtual void Load(Guid clsid) - { - try - { - // load the configuration if this is the first time. - lock (m_staticLock) - { - if (m_configuration == null) - { - m_configuration = LoadConfiguration(); - m_endpointCache = new ConfiguredEndpointCollection(m_configuration); - m_verifiedEndpoints = new Dictionary(); - m_configuration.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); - } - - lock (m_lock) - { - // set the start time. - m_startTime = DateTime.UtcNow; - - // create session. - m_session = CreateSession(clsid); - - // read available LocaleIDs from the server. - m_localeIds = GetLocaleIDs(); - - // look up default time zone. - DateTime now = DateTime.Now; - - m_timebias = (int)-TimeZone.CurrentTimeZone.GetUtcOffset(now).TotalMinutes; - - if (TimeZone.CurrentTimeZone.IsDaylightSavingTime(now)) - { - m_timebias += 60; - } - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Could connect to server."); - throw ComUtils.CreateComException(e); - } - } - - /// - /// Called when the object is unloaded by the COM wrapper process. - /// - public virtual void Unload() - { - // close session. - lock (m_lock) - { - if (m_session != null) - { - m_session.Close(); - } - - if (m_continuationPointTimer != null) - { - m_continuationPointTimer.Dispose(); - m_continuationPointTimer = null; - } - } - } - - /// - /// Creates an application instance certificate if one does not already exist. - /// - public void CheckApplicationInstanceCertificate(ApplicationConfiguration configuration) - { - X509Certificate2 certificate = configuration.SecurityConfiguration.ApplicationCertificate.Find(true); - - if (certificate != null) - { - return; - } - - CertificateIdentifier id = configuration.SecurityConfiguration.ApplicationCertificate; - - List hostNames = new List(); - hostNames.Add(System.Net.Dns.GetHostName()); - hostNames.Add(System.Net.Dns.GetHostAddresses(hostNames[0])[0].ToString()); - - certificate = Opc.Ua.CertificateFactory.CreateCertificate( - id.StoreType, - id.StorePath, - configuration.ApplicationUri, - configuration.ApplicationName, - id.SubjectName, - hostNames, - 1024, - 120); - - configuration.CertificateValidator.Update(configuration.SecurityConfiguration); - } - - /// - /// Loads the configuration for the DaProxy server. - /// - private ApplicationConfiguration LoadConfiguration() - { - // TBD - normally this information would be loaded from the app.config file, however, - // the .NET configuration libraries have a problem loading config sections if the - // assembly that defines that config section is not in the same directory as the EXE. - // Since that is difficult to guarantee and a likely source of endless configuaration - // problems it is necessary to use something other than the app.config. - - // In this case the XML that would normally stored in the app.config is loaded from the - // directory where the wrapper assembly resides. - - XmlTextReader reader = new XmlTextReader(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName + ".proxyconfig"); - - try - { - DataContractSerializer serializer = new DataContractSerializer(typeof(ApplicationConfiguration)); - - ApplicationConfiguration configuration = (ApplicationConfiguration)serializer.ReadObject(reader); - - if (configuration != null) - { - configuration.Validate(ApplicationType.Client); - } - - CheckApplicationInstanceCertificate(configuration); - - return configuration; - } - catch - { - // create a default configuration object. - ApplicationConfiguration configuration = new ApplicationConfiguration(); - - // Need to specify the application instance certificate for the client. - configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); - configuration.SecurityConfiguration.ApplicationCertificate.StoreType = CertificateStoreType.Windows; - configuration.SecurityConfiguration.ApplicationCertificate.StorePath = "LocalMachine\\My"; - configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = "UA Sample Client"; - - configuration.Validate(ApplicationType.Client); - - return configuration; - } - finally - { - reader.Close(); - } - } - - /// - /// Reads the UA endpoint information associated the CLSID - /// - /// The CLSID used to activate the COM server. - /// The endpoint. - private ConfiguredEndpoint LoadConfiguredEndpoint(Guid clsid) - { - try - { - string relativePath = Utils.Format("%CommonApplicationData%\\OPC Foundation\\ComPseudoServers\\{0}.xml", clsid); - string absolutePath = Utils.GetAbsoluteFilePath(relativePath, false, false, false); - - // oops - nothing found. - if (absolutePath == null) - { - return null; - } - - // open the file. - FileStream istrm = File.Open(absolutePath, FileMode.Open, FileAccess.Read); - - using (XmlTextReader reader = new XmlTextReader(istrm)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(ConfiguredEndpoint)); - return (ConfiguredEndpoint)serializer.ReadObject(reader, false); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error loading endpoint configuration for COM Proxy with CLSID={0}.", clsid); - return null; - } - } - - /// - /// Saves the UA endpoint information associated the CLSID. - /// - /// The CLSID used to activate the COM server. - /// The endpoint. - private void SaveConfiguredEndpoint(Guid clsid, ConfiguredEndpoint endpoint) - { - try - { - string relativePath = Utils.Format("%CommonApplicationData%\\OPC Foundation\\ComPseudoServers\\{0}.xml", clsid); - string absolutePath = Utils.GetAbsoluteFilePath(relativePath, false, false, true); - - // oops - nothing found. - if (absolutePath == null) - { - absolutePath = Utils.GetAbsoluteFilePath(relativePath, true, false, true); - } - - // open the file. - FileStream ostrm = File.Open(absolutePath, FileMode.Open, FileAccess.ReadWrite); - - using (XmlTextWriter writer = new XmlTextWriter(ostrm, System.Text.Encoding.UTF8)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(ConfiguredEndpoint)); - serializer.WriteObject(writer, endpoint); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error saving endpoint configuration for COM Proxy with CLSID={0}.", clsid); - } - } - #endregion - - #region Internal Interface - /// - /// Changes the name of an existing group. - /// - internal int SetGroupName(string oldName, string newName) - { - lock (m_lock) - { - // look up existing group. - Group group = (Group)m_groups[oldName]; - - // validate arguments. - if (newName == null || newName.Length == 0 || group == null) - { - return ResultIds.E_INVALIDARG; - } - - // check that new name is unique among all groups. - if (m_groups.ContainsKey(newName)) - { - return ResultIds.E_DUPLICATENAME; - } - - // update group table. - m_groups.Remove(oldName); - m_groups[newName] = group; - - return ResultIds.S_OK; - } - } - - /// - /// Sets the last update time. - /// - internal void SetLastUpdate() - { - lock (m_lock) - { - m_lastUpdateTime = DateTime.UtcNow; - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //-----------------------------------------------------------------------------------------------------------// - #region IOPCCommon Members - /// - /// Sets the Locale ID for the server. - /// - public void SetLocaleID(int dwLcid) - { - lock (m_lock) - { - if (m_session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - try - { - bool localeSupported = false; - - foreach (int locale in m_localeIds) - { - if (dwLcid == locale) - { - if (locale != m_lcid) - { - UpdateLocale(m_session, ComUtils.GetLocale(locale)); - } - - // save the passed locale value. - m_lcid = dwLcid; - localeSupported = true; - break; - } - } - - if (!localeSupported) throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Update locale ID for the session. - /// - private void UpdateLocale(Session session, string locale) - { - if (session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - try - { - StringCollection preferredLocales = new StringCollection(); - preferredLocales.Add(locale); - session.ChangePreferredLocales(preferredLocales); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - - /// - /// Get the local IDs from the server. - /// - internal List GetLocaleIDs() - { - lock (m_lock) - { - string[] locales = null; - List localeList = new List(); - DataValueCollection values = null; - DiagnosticInfoCollection diagnosticInfos = null; - - try - { - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - ReadValueId valueId = new ReadValueId(); - valueId.NodeId = new NodeId(Opc.Ua.Variables.Server_ServerCapabilities_LocaleIdArray); - valueId.AttributeId = Attributes.Value; - nodesToRead.Add(valueId); - - // read values from the UA server. - ResponseHeader responseHeader = m_session.Read( - null, - 0, - TimestampsToReturn.Neither, - nodesToRead, - out values, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(values, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - - // add the default locale - localeList.Add(ComUtils.LOCALE_SYSTEM_DEFAULT); - localeList.Add(ComUtils.LOCALE_USER_DEFAULT); - - // cache the supported locales. - locales = values[0].Value as string[]; - - if (locales != null) - { - foreach (string locale in locales) - { - localeList.Add(ComUtils.GetLocale(locale)); - } - } - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - - return localeList; - } - } - - /// - /// Gets the available Locale IDs from the server. - /// - public void QueryAvailableLocaleIDs(out int pdwCount, out System.IntPtr pdwLcid) - { - if (m_session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - lock (m_lock) - { - try - { - pdwCount = 0; - pdwLcid = IntPtr.Zero; - - // marshal parameters. - if (m_localeIds != null && m_localeIds.Count > 0) - { - pdwLcid = Marshal.AllocCoTaskMem(m_localeIds.Count * Marshal.SizeOf(typeof(int))); - - int[] lcids = new int[m_localeIds.Count]; - - for (int ii = 0; ii < m_localeIds.Count; ii++) - { - lcids[ii] = m_localeIds[ii]; - } - - Marshal.Copy(lcids, 0, pdwLcid, m_localeIds.Count); - pdwCount = m_localeIds.Count; - } - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Gets the current Locale ID from the server. - /// - public void GetLocaleID(out int pdwLcid) - { - lock (m_lock) - { - try - { - pdwLcid = m_lcid; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Gets the error string from the server. - /// - void OpcRcw.Comn.IOPCCommon.GetErrorString(int dwError, out string ppString) - { - lock (m_lock) - { - try - { - // look up COM errors locally. - ppString = ComUtils.GetSystemMessage(dwError, m_lcid); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Sets the name of the client. - /// - public void SetClientName(string szName) - { - lock (m_lock) - { - m_clientName = szName; - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //-----------------------------------------------------------------------------------------------------------// - #region IOPCServer Members - /// - /// IOPCServer::GetGroupByName - Returns an additional interface pointer for the group based on its name. - /// - public void GetGroupByName(string szName, ref Guid riid, out object ppUnk) - { - lock (m_lock) - { - if (m_session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (szName == null || szName.Length == 0) - { - throw ComUtils.CreateComException("E_INVALIDARG", ResultIds.E_INVALIDARG); - } - - try - { - if (m_groups.ContainsKey(szName)) - { - ppUnk = m_groups[szName]; - return; - } - else - { - // group not found. - throw ComUtils.CreateComException("E_INVALIDARG", ResultIds.E_INVALIDARG); - } - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCServer::GetErrorString - Returns the error string for a server specific error code. - /// - public void GetErrorString(int dwError, int dwLocale, out string ppString) - { - lock (m_lock) - { - try - { - // check if locale is supported - if (!IsLocaleSupported(dwLocale)) - { - throw ComUtils.CreateComException("E_INVALIDARG", ResultIds.E_INVALIDARG); - } - - ppString = null; - - // look up COM errors locally - ppString = ComUtils.GetSystemMessage(dwError, dwLocale); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Checks if the local ID is supported. - /// - internal bool IsLocaleSupported(int myLocale) - { - lock (m_lock) - { - foreach (int locale in m_localeIds) - { - if (myLocale == locale) - { - return true; - } - } - - return false; - } - } - - /// - /// IOPCServer::RemoveGroup - Deletes the group. - /// - public void RemoveGroup(int hServerGroup, int bForce) - { - Group groupToRemove = null; - - try - { - lock (m_lock) - { - if (m_session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (hServerGroup == 0) - { - throw ComUtils.CreateComException(ResultIds.S_OK); - } - - // find the group. - foreach (KeyValuePair current in m_groups) - { - if (current.Value.ServerHandle == hServerGroup) - { - groupToRemove = current.Value; - m_groups.Remove(current.Key); - break; - } - } - } - - // no such group found. - if (groupToRemove == null) - { - throw ComUtils.CreateComException("E_FAIL", ResultIds.E_FAIL); - } - - // delete the subscription for the group. - groupToRemove.Dispose(); - } - catch (Exception e) - { - Utils.Trace(e, "Error removing group."); - throw ComUtils.CreateComException(e); - } - } - - /// - /// IOPCServer::CreateGroupEnumerator - Creates various enumerators for the groups provided by the Server. - /// - public void CreateGroupEnumerator(OpcRcw.Da.OPCENUMSCOPE dwScope, ref Guid riid, out object ppUnk) - { - lock (m_lock) - { - try - { - switch (dwScope) - { - case OPCENUMSCOPE.OPC_ENUM_PUBLIC: - case OPCENUMSCOPE.OPC_ENUM_PUBLIC_CONNECTIONS: - { - if (riid == typeof(OpcRcw.Comn.IEnumString).GUID) - { - ppUnk = new EnumString(null); - return; - } - - if (riid == typeof(OpcRcw.Comn.IEnumUnknown).GUID) - { - ppUnk = new EnumUnknown(null); - return; - } - - throw ComUtils.CreateComException("E_NOINTERFACE", ResultIds.E_NOINTERFACE); - } - } - - if (riid == typeof(IEnumUnknown).GUID) - { - ppUnk = new EnumUnknown(m_groups); - return; - } - - if (riid == typeof(OpcRcw.Comn.IEnumString).GUID) - { - ArrayList names = new ArrayList(m_groups.Count); - - foreach (string name in m_groups.Keys) - { - names.Add(name); - } - - ppUnk = new EnumString(names); - return; - } - - throw ComUtils.CreateComException("E_NOINTERFACE", ResultIds.E_NOINTERFACE); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCServer::AddGroup - Adds a group to the Server. - /// - public void AddGroup( - string szName, - int bActive, - int dwRequestedUpdateRate, - int hClientGroup, - System.IntPtr pTimeBias, - System.IntPtr pPercentDeadband, - int dwLCID, - out int phServerGroup, - out int pRevisedUpdateRate, - ref Guid riid, - out object ppUnk) - { - lock (m_lock) - { - try - { - if (m_session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate other arguments. - float deadband = 0; - - if (pPercentDeadband != IntPtr.Zero) - { - float[] array = new float[1]; - Marshal.Copy(pPercentDeadband, array, 0, 1); - deadband = array[0]; - } - - // check if locale is supported. - if (dwLCID != 0) - { - if (!IsLocaleSupported(dwLCID)) - { - // throw ComUtils.CreateComException("E_INVALIDARG", ResultIds.E_INVALIDARG); - } - } - - // look up default time zone. - int timebias = m_timebias; - - // use specifed time zone bias. - if (pTimeBias != IntPtr.Zero) - { - timebias = Marshal.ReadInt32(pTimeBias); - } - - // throttle the update rates. - if (dwRequestedUpdateRate < 100) - { - dwRequestedUpdateRate = 100; - } - - // create a new group. - int serverHandle = 0; - int revisedUpdateRate = 0; - - Group group = CreateGroup( - szName, - hClientGroup, - dwRequestedUpdateRate, - (bActive != 0), - deadband, - dwLCID, - timebias, - out serverHandle, - out revisedUpdateRate); - - // return results. - phServerGroup = serverHandle; - pRevisedUpdateRate = revisedUpdateRate; - ppUnk = group; - } - catch (Exception e) - { - Utils.Trace(e, "Error creating group."); - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Creates a new group. - /// - internal Group CreateGroup( - string name, - int clientHandle, - int updateRate, - bool active, - float deadband, - int lcid, - int timebias, - out int serverHandle, - out int revisedUpdateRate) - { - lock (m_lock) - { - Group newGroup = null; - - // assign a unique handle. - serverHandle = ++m_nextHandle; - - // generate a unique name. - if (String.IsNullOrEmpty(name)) - { - name = String.Format("Group_{0:D4}", serverHandle); - } - - // make sure that the group name is unique. - if (m_groups.ContainsKey(name)) - { - throw ComUtils.CreateComException("E_DUPLICATENAME", ResultIds.E_DUPLICATENAME); - } - - // create UA subscription. - Subscription subscription = new Subscription(m_session.DefaultSubscription); - - // fill in the subscription parameters - subscription.DisplayName = name; - subscription.PublishingInterval = updateRate; - subscription.KeepAliveCount = 10; // may be overridden by SetKeepAlive. - subscription.PublishingEnabled = false; - subscription.TimestampsToReturn = TimestampsToReturn.Both; - - // create UA subscripton. - m_session.AddSubscription(subscription); - subscription.Create(); - - // return revised update rate. - revisedUpdateRate = (int)subscription.CurrentPublishingInterval; - - // create the cache. - if (m_cache == null) - { - m_cache = new NodeIdDictionary(); - } - - // create new group object. - newGroup = new Group( - this, - m_lock, - name, - serverHandle, - clientHandle, - revisedUpdateRate, - active, - deadband, - lcid, - timebias, - subscription, - m_cache); - - // save group object. - m_groups.Add(name, newGroup); - - // start the update thread. - if (m_updateThread == null) - { - m_updateThread = new Thread(new ThreadStart(OnUpdateGroups)); - m_updateThread.IsBackground = true; - m_updateThread.Name = m_session.SessionName; - m_updateThread.Start(); - } - - // return the new group. - return newGroup; - } - } - - /// - /// A thread that periodically polls the groups to see if they have callbacks to send. - /// - private void OnUpdateGroups() - { - try - { - while (true) - { - lock (m_lock) - { - // loop until session disconnected. - if (!m_session.Connected) - { - return; - } - - // check all groups. - foreach (KeyValuePair group in m_groups) - { - try - { - group.Value.Update(DateTime.UtcNow.Ticks); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error updating group: {0}", group.Key); - } - } - } - - // wait before checking again. - Thread.Sleep(100); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error updating groups for Session: {0}", m_session.SessionName); - } - } - - /// - /// IOPCServer::GetStatus - Gets a current status information about the Server. - /// - public void GetStatus(out System.IntPtr ppServerStatus) - { - lock (m_lock) - { - // intialize default values. - OpcRcw.Da.OPCSERVERSTATUS status = new OPCSERVERSTATUS(); - - status.ftStartTime = ComUtils.GetFILETIME(m_startTime); - status.ftCurrentTime = ComUtils.GetFILETIME(DateTime.UtcNow); - status.ftLastUpdateTime = ComUtils.GetFILETIME(m_lastUpdateTime); - status.dwBandWidth = -1; - status.dwGroupCount = m_groups.Count; - status.wReserved = 0; - status.dwServerState = OPCSERVERSTATE.OPC_STATUS_FAILED; - status.wMajorVersion = 0; - status.wMinorVersion = 0; - status.wBuildNumber = 0; - status.szVendorInfo = null; - - try - { - UpdateServerStatus(ref status); - } - catch (Exception e) - { - Utils.Trace(e, "Error reading server status."); - // return a status structure with a failed state. - } - - // marshal parameters. - ppServerStatus = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OpcRcw.Da.OPCSERVERSTATUS))); - Marshal.StructureToPtr(status, ppServerStatus, false); - } - } - - /// - /// Updates the server status structure with the values from the server. - /// - private void UpdateServerStatus(ref OpcRcw.Da.OPCSERVERSTATUS status) - { - // read the current status. - ReadValueId nodeToRead = new ReadValueId(); - - nodeToRead.NodeId = Opc.Ua.Variables.Server_ServerStatus; - nodeToRead.AttributeId = Attributes.Value; - nodeToRead.DataEncoding = null; - nodeToRead.IndexRange = null; - - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - nodesToRead.Add(nodeToRead); - - DataValueCollection values = null; - DiagnosticInfoCollection diagnosticInfos = null; - - m_session.Read( - null, - 0, - TimestampsToReturn.Neither, - nodesToRead, - out values, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(values, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - - // check for read error. - if (StatusCode.IsBad(values[0].StatusCode)) - { - return; - } - - // get remote status. - ServerStatusDataType remoteStatus = ExtensionObject.ToEncodeable(values[0].Value as ExtensionObject) as ServerStatusDataType; - - if (remoteStatus == null) - { - return; - } - - // extract the times. - status.ftStartTime = ComUtils.GetFILETIME(remoteStatus.StartTime); - status.ftCurrentTime = ComUtils.GetFILETIME(remoteStatus.CurrentTime); - - // convert the server state. - switch (remoteStatus.State) - { - case ServerState.Running: { status.dwServerState = OPCSERVERSTATE.OPC_STATUS_RUNNING; break; } - case ServerState.Suspended: { status.dwServerState = OPCSERVERSTATE.OPC_STATUS_SUSPENDED; break; } - case ServerState.CommunicationFault: { status.dwServerState = OPCSERVERSTATE.OPC_STATUS_COMM_FAULT; break; } - case ServerState.Failed: { status.dwServerState = OPCSERVERSTATE.OPC_STATUS_FAILED; break; } - case ServerState.NoConfiguration: { status.dwServerState = OPCSERVERSTATE.OPC_STATUS_NOCONFIG; break; } - case ServerState.Test: { status.dwServerState = OPCSERVERSTATE.OPC_STATUS_TEST; break; } - default: { status.dwServerState = OPCSERVERSTATE.OPC_STATUS_FAILED; break; } - } - - BuildInfo buildInfo = remoteStatus.BuildInfo; - - // construct the vendor info. - status.szVendorInfo = String.Format("{0}, {1}", buildInfo.ProductName, buildInfo.ManufacturerName); - - // parse the software version. - if (!String.IsNullOrEmpty(buildInfo.SoftwareVersion)) - { - string[] fields = buildInfo.SoftwareVersion.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries); - - if (fields.Length > 0) - { - status.wMajorVersion = ExtractVersionFromString(fields[0]); - } - - if (fields.Length > 1) - { - status.wMinorVersion = ExtractVersionFromString(fields[1]); - } - } - - if (!String.IsNullOrEmpty(buildInfo.BuildNumber)) - { - string[] fields = buildInfo.SoftwareVersion.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries); - - if (fields.Length > 0) - { - status.wBuildNumber = ExtractVersionFromString(fields[0]); - } - } - } - - /// - /// Extracts the version number from a string. - /// - private short ExtractVersionFromString(string version) - { - if (String.IsNullOrEmpty(version)) - { - return 0; - } - - int count = 0; - - while (count < version.Length && Char.IsDigit(version[count])) - { - count++; - } - - try - { - return System.Convert.ToInt16(version.Substring(0, count)); - } - catch - { - return 0; - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - #region IOPCBrowse Members - /// - /// IOPCBrowse::Browse - Browses a single branch of the address space and returns zero or more OPCBROWSEELEMENT structures. - /// - public void Browse( - string szItemID, - ref System.IntPtr pszContinuationPoint, - int dwMaxElementsReturned, - OPCBROWSEFILTER dwBrowseFilter, - string szElementNameFilter, - string szVendorFilter, - int bReturnAllProperties, - int bReturnPropertyValues, - int dwPropertyCount, - int[] pdwPropertyIDs, - out int pbMoreElements, - out int pdwCount, - out System.IntPtr ppBrowseElements) - { - try - { - NodeId startId = ItemIdToNodeId(szItemID); - - if (startId == null) - { - throw new COMException("E_INVALIDITEMID", ResultIds.E_INVALIDITEMID); - } - - // unmarshal continuation point. - string continuationPoint = null; - - if (pszContinuationPoint != IntPtr.Zero) - { - continuationPoint = Marshal.PtrToStringUni(pszContinuationPoint); - } - - // lookup continuation point. - ContinuationPoint cp = null; - - if (!String.IsNullOrEmpty(continuationPoint)) - { - // find existing continuation point. - lock (m_lock) - { - for (LinkedListNode current = m_continuationPoints.First; current != null; current = current.Next) - { - if (current.Value.Id == continuationPoint) - { - cp = current.Value; - m_continuationPoints.Remove(current); - break; - } - } - } - - // no longer valid. - if (cp == null) - { - throw new COMException("E_INVALIDCONTINUATIONPOINT", ResultIds.E_INVALIDCONTINUATIONPOINT); - } - } - - // find references. - IList elements = Browse( - startId, - ref cp, - dwMaxElementsReturned, - dwBrowseFilter, - szElementNameFilter); - - // save continuation point. - if (cp != null) - { - cp.Id = Guid.NewGuid().ToString(); - m_continuationPoints.AddLast(cp); - pszContinuationPoint = Marshal.StringToCoTaskMemUni(cp.Id); - } - - // return a valid the continution point. - if (pszContinuationPoint == IntPtr.Zero) - { - pszContinuationPoint = Marshal.StringToCoTaskMemUni(String.Empty); - } - - // fetch any properties. - if (bReturnAllProperties != 0 || dwPropertyCount > 0) - { - for (int ii = 0; ii < elements.Count; ii++) - { - elements[ii].Properties = GetItemProperties( - elements[ii].Node, - bReturnAllProperties != 0, - pdwPropertyIDs, - bReturnPropertyValues != 0); - } - } - - // marshal return arguments. - pbMoreElements = 0; - pdwCount = 0; - ppBrowseElements = IntPtr.Zero; - - if (elements != null) - { - pdwCount = elements.Count; - ppBrowseElements = GetBrowseElements(elements); - } - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - - /// - /// Finds the references that meet the browse criteria. - /// - private IList Browse( - NodeId startId, - ref ContinuationPoint cp, - int dwMaxElementsReturned, - OPCBROWSEFILTER dwBrowseFilter, - string szElementNameFilter) - { - IList filteredResults = new List(); - IList unprocessedResults = new List(); - - byte[] continuationPoint = null; - - while (dwMaxElementsReturned == 0 || filteredResults.Count < dwMaxElementsReturned) - { - ReferenceDescriptionCollection currentBatch = null; - - if (cp == null) - { - currentBatch = Browse(startId, dwMaxElementsReturned, out continuationPoint); - - if (continuationPoint != null) - { - cp = new ContinuationPoint(); - cp.LastCP = continuationPoint; - cp.UnprocessedElements = null; - } - } - else - { - if (cp.UnprocessedElements != null) - { - // add any unprocessed results from the previous call. - for (int ii = 0; ii < cp.UnprocessedElements.Count; ii++) - { - if (dwMaxElementsReturned == 0 || filteredResults.Count < dwMaxElementsReturned) - { - filteredResults.Add(cp.UnprocessedElements[ii]); - } - else - { - unprocessedResults.Add(cp.UnprocessedElements[ii]); - } - } - - // check if all done. - if (unprocessedResults.Count == 0 && cp.LastCP == null) - { - cp = null; - break; - } - - // check for max results. - if (unprocessedResults.Count > 0) - { - cp = new ContinuationPoint(); - cp.LastCP = null; - cp.UnprocessedElements = unprocessedResults; - break; - } - } - - // get the next batch. - if (cp != null && cp.LastCP != null) - { - continuationPoint = cp.LastCP; - currentBatch = BrowseNext(ref continuationPoint); - - if (continuationPoint != null) - { - cp = new ContinuationPoint(); - cp.LastCP = continuationPoint; - cp.UnprocessedElements = null; - } - } - } - - // apply the filters. - ApplyFilters( - currentBatch, - dwBrowseFilter, - szElementNameFilter, - dwMaxElementsReturned, - filteredResults, - unprocessedResults); - - // check if all done. - if (unprocessedResults.Count == 0 && (cp == null || cp.LastCP == null)) - { - cp = null; - break; - } - - // check for max results. - if (unprocessedResults.Count > 0) - { - cp = new ContinuationPoint(); - cp.LastCP = continuationPoint; - cp.UnprocessedElements = unprocessedResults; - break; - } - } - - return filteredResults; - } - - /// - /// Gets the properties for the browse element. - /// - private List GetItemProperties( - INode node, - bool returnAllProperties, - int[] propertyIds, - bool returnPropertyValues) - { - int[] availablePropertyIds = GetAvailableProperties(node); - - List properties = new List(); - - // determine whether any of the request properties are supported. - if (propertyIds != null && propertyIds.Length > 0) - { - for (int ii = 0; ii < propertyIds.Length; ii++) - { - bool exists = false; - - for (int jj = 0; jj < availablePropertyIds.Length; jj++) - { - if (availablePropertyIds[jj] == propertyIds[ii]) - { - exists = true; - break; - } - } - - ItemProperty property = new ItemProperty(); - - property.Id = propertyIds[ii]; - property.ErrorId = ResultIds.S_OK; - - if (!exists) - { - property.ErrorId = ResultIds.E_INVALID_PID; - } - - properties.Add(property); - } - } - - // return all available properties. - else - { - for (int ii = 0; ii < availablePropertyIds.Length; ii++) - { - ItemProperty property = new ItemProperty(); - - property.Id = availablePropertyIds[ii]; - property.ErrorId = ResultIds.S_OK; - - properties.Add(property); - } - } - - // get description and datatype. - List valuesToFetch = new List(properties.Count); - List indexesForValues = new List(properties.Count); - - for (int ii = 0; ii < properties.Count; ii++) - { - ItemProperty property = properties[ii]; - - if (property.ErrorId == 0) - { - property.Description = PropertyIds.GetDescription(property.Id); - property.DataType = (short)PropertyIds.GetVarType(property.Id); - - if (returnPropertyValues) - { - valuesToFetch.Add(property.Id); - indexesForValues.Add(ii); - } - } - } - - // fetch any property values. - if (valuesToFetch.Count > 0) - { - try - { - int[] errors = null; - - object[] values = ReadPropertyValues(node, valuesToFetch, out errors); - - // update property objects. - for (int ii = 0; ii < errors.Length; ii++) - { - ItemProperty property = properties[indexesForValues[ii]]; - - property.Value = values[ii]; - property.ErrorId = errors[ii]; - - if (property.ErrorId < 0) - { - property.Value = null; - } - } - } - catch (Exception e) - { - // update property objects with errors. - int error = Marshal.GetHRForException(e); - - for (int ii = 0; ii < indexesForValues.Count; ii++) - { - ItemProperty property = properties[indexesForValues[ii]]; - - property.Value = null; - property.ErrorId = error; - } - } - } - - // save the properties in the element. - return properties; - } - - /// - /// Applies the browse filters to a set of references. - /// - private void ApplyFilters( - ReferenceDescriptionCollection currentBatch, - OPCBROWSEFILTER dwBrowseFilter, - string szElementNameFilter, - int maxReferencesReturned, - IList filteredResults, - IList unprocessedResults) - { - // apply the filters to each item in the batch. - foreach (ReferenceDescription reference in currentBatch) - { - // check for a valid node. - INode target = m_session.NodeCache.FetchNode(reference.NodeId); - - if (target == null) - { - continue; - } - - // create the browse element. - BrowseElement element = new BrowseElement(); - - element.Node = target; - element.Name = target.BrowseName.Name; - element.ItemId = NodeIdToItemId(target.NodeId); - - // apply the element name filter. - if (!String.IsNullOrEmpty(szElementNameFilter)) - { - if (!ComUtils.Match(element.Name, szElementNameFilter, true)) - { - continue; - } - } - - element.IsItem = IsItem(target); - element.HasChildren = HasChildren(target); - - // apply the browse filter. - if (dwBrowseFilter != OPCBROWSEFILTER.OPC_BROWSE_FILTER_ALL) - { - if (dwBrowseFilter == OPCBROWSEFILTER.OPC_BROWSE_FILTER_ITEMS) - { - if (!element.IsItem) - { - continue; - } - } - else - { - if (!element.HasChildren) - { - continue; - } - } - } - - // must save the results to return in a subsequent browse. - if (maxReferencesReturned != 0 && filteredResults.Count >= maxReferencesReturned) - { - unprocessedResults.Add(element); - } - - // can return the results in this browse. - else - { - filteredResults.Add(element); - } - } - } - - /// - /// Browses the specified node. - /// - private ReferenceDescriptionCollection Browse( - NodeId nodeId, - int maxReferencesReturned, - out byte[] continuationPoint) - { - try - { - // fetch initial set of references. - ReferenceDescriptionCollection references; - - m_session.Browse( - null, - null, - nodeId, - (uint)maxReferencesReturned, - BrowseDirection.Forward, - ReferenceTypeIds.HierarchicalReferences, - true, - (uint)(NodeClass.Object | NodeClass.Variable), - out continuationPoint, - out references); - - // return the results. - return references; - } - catch (Exception e) - { - throw new COMException(e.Message, MapBrowseStatusToErrorCode(e)); - } - } - - /// - /// Continues the browse operation. - /// - private ReferenceDescriptionCollection BrowseNext(ref byte[] continuationPoint) - { - try - { - ReferenceDescriptionCollection references; - byte[] revisedContuinationPoint; - - m_session.BrowseNext( - null, - false, - continuationPoint, - out revisedContuinationPoint, - out references); - - // return the results. - return references; - } - catch (Exception e) - { - throw new COMException(e.Message, MapBrowseStatusToErrorCode(e)); - } - } - - /// - /// Allocates and marshals an array of OPCBROWSEELEMENT structures. - /// - internal static IntPtr GetBrowseElements(IList input) - { - IntPtr output = IntPtr.Zero; - - if (input != null && input.Count > 0) - { - output = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OpcRcw.Da.OPCBROWSEELEMENT))*input.Count); - - IntPtr pos = output; - - for (int ii = 0; ii < input.Count; ii++) - { - OpcRcw.Da.OPCBROWSEELEMENT element = GetBrowseElement(input[ii]); - Marshal.StructureToPtr(element, pos, false); - pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCBROWSEELEMENT))); - } - } - - return output; - } - - /// - /// Allocates and marshals an OPCBROWSEELEMENT structure. - /// - internal static OpcRcw.Da.OPCBROWSEELEMENT GetBrowseElement(BrowseElement input) - { - OpcRcw.Da.OPCBROWSEELEMENT output = new OpcRcw.Da.OPCBROWSEELEMENT(); - - if (input != null) - { - output.szName = input.Name; - output.szItemID = input.ItemId; - output.dwFlagValue = 0; - output.ItemProperties = GetItemProperties(input.Properties); - - if (input.IsItem) - { - output.dwFlagValue |= OpcRcw.Da.Constants.OPC_BROWSE_ISITEM; - } - - if (input.HasChildren) - { - output.dwFlagValue |= OpcRcw.Da.Constants.OPC_BROWSE_HASCHILDREN; - } - } - - return output; - } - - /// - /// Allocates and marshals an array of OPCITEMPROPERTIES structures. - /// - internal static OpcRcw.Da.OPCITEMPROPERTIES GetItemProperties(IList input) - { - OpcRcw.Da.OPCITEMPROPERTIES output = new OpcRcw.Da.OPCITEMPROPERTIES(); - - if (input != null && input.Count > 0) - { - output.hrErrorID = ResultIds.S_OK; - output.dwReserved = 0; - output.dwNumProperties = input.Count; - output.pItemProperties = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMPROPERTY))*input.Count); - - bool error = false; - - IntPtr pos = output.pItemProperties; - - for (int ii = 0; ii < input.Count; ii++) - { - OpcRcw.Da.OPCITEMPROPERTY property = GetItemProperty(input[ii]); - Marshal.StructureToPtr(property, pos, false); - pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMPROPERTY))); - - if (input[ii].ErrorId < 0) - { - error = true; - } - } - - // set flag indicating one or more properties contained errors. - if (error) - { - output.hrErrorID = ResultIds.S_FALSE; - } - } - - return output; - } - - /// - /// Allocates and marshals an arary of OPCITEMPROPERTY structures. - /// - internal static OpcRcw.Da.OPCITEMPROPERTY GetItemProperty(ItemProperty input) - { - OpcRcw.Da.OPCITEMPROPERTY output = new OpcRcw.Da.OPCITEMPROPERTY(); - - if (input != null) - { - output.dwPropertyID = input.Id; - output.szDescription = input.Description; - output.vtDataType = input.DataType; - output.vValue = ComUtils.GetVARIANT(input.Value); - output.wReserved = 0; - output.hrErrorID = input.ErrorId; - } - - return output; - } - - /// - /// Allocates and marshals an array of OPCITEMPROPERTIES structures. - /// - internal static IntPtr GetItemProperties(IList input) - { - IntPtr output = IntPtr.Zero; - - if (input != null && input.Count > 0) - { - output = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMPROPERTIES))*input.Count); - - IntPtr pos = output; - - for (int ii = 0; ii < input.Count; ii++) - { - Marshal.StructureToPtr(input[ii], pos, false); - pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMPROPERTIES))); - } - } - - return output; - } - - /// - /// IOPCBrowse::GetProperties - Returns an array of OPCITEMPROPERTIES, one for each ItemID. - /// - public void GetProperties( - int dwItemCount, - string[] pszItemIDs, - int bReturnPropertyValues, - int dwPropertyCount, - int[] pdwPropertyIDs, - out System.IntPtr ppItemProperties) - { - lock (m_lock) - { - try - { - if (dwItemCount == 0 || pszItemIDs == null) - { - throw ComUtils.CreateComException("E_INVALIDARG", ResultIds.E_INVALIDARG); - } - - ppItemProperties = IntPtr.Zero; - - OPCITEMPROPERTIES[] results = new OPCITEMPROPERTIES[dwItemCount]; - - for (int ii = 0; ii < dwItemCount; ii++) - { - // initialize result. - OPCITEMPROPERTIES result = new OPCITEMPROPERTIES(); - - result.hrErrorID = ResultIds.S_OK; - result.dwReserved = 0; - result.dwNumProperties = 0; - result.pItemProperties = IntPtr.Zero; - - // lookup item id. - NodeId nodeId = ItemIdToNodeId(pszItemIDs[ii]); - - if (nodeId == null) - { - result.hrErrorID = ResultIds.E_INVALIDITEMID; - continue; - } - - // find node. - INode node = m_session.NodeCache.FetchNode(nodeId); - - if (node == null) - { - result.hrErrorID = ResultIds.E_UNKNOWNITEMID; - continue; - } - - // get properties. - List properties = GetItemProperties( - node, - false, - pdwPropertyIDs, - bReturnPropertyValues != 0); - - // marshal properties. - result = GetItemProperties(properties); - } - - ppItemProperties = GetItemProperties(results); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - #region IOPCBrowseServerAddressSpace Members - - /// - /// IOPCBrowseServerAddressSpace::GetItemID - Provides a way to assemble a 'fully qualified' ITEM ID in a hierarchical space. - /// - public void GetItemID( - string szItemDataID, - out string szItemID) - { - lock (m_lock) - { - try - { - // find the current node. - INode node = null; - - // ensure browse stack has been initialized. - if (m_browseStack.Count == 0) - { - node = m_session.NodeCache.Find(Objects.ObjectsFolder); - m_browseStack.Push(node); - } - - node = m_browseStack.Peek(); - - // check if looking for the current node. - if (String.IsNullOrEmpty(szItemDataID)) - { - szItemID = NodeIdToItemId(node.NodeId); - return; - } - - // attempt to find the child name. - node = FindChildByName(node.NodeId, szItemDataID); - - if (node != null) - { - szItemID = NodeIdToItemId(node.NodeId); - return; - } - - // check for a fully qualified item id. - NodeId nodeId = ItemIdToNodeId(szItemDataID); - - if (nodeId != null) - { - node = m_session.NodeCache.Find(nodeId); - - if (node != null) - { - szItemID = NodeIdToItemId(node.NodeId); - return; - } - } - - // not found. - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - // AMaksumov: replaces characters that CTT cannot handle - internal string ConvertToItemID(string myString) - { - string myNewString = ""; - - if (myString != null && myString != String.Empty) - { - myNewString = myString.Replace("=", "*"); - } - - return myNewString; - } - - // AMaksumov: puts replaced characters back to string - internal string ConvertFromItemID(string myString) - { - string myNewString = ""; - - if (myString != null && myString != String.Empty) - { - myNewString = myString.Replace("*", "="); - } - - return myNewString; - } - - /// - /// Parses an ItemId (returns null if parsing fails). - /// - internal static NodeId ItemIdToNodeId(string itemId) - { - // check for root. - if (String.IsNullOrEmpty(itemId)) - { - return Objects.ObjectsFolder; - } - - // replace then '=' signs in item id because the CTT does not like them. - StringBuilder buffer = new StringBuilder(itemId.Length); - - for (int ii = 0; ii < itemId.Length; ii++) - { - if (itemId[ii] == '*') - { - buffer.Append('='); - } - else - { - buffer.Append(itemId[ii]); - } - } - - // parse the node id. - try - { - return NodeId.Parse(buffer.ToString()); - } - catch - { - return null; - } - } - - /// - /// Converts a NodeId to an ItemId - /// - internal static string NodeIdToItemId(ExpandedNodeId nodeId) - { - if (NodeId.IsNull(nodeId)) - { - return null; - } - - if (nodeId == Objects.ObjectsFolder) - { - return String.Empty; - } - - // remove '=' signs from item id because the CTT does not like them. - string itemId = nodeId.ToString(); - StringBuilder buffer = new StringBuilder(itemId.Length); - - for (int ii = 0; ii < itemId.Length; ii++) - { - if (itemId[ii] == '=') - { - buffer.Append('*'); - } - else - { - buffer.Append(itemId[ii]); - } - } - - return buffer.ToString(); - } - - /// - /// IOPCBrowseServerAddressSpace::BrowseAccessPaths - Provides a way to browse the available AccessPaths for an item ID - not supported. - /// - public void BrowseAccessPaths( - string szItemID, - out OpcRcw.Comn.IEnumString ppIEnumString) - { - lock (m_lock) - { - // access paths not supported. - try - { - throw ComUtils.CreateComException("BrowseAccessPaths", ResultIds.E_NOTIMPL); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCBrowseServerAddressSpace::QueryOrganization - Determines if the ServerAddressSpace is flat or hierarchical. - /// - public void QueryOrganization(out OpcRcw.Da.OPCNAMESPACETYPE pNameSpaceType) - { - lock (m_lock) - { - // only hierarchial spaces supported. - try - { - pNameSpaceType = OPCNAMESPACETYPE.OPC_NS_HIERARCHIAL; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - - // return ResultIds.S_OK; - } - - /// - /// Finds the path to the Node from the Objects folder. - /// - /// - /// The DA proxy exposes only nodes that can be related back to the Objects folder via HierarchicalReferences references. - /// If the client browses to a specific node the proxy must determine if that node has a reference back to the - /// Objects folder. If it does not then it is not a valid node. - /// - private bool FindPathToNode(INode startNode, Stack path) - { - // find all parent nodes. - foreach (INode node in m_session.NodeCache.Find(startNode.NodeId, ReferenceTypeIds.HierarchicalReferences, true, true)) - { - // ignore external nodes. - if (node.NodeId.IsAbsolute) - { - continue; - } - - // ignore non-objects/variables. - if ((node.NodeClass & (NodeClass.Object | NodeClass.Variable)) == 0) - { - continue; - } - - // check if objects folder found. - if (node.NodeId == Objects.ObjectsFolder) - { - path.Push(node); - return true; - } - - // recursively follow parents. - if (FindPathToNode(node, path)) - { - path.Push(node); - return true; - } - } - - // path does not lead to the objects folder. - return false; - } - - /// - /// Finds the child node with the specified browse name. - /// - private INode FindChildByName(ExpandedNodeId startId, string browseName) - { - // find all parent nodes. - foreach (INode child in m_session.NodeCache.Find(startId, ReferenceTypeIds.HierarchicalReferences, false, true)) - { - // ignore external nodes. - if (child.NodeId.IsAbsolute) - { - continue; - } - - // ignore non-objects/variables. - if ((child.NodeClass & (NodeClass.Object | NodeClass.Variable)) == 0) - { - continue; - } - - // ignore the namespace when comparing. - if (browseName == child.BrowseName.Name) - { - return child; - } - } - - // child with specified browse name does not exist. - return null; - } - - /// - /// IOPCBrowseServerAddressSpace::ChangeBrowsePosition - Provides a way to move UP or DOWN or TO in a hierarchical space. - /// - public void ChangeBrowsePosition(OpcRcw.Da.OPCBROWSEDIRECTION dwBrowseDirection, string szString) - { - lock (m_lock) - { - try - { - switch (dwBrowseDirection) - { - // move to a specified position or root. - case OPCBROWSEDIRECTION.OPC_BROWSE_TO: - { - // move to root. - if (String.IsNullOrEmpty(szString)) - { - m_browseStack.Clear(); - m_browseStack.Push(m_session.NodeCache.Find(Objects.ObjectsFolder)); - break; - } - - // parse the item id. - NodeId nodeId = ItemIdToNodeId(szString); - - if (nodeId == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // find the current node. - INode node = m_session.NodeCache.Find(nodeId); - - if (node == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // only can browse to branch - if (!HasChildren(node)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // build a new browse stack. - Stack browseStack = new Stack(); - - if (!FindPathToNode(node, browseStack)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // push target node onto stack. - browseStack.Push(m_session.NodeCache.Find(nodeId)); - - m_browseStack = browseStack; - break; - } - - // move to a child branch. - case OPCBROWSEDIRECTION.OPC_BROWSE_DOWN: - { - // check for invalid name. - if (String.IsNullOrEmpty(szString)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // 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_INVALIDARG); - } - - // only can browse to branch - if (!HasChildren(child)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // save the new position. - m_browseStack.Push(child); - break; - } - - // move to a parent branch. - case OPCBROWSEDIRECTION.OPC_BROWSE_UP: - { - // check for invalid name. - if (!String.IsNullOrEmpty(szString)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // 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_FAIL); - } - } - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Applies the browse filters to a node. - /// - private bool ApplyFilters( - INode child, - OpcRcw.Da.OPCBROWSETYPE dwBrowseFilterType, - string szFilterCriteria, - short vtDataTypeFilter, - int dwAccessRightsFilter) - { - bool hasChildren = HasChildren(child); - - // apply branch filter. - if (dwBrowseFilterType == OPCBROWSETYPE.OPC_BRANCH && !hasChildren) - { - return false; - } - - // apply leaf filter. - if (dwBrowseFilterType == OPCBROWSETYPE.OPC_LEAF && hasChildren) - { - return false; - } - - // check for items. - bool isItem = IsItem(child); - - if (!isItem && !hasChildren) - { - return false; - } - - // apply flat filter. - if (dwBrowseFilterType == OPCBROWSETYPE.OPC_FLAT && !isItem) - { - return false; - } - - // apply name filter. - if (dwBrowseFilterType != OPCBROWSETYPE.OPC_FLAT) - { - if (!String.IsNullOrEmpty(szFilterCriteria)) - { - if (!ComUtils.Match(child.BrowseName.Name, szFilterCriteria, true)) - { - return false; - } - } - } - - // check for variable. - VariableNode variable = child as VariableNode; - - if (variable != null) - { - // apply access right filter. - if (dwAccessRightsFilter != 0) - { - if (dwAccessRightsFilter == OpcRcw.Da.Constants.OPC_READABLE && ((variable.AccessLevel & AccessLevels.CurrentRead) == 0)) - { - return false; - } - - if (dwAccessRightsFilter == OpcRcw.Da.Constants.OPC_WRITEABLE && ((variable.AccessLevel & AccessLevels.CurrentWrite) == 0)) - { - return false; - } - } - - // lookup the requested datatype. - if (vtDataTypeFilter != 0) - { - bool isArray = false; - NodeId requestedDataTypeId = ComUtils.GetDataTypeId(vtDataTypeFilter, out isArray); - - VarEnum varType = DataTypeToVarType(variable.DataType, variable.ValueRank); - - if (varType != VarEnum.VT_VARIANT && (short)varType != vtDataTypeFilter) - { - return false; - } - } - - // must match item id rather than name when browsing flat. - if (dwBrowseFilterType == OPCBROWSETYPE.OPC_FLAT) - { - if (!String.IsNullOrEmpty(szFilterCriteria)) - { - string itemId = NodeIdToItemId(child.NodeId); - - if (!ComUtils.Match(itemId, szFilterCriteria, true)) - { - return false; - } - } - } - } - - return true; - } - - /// - /// Browses the children of a node. - /// - private void BrowseChildren( - INode parent, - OpcRcw.Da.OPCBROWSETYPE dwBrowseFilterType, - string szFilterCriteria, - short vtDataTypeFilter, - int dwAccessRightsFilter, - List hits) - { - Dictionary nodes = new Dictionary(); - - // find children. - IList children = m_session.NodeCache.Find(parent.NodeId, ReferenceTypeIds.HierarchicalReferences, false, true); - - 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 (nodes.ContainsKey(child.BrowseName.Name)) - { - continue; - } - - bool match = ApplyFilters( - child, - dwBrowseFilterType, - szFilterCriteria, - vtDataTypeFilter, - dwAccessRightsFilter); - - // add child. - if (match) - { - hits.Add(child); - nodes.Add(child.BrowseName.Name, child); - } - - // recursively follow children when browsing flat. - if (dwBrowseFilterType == OPCBROWSETYPE.OPC_FLAT) - { - BrowseChildren( - child, - dwBrowseFilterType, - szFilterCriteria, - vtDataTypeFilter, - dwAccessRightsFilter, - hits); - } - } - } - - /// - /// IOPCBrowseServerAddressSpace::BrowseOPCItemIDs - Gets an IENUMString for a list of ItemIDs as determined by the passed parameters. - /// - public void BrowseOPCItemIDs( - OpcRcw.Da.OPCBROWSETYPE dwBrowseFilterType, - string szFilterCriteria, - short vtDataTypeFilter, - int dwAccessRightsFilter, - out OpcRcw.Comn.IEnumString ppIEnumString) - { - lock (m_lock) - { - try - { - // find the current node. - INode parent = null; - - // ensure browse stack has been initialized. - if (m_browseStack.Count == 0) - { - parent = m_session.NodeCache.Find(Objects.ObjectsFolder); - m_browseStack.Push(parent); - } - - parent = m_browseStack.Peek(); - - if (parent == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - // apply filters. - List hits = new List(); - - BrowseChildren( - parent, - dwBrowseFilterType, - szFilterCriteria, - vtDataTypeFilter, - dwAccessRightsFilter, - hits); - - // build list of names to return. - Dictionary nodes = new Dictionary(); - List names = new List(); - - foreach (INode child in hits) - { - string name = child.BrowseName.Name; - - if (dwBrowseFilterType == OPCBROWSETYPE.OPC_FLAT) - { - name = NodeIdToItemId(child.NodeId); - } - - if (!nodes.ContainsKey(name)) - { - nodes.Add(name, child); - names.Add(name); - } - } - - // create enumerator. - ppIEnumString = (OpcRcw.Comn.IEnumString)new EnumString(names); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - private List m_names = new List(); - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //-----------------------------------------------------------------------------------------------------------// - #region IOPCItemProperties Members - - /// - /// IOPCItemProperties::QueryAvailableProperties - Returns a list of ID codes and descriptions for the available - /// properties for this ITEMID - /// - public void QueryAvailableProperties( - string szItemID, - out int pdwCount, - out System.IntPtr ppPropertyIDs, - out System.IntPtr ppDescriptions, - out System.IntPtr ppvtDataTypes) - { - lock (m_lock) - { - try - { - // validate item id. - if (String.IsNullOrEmpty(szItemID)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDITEMID); - } - - // find the node id. - NodeId nodeId = ItemIdToNodeId(szItemID); - - if (nodeId == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - // find the node. - INode node = m_session.NodeCache.Find(nodeId); - - if (node == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - // find the available properties. - int[] propertyIds = GetAvailableProperties(node); - string[] descriptions = new string[propertyIds.Length]; - short[] datatypes = new short[propertyIds.Length]; - - for (int ii = 0; ii < propertyIds.Length; ii++) - { - descriptions[ii] = PropertyIds.GetDescription(propertyIds[ii]); - datatypes[ii] = (short)PropertyIds.GetVarType(propertyIds[ii]); - } - - // marshal the results. - pdwCount = propertyIds.Length; - ppPropertyIDs = ComUtils.GetInt32s(propertyIds); - ppDescriptions = ComUtils.GetUnicodeStrings(descriptions); - ppvtDataTypes = ComUtils.GetInt16s(datatypes); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Converts a exception returned during a Browse to an HRESULT. - /// - private int MapBrowseStatusToErrorCode(Exception e) - { - COMException ce = e as COMException; - - if (ce != null) - { - return ce.ErrorCode; - } - - ServiceResultException sre = e as ServiceResultException; - - if (sre != null) - { - return MapBrowseStatusToErrorCode(sre.StatusCode); - } - - return ResultIds.E_FAIL; - } - - /// - /// Converts a StatusCode returned during a Browse to an HRESULT. - /// - private int MapBrowseStatusToErrorCode(StatusCode statusCode) - { - // map good status. - if (StatusCode.IsGood(statusCode)) - { - return ResultIds.S_OK; - } - - // map bad status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadContinuationPointInvalid: { return ResultIds.E_INVALIDCONTINUATIONPOINT; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALIDITEMID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_UNKNOWNITEMID; } - } - - return ResultIds.E_FAIL; - } - - // uncertain values for property reads are errors. - return ResultIds.E_FAIL; - } - - /// - /// Converts a StatusCode returned during a Read to an HRESULT. - /// - private int MapPropertyReadStatusToErrorCode(StatusCode statusCode) - { - // map good status. - if (StatusCode.IsGood(statusCode)) - { - return ResultIds.S_OK; - } - - // map bad status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadOutOfMemory: { return ResultIds.E_OUTOFMEMORY; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALID_PID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_INVALID_PID; } - case StatusCodes.BadNotReadable: { return ResultIds.E_BADRIGHTS; } - case StatusCodes.BadUserAccessDenied: { return ResultIds.E_ACCESSDENIED; } - case StatusCodes.BadAttributeIdInvalid: { return ResultIds.E_INVALID_PID; } - case StatusCodes.BadTypeMismatch: { return ResultIds.E_BADTYPE; } - } - - return ResultIds.E_FAIL; - } - - // uncertain values for property reads are errors. - return ResultIds.E_FAIL; - } - - /// - /// Converts a StatusCode returned during a Read to an HRESULT. - /// - internal static int MapReadStatusToErrorCode(StatusCode statusCode) - { - // map bad well known status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadOutOfMemory: { return ResultIds.E_OUTOFMEMORY; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALIDITEMID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_UNKNOWNITEMID; } - case StatusCodes.BadNotReadable: { return ResultIds.E_BADRIGHTS; } - case StatusCodes.BadUserAccessDenied: { return ResultIds.E_ACCESSDENIED; } - case StatusCodes.BadAttributeIdInvalid: { return ResultIds.E_UNKNOWNITEMID; } - case StatusCodes.BadUnexpectedError: { return ResultIds.E_FAIL; } - case StatusCodes.BadInternalError: { return ResultIds.E_FAIL; } - case StatusCodes.BadSessionClosed: { return ResultIds.E_FAIL; } - case StatusCodes.BadTypeMismatch: { return ResultIds.E_BADTYPE; } - } - } - - // all other values are mapped to quality codes. - return ResultIds.S_OK; - } - - /// - /// Converts a StatusCode returned during a Write to an HRESULT. - /// - internal static int MapWriteStatusToErrorCode(StatusCode statusCode) - { - // map bad status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadOutOfMemory: { return ResultIds.E_OUTOFMEMORY; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALIDITEMID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_UNKNOWNITEMID; } - case StatusCodes.BadNotWritable: { return ResultIds.E_BADRIGHTS; } - case StatusCodes.BadUserAccessDenied: { return ResultIds.E_ACCESSDENIED; } - case StatusCodes.BadAttributeIdInvalid: { return ResultIds.E_UNKNOWNITEMID; } - case StatusCodes.BadTypeMismatch: { return ResultIds.E_BADTYPE; } - case StatusCodes.BadWriteNotSupported: { return ResultIds.E_NOTSUPPORTED; } - case StatusCodes.BadOutOfRange: { return ResultIds.E_RANGE; } - } - - return ResultIds.E_FAIL; - } - - // ignore uncertain and success codes. - return ResultIds.S_OK; - } - - /// - /// Converts a VARIANT value to a Builtin Type. - /// - private object VariantValueToScalarValue(object value, NodeId builtinTypeId) - { - switch ((uint)builtinTypeId.Identifier) - { - case DataTypes.Guid: - { - return new Uuid((string)value); - } - - case DataTypes.XmlElement: - { - XmlDocument document = new XmlDocument(); - document.InnerXml = (string)value; - return document.DocumentElement; - } - - case DataTypes.NodeId: - { - return NodeId.Parse((string)value); - } - - case DataTypes.ExpandedNodeId: - { - return ExpandedNodeId.Parse((string)value); - } - - case DataTypes.QualifiedName: - { - return QualifiedName.Parse((string)value); - } - - case DataTypes.LocalizedText: - { - return new LocalizedText(ComUtils.GetLocale(m_lcid), (string)value); - } - - case DataTypes.StatusCode: - { - return new StatusCode((uint)value); - } - - case DataTypes.DiagnosticInfo: - { - BinaryDecoder decoder = new BinaryDecoder((byte[])value, m_session.MessageContext); - DiagnosticInfo decodedValue = decoder.ReadDiagnosticInfo(null); - decoder.Close(); - return decodedValue; - } - - case DataTypes.DataValue: - { - BinaryDecoder decoder = new BinaryDecoder((byte[])value, m_session.MessageContext); - DataValue decodedValue = decoder.ReadDataValue(null); - decoder.Close(); - return decodedValue; - } - - case DataTypes.Structure: - { - BinaryDecoder decoder = new BinaryDecoder((byte[])value, m_session.MessageContext); - ExtensionObject decodedValue = decoder.ReadExtensionObject(null); - decoder.Close(); - return decodedValue; - } - } - - return value; - } - - /// - /// Converts a VARIANT value to a Builtin Type. - /// - private object VariantValueToArrayValue(Array value, NodeId builtinTypeId) - { - if (value == null) - { - return null; - } - - Type elementType = TypeInfo.GetSystemType(builtinTypeId, m_session.Factory); - - if (elementType == typeof(Variant)) - { - elementType = typeof(object); - } - - Array result = Array.CreateInstance(elementType, value.Length); - - for (int ii = 0; ii < value.Length; ii++) - { - object elementValue = VariantValueToValue(value.GetValue(ii), builtinTypeId); - result.SetValue(elementValue, ii); - } - - return result; - } - - /// - /// Converts a VARIANT value to specified built-in type. - /// - private object VariantValueToValue(object value, NodeId builtinTypeId) - { - if (value == null) - { - return null; - } - - Array array = value as Array; - - if (array != null && !typeof(byte[]).IsInstanceOfType(value)) - { - return VariantValueToArrayValue(array, builtinTypeId); - } - - return VariantValueToScalarValue(value, builtinTypeId); - } - - /// - /// Converts a value to the canonical type. - /// - internal object VariantValueToValue(INode node, object value, out int error) - { - error = ResultIds.E_BADTYPE; - - lock (m_lock) - { - // VT_EMPTY is never accepted as a valid value. - if (value == null) - { - error = ResultIds.E_BADTYPE; - return null; - } - - // check for variable. - VariableNode variable = node as VariableNode; - - if (variable == null) - { - return null; - } - - try - { - error = ResultIds.S_OK; - - // lookup canonical type. - VarEnum canonicalType = DataTypeToVarType(variable.DataType, variable.ValueRank); - - if (canonicalType == VarEnum.VT_EMPTY) - { - error = ResultIds.S_OK; - return value; - } - - // change type. - object canonicalValue = null; - error = ComUtils.ChangeTypeForCOM(value, canonicalType, out canonicalValue); - - if (error < 0) - { - return null; - } - - // find the target built-in type. - BuiltInType builtInType = GetBuiltInType(variable.DataType); - - // convert to UA value. - return VariantValueToValue(canonicalValue, new NodeId((uint)(int)builtInType)); - } - catch (COMException e) - { - error = e.ErrorCode; - } - catch (Exception) - { - error = ResultIds.E_FAIL; - } - - return null; - } - } - - /// - /// Converts a value to a VARIANT compatible object. - /// - private object ValueToVariantValue(object value, out int error) - { - error = ResultIds.S_OK; - - try - { - return ComUtils.GetVARIANT(value); - } - catch - { - error = ResultIds.DISP_E_TYPEMISMATCH; - return null; - } - } - - /// - /// Converts a value to a VARIANT compatible object. - /// - private object ValueToVariantValue(object value) - { - return ComUtils.GetVARIANT(value); - } - - /// - /// Extracts a property value from a data value. - /// - private object DataValueToPropertyValue(DataValue value, Type expectedType, out int error) - { - error = ResultIds.E_INVALID_PID; - - // check for null. - if (value == null) - { - return null; - } - - // check status code. - error = MapPropertyReadStatusToErrorCode(value.StatusCode); - - if (error < 0) - { - return null; - } - - if (expectedType != null) - { - // check for scalar extension object. - ExtensionObject extension = value.Value as ExtensionObject; - - if (extension != null) - { - if (expectedType.IsInstanceOfType(extension.Body)) - { - return extension.Body; - } - - error = ResultIds.E_BADTYPE; - return null; - } - - // check for array of extension objects. - ExtensionObject[] extensions = value.Value as ExtensionObject[]; - - if (extensions != null) - { - Type elementType = value.GetType().GetElementType(); - - // handle explicit type conversion. - Array result = Array.CreateInstance(elementType, extensions.Length); - - for (int ii = 0; ii < extensions.Length; ii++) - { - result.SetValue(extensions[ii].Body, ii); - } - - return result; - } - - // check if a specific type was requested. - if (!expectedType.IsInstanceOfType(value.Value)) - { - error = ResultIds.E_BADTYPE; - return null; - } - - return value.Value; - } - - // convert value. - return ValueToVariantValue(value.Value, out error); - } - - /// - /// Checks if the datatype id is a built-in type. - /// - private bool IsBuiltInType(ExpandedNodeId nodeId, out BuiltInType builtinType) - { - builtinType = BuiltInType.Null; - - if (nodeId.IsAbsolute || nodeId.NamespaceIndex != 0 || nodeId.IdType != IdType.Numeric) - { - return false; - } - - uint id = (uint)nodeId.Identifier; - - if (id > 0 && id <= DataTypes.BaseDataType) - { - builtinType = (BuiltInType)(int)id; - return true; - } - - switch (id) - { - case DataTypes.Enumeration: { builtinType = BuiltInType.Int32; break; } - case DataTypes.Number: { builtinType = BuiltInType.Double; break; } - case DataTypes.Integer: { builtinType = BuiltInType.Int64; break; } - case DataTypes.UInteger: { builtinType = BuiltInType.UInt64; break; } - - default: - { - return false; - } - } - - return true; - } - - /// - /// Finds the built-in type for the datatype. - /// - private BuiltInType GetBuiltInType(NodeId datatypeId) - { - BuiltInType builtinType = BuiltInType.Variant; - - ExpandedNodeId subtypeId = datatypeId; - - while (!IsBuiltInType(subtypeId, out builtinType)) - { - IList supertypeIds = m_session.NodeCache.Find(subtypeId, ReferenceTypeIds.HasSubtype, true, true); - - if (supertypeIds.Count == 0) - { - break; - } - - subtypeId = supertypeIds[0].NodeId; - } - - return builtinType; - } - - /// - /// Converts a datatype to a vartype. - /// - internal VarEnum DataTypeToVarType(NodeId datatypeId, int valueRank) - { - // variables which can be scalars or arrays must be VT_VARIANT. - if (valueRank < ValueRanks.Scalar) - { - return VarEnum.VT_EMPTY; - } - - VarEnum varType = VarEnum.VT_EMPTY; - - // find built-in type for data type. - BuiltInType builtinType = GetBuiltInType(datatypeId); - - switch (builtinType) - { - case BuiltInType.Boolean: { varType = VarEnum.VT_BOOL; break; } - case BuiltInType.SByte: { varType = VarEnum.VT_I1; break; } - case BuiltInType.Byte: { varType = VarEnum.VT_UI1; break; } - case BuiltInType.Int16: { varType = VarEnum.VT_I2; break; } - case BuiltInType.UInt16: { varType = VarEnum.VT_UI2; break; } - case BuiltInType.Int32: { varType = VarEnum.VT_I4; break; } - case BuiltInType.UInt32: { varType = VarEnum.VT_UI4; break; } - case BuiltInType.Int64: { varType = VarEnum.VT_I8; break; } - case BuiltInType.UInt64: { varType = VarEnum.VT_UI8; break; } - case BuiltInType.Float: { varType = VarEnum.VT_R4; break; } - case BuiltInType.Double: { varType = VarEnum.VT_R8; break; } - case BuiltInType.String: { varType = VarEnum.VT_BSTR; break; } - case BuiltInType.DateTime: { varType = VarEnum.VT_DATE; break; } - case BuiltInType.Guid: { varType = VarEnum.VT_BSTR; break; } - case BuiltInType.ByteString: { varType = VarEnum.VT_UI1 | VarEnum.VT_ARRAY; break; } - case BuiltInType.XmlElement: { varType = VarEnum.VT_BSTR; break; } - case BuiltInType.NodeId: { varType = VarEnum.VT_BSTR; break; } - case BuiltInType.ExpandedNodeId: { varType = VarEnum.VT_BSTR; break; } - case BuiltInType.StatusCode: { varType = VarEnum.VT_UI4; break; } - case BuiltInType.QualifiedName: { varType = VarEnum.VT_BSTR; break; } - case BuiltInType.LocalizedText: { varType = VarEnum.VT_BSTR; break; } - case BuiltInType.ExtensionObject: { varType = VarEnum.VT_UI1 | VarEnum.VT_ARRAY; break; } - case BuiltInType.DataValue: { varType = VarEnum.VT_EMPTY; break; } - case BuiltInType.Variant: { varType = VarEnum.VT_VARIANT; break; } - } - - // check for array values. - if (valueRank >= ValueRanks.OneOrMoreDimensions) - { - if ((varType & VarEnum.VT_ARRAY) != 0) - { - varType = VarEnum.VT_VARIANT; - } - - return varType | VarEnum.VT_ARRAY; - } - - // return scalar value. - return varType; - } - - /// - /// Reads a set of property values for a node. - /// - private object[] ReadPropertyValues(INode node, IList propertyIds, out int[] errors) - { - errors = new int[propertyIds.Count]; - object[] values = new object[propertyIds.Count]; - - VariableNode variable = node as VariableNode; - - if (variable == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALID_PID); - } - - Dictionary attributes = new Dictionary(); - Dictionary properties = new Dictionary(); - - for (int ii = 0; ii < propertyIds.Count; ii++) - { - switch (propertyIds[ii]) - { - case PropertyIds.DataType: - { - attributes[Attributes.DataType] = null; - attributes[Attributes.ValueRank] = null; - break; - } - - case PropertyIds.Value: - case PropertyIds.Quality: - case PropertyIds.Timestamp: - { - attributes[Attributes.Value] = null; - break; - } - - case PropertyIds.AccessRights: - { - attributes[Attributes.AccessLevel] = null; - break; - } - - case PropertyIds.ScanRate: - { - attributes[Attributes.MinimumSamplingInterval] = null; - break; - } - - case PropertyIds.EuType: - { - attributes[Attributes.DataType] = null; - properties[Opc.Ua.BrowseNames.EURange] = null; - properties[Opc.Ua.BrowseNames.EnumStrings] = null; - break; - } - - case PropertyIds.EuInfo: - { - properties[Opc.Ua.BrowseNames.EnumStrings] = null; - break; - } - - case PropertyIds.Description: - { - attributes[Attributes.Description] = null; - break; - } - - case PropertyIds.EngineeringUnits: - { - properties[Opc.Ua.BrowseNames.EngineeringUnits] = null; - break; - } - - case PropertyIds.HighEU: - case PropertyIds.LowEU: - { - properties[Opc.Ua.BrowseNames.EURange] = null; - break; - } - - case PropertyIds.HighIR: - case PropertyIds.LowIR: - { - properties[Opc.Ua.BrowseNames.InstrumentRange] = null; - break; - } - - case PropertyIds.OpenLabel: - { - properties[Opc.Ua.BrowseNames.FalseState] = null; - break; - } - - case PropertyIds.CloseLabel: - { - properties[Opc.Ua.BrowseNames.TrueState] = null; - break; - } - - case PropertyIds.TimeZone: - { - properties[Opc.Ua.BrowseNames.LocalTime] = null; - break; - } - } - } - - ReadValueIdCollection valuesToRead = new ReadValueIdCollection(); - - // build list of attributes to read. - foreach (uint attributeId in attributes.Keys) - { - ReadValueId nodeToRead = new ReadValueId(); - - nodeToRead.NodeId = ExpandedNodeId.ToNodeId(node.NodeId, m_session.NamespaceUris); - nodeToRead.AttributeId = attributeId; - - valuesToRead.Add(nodeToRead); - - // save a handle to correlate the results with the request. - nodeToRead.Handle = attributeId; - } - - // build list of properties to read. - foreach (string propertyName in properties.Keys) - { - VariableNode propertyNode = m_session.NodeCache.Find( - node.NodeId, - ReferenceTypeIds.HasProperty, - false, - true, - new QualifiedName(propertyName)) as VariableNode; - - if (propertyNode == null) - { - continue; - } - - ReadValueId nodeToRead = new ReadValueId(); - - nodeToRead.NodeId = propertyNode.NodeId; - nodeToRead.AttributeId = Attributes.Value; - - valuesToRead.Add(nodeToRead); - - // save a handle to correlate the results with the request. - nodeToRead.Handle = propertyName; - } - - // read the values. - DataValueCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - if (valuesToRead.Count > 0) - { - m_session.Read( - null, - 0, - TimestampsToReturn.Both, - valuesToRead, - out results, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(results, valuesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToRead); - } - - // update tables. - for (int ii = 0; ii < valuesToRead.Count; ii++) - { - ReadValueId valueToRead = valuesToRead[ii]; - - string propertyName = valueToRead.Handle as string; - - if (propertyName != null) - { - properties[propertyName] = results[ii]; - } - - uint? attributeId = valueToRead.Handle as uint?; - - if (attributeId != null) - { - attributes[attributeId.Value] = results[ii]; - } - } - - // calculate DA property values. - for (int ii = 0; ii < propertyIds.Count; ii++) - { - int errorId = 0; - int propertyId = propertyIds[ii]; - - switch (propertyId) - { - case PropertyIds.DataType: - { - NodeId datatypeId = (NodeId)DataValueToPropertyValue(attributes[Attributes.DataType], typeof(NodeId), out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - int? valueRank = (int?)DataValueToPropertyValue(attributes[Attributes.ValueRank], typeof(int), out errorId); - - if (errorId < 0) - { - valueRank = ValueRanks.Scalar; - break; - } - - VarEnum varType = DataTypeToVarType(datatypeId, valueRank.Value); - - if (varType == VarEnum.VT_VARIANT) - { - varType = VarEnum.VT_EMPTY; - } - - values[ii] = (short)varType; - break; - } - - case PropertyIds.Value: - case PropertyIds.Quality: - case PropertyIds.Timestamp: - { - DataValue dataValue = attributes[Attributes.Value]; - - if (dataValue == null) - { - errors[ii] = ResultIds.E_INVALID_PID; - break; - } - - errors[ii] = MapPropertyReadStatusToErrorCode(dataValue.StatusCode); - - if (errors[ii] < 0) - { - break; - } - - if (propertyId == PropertyIds.Timestamp) - { - values[ii] = dataValue.SourceTimestamp; - errors[ii] = ResultIds.S_OK; - break; - } - - if (propertyId == PropertyIds.Quality) - { - values[ii] = ComUtils.GetQualityCode(dataValue.StatusCode); - errors[ii] = ResultIds.S_OK; - break; - } - - values[ii] = ValueToVariantValue(dataValue.Value, out errorId); - errors[ii] = errorId; - break; - } - - case PropertyIds.AccessRights: - { - byte? accessLevel = (byte?)DataValueToPropertyValue(attributes[Attributes.AccessLevel], typeof(byte), out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - values[ii] = ComUtils.GetAccessRights(accessLevel.Value); - errors[ii] = ResultIds.S_OK; - break; - } - - case PropertyIds.ScanRate: - { - double? samplingInterval = (double?)DataValueToPropertyValue(attributes[Attributes.MinimumSamplingInterval], typeof(double), out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - if (samplingInterval.Value == MinimumSamplingIntervals.Indeterminate) - { - values[ii] = (float)0; - } - else - { - values[ii] = (float)samplingInterval.Value; - } - - errors[ii] = ResultIds.S_OK; - break; - } - - case PropertyIds.EuType: - { - // check if datatype attribute supported. - DataValue dataValue = attributes[Attributes.DataType]; - - if (dataValue == null || StatusCode.IsBad(dataValue.StatusCode)) - { - errors[ii] = ResultIds.E_INVALID_PID; - break; - } - - errors[ii] = ResultIds.S_OK; - - // check for analog items. - Range euRange = (Range)DataValueToPropertyValue(properties[Opc.Ua.BrowseNames.EURange], typeof(Range), out errorId); - - if (errorId == 0) - { - values[ii] = (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG; - break; - } - - // check for enumerated items. - LocalizedText[] enumStrings = (LocalizedText[])DataValueToPropertyValue(properties[Opc.Ua.BrowseNames.EnumStrings], typeof(LocalizedText[]), out errorId); - - if (errorId == 0) - { - values[ii] = (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED; - break; - } - - // normal item. - values[ii] = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM; - break; - } - - case PropertyIds.EuInfo: - { - // check if datatype attribute supported. - DataValue dataValue = attributes[Attributes.DataType]; - - if (dataValue == null || StatusCode.IsBad(dataValue.StatusCode)) - { - errors[ii] = ResultIds.E_INVALID_PID; - break; - } - - errors[ii] = ResultIds.S_OK; - - // check for enumerated items. - LocalizedText[] enumStrings = (LocalizedText[])DataValueToPropertyValue(properties[Opc.Ua.BrowseNames.EnumStrings], typeof(LocalizedText[]), out errorId); - - if (errorId == 0) - { - values[ii] = ValueToVariantValue(enumStrings); - break; - } - break; - } - - case PropertyIds.Description: - { - LocalizedText description = (LocalizedText)DataValueToPropertyValue(attributes[Attributes.Description], typeof(LocalizedText), out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - values[ii] = ValueToVariantValue(description); - errors[ii] = ResultIds.S_OK; - break; - } - - case PropertyIds.EngineeringUnits: - { - EUInformation euInfo = (EUInformation)DataValueToPropertyValue(properties[Opc.Ua.BrowseNames.EngineeringUnits], typeof(EUInformation), out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - values[ii] = ValueToVariantValue(euInfo.DisplayName); - errors[ii] = ResultIds.S_OK; - break; - } - - case PropertyIds.HighEU: - case PropertyIds.LowEU: - { - Range euRange = (Range)DataValueToPropertyValue(properties[Opc.Ua.BrowseNames.EURange], typeof(Range), out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - if (propertyId == PropertyIds.HighEU) - { - values[ii] = euRange.High; - } - else - { - values[ii] = euRange.Low; - } - - errors[ii] = ResultIds.S_OK; - break; - } - - case PropertyIds.HighIR: - case PropertyIds.LowIR: - { - Range euRange = (Range)DataValueToPropertyValue(properties[Opc.Ua.BrowseNames.InstrumentRange], typeof(Range), out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - if (propertyId == PropertyIds.HighIR) - { - values[ii] = euRange.High; - } - else - { - values[ii] = euRange.Low; - } - - errors[ii] = ResultIds.S_OK; - break; - } - - case PropertyIds.OpenLabel: - { - LocalizedText label = (LocalizedText)DataValueToPropertyValue(properties[Opc.Ua.BrowseNames.FalseState], typeof(LocalizedText), out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - values[ii] = ValueToVariantValue(label); - errors[ii] = ResultIds.S_OK; - break; - } - - case PropertyIds.CloseLabel: - { - LocalizedText label = (LocalizedText)DataValueToPropertyValue(properties[Opc.Ua.BrowseNames.TrueState], typeof(LocalizedText), out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - values[ii] = ValueToVariantValue(label); - errors[ii] = ResultIds.S_OK; - break; - } - - case PropertyIds.TimeZone: - { - ExtensionObject extension = (ExtensionObject)DataValueToPropertyValue( - properties[Opc.Ua.BrowseNames.LocalTime], - typeof(ExtensionObject), - out errorId); - - if (errorId < 0) - { - errors[ii] = errorId; - break; - } - - TimeZoneDataType timezone = extension.Body as TimeZoneDataType; - - if (timezone == null) - { - errors[ii] = ResultIds.DISP_E_TYPEMISMATCH; - break; - } - - values[ii] = (int)timezone.Offset; - errors[ii] = ResultIds.S_OK; - break; - } - - default: - { - errors[ii] = ResultIds.E_INVALID_PID; - break; - } - } - } - - return values; - } - - /// - /// IOPCItemProperties::GetItemProperties - Returns a list of the current data values for the passed ID codes - /// - public void GetItemProperties( - string szItemID, - int dwCount, - int[] pdwPropertyIDs, - out System.IntPtr ppvData, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - try - { - // validate arguments. - if (dwCount == 0 || pdwPropertyIDs == null || dwCount != pdwPropertyIDs.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // no properties at root. - if (String.IsNullOrEmpty(szItemID)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // find the node id. - NodeId nodeId = ItemIdToNodeId(szItemID); - - if (nodeId == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - // find the node. - INode node = m_session.NodeCache.Find(nodeId); - - if (node == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - // read the properties. - int[] errors = null; - object[] values = null; - - try - { - values = ReadPropertyValues(node, pdwPropertyIDs, out errors); - } - catch (Exception e) - { - for (int ii = 0; ii < errors.Length; ii++) - { - errors[ii] = Marshal.GetHRForException(e); - } - - values = new object[errors.Length]; - } - - // marshal the return parameters. - ppvData = ComUtils.GetVARIANTs(values, false); - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// Returns the available properties for the node. - /// - private int[] GetAvailableProperties(INode node) - { - VariableNode variable = node as VariableNode; - - if (variable == null) - { - return new int[0]; - } - - List propertyIds = new List(); - - propertyIds.Add(PropertyIds.DataType); - propertyIds.Add(PropertyIds.Value); - propertyIds.Add(PropertyIds.Quality); - propertyIds.Add(PropertyIds.Timestamp); - propertyIds.Add(PropertyIds.AccessRights); - propertyIds.Add(PropertyIds.ScanRate); - propertyIds.Add(PropertyIds.EuType); - propertyIds.Add(PropertyIds.EuInfo); - - if (!LocalizedText.IsNullOrEmpty(variable.Description)) - { - propertyIds.Add(PropertyIds.Description); - } - - IList properties = m_session.NodeCache.Find(node.NodeId, ReferenceTypeIds.HasProperty, false, true); - - foreach (INode property in properties) - { - if (property.BrowseName == Opc.Ua.BrowseNames.EURange) - { - propertyIds.Add(PropertyIds.HighEU); - propertyIds.Add(PropertyIds.LowEU); - continue; - } - - if (property.BrowseName == Opc.Ua.BrowseNames.EngineeringUnits) - { - propertyIds.Add(PropertyIds.EngineeringUnits); - continue; - } - - if (property.BrowseName == Opc.Ua.BrowseNames.InstrumentRange) - { - propertyIds.Add(PropertyIds.HighIR); - propertyIds.Add(PropertyIds.LowIR); - continue; - } - - if (property.BrowseName == Opc.Ua.BrowseNames.TrueState) - { - propertyIds.Add(PropertyIds.CloseLabel); - continue; - } - - if (property.BrowseName == Opc.Ua.BrowseNames.FalseState) - { - propertyIds.Add(PropertyIds.OpenLabel); - continue; - } - - if (property.BrowseName == Opc.Ua.BrowseNames.LocalTime) - { - propertyIds.Add(PropertyIds.TimeZone); - continue; - } - } - - // return as array. - return propertyIds.ToArray(); - } - - /// - /// IOPCItemProperties::LookupItemIDs - Returns a list of ITEMIDs (if available) for each of the passed ID codes - /// - public void LookupItemIDs( - string szItemID, - int dwCount, - int[] pdwPropertyIDs, - out System.IntPtr ppszNewItemIDs, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - try - { - // validate arguments. - if (szItemID == null || szItemID.Length == 0 || dwCount == 0 || pdwPropertyIDs == null || dwCount != pdwPropertyIDs.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // validate item id. - if (String.IsNullOrEmpty(szItemID)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDITEMID); - } - - // find the node id. - NodeId nodeId = ItemIdToNodeId(szItemID); - - if (nodeId == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - // find the node. - INode node = m_session.NodeCache.Find(nodeId); - - if (node == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - // get the available properties. - int[] availableProperties = GetAvailableProperties(node); - - // no item ids conversions supports but must return the correct error code. - string[] itemIds = new string[dwCount]; - int[] errors = new int[dwCount]; - - for (int ii = 0; ii < itemIds.Length; ii++) - { - errors[ii] = ResultIds.E_INVALID_PID; - - for (int jj = 0; jj < availableProperties.Length; jj++) - { - if (pdwPropertyIDs[ii] > PropertyIds.EuInfo && availableProperties[jj] == pdwPropertyIDs[ii]) - { - errors[ii] = ResultIds.E_FAIL; - break; - } - } - } - - // marshal the return parameters. - ppszNewItemIDs = ComUtils.GetUnicodeStrings(itemIds); - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - #region IOPCItemIO Members - - /// - /// IOPCItemIO::WriteVQT - Writes one or more values, qualities and timestamps for the items specified. - /// This is functionally similar to the IOPCSyncIO2::WriteVQT except that there is no associated group. - /// - public void WriteVQT( - int dwCount, - string[] pszItemIDs, - OPCITEMVQT[] pItemVQT, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || pszItemIDs == null || pItemVQT == null || dwCount != pszItemIDs.Length || dwCount != pItemVQT.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - int[] errors = new int[dwCount]; - - // build list of values to write. - WriteValueCollection valuesToWrite = new WriteValueCollection(); - - for (int ii = 0; ii < dwCount; ii++) - { - NodeId nodeId = ItemIdToNodeId(pszItemIDs[ii]); - - if (nodeId == null) - { - errors[ii] = ResultIds.E_INVALIDITEMID; - continue; - } - - VariableNode variable = m_session.NodeCache.Find(nodeId) as VariableNode; - - if (variable == null) - { - errors[ii] = ResultIds.E_UNKNOWNITEMID; - continue; - } - - WriteValue valueToWrite = new WriteValue(); - - valueToWrite.NodeId = nodeId; - valueToWrite.IndexRange = null; - valueToWrite.AttributeId = Attributes.Value; - - DataValue value = new DataValue(); - - int error = 0; - value.Value = VariantValueToValue(variable, pItemVQT[ii].vDataValue, out error); - - if (error != ResultIds.S_OK) - { - errors[ii] = error; - continue; - } - - if (pItemVQT[ii].bQualitySpecified != 0) - { - value.StatusCode = ComUtils.GetQualityCode(pItemVQT[ii].wQuality); - } - - if (pItemVQT[ii].bTimeStampSpecified != 0) - { - value.SourceTimestamp = ComUtils.GetDateTime(pItemVQT[ii].ftTimeStamp); - } - - valueToWrite.Value = value; - - // needed to correlate results to input. - valueToWrite.Handle = ii; - - valuesToWrite.Add(valueToWrite); - } - - // write values from server. - StatusCodeCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - if (valuesToWrite.Count > 0) - { - m_session.Write( - null, - valuesToWrite, - out results, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(results, valuesToWrite); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToWrite); - } - - for (int ii = 0; ii < valuesToWrite.Count; ii++) - { - // get index in original array. - int index = (int)valuesToWrite[ii].Handle; - - // map UA code to DA code. - errors[index] = MapWriteStatusToErrorCode(results[ii]); - } - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - - /// - /// IOPCItemIO::Read - Reads one or more values, qualities and timestamps for the items specified. - /// This is functionally similar to the IOPCSyncIO::Read method. - /// - public void Read( - int dwCount, - string[] pszItemIDs, - int[] pdwMaxAge, - out System.IntPtr ppvValues, - out System.IntPtr ppwQualities, - out System.IntPtr ppftTimeStamps, - out System.IntPtr ppErrors) - { - lock (m_lock) - { - if (m_session == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); - - // validate arguments. - if (dwCount == 0 || pszItemIDs == null || pdwMaxAge == null || dwCount != pszItemIDs.Length || dwCount != pdwMaxAge.Length) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - try - { - object[] values = new object[dwCount]; - short[] qualities = new short[dwCount]; - DateTime[] timestamps = new DateTime[dwCount]; - int[] errors = new int[dwCount]; - - // use the minimum max age for all items. - int maxAge = Int32.MaxValue; - - // build list of values to read. - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - - for (int ii = 0; ii < dwCount; ii++) - { - values[ii] = null; - qualities[ii] = OpcRcw.Da.Qualities.OPC_QUALITY_BAD; - timestamps[ii] = DateTime.MinValue; - - NodeId nodeId = ItemIdToNodeId(pszItemIDs[ii]); - - if (nodeId == null) - { - errors[ii] = ResultIds.E_INVALIDITEMID; - continue; - } - - ReadValueId nodeToRead = new ReadValueId(); - - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.Value; - - // needed to correlate results to input. - nodeToRead.Handle = ii; - - nodesToRead.Add(nodeToRead); - - // calculate max age. - if (maxAge > pdwMaxAge[ii]) - { - maxAge = pdwMaxAge[ii]; - } - } - - // read values from server. - DataValueCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - if (nodesToRead.Count > 0) - { - m_session.Read( - null, - maxAge, - TimestampsToReturn.Both, - nodesToRead, - out results, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(results, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - } - - for (int ii = 0; ii < nodesToRead.Count; ii++) - { - // get index in original array. - int index = (int)nodesToRead[ii].Handle; - - DataValue dataValue = results[ii]; - - if (dataValue == null) - { - errors[index] = ResultIds.E_FAIL; - continue; - } - - errors[index] = MapReadStatusToErrorCode(dataValue.StatusCode); - - if (errors[index] < 0) - { - continue; - } - - values[index] = ValueToVariantValue(dataValue.Value); - qualities[index] = ComUtils.GetQualityCode(dataValue.StatusCode); - timestamps[index] = dataValue.SourceTimestamp; - errors[index] = ResultIds.S_OK; - } - - // marshal results. - ppvValues = ComUtils.GetVARIANTs(values, false); - ppwQualities = ComUtils.GetInt16s(qualities); - ppftTimeStamps = ComUtils.GetFILETIMEs(timestamps); - - // marshal error codes. - ppErrors = ComUtils.GetInt32s(errors); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e); - } - } - } - #endregion - - #region Private Methods - /// - /// Removes all expired continuation points. - /// - private void CleanupContinuationPoints(object state) - { - ByteStringCollection continuationPoints = new ByteStringCollection(); - - lock (m_lock) - { - LinkedListNode node = m_continuationPoints.First; - - while (node != null) - { - if (DateTime.UtcNow.Ticks - node.Value.Timestamp.Ticks > TimeSpan.TicksPerMinute*10) - { - if (node.Value.LastCP != null) - { - continuationPoints.Add(node.Value.LastCP); - } - - LinkedListNode next = node.Next; - m_continuationPoints.Remove(node); - node = next; - continue; - } - - node = node.Next; - } - - // start a 5 minute timer to check for expired continuation points. - if (m_continuationPoints.Count > 0) - { - if (m_continuationPointTimer != null) - { - m_continuationPointTimer.Dispose(); - } - - m_continuationPointTimer = new Timer(CleanupContinuationPoints, null, 600000, Timeout.Infinite); - } - } - - // release the continuation points on the server. - if (continuationPoints.Count > 0) - { - try - { - BrowseResultCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - m_session.BrowseNext( - null, - true, - continuationPoints, - out results, - out diagnosticInfos); - } - catch (Exception e) - { - Utils.Trace(e, "Error releasing continuation points."); - } - } - } - - /// - /// Checks is the node is a property that is not visible in the address space. - /// - private bool IsHiddenProperty(INode property) - { - // ignore invalid properties. - if (property == null || property.BrowseName == null) - { - return true; - } - - // only UA defined properties are hidden. - if (property.BrowseName.NamespaceIndex != 0) - { - return false; - } - - // check browse name. - switch (property.BrowseName.Name) - { - case Opc.Ua.BrowseNames.EnumStrings: - case Opc.Ua.BrowseNames.EngineeringUnits: - case Opc.Ua.BrowseNames.TrueState: - case Opc.Ua.BrowseNames.FalseState: - case Opc.Ua.BrowseNames.EURange: - case Opc.Ua.BrowseNames.InstrumentRange: - case Opc.Ua.BrowseNames.LocalTime: - { - return true; - } - } - - // anything else is visable as a property. - return false; - } - - /// - /// Determines if it's a Branch Node. - /// - private bool HasChildren(INode node) - { - // objects are always branches. - if (node.NodeClass == NodeClass.Object) - { - return true; - } - - // variables could be branches. - VariableNode variable = node as VariableNode; - - if (variable == null) - { - return false; - } - - // look for children - IList references = variable.ReferenceTable.Find(ReferenceTypeIds.HierarchicalReferences, false, true, m_session.TypeTree); - - if (references.Count == 0) - { - return false; - } - - // check for non-hidden children. - foreach (IReference reference in references) - { - if (!m_session.TypeTree.IsTypeOf(reference.ReferenceTypeId, ReferenceTypeIds.HasProperty)) - { - return true; - } - - INode property = m_session.NodeCache.Find(reference.TargetId); - - if (!IsHiddenProperty(property)) - { - return true; - } - } - - return false; - } - - /// - /// Determines if it's a Leaf Node. - /// - private bool IsItem(INode node) - { - // objects are never leaves. - if (node.NodeClass == NodeClass.Object) - { - return false; - } - - // variables could be leaves. - VariableNode variable = node as VariableNode; - - if (variable == null) - { - return false; - } - - // check if the node is not visible. - if (IsHiddenProperty(variable)) - { - return false; - } - - // all other variables are leaves. - return true; - } - - #region ContinuationPoint Class - /// - /// Stores information about a continuation point. - /// - private class ContinuationPoint - { - public string Id; - public DateTime Timestamp; - public byte[] LastCP; - public IList UnprocessedElements; - public int MaxElementsReturned; - - public ContinuationPoint() - { - Timestamp = DateTime.UtcNow; - MaxElementsReturned = 0; - } - } - #endregion - #endregion - - #region Private Fields - private static object m_staticLock = new object(); - private static ApplicationConfiguration m_configuration; - private static ConfiguredEndpointCollection m_endpointCache; - private static Dictionary m_verifiedEndpoints; - - private object m_lock = new object(); - private Opc.Ua.Client.Session m_session; - private string m_clientName; - private Dictionary m_groups = new Dictionary(); - private LinkedList m_continuationPoints = new LinkedList(); - private Stack m_browseStack = new Stack(); - private int m_lcid = ComUtils.LOCALE_SYSTEM_DEFAULT; - private List m_localeIds = null; - private int m_timebias = 0; - private int m_nextHandle = 1; - private DateTime m_startTime = DateTime.MinValue; - private DateTime m_lastUpdateTime = DateTime.MinValue; - private Thread m_updateThread; - private NodeIdDictionary m_cache; - private Timer m_continuationPointTimer; - #endregion - } - - #region BrowseFilters Class - /// - /// Defines a set of filters to apply when browsing. - /// - public class BrowseFilters - { - /// - /// The maximum number of elements to return. Zero means no limit. - /// - public int MaxElementsReturned - { - get { return m_maxElementsReturned; } - set { m_maxElementsReturned = value; } - } - - /// - /// The type of element to return. - /// - public OPCBROWSEFILTER BrowseFilter - { - get { return m_browseFilter; } - set { m_browseFilter = value; } - } - - /// - /// An expression used to match the name of the element. - /// - public string ElementNameFilter - { - get { return m_elementNameFilter; } - set { m_elementNameFilter = value; } - } - - /// - /// A filter which has semantics that defined by the server. - /// - public string VendorFilter - { - get { return m_vendorFilter; } - set { m_vendorFilter = value; } - } - - /// - /// Whether all supported properties to return with each element. - /// - public bool ReturnAllProperties - { - get { return m_returnAllProperties; } - set { m_returnAllProperties = value; } - } - - /// - /// A list of names of the properties to return with each element. - /// - public int[] PropertyIds - { - get { return m_propertyIds; } - set { m_propertyIds = value; } - } - - /// - /// Whether property values should be returned with the properties. - /// - public bool ReturnPropertyValues - { - get { return m_returnPropertyValues; } - set { m_returnPropertyValues = value; } - } - - #region Private Members - private int m_maxElementsReturned = 0; - private OPCBROWSEFILTER m_browseFilter = OPCBROWSEFILTER.OPC_BROWSE_FILTER_ALL; - private string m_elementNameFilter = null; - private string m_vendorFilter = null; - private bool m_returnAllProperties = false; - private int[] m_propertyIds = null; - private bool m_returnPropertyValues = false; - #endregion - } - #endregion - - #region ItemProperty Class - /// - /// Contains a description of a single item property. - /// - public class ItemProperty - { - /// - /// The property identifier. - /// - public int Id - { - get { return m_id; } - set { m_id = value; } - } - - /// - /// A short description of the property. - /// - public string Description - { - get { return m_description; } - set { m_description = value; } - } - - /// - /// The data type of the property. - /// - public short DataType - { - get { return m_datatype; } - set { m_datatype = value; } - } - - /// - /// The value of the property. - /// - public object Value - { - get { return m_value; } - set { m_value = value; } - } - - /// - /// The primary identifier for the property if it is directly accessible as an item. - /// - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// The error id for the result of an operation on an property. - /// - public int ErrorId - { - get { return m_errorId; } - set { m_errorId = value; } - } - - #region Private Members - private int m_id; - private string m_description = null; - private short m_datatype = 0; - private object m_value = null; - private string m_itemId = null; - private int m_errorId = 0; - #endregion - } - #endregion - - #region BrowseElement Class - /// - /// Contains a description of an element in the server address space. - /// - [Serializable] - public class BrowseElement - { - /// - /// The node associated withe the element. - /// - public INode Node - { - get { return m_node; } - set { m_node = value; } - } - - /// - /// A descriptive name for element that is unique within a branch. - /// - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// The primary identifier for the element within the server namespace. - /// - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Whether the element refers to an item with data that can be accessed. - /// - public bool IsItem - { - get { return m_isItem; } - set { m_isItem = value; } - } - - /// - /// Whether the element has children. - /// - public bool HasChildren - { - get { return m_hasChildren; } - set { m_hasChildren = value; } - } - - /// - /// The set of properties for the element. - /// - public IList Properties - { - get { return m_properties; } - set { m_properties = value; } - } - - #region Private Members - private INode m_node = null; - private string m_name = null; - private string m_itemId = null; - private bool m_isItem = false; - private bool m_hasChildren = false; - private IList m_properties = null; - #endregion - }; - #endregion; -} - -/// -/// Stores the last value received for an item. -/// -public class CachedValue -{ - #region Constructors - /// - /// Constructs the object with a NodeId. - /// - public CachedValue(NodeId nodeId) - { - m_nodeId = nodeId; - } - #endregion - - #region Public Members - /// - /// The NodeId for the cached value. - /// - public NodeId NodeId - { - get { return m_nodeId; } - } - - /// - /// When the value was placed in the cache. - /// - public DateTime Timestamp - { - get { return m_timestamp; } - } - - /// - /// The value in the cache. - /// - public DataValue LastValue - { - get { return m_lastValue; } - } - - /// - /// Adds a reference to the item. - /// - public int AddRef() - { - return ++m_refs; - } - - /// - /// Releases the item. - /// - public int Release() - { - return --m_refs; - } - - /// - /// Updates the value in the cache. - /// - public void Update(DataValue value) - { - if (value != null) - { - // don't replace entries with old data. - if (m_lastValue != null && m_lastValue.SourceTimestamp > value.SourceTimestamp) - { - return; - } - - m_lastValue = value; - m_timestamp = DateTime.UtcNow; - } - } - #endregion - - #region Private Fields - private NodeId m_nodeId; - private DateTime m_timestamp; - private DataValue m_lastValue; - private int m_refs; - #endregion -} - -namespace Opc.Ua.Com -{ - /// - /// A class declared in the default namespace for the assembly. Necessary to allow the server to be marked as COM visible. - /// - [ComVisible(true)] - [Guid("25501B7C-2E39-4fd8-BA5A-FAB081375498")] - [ProgId("OpcUa.DaProxy")] - public class DaProxy : Opc.Ua.Com.Server.Da.Server - { - } -} diff --git a/ComIOP/Common/Server/Da/ComDaAsyncRequest.cs b/ComIOP/Common/Server/Da/ComDaAsyncRequest.cs deleted file mode 100644 index 4ab6ec6c6..000000000 --- a/ComIOP/Common/Server/Da/ComDaAsyncRequest.cs +++ /dev/null @@ -1,166 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// Specifies the parameters for an async request. - /// - public class ComDaAsnycRequest - { - #region Public Properties - /// - /// Gets or sets the cancel id. - /// - /// The cancel id. - public int CancelId - { - get { return m_cancelId; } - set { m_cancelId = value; } - } - - /// - /// Gets or sets a flag indicating that the request was cancelled. - /// - /// True if cancelled. - public bool Cancelled - { - get { return m_cancelled; } - set { m_cancelled = value; } - } - - /// - /// Gets or sets the transaction id. - /// - /// The transaction id. - public int TransactionId - { - get { return m_transactionId; } - set { m_transactionId = value; } - } - - /// - /// Gets or sets the server handles. - /// - /// The server handles. - public int[] ServerHandles - { - get { return m_serverHandles; } - set { m_serverHandles = value; } - } - - /// - /// Gets or sets the client handles. - /// - /// The client handles. - public int[] ClientHandles - { - get { return m_clientHandles; } - set { m_clientHandles = value; } - } - #endregion - - #region Private Fields - private int m_transactionId; - private int m_cancelId; - private bool m_cancelled; - private int[] m_serverHandles; - private int[] m_clientHandles; - #endregion - } - - /// - /// Specifies the parameters for an async read request. - /// - public class ComDaAsnycReadRequest : ComDaAsnycRequest - { - #region Public Properties - /// - /// Gets or sets the max age. - /// - /// The max age. - public uint MaxAge - { - get { return m_maxAge; } - set { m_maxAge = value; } - } - - /// - /// Gets or sets a flag indicating that it is a read request. - /// - /// The refresh flag. - public bool IsRefresh - { - get { return m_isRefresh; } - set { m_isRefresh = value; } - } - - /// - /// Gets or sets a flag indicating that it is the first update after activation. - /// - public bool IsFirstUpdate { get; set; } - #endregion - - #region Private Fields - private uint m_maxAge; - private bool m_isRefresh; - #endregion - } - - /// - /// Specifies the parameters for an async write request. - /// - public class ComDaAsnycWriteRequest : ComDaAsnycRequest - { - #region Public Properties - /// - /// Gets or sets the results. - /// - /// The results. - public DaValue[] Values - { - get { return m_values; } - set { m_values = value; } - } - #endregion - - #region Private Fields - private DaValue[] m_values; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/ComDaBrowseCache.cs b/ComIOP/Common/Server/Da/ComDaBrowseCache.cs deleted file mode 100644 index 365f5bc20..000000000 --- a/ComIOP/Common/Server/Da/ComDaBrowseCache.cs +++ /dev/null @@ -1,1972 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// Maintains a shared cache of browse information. - /// - public class ComDaBrowseCache - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The object used to map namespace indexes. - public ComDaBrowseCache(ComNamespaceMapper mapper) - { - m_mapper = mapper; - m_cache = new Dictionary(); - m_browseBlockSize = 10; - } - #endregion - - #region Public Methods - /// - /// Gets or sets the size of the blocks to use when browsing. - /// - /// The size of the block. - public int BrowseBlockSize - { - get { return m_browseBlockSize; } - set { m_browseBlockSize = value; } - } - - /// - /// Finds the element. - /// - /// The session. - /// The item id. - /// Null if the item does not exist. - public ComDaBrowseElement FindElement(Session session, string itemId) - { - BrowseElement element = Lookup(session, itemId); - - if (element == null) - { - return null; - } - - return element; - } - - /// - /// Finds the parent. - /// - /// The session. - /// The item id. - /// Null if the item or parent does not exist. - public ComDaBrowseElement FindParent(Session session, string itemId) - { - BrowseElement element = Lookup(session, itemId); - - if (element == null) - { - return null; - } - - BrowseElement parent = Lookup(session, element.ParentId); - - if (parent == null) - { - return null; - } - - return parent; - } - - /// - /// Finds the child with the specified name. - /// - /// The session. - /// The item id. - /// Name of the child. - /// - /// Null if the item or child does not exist. - /// - public ComDaBrowseElement FindChild(Session session, string itemId, string childName) - { - TraceState("FindChild", itemId, childName); - - // find the element in the cache. - BrowseElement parent = null; - - lock (m_lock) - { - if (itemId == null) - { - itemId = String.Empty; - } - - if (!m_cache.TryGetValue(itemId, out parent)) - { - parent = null; - } - } - - // fetch the element from the server. - if (parent == null) - { - NodeId nodeId = m_mapper.GetRemoteNodeId(itemId); - parent = CreateBrowseElement(session, nodeId); - - if (parent == null) - { - return null; - } - } - - // name make actually be an item id. - string childId = childName; - - // look up the child reference. - ReferenceDescription reference = null; - - if (parent.ReferencesByName.TryGetValue(childName, out reference)) - { - childId = m_mapper.GetLocalItemId((NodeId)reference.NodeId); - } - - // look up target of reference in the cache. - BrowseElement child = null; - - lock (m_lock) - { - if (m_cache.TryGetValue(childId, out child)) - { - return child; - } - } - - // return the child. - return Lookup(session, childId); - } - - /// - /// Looks up the cached element using the specified session. - /// - /// The session. - /// The item id. - /// The element. Null if the item id does not exist. - private BrowseElement Lookup(Session session, string itemId) - { - BrowseElement element = null; - - lock (m_lock) - { - if (itemId == null) - { - itemId = String.Empty; - } - - if (m_cache.TryGetValue(itemId, out element)) - { - return element; - } - } - - NodeId nodeId = m_mapper.GetRemoteNodeId(itemId); - - element = CreateBrowseElement(session, nodeId); - - if (element != null) - { - lock (m_lock) - { - m_cache[itemId] = element; - } - } - - return element; - } - - /// - /// Browses for children of the specified item. - /// - /// The session. - /// The item id. - /// The element filter. - /// The name filter. - /// The data type filter. - /// The access rights filter. - /// - /// The list of names that meet the criteria. - /// - public IList BrowseForNames( - Session session, - string itemId, - BrowseElementFilter elementFilter, - string nameFilter, - short dataTypeFilter, - int accessRightsFilter) - { - TraceState("BrowseForNames", itemId, elementFilter, nameFilter, dataTypeFilter, accessRightsFilter); - - // look up the parent. - BrowseElement parent = Lookup(session, itemId); - - if (parent == null) - { - return null; - } - - // fetch the children. - List children = LookupChildElements(session, parent); - - // search the children. - List hits = new List(); - - for (int ii = 0; ii < children.Count; ii++) - { - BrowseElement child = children[ii]; - - // apply the name filter. - if (!String.IsNullOrEmpty(nameFilter)) - { - if (!ComUtils.Match(child.BrowseName, nameFilter, false)) - { - continue; - } - } - - // branches must have children. - if (elementFilter == BrowseElementFilter.Branch) - { - if (child.NodeClass == NodeClass.Variable && child.ReferencesByName.Count == 0) - { - continue; - } - } - - // items must be variables. - if (elementFilter == BrowseElementFilter.Item) - { - if (child.NodeClass != NodeClass.Variable) - { - continue; - } - } - - if (child.NodeClass == NodeClass.Variable) - { - // apply data type filter. - if (dataTypeFilter != 0) - { - if (child.CanonicalDataType != dataTypeFilter) - { - continue; - } - } - - // apply access rights filter. - if (accessRightsFilter != 0) - { - if ((child.AccessRights & accessRightsFilter) == 0) - { - continue; - } - } - } - - // a match. - hits.Add(child.BrowseName); - } - - // return all of the matching names. - return hits; - } - - /// - /// Browses for children of the specified item. - /// - /// The session. - /// The item id. - /// The name filter. - /// The data type filter. - /// The access rights filter. - /// - /// The list of names that meet the criteria. - /// - public IList BrowseFlat( - Session session, - string itemId, - string nameFilter, - short dataTypeFilter, - int accessRightsFilter) - { - TraceState("BrowseFlat", itemId, nameFilter, dataTypeFilter, accessRightsFilter); - - // look up the parent. - BrowseElement parent = Lookup(session, itemId); - - if (parent == null) - { - return null; - } - - // search the children. - List hits = new List(); - Dictionary branches = new Dictionary(); - branches.Add(parent.ItemId, parent); - - // recusively find the item ids. - BrowseFlat( - session, - parent, - nameFilter, - dataTypeFilter, - accessRightsFilter, - branches, - hits); - - // return all of the matching item ids. - return hits; - } - - /// - /// Recursively browses the address space. - /// - /// The session. - /// The parent. - /// The name filter. - /// The data type filter. - /// The access rights filter. - /// The table of followed branches. - /// The item ids found for variables that meet the criteria. - private void BrowseFlat( - Session session, - BrowseElement parent, - string nameFilter, - short dataTypeFilter, - int accessRightsFilter, - Dictionary branches, - List hits) - { - // fetch the children. - List children = LookupChildElements(session, parent); - - for (int ii = 0; ii < children.Count; ii++) - { - BrowseElement child = children[ii]; - - // recusively follow branches but need to guard against loops. - if (child.ReferencesByName.Count > 0) - { - if (!branches.ContainsKey(child.ItemId)) - { - branches.Add(child.ItemId, child); - BrowseFlat(session, child, nameFilter, dataTypeFilter, accessRightsFilter, branches, hits); - } - } - - // nothing more to do if not a variable. - if (child.NodeClass != NodeClass.Variable) - { - continue; - } - - // apply the name filter to the item id. - if (!String.IsNullOrEmpty(nameFilter)) - { - if (!ComUtils.Match(child.ItemId, nameFilter, false)) - { - continue; - } - } - - // apply data type filter. - if (dataTypeFilter != 0) - { - if (child.CanonicalDataType != dataTypeFilter) - { - continue; - } - } - - // apply access rights filter. - if (accessRightsFilter != 0) - { - if ((child.AccessRights & accessRightsFilter) == 0) - { - continue; - } - } - - // a match. - hits.Add(child.ItemId); - } - } - - /// - /// Browses for the children of the specified item. - /// - /// The session. - /// The item id. - /// The queue of elements that meet the criteria. - public Queue BrowseForElements(Session session, string itemId) - { - TraceState("BrowseForElements", itemId); - - // look up the parent. - BrowseElement parent = Lookup(session, itemId); - - if (parent == null) - { - return null; - } - - // fetch the children. - List children = LookupChildElements(session, parent); - - // search the children. - Queue hits = new Queue(); - - for (int ii = 0; ii < children.Count; ii++) - { - hits.Enqueue(children[ii]); - } - - // return all of the matching names. - return hits; - } - - /// - /// Gets the available properties for the specified item. - /// - /// The session. - /// The item id. - /// Null if the item is not value. The list of supported properties otherwise. - public IList GetAvailableProperties(Session session, string itemId) - { - // no properties for the root. - if (String.IsNullOrEmpty(itemId)) - { - return null; - } - - // find the element. - BrowseElement element = Lookup(session, itemId); - - if (element == null) - { - return null; - } - - // check which supported properties are available for the element. - List availableProperties = new List(); - - for (int ii = 0; ii < s_SupportedProperties.Length; ii++) - { - DaValue value = GetPropertyValue(element, s_SupportedProperties[ii].PropertyId); - - if (value != null && value.Error != ResultIds.E_INVALID_PID) - { - availableProperties.Add(s_SupportedProperties[ii]); - } - } - - // return the list. - return availableProperties; - } - - /// - /// Gets the properties. - /// - /// The session. - /// The requests. - /// The property ids. - /// The list of properities. - public IList GetPropertyValues(Session session, ComDaReadPropertiesRequest[] requests, params int[] propertyIds) - { - TraceState("GetPropertyValues", requests.Length); - - // select all supported properties if none provided - IList properties = s_SupportedProperties; - - if (propertyIds == null || propertyIds.Length == 0) - { - propertyIds = new int[s_SupportedProperties.Length]; - - for (int ii = 0; ii < propertyIds.Length; ii++) - { - propertyIds[ii] = s_SupportedProperties[ii].PropertyId; - } - } - - // return the descriptions that match the requested properties. - else - { - properties = new DaProperty[propertyIds.Length]; - - for (int ii = 0; ii < propertyIds.Length; ii++) - { - for (int jj = 0; jj < s_SupportedProperties.Length; jj++) - { - if (propertyIds[ii] == s_SupportedProperties[jj].PropertyId) - { - properties[ii] = s_SupportedProperties[jj]; - break; - } - } - } - } - - // build a list of elements to create. - BrowseElement[] elements = new BrowseElement[requests.Length]; - int[] indexes = new int[requests.Length]; - - BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); - - for (int ii = 0; ii < requests.Length; ii++) - { - BrowseElement element = null; - - // lookup element in cache. - lock (m_lock) - { - string itemId = requests[ii].ItemId; - - if (String.IsNullOrEmpty(itemId)) - { - requests[ii].Error = ResultIds.E_INVALIDITEMID; - elements[ii] = null; - continue; - } - - // if (m_cache.TryGetValue(itemId, out element)) - // { - // UpdateReadPropertyRequest(requests[ii], element, propertyIds); - // continue; - // } - - // create a new element. - elements[ii] = element = new BrowseElement(); - } - - element.ItemId = requests[ii].ItemId; - element.NodeId = m_mapper.GetRemoteNodeId(element.ItemId); - - // prepare a request to browse the children. - indexes[ii] = PrepareBrowseElementBrowseRequest(element.NodeId, nodesToBrowse); - } - - // check if nothing more to do. - if (nodesToBrowse.Count == 0) - { - return properties; - } - - // browse all elements at once. - BrowseResultCollection results = Browse(session, nodesToBrowse); - - // validate results and prepare read requests. - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - - for (int ii = 0; ii < elements.Length; ii++) - { - BrowseElement element = elements[ii]; - - if (element == null) - { - continue; - } - - // update the element with the children found. - if (!UpdateBrowseElement(element, nodesToBrowse, results, indexes[ii])) - { - requests[ii].Error = ResultIds.E_UNKNOWNITEMID; - elements[ii] = null; - continue; - } - - // prepare to read the properties from the server. - indexes[ii] = PrepareBrowseElementReadRequest( - element.NodeId, - element.ReferencesByName, - nodesToRead, - NodeClass.Unspecified, - false); - } - - // check if nothing to do. - if (nodesToRead.Count == 0) - { - return properties; - } - - // read all child properties at once. - DataValueCollection values = Read(session, nodesToRead); - - // process results and build final table. - for (int ii = 0; ii < elements.Length; ii++) - { - BrowseElement element = elements[ii]; - - if (element == null) - { - continue; - } - - // update the browse element with the property values. - if (!UpdateBrowseElement(session.TypeTree, element, nodesToRead, values, NodeClass.Unspecified, false, indexes[ii])) - { - requests[ii].Error = ResultIds.E_UNKNOWNITEMID; - continue; - } - - UpdateReadPropertyRequest(requests[ii], element, propertyIds); - - // save element in cache. - lock (m_lock) - { - element.CacheTimestamp = DateTime.UtcNow; - m_cache[element.ItemId] = element; - } - } - - // return the descriptions. - return properties; - } - #endregion - - #region Static Fields - /// - /// The set of supported properties for variables. - /// - private static DaProperty[] s_SupportedProperties = new DaProperty[] - { - new DaProperty(PropertyIds.DataType), - new DaProperty(PropertyIds.Value), - new DaProperty(PropertyIds.Quality), - new DaProperty(PropertyIds.Timestamp), - new DaProperty(PropertyIds.AccessRights), - new DaProperty(PropertyIds.ScanRate), - new DaProperty(PropertyIds.EuType), - new DaProperty(PropertyIds.EuInfo), - new DaProperty(PropertyIds.UaBuiltInType), - new DaProperty(PropertyIds.UaDataTypeId), - new DaProperty(PropertyIds.UaValueRank), - new DaProperty(PropertyIds.UaBrowseName), - new DaProperty(PropertyIds.UaDescription), - new DaProperty(PropertyIds.Description), - new DaProperty(PropertyIds.HighEU), - new DaProperty(PropertyIds.LowEU), - new DaProperty(PropertyIds.HighIR), - new DaProperty(PropertyIds.LowIR), - new DaProperty(PropertyIds.EngineeringUnits), - new DaProperty(PropertyIds.CloseLabel), - new DaProperty(PropertyIds.OpenLabel), - new DaProperty(PropertyIds.TimeZone) - }; - #endregion - - #region Private Methods - /// - /// Dumps the current state of the browser. - /// - private void TraceState(string context, params object[] args) - { - #if TRACESTATE - if ((Utils.TraceMask & Utils.TraceMasks.Information) == 0) - { - return; - } - - StringBuilder buffer = new StringBuilder(); - - buffer.AppendFormat("ComDaBrowseCache::{0}", context); - - if (args != null) - { - buffer.Append("( "); - - for (int ii = 0; ii < args.Length; ii++) - { - if (ii > 0) - { - buffer.Append(", "); - } - - buffer.Append(new Variant(args[ii])); - } - - buffer.Append(" )"); - } - - Utils.Trace("{0}", buffer.ToString()); - #endif - } - - /// - /// Updates the read property request with the property values. - /// - /// The request. - /// The element. - /// The property ids. - private void UpdateReadPropertyRequest(ComDaReadPropertiesRequest request, BrowseElement element, int[] propertyIds) - { - if (element == null) - { - request.Error = ResultIds.E_UNKNOWNITEMID; - return; - } - - request.Values = new DaValue[propertyIds.Length]; - - for (int ii = 0; ii < propertyIds.Length; ii++) - { - request.Values[ii] = GetPropertyValue(element, propertyIds[ii]); - } - } - - /// - /// Gets the property value from the browse element. - /// - /// The element. - /// The property id. - /// The value containing the property value. - private DaValue GetPropertyValue(BrowseElement element, int propertyId) - { - DaValue value = new DaValue(); - value.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD; - value.Timestamp = element.CacheTimestamp; - - // check for objects - they only support the description property. - if (element.NodeClass == NodeClass.Object) - { - switch (propertyId) - { - case PropertyIds.Description: { value.Value = element.BrowseName; break; } - case PropertyIds.UaBrowseName: { value.Value = element.UaBrowseName; break; } - case PropertyIds.UaDescription: { value.Value = element.UaDescription; break; } - - default: - { - value.Error = ResultIds.E_INVALID_PID; - return value; - } - } - - return value; - } - - // handle variable properties. - switch (propertyId) - { - case PropertyIds.Description: { value.Value = element.BrowseName; break; } - case PropertyIds.DataType: { value.Value = element.CanonicalDataType; break; } - case PropertyIds.ScanRate: { value.Value = element.ScanRate; break; } - case PropertyIds.AccessRights: { value.Value = element.AccessRights; break; } - case PropertyIds.EuType: { value.Value = element.EuType; break; } - case PropertyIds.EuInfo: { value.Value = element.EuInfo; break; } - case PropertyIds.UaBuiltInType: { value.Value = (int)element.BuiltInType; break; } - case PropertyIds.UaDataTypeId: { value.Value = element.DataTypeId; break; } - case PropertyIds.UaValueRank: { value.Value = element.ValueRank; break; } - case PropertyIds.UaBrowseName: { value.Value = element.UaBrowseName; break; } - case PropertyIds.UaDescription: { value.Value = element.UaDescription; break; } - - case PropertyIds.EngineeringUnits: - { - if (element.EngineeringUnits == null) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.EngineeringUnits; - value.Value = element.EngineeringUnits; - break; - } - - case PropertyIds.HighEU: - { - if (element.HighEU == Double.MaxValue) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.HighEU; - break; - } - - case PropertyIds.LowEU: - { - if (element.LowEU == Double.MaxValue) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.LowEU; - break; - } - - case PropertyIds.HighIR: - { - if (element.HighIR == Double.MaxValue) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.HighIR; - break; - } - - case PropertyIds.LowIR: - { - if (element.LowIR == Double.MaxValue) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.LowIR; - break; - } - - case PropertyIds.CloseLabel: - { - if (element.CloseLabel == null) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.CloseLabel; - break; - } - - case PropertyIds.OpenLabel: - { - if (element.OpenLabel == null) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.OpenLabel; - break; - } - - case PropertyIds.TimeZone: - { - if (element.TimeZone == Int32.MaxValue) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.TimeZone; - break; - } - - case PropertyIds.Value: - { - if (element.LastValue == null) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.LastValue.Value; - break; - } - - case PropertyIds.Quality: - { - if (element.LastValue == null) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.LastValue.Quality; - break; - } - - case PropertyIds.Timestamp: - { - if (element.LastValue == null) - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - - value.Value = element.LastValue.Timestamp; - break; - } - - default: - { - value.Error = ResultIds.E_INVALID_PID; - break; - } - } - - return value; - } - - /// - /// Creates the browse element. - /// - /// The session. - /// The node id. - /// The browse element; null if the node id does not refers to a valid element. - private BrowseElement CreateBrowseElement(Session session, NodeId nodeId) - { - TraceState("CreateBrowseElement", nodeId); - BrowseElement element = new BrowseElement(); - - element.NodeId = nodeId; - element.ItemId = m_mapper.GetLocalItemId(nodeId); - - // browse the server for the children. - BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); - int index = PrepareBrowseElementBrowseRequest(nodeId, nodesToBrowse); - - // browse all elements at once. - BrowseResultCollection results = Browse(session, nodesToBrowse); - - // update the element with the children found. - if (!UpdateBrowseElement(element, nodesToBrowse, results, index)) - { - return null; - } - - // read the properties from the server. - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - index = PrepareBrowseElementReadRequest(nodeId, element.ReferencesByName, nodesToRead, NodeClass.Unspecified, true); - - DataValueCollection values = Read(session, nodesToRead); - - // update the browse element with the property values. - if (!UpdateBrowseElement(session.TypeTree, element, nodesToRead, values, NodeClass.Unspecified, true, index)) - { - return null; - } - - return element; - } - - /// - /// Creates the children of the browse element. - /// - /// The session. - /// The parent. - /// - /// The browse element; null if the node id does not refers to a valid element. - /// - private List LookupChildElements(Session session, BrowseElement parent) - { - List children = new List(); - List childrenToFind = new List(); - List indexes = new List(); - - BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); - - // create an element for each child reference. - foreach (ReferenceDescription reference in parent.ReferencesByName.Values) - { - NodeId nodeId = (NodeId)reference.NodeId; - string itemId = m_mapper.GetLocalItemId(nodeId); - - BrowseElement child = null; - - lock (m_lock) - { - // check if child has already been cached. - if (m_cache.TryGetValue(itemId, out child)) - { - child.ParentId = parent.ItemId; - children.Add(child); - continue; - } - - // create a new element. - child = new BrowseElement(); - } - - child.NodeId = nodeId; - child.ItemId = itemId; - child.NodeClass = reference.NodeClass; - child.BrowseName = child.UaBrowseName = m_mapper.GetLocalBrowseName(reference.BrowseName); - - if (reference.DisplayName != null) - { - child.BrowseName = reference.DisplayName.Text; - } - - int index = PrepareBrowseElementBrowseRequest(child.NodeId, nodesToBrowse); - - childrenToFind.Add(child); - indexes.Add(index); - } - - // check if nothing to do because everything was in the cache. - if (childrenToFind.Count == 0) - { - return children; - } - - // browse all elements at once. - BrowseResultCollection results = Browse(session, nodesToBrowse); - - // validate results and prepare read requests. - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - - for (int ii = 0; ii < childrenToFind.Count; ii++) - { - BrowseElement child = childrenToFind[ii]; - - // update the element with the children found. - if (!UpdateBrowseElement(child, nodesToBrowse, results, indexes[ii])) - { - children[ii] = null; - continue; - } - - // all done with objects. - if (child.NodeClass == NodeClass.Object) - { - child.ParentId = parent.ItemId; - children.Add(child); - - lock (m_lock) - { - child.CacheTimestamp = DateTime.UtcNow; - m_cache[child.ItemId] = child; - } - } - - // prepare to read the properties from the server. - indexes[ii] = PrepareBrowseElementReadRequest(child.NodeId, child.ReferencesByName, nodesToRead, child.NodeClass, true); - } - - // check if nothing to do because only objects with no properties.. - if (nodesToRead.Count == 0) - { - return children; - } - - // read all child properties at once. - DataValueCollection values = Read(session, nodesToRead); - - // process results and build final table. - for (int ii = 0; ii < childrenToFind.Count; ii++) - { - BrowseElement child = childrenToFind[ii]; - - if (child == null || child.NodeClass == NodeClass.Object) - { - continue; - } - - // update the browse element with the property values. - if (!UpdateBrowseElement(session.TypeTree, child, nodesToRead, values, child.NodeClass, true, indexes[ii])) - { - continue; - } - - // add variables to the cache. - child.ParentId = parent.ItemId; - children.Add(child); - - lock (m_lock) - { - child.CacheTimestamp = DateTime.UtcNow; - m_cache[child.ItemId] = child; - } - } - - return children; - } - - /// - /// Prepares a browse request for the children of a node. - /// - /// The node id. - /// The nodes to browse. - private int PrepareBrowseElementBrowseRequest( - NodeId nodeId, - BrowseDescriptionCollection nodesToBrowse) - { - int index = nodesToBrowse.Count; - - BrowseDescription nodeToBrowse = new BrowseDescription(); - - nodeToBrowse.NodeId = nodeId; - nodeToBrowse.BrowseDirection = BrowseDirection.Forward; - nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.Organizes; - nodeToBrowse.IncludeSubtypes = true; - nodeToBrowse.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable); - nodeToBrowse.ResultMask = (uint)(BrowseResultMask.DisplayName | BrowseResultMask.BrowseName | BrowseResultMask.NodeClass); - - nodesToBrowse.Add(nodeToBrowse); - - nodeToBrowse = new BrowseDescription(); - - nodeToBrowse.NodeId = nodeId; - nodeToBrowse.BrowseDirection = BrowseDirection.Forward; - nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasChild; - nodeToBrowse.IncludeSubtypes = true; - nodeToBrowse.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable); - nodeToBrowse.ResultMask = (uint)(BrowseResultMask.DisplayName | BrowseResultMask.BrowseName | BrowseResultMask.NodeClass); - - nodesToBrowse.Add(nodeToBrowse); - - return index; - } - - /// - /// Updates the browse element with the children returned in the browse results. - /// - /// The element. - /// The nodes to browse. - /// The results. - /// The index of the first browse result associated with the element. - /// - private bool UpdateBrowseElement( - BrowseElement element, - BrowseDescriptionCollection nodesToBrowse, - BrowseResultCollection results, - int first) - { - // check for a valid range within the collection. - if (first < 0 || first >= nodesToBrowse.Count) - { - return false; - } - - bool missingReferences = false; - - // process all references. - Dictionary referencesByName = new Dictionary(); - Dictionary duplicateNames = new Dictionary(); - - for (int ii = first; ii < first+2; ii++) - { - BrowseResult result = results[ii]; - - // check for errors - rejected node id are fatal; others can be ignored. - if (StatusCode.IsBad(result.StatusCode)) - { - if (result.StatusCode == StatusCodes.BadNodeIdInvalid || result.StatusCode == StatusCodes.BadNodeIdInvalid || result.StatusCode == StatusCodes.BadNodeNotInView) - { - return false; - } - - missingReferences = true; - continue; - } - - // eliminate duplicates and index references by browse name. - for (int jj = 0; jj < result.References.Count; jj++) - { - ReferenceDescription reference = result.References[jj]; - - // ignore off server references. - if (reference.NodeId == null || reference.NodeId.IsAbsolute) - { - continue; - } - - // construct the browse name. - string browseName = m_mapper.GetLocalBrowseName(reference.BrowseName); - - if (reference.DisplayName != null) - { - browseName = reference.DisplayName.Text; - } - - // check for duplicates. - ReferenceDescription duplicate = null; - - if (referencesByName.TryGetValue(browseName, out duplicate)) - { - if (reference.NodeId != duplicate.NodeId) - { - duplicateNames[browseName] = duplicate; - } - - continue; - } - - // add to table. - referencesByName.Add(browseName, reference); - } - } - - // remove duplicates. - foreach (string duplicateName in duplicateNames.Keys) - { - referencesByName.Remove(duplicateName); - } - - // save child lookup table. - element.ReferencesByName = referencesByName; - element.MissingReferences = missingReferences; - - // update the masks. - SetElementMasks(element); - return true; - } - - /// - /// Prepares a read request for the browse element properties. - /// - /// The node id. - /// The children indexed by name. - /// The nodes to read. - /// The node class - passed only if all of the information in the ReferenceDescription is available. - /// If true the only properties essential for browing will be fetched. - /// - private int PrepareBrowseElementReadRequest( - NodeId nodeId, - Dictionary childrenByName, - ReadValueIdCollection nodesToRead, - NodeClass nodeClass, - bool onlyEssentialProperties) - { - int index = nodesToRead.Count; - - ReadValueId nodeToRead = new ReadValueId(); - - if (nodeClass == NodeClass.Unspecified) - { - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.NodeClass; - nodesToRead.Add(nodeToRead); - - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.BrowseName; - nodesToRead.Add(nodeToRead); - - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.DisplayName; - nodesToRead.Add(nodeToRead); - } - - if (!onlyEssentialProperties) - { - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.Description; - nodesToRead.Add(nodeToRead); - } - - // nothing more to fetch for objects. - if (nodeClass == NodeClass.Object) - { - return index; - } - - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.DataType; - nodesToRead.Add(nodeToRead); - - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.ValueRank; - nodesToRead.Add(nodeToRead); - - if (!onlyEssentialProperties) - { - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.MinimumSamplingInterval; - nodesToRead.Add(nodeToRead); - - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.UserAccessLevel; - nodesToRead.Add(nodeToRead); - - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = nodeId; - nodeToRead.AttributeId = Attributes.Value; - nodesToRead.Add(nodeToRead); - - ReferenceDescription property = null; - - if (childrenByName.TryGetValue(Opc.Ua.BrowseNames.EURange, out property)) - { - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = (NodeId)property.NodeId; - nodeToRead.AttributeId = Attributes.Value; - nodeToRead.Handle = Opc.Ua.BrowseNames.EURange; - nodesToRead.Add(nodeToRead); - } - - if (childrenByName.TryGetValue(Opc.Ua.BrowseNames.InstrumentRange, out property)) - { - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = (NodeId)property.NodeId; - nodeToRead.AttributeId = Attributes.Value; - nodeToRead.Handle = Opc.Ua.BrowseNames.InstrumentRange; - nodesToRead.Add(nodeToRead); - } - - if (childrenByName.TryGetValue(Opc.Ua.BrowseNames.EngineeringUnits, out property)) - { - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = (NodeId)property.NodeId; - nodeToRead.AttributeId = Attributes.Value; - nodeToRead.Handle = Opc.Ua.BrowseNames.EngineeringUnits; - nodesToRead.Add(nodeToRead); - } - - if (childrenByName.TryGetValue(Opc.Ua.BrowseNames.EnumStrings, out property)) - { - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = (NodeId)property.NodeId; - nodeToRead.AttributeId = Attributes.Value; - nodeToRead.Handle = Opc.Ua.BrowseNames.EnumStrings; - nodesToRead.Add(nodeToRead); - } - - if (childrenByName.TryGetValue(Opc.Ua.BrowseNames.TrueState, out property)) - { - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = (NodeId)property.NodeId; - nodeToRead.AttributeId = Attributes.Value; - nodeToRead.Handle = Opc.Ua.BrowseNames.TrueState; - nodesToRead.Add(nodeToRead); - } - - if (childrenByName.TryGetValue(Opc.Ua.BrowseNames.FalseState, out property)) - { - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = (NodeId)property.NodeId; - nodeToRead.AttributeId = Attributes.Value; - nodeToRead.Handle = Opc.Ua.BrowseNames.FalseState; - nodesToRead.Add(nodeToRead); - } - - if (childrenByName.TryGetValue(Opc.Ua.BrowseNames.LocalTime, out property)) - { - nodeToRead = new ReadValueId(); - nodeToRead.NodeId = (NodeId)property.NodeId; - nodeToRead.AttributeId = Attributes.Value; - nodeToRead.Handle = Opc.Ua.BrowseNames.LocalTime; - nodesToRead.Add(nodeToRead); - } - } - - return index; - } - - /// - /// Updates the browse element with the properties return in the read results. - /// - /// The type tree. - /// The element. - /// The nodes to read. - /// The values. - /// The node class - passed only if all of the information in the ReferenceDescription is available. - /// If true the only properties essential for browing were fetched. - /// The first. - /// - private bool UpdateBrowseElement( - ITypeTable typeTree, - BrowseElement element, - ReadValueIdCollection nodesToRead, - DataValueCollection values, - NodeClass nodeClass, - bool onlyEssentialProperties, - int first) - { - // check for a valid range within the collection. - if (first < 0 || first >= nodesToRead.Count) - { - return false; - } - - if (nodeClass == NodeClass.Unspecified) - { - // verify node class. - NodeClass actualNodeClass = (NodeClass)values[first++].GetValue((int)NodeClass.Unspecified); - - if (actualNodeClass != NodeClass.Variable && actualNodeClass != NodeClass.Object) - { - return false; - } - - element.NodeClass = actualNodeClass; - - // verify browse name. - QualifiedName browseName = values[first++].GetValue(null); - - if (QualifiedName.IsNull(browseName)) - { - return false; - } - - element.BrowseName = element.UaBrowseName = m_mapper.GetLocalBrowseName(browseName); - - // verify display name. - LocalizedText displayName = values[first++].GetValue(null); - - if (LocalizedText.IsNullOrEmpty(displayName)) - { - return false; - } - - element.BrowseName = displayName.Text; - } - - if (!onlyEssentialProperties) - { - // check if long description exists. - LocalizedText description = values[first++].GetValue(null); - - if (!LocalizedText.IsNullOrEmpty(description)) - { - element.UaDescription = description.Text; - } - else - { - element.UaDescription = ""; - } - } - - // update the masks. - SetElementMasks(element); - - // nothing more to do. - if (nodeClass == NodeClass.Object) - { - return true; - } - - // verify data type. - NodeId dataTypeId = values[first++].GetValue(null); - - if (dataTypeId == null && element.NodeClass == NodeClass.Variable) - { - return false; - } - - int valueRank = values[first++].GetValue(ValueRanks.Scalar); - - // update data type information. - if (dataTypeId != null) - { - element.BuiltInType = DataTypes.GetBuiltInType(dataTypeId, typeTree); - element.DataTypeId = m_mapper.GetLocalItemId(dataTypeId); - element.ValueRank = valueRank; - element.CanonicalDataType = (short)ComUtils.GetVarType(new TypeInfo(element.BuiltInType, element.ValueRank)); - } - - if (!onlyEssentialProperties) - { - // update scan rate. - element.ScanRate = (float)values[first++].GetValue(MinimumSamplingIntervals.Indeterminate); - - // update access rights. - byte userAccessLevel = values[first++].GetValue(0); - - if ((userAccessLevel & AccessLevels.CurrentRead) != 0) - { - element.AccessRights |= OpcRcw.Da.Constants.OPC_READABLE; - } - - if ((userAccessLevel & AccessLevels.CurrentWrite) != 0) - { - element.AccessRights |= OpcRcw.Da.Constants.OPC_WRITEABLE; - } - - if ((userAccessLevel & AccessLevels.HistoryRead) != 0) - { - element.IsHistoricalItem = true; - } - - // cache the latest value. - DataValue value = values[first++]; - - if (element.NodeClass == NodeClass.Variable) - { - element.LastValue = m_mapper.GetLocalDataValue(value); - } - - // update HighEU and LowEU - element.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM; - element.HighEU = Double.MaxValue; - element.LowEU = Double.MaxValue; - - if (element.ReferencesByName.ContainsKey(Opc.Ua.BrowseNames.EURange)) - { - Range euRange = values[first++].GetValue(null); - - if (euRange != null) - { - element.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG; - element.HighEU = euRange.High; - element.LowEU = euRange.Low; - } - } - - // update HighIR and LowIR - element.HighIR = Double.MaxValue; - element.LowIR = Double.MaxValue; - - if (element.ReferencesByName.ContainsKey(Opc.Ua.BrowseNames.InstrumentRange)) - { - Range instrumentRange = values[first++].GetValue(null); - - if (instrumentRange != null) - { - element.HighIR = instrumentRange.High; - element.LowIR = instrumentRange.Low; - } - } - - // update EngineeringUnits - element.EngineeringUnits = null; - - if (element.ReferencesByName.ContainsKey(Opc.Ua.BrowseNames.EngineeringUnits)) - { - EUInformation engineeringUnits = values[first++].GetValue(null); - - if (engineeringUnits != null && engineeringUnits.DisplayName != null) - { - element.EngineeringUnits = engineeringUnits.DisplayName.Text; - } - } - - // update EUInfo - element.EuInfo = null; - - if (element.ReferencesByName.ContainsKey(Opc.Ua.BrowseNames.EnumStrings)) - { - LocalizedText[] enumStrings = values[first++].GetValue(null); - - if (enumStrings != null) - { - string[] strings = new string[enumStrings.Length]; - - for (int ii = 0; ii < enumStrings.Length; ii++) - { - if (enumStrings[ii] != null) - { - strings[ii] = enumStrings[ii].Text; - } - } - - element.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED; - element.EuInfo = strings; - } - } - - // update CloseLabel - element.CloseLabel = null; - - if (element.ReferencesByName.ContainsKey(Opc.Ua.BrowseNames.TrueState)) - { - LocalizedText trueState = values[first++].GetValue(null); - - if (trueState != null) - { - element.CloseLabel = trueState.Text; - } - } - - // update OpenLabel - element.OpenLabel = null; - - if (element.ReferencesByName.ContainsKey(Opc.Ua.BrowseNames.FalseState)) - { - LocalizedText falseState = values[first++].GetValue(null); - - if (falseState != null) - { - element.OpenLabel = falseState.Text; - } - } - - // update TimeZone - element.TimeZone = Int32.MaxValue; - - if (element.ReferencesByName.ContainsKey(Opc.Ua.BrowseNames.LocalTime)) - { - TimeZoneDataType timeZone = values[first++].GetValue(null); - - if (timeZone != null) - { - element.TimeZone = timeZone.Offset; - } - } - } - - return true; - } - - /// - /// Sets the element masks. - /// - /// The element to update. - private void SetElementMasks(BrowseElement element) - { - element.HasChildren = (element.ReferencesByName.Count > 0); - element.IsItem = (element.NodeClass == NodeClass.Variable); - } - - /// - /// Sends the browse request to the server. - /// - /// The session. - /// The nodes to browse. - /// - private BrowseResultCollection Browse(Session session, BrowseDescriptionCollection nodesToBrowse) - { - BrowseResultCollection results = null; - - // break the request into smaller blocks. - if (m_browseBlockSize > 0 && nodesToBrowse.Count > m_browseBlockSize) - { - results = new BrowseResultCollection(); - - for (int ii = 0; ii < nodesToBrowse.Count; ii += m_browseBlockSize) - { - BrowseDescriptionCollection x = new BrowseDescriptionCollection(); - - for (int jj = ii; jj < ii + m_browseBlockSize && jj < nodesToBrowse.Count; jj++) - { - x.Add(nodesToBrowse[jj]); - } - - BrowseResultCollection y = BrowseBlock(session, x); - results.AddRange(y); - } - - return results; - } - - // small enough to do directly. - return BrowseBlock(session, nodesToBrowse); - } - - /// - /// Sends the browse request to the server. - /// - /// The session. - /// The nodes to browse. - /// - private BrowseResultCollection BrowseBlock(Session session, BrowseDescriptionCollection nodesToBrowse) - { - try - { - // Utils.Trace("Browsing {0} Nodes", nodesToBrowse.Count); - - ViewDescription view = new ViewDescription(); - Dictionary combinedResults = new Dictionary(); - - // initialize the table of indexes used to correlate results. - BrowseDescriptionCollection browseOperations = nodesToBrowse; - List browseIndexes = new List(); - - for (int ii = 0; ii < nodesToBrowse.Count; ii++) - { - browseIndexes.Add(ii); - } - - BrowseDescriptionCollection unprocessedOperations = new BrowseDescriptionCollection(); - List unprocessedBrowseIndexes = new List(); - - while (browseOperations.Count > 0) - { - // start the browse operation. - BrowseResultCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.Browse( - null, - view, - 0, - browseOperations, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, browseOperations); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browseOperations); - - unprocessedOperations.Clear(); - unprocessedBrowseIndexes.Clear(); - - ByteStringCollection continuationPoints = new ByteStringCollection(); - List continuationPointIndexes = new List(); - - for (int ii = 0; ii < browseOperations.Count; ii++) - { - int index = browseIndexes[ii]; - - // Utils.Trace("{0}/{1}/{2}", browseOperations[ii].NodeId, browseOperations[ii].ReferenceTypeId, results[ii].References.Count); - - // look up results. - BrowseResult combinedResult = null; - - if (!combinedResults.TryGetValue(index, out combinedResult)) - { - combinedResults[index] = combinedResult = new BrowseResult(); - } - - // check for error. - if (StatusCode.IsBad(results[ii].StatusCode)) - { - // this error indicates that the server does not have enough simultaneously active - // continuation points. This request will need to be resent after the other operations - // have been completed and their continuation points released. - if (results[ii].StatusCode == StatusCodes.BadNoContinuationPoints) - { - unprocessedOperations.Add(browseOperations[ii]); - unprocessedBrowseIndexes.Add(index); - continue; - } - - // save error. - if (StatusCode.IsGood(combinedResult.StatusCode)) - { - combinedResult.StatusCode = results[ii].StatusCode; - } - - continue; - } - - // check if all references have been fetched. - if (results[ii].References.Count == 0) - { - continue; - } - - // save results. - combinedResult.References.AddRange(results[ii].References); - - // check for continuation point. - if (results[ii].ContinuationPoint != null && results[ii].ContinuationPoint.Length > 0) - { - continuationPoints.Add(results[ii].ContinuationPoint); - continuationPointIndexes.Add(index); - } - } - - // process continuation points. - ByteStringCollection revisedContinuationPoints = new ByteStringCollection(); - List revisedContinuationPointIndexes = new List(); - - while (continuationPoints.Count > 0) - { - bool releaseContinuationPoints = false; - - // continue browse operation. - session.BrowseNext( - null, - releaseContinuationPoints, - continuationPoints, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, continuationPoints); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); - - revisedContinuationPoints.Clear(); - revisedContinuationPointIndexes.Clear(); - - for (int ii = 0; ii < continuationPoints.Count; ii++) - { - int index = continuationPointIndexes[ii]; - - // look up results. - BrowseResult combinedResult = null; - - if (!combinedResults.TryGetValue(index, out combinedResult)) - { - combinedResults[index] = new BrowseResult(); - } - - // check for error. - if (StatusCode.IsBad(results[ii].StatusCode)) - { - // save error. - if (StatusCode.IsGood(combinedResult.StatusCode)) - { - combinedResult.StatusCode = results[ii].StatusCode; - } - - continue; - } - - // check if all references have been fetched. - if (results[ii].References.Count == 0) - { - continue; - } - - // save results. - combinedResult.References.AddRange(results[ii].References); - - // check for continuation point. - if (results[ii].ContinuationPoint != null && results[ii].ContinuationPoint.Length > 0) - { - revisedContinuationPoints.Add(results[ii].ContinuationPoint); - revisedContinuationPointIndexes.Add(index); - } - } - - // check if browsing must continue; - continuationPoints = revisedContinuationPoints; - continuationPointIndexes = revisedContinuationPointIndexes; - } - - // check if unprocessed results exist. - browseOperations = unprocessedOperations; - browseIndexes = unprocessedBrowseIndexes; - } - - // reconstruct list of combined results. - BrowseResultCollection finalResults = new BrowseResultCollection(); - - for (int ii = 0; ii < nodesToBrowse.Count; ii++) - { - BrowseResult combinedResult = null; - - if (!combinedResults.TryGetValue(ii, out combinedResult)) - { - combinedResult = new BrowseResult(); - } - - finalResults.Add(combinedResult); - } - - // return complete list. - return finalResults; - } - catch (Exception e) - { - throw ComUtils.CreateComException(e, ResultIds.E_FAIL); - } - } - - /// - /// Sends the read request to the server. - /// - /// The session. - /// The nodes to read. - /// - private DataValueCollection Read(Session session, ReadValueIdCollection nodesToRead) - { - // read attribute values from the server. - DataValueCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - try - { - session.Read( - null, - 0, - TimestampsToReturn.Source, - nodesToRead, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - } - catch (Exception e) - { - // convert to item level errors. - ServiceResult error = new ServiceResult(e, StatusCodes.BadUnexpectedError); - - results = new DataValueCollection(); - - for (int ii = 0; ii < nodesToRead.Count; ii++) - { - results.Add(new DataValue(error.StatusCode)); - } - } - - return results; - } - #endregion - - #region BrowseElement Class - /// - /// Stores a element in the address space. - /// - private class BrowseElement : ComDaBrowseElement - { - public NodeId NodeId; - public NodeClass NodeClass; - public string UaBrowseName; - public string UaDescription; - public BuiltInType BuiltInType; - public string DataTypeId; - public int ValueRank; - public short CanonicalDataType; - public DaValue LastValue; - public float ScanRate; - public int AccessRights; - public int EuType; - public string[] EuInfo; - public double HighEU; - public double LowEU; - public double HighIR; - public double LowIR; - public string EngineeringUnits; - public string CloseLabel; - public string OpenLabel; - public int TimeZone; - public DateTime CacheTimestamp; - public Dictionary ReferencesByName; - public bool MissingReferences; - public string ParentId; - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private ComNamespaceMapper m_mapper; - private Dictionary m_cache; - private int m_browseBlockSize; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/ComDaBrowseElement.cs b/ComIOP/Common/Server/Da/ComDaBrowseElement.cs deleted file mode 100644 index 76f0d5ba5..000000000 --- a/ComIOP/Common/Server/Da/ComDaBrowseElement.cs +++ /dev/null @@ -1,155 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Text; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// Specifies the parameters used to create a DA group item. - /// - public class ComDaBrowseElement : IFormattable - { - #region Public Properties - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string BrowseName - { - get { return m_browseName; } - set { m_browseName = value; } - } - - /// - /// Gets or sets a value indicating whether this instance is item. - /// - /// true if this instance is an item; otherwise, false. - public bool IsItem - { - get { return m_isItem; } - set { m_isItem = value; } - } - - /// - /// Gets or sets a value indicating whether this instance is an historical item. - /// - /// true if this instance is an historical item; otherwise, false. - public bool IsHistoricalItem - { - get { return m_isHistoricalItem; } - set { m_isHistoricalItem = value; } - } - - /// - /// Gets or sets a value indicating whether this instance has children. - /// - /// - /// true if this instance has children; otherwise, false. - /// - public bool HasChildren - { - get { return m_hasChildren; } - set { m_hasChildren = value; } - } - #endregion - - #region IFormattable Members - /// - /// Returns a that represents the current . - /// - public override string ToString() - { - return ToString(null, null); - } - - /// - /// Formats the value of the current instance using the specified format. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - StringBuilder buffer = new StringBuilder(); - - buffer.Append(m_browseName); - buffer.Append('['); - buffer.Append(m_itemId); - buffer.Append(']'); - - return buffer.ToString(); - } - #endregion - - #region Private Fields - private string m_itemId; - private string m_browseName; - private bool m_hasChildren; - private bool m_isItem; - private bool m_isHistoricalItem; - #endregion - } - - /// - /// The filter which selectes the type of elements to return. - /// - public enum BrowseElementFilter - { - /// - /// Returns all elements. - /// - All = 0x1, - - /// - /// Returns elements with children. - /// - Branch = 0x2, - - /// - /// Returns elements which are items. - /// - Item = 0x3 - } -} diff --git a/ComIOP/Common/Server/Da/ComDaBrowseManager.cs b/ComIOP/Common/Server/Da/ComDaBrowseManager.cs deleted file mode 100644 index bccc4b01b..000000000 --- a/ComIOP/Common/Server/Da/ComDaBrowseManager.cs +++ /dev/null @@ -1,613 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// A class which provides the COM DA browse features. - /// - public class ComDaBrowseManager - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The object used to map namespace indexes. - /// The cache. - public ComDaBrowseManager(ComNamespaceMapper mapper, ComDaBrowseCache cache) - { - m_mapper = mapper; - m_cache = cache; - m_continuationPoints = new Dictionary(); - } - #endregion - - #region Public Methods - /// - /// Browses up. - /// - /// The session. - public void BrowseUp(Session session) - { - TraceState("BrowseUp"); - - // find the id of the current node. - string itemId = null; - - lock (m_lock) - { - // check if already at root. - if (m_browsePosition == null || String.IsNullOrEmpty(m_browsePosition.ItemId)) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - itemId = m_browsePosition.ItemId; - } - - // find the parent - revert to root if parent does not exist. - ComDaBrowseElement parent = m_cache.FindParent(session, itemId); - - lock (m_lock) - { - m_browsePosition = parent; - } - } - - /// - /// Moves the current browse position down. - /// - /// The session. - /// Name of the target. - public void BrowseDown(Session session, string targetName) - { - TraceState("BrowseDown", targetName); - - // find the id of the current element. - string itemId = null; - - lock (m_lock) - { - if (m_browsePosition != null) - { - itemId = m_browsePosition.ItemId; - } - } - - // try to fetch the child. - ComDaBrowseElement child = m_cache.FindChild(session, itemId, targetName); - - if (child != null) - { - TraceState("child", child.ItemId, child.BrowseName, child.IsItem, child.HasChildren); - } - - if (child == null || (!child.HasChildren && child.IsItem)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // update the browse position. - lock (m_lock) - { - m_browsePosition = child; - } - } - - /// - /// Moves the current browse position to the specified item. - /// - /// The session. - /// The item id. - public void BrowseTo(Session session, string itemId) - { - TraceState("BrowseTo", itemId); - - // try to fetch the target. - ComDaBrowseElement target = m_cache.FindElement(session, itemId); - - if (target == null) - { - BrowseDown(session, itemId); - return; - } - - if (!target.HasChildren) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // update the browse position. - lock (m_lock) - { - m_browsePosition = target; - } - } - - /// - /// Gets the browse position. - /// - /// The session. - /// - public ComDaBrowseElement GetBrowsePosition(Session session) - { - return m_browsePosition; - } - - /// - /// Browses for children of the specified item. - /// - /// The session. - /// The element filter. - /// The name filter. - /// The data type filter. - /// The access rights filter. - /// - /// The list of names that meet the criteria. - /// - public IList BrowseForNames( - Session session, - BrowseElementFilter elementFilter, - string nameFilter, - short dataTypeFilter, - int accessRightsFilter) - { - // find the id of the current element. - string itemId = null; - - lock (m_lock) - { - if (m_browsePosition != null) - { - itemId = m_browsePosition.ItemId; - } - } - - // find the names. - IList hits = m_cache.BrowseForNames( - session, - itemId, - elementFilter, - nameFilter, - dataTypeFilter, - accessRightsFilter); - - if (hits == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - // return the names. - return hits; - } - - /// - /// Browses for children of the specified item. - /// - /// The session. - /// The name filter. - /// The data type filter. - /// The access rights filter. - /// - /// The list of names that meet the criteria. - /// - public IList BrowseFlat( - Session session, - string nameFilter, - short dataTypeFilter, - int accessRightsFilter) - { - // find the id of the current element. - string itemId = null; - - lock (m_lock) - { - if (m_browsePosition != null) - { - itemId = m_browsePosition.ItemId; - } - } - - // find the item ids. - IList hits = m_cache.BrowseFlat( - session, - itemId, - nameFilter, - dataTypeFilter, - accessRightsFilter); - - if (hits == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - // return the item ids. - return hits; - } - - /// - /// Browses for the children of the specified item. - /// - /// The session. - /// The item id. - /// The continuation point. - /// The max elements returned. - /// The element filter. - /// The name filter. - /// The revised continuation point. - /// The list of elements that meet the criteria. - public List BrowseForElements( - Session session, - string itemId, - string continuationPoint, - int maxElementsReturned, - int elementFilter, - string nameFilter, - out string revisedContinuationPoint) - { - TraceState("BrowseForElements", itemId, continuationPoint, maxElementsReturned, elementFilter, nameFilter); - - revisedContinuationPoint = String.Empty; - - // look up continuation point. - ContinuationPoint cp = null; - - if (!String.IsNullOrEmpty(continuationPoint)) - { - if (!m_continuationPoints.TryGetValue(continuationPoint, out cp)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDCONTINUATIONPOINT); - } - - m_continuationPoints.Remove(continuationPoint); - } - - // get the element queue. - Queue elements = null; - - // get element from continuation point. - if (cp != null) - { - elements = cp.Elements; - } - - // get list from cache. - else - { - elements = m_cache.BrowseForElements(session, itemId); - - // check if nothing found. - if (elements == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - } - - // apply filters. - List hits = new List(); - - while (elements.Count > 0) - { - ComDaBrowseElement hit = elements.Dequeue(); - - // apply name filter. - if (!String.IsNullOrEmpty(nameFilter)) - { - if (!ComUtils.Match(hit.BrowseName, nameFilter, true)) - { - continue; - } - } - - // apply element filter - if (elementFilter == (int)OpcRcw.Da.OPCBROWSEFILTER.OPC_BROWSE_FILTER_BRANCHES) - { - if (!hit.HasChildren) - { - continue; - } - } - - if (elementFilter == (int)OpcRcw.Da.OPCBROWSEFILTER.OPC_BROWSE_FILTER_ITEMS) - { - if (!hit.IsItem) - { - continue; - } - } - - // check max reached. - if (maxElementsReturned > 0 && hits.Count == maxElementsReturned) - { - elements.Enqueue(hit); - - cp = new ContinuationPoint(); - cp.Id = Guid.NewGuid().ToString(); - cp.Elements = elements; - - m_continuationPoints.Add(cp.Id, cp); - revisedContinuationPoint = cp.Id; - break; - } - - // add the result. - hits.Add(hit); - } - - // return results. - return hits; - } - - /// - /// Gets the item id for the specified browse element. - /// - /// The session. - /// The name of the browse element. - /// Null if the browseName is not valid for the current position. - public string GetItemId(Session session, string browseName) - { - TraceState("GetItemId", browseName); - - // find the id of the current element. - string itemId = null; - - lock (m_lock) - { - if (m_browsePosition != null) - { - itemId = m_browsePosition.ItemId; - } - } - - // return the current element. - if (String.IsNullOrEmpty(browseName)) - { - return itemId; - } - - // try to fetch the child. - ComDaBrowseElement child = m_cache.FindChild(session, itemId, browseName); - - if (child == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // return child id. - return child.ItemId; - } - - /// - /// Gets the properties. - /// - /// The session. - /// The item id. - /// The list of properities. - public IList GetAvailableProperties(Session session, string itemId) - { - IList properties = m_cache.GetAvailableProperties(session, itemId); - - if (properties == null) - { - throw ComUtils.CreateComException(ResultIds.E_UNKNOWNITEMID); - } - - return properties; - } - - /// - /// Gets the item ids for the properties. - /// - /// The session. - /// The item id. - /// The property ids. - /// The item ids. - /// Any errors. - public IList GetItemIds(Session session, string itemId, int[] propertyIds, out string[] itemIds) - { - TraceState("GetItemId", itemId); - - // no properties for the root. - if (String.IsNullOrEmpty(itemId)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDITEMID); - } - - // select all available properties if none provided. - IList properties = GetAvailableProperties(session, itemId); - - if (propertyIds == null || propertyIds.Length == 0) - { - propertyIds = new int[properties.Count]; - - for (int ii = 0; ii < propertyIds.Length; ii++) - { - propertyIds[ii] = properties[ii].PropertyId; - } - } - - itemIds = new string[propertyIds.Length]; - int[] results = new int[propertyIds.Length]; - - for (int ii = 0; ii < propertyIds.Length; ii++) - { - results[ii] = ResultIds.E_INVALID_PID; - - // must return E_INVALID_PID for standard properties. - if (propertyIds[ii] <= PropertyIds.EuInfo) - { - continue; - } - - // supported properties must return E_FAIL. - for (int jj = 0; jj < properties.Count; jj++) - { - if (properties[jj].PropertyId == propertyIds[ii]) - { - results[ii] = ResultIds.E_FAIL; - break; - } - } - } - - return results; - } - - /// - /// Gets the properties for list of items. - /// - /// The session. - /// The requests. - /// The property ids. - /// The list of properities. - public IList GetPropertyValues(Session session, ComDaReadPropertiesRequest[] requests, params int[] propertyIds) - { - return m_cache.GetPropertyValues(session, requests, propertyIds); - } - - /// - /// Gets the property values for a single item. - /// - /// The session. - /// The item id. - /// The property ids. - /// The list of properities. - public DaValue[] GetPropertyValues(Session session, string itemId, params int[] propertyIds) - { - TraceState("GetPropertyValues", itemId); - - ComDaReadPropertiesRequest request = new ComDaReadPropertiesRequest(); - request.ItemId = itemId; - - GetPropertyValues(session, new ComDaReadPropertiesRequest[] { request }, propertyIds); - - return request.Values; - } - #endregion - - #region Private Methods - /// - /// Dumps the current state of the browser. - /// - private void TraceState(string context, params object[] args) - { - #if TRACESTATE - if ((Utils.TraceMask & Utils.TraceMasks.Information) == 0) - { - return; - } - - StringBuilder buffer = new StringBuilder(); - - buffer.AppendFormat("ComDaBrowser::{0}", context); - - if (args != null) - { - buffer.Append("( "); - - for (int ii = 0; ii < args.Length; ii++) - { - if (ii > 0) - { - buffer.Append(", "); - } - - buffer.Append(new Variant(args[ii])); - } - - buffer.Append(" )"); - } - - Utils.Trace("{0}", buffer.ToString()); - #endif - } - #endregion - - #region ContinuationPoint Class - /// - /// Stores a continuation point. - /// - private class ContinuationPoint - { - public string Id; - public Queue Elements; - } - #endregion - - #region Static Fields - /// - /// The set of supported properties for variables. - /// - private static DaProperty[] s_SupportedProperties = new DaProperty[] - { - new DaProperty(PropertyIds.DataType), - new DaProperty(PropertyIds.Value), - new DaProperty(PropertyIds.Quality), - new DaProperty(PropertyIds.Timestamp), - new DaProperty(PropertyIds.ScanRate), - new DaProperty(PropertyIds.AccessRights), - new DaProperty(PropertyIds.EuType), - new DaProperty(PropertyIds.EuInfo), - new DaProperty(PropertyIds.UaBuiltInType), - new DaProperty(PropertyIds.UaDataTypeId), - new DaProperty(PropertyIds.UaValueRank), - new DaProperty(PropertyIds.UaBrowseName), - new DaProperty(PropertyIds.UaDescription), - new DaProperty(PropertyIds.Description), - new DaProperty(PropertyIds.HighEU), - new DaProperty(PropertyIds.LowEU), - new DaProperty(PropertyIds.HighIR), - new DaProperty(PropertyIds.LowIR), - new DaProperty(PropertyIds.EngineeringUnits), - new DaProperty(PropertyIds.CloseLabel), - new DaProperty(PropertyIds.OpenLabel), - new DaProperty(PropertyIds.TimeZone) - }; - #endregion - - #region Private Fields - private object m_lock = new object(); - private ComNamespaceMapper m_mapper; - private ComDaBrowseElement m_browsePosition; - private Dictionary m_continuationPoints; - private ComDaBrowseCache m_cache; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/ComDaCreateItemRequest.cs b/ComIOP/Common/Server/Da/ComDaCreateItemRequest.cs deleted file mode 100644 index 46819f604..000000000 --- a/ComIOP/Common/Server/Da/ComDaCreateItemRequest.cs +++ /dev/null @@ -1,150 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// Specifies the parameters used to create a DA group item. - /// - public class ComDaCreateItemRequest - { - #region Public Properties - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the access path. - /// - /// The access path. - public string AccessPath - { - get { return m_accessPath; } - set { m_accessPath = value; } - } - - /// - /// Gets or sets a value indicating whether this item is active. - /// - /// true if active; otherwise, false. - public bool Active - { - get { return m_active; } - set { m_active = value; } - } - - /// - /// Gets or sets the client handle. - /// - /// The client handle. - public int ClientHandle - { - get { return m_clientHandle; } - set { m_clientHandle = value; } - } - - /// - /// Gets or sets the requested data type. - /// - /// The requested data type. - public short RequestedDataType - { - get { return m_requestedDataType; } - set { m_requestedDataType = value; } - } - - /// - /// Gets or sets the server handle. - /// - /// The server handle. - public int ServerHandle - { - get { return m_serverHandle; } - set { m_serverHandle = value; } - } - - /// - /// Gets or sets the canonical data type for the item. - /// - /// The canonical data type. - public short CanonicalDataType - { - get { return m_canonicalDataType; } - set { m_canonicalDataType = value; } - } - - /// - /// Gets or sets the access rights for the item. - /// - /// The access rights. - public int AccessRights - { - get { return m_accessRights; } - set { m_accessRights = value; } - } - - /// - /// Gets or sets the error associated with the operation. - /// - /// The error. - public int Error - { - get { return m_error; } - set { m_error = value; } - } - #endregion - - #region Private Fields - private string m_itemId; - private string m_accessPath; - private bool m_active; - private int m_clientHandle; - private short m_requestedDataType; - private int m_serverHandle; - private short m_canonicalDataType; - private int m_accessRights; - private int m_error; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/ComDaGroup.cs b/ComIOP/Common/Server/Da/ComDaGroup.cs deleted file mode 100644 index 02f748292..000000000 --- a/ComIOP/Common/Server/Da/ComDaGroup.cs +++ /dev/null @@ -1,2910 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// A class that implements a COM DA group. - /// - public class ComDaGroup : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The group manager. - /// The name. - /// The server handle. - public ComDaGroup(ComDaGroupManager manager, string name, int serverHandle) - { - m_manager = manager; - m_name = name; - m_serverHandle = serverHandle; - m_clientHandle = 0; - m_active = true; - m_enabled = true; - m_updateRate = 0; - m_deadband = 0; - m_timeBias = 0; - m_itemsByHandle = new Dictionary(); - m_items = new List(); - m_requests = new List(); - m_keepAliveTime = 0; - m_updateTimer = null; - m_itemsByMonitoredItem = new Dictionary(); - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - m_disposed = true; - - if (disposing) - { - lock (m_lock) - { - if (m_updateTimer != null) - { - m_updateTimer.Dispose(); - m_updateTimer = null; - } - - // release the callback. - Utils.SilentDispose(m_callback); - m_callback = null; - - // clear all outstanding requests. - m_requests.Clear(); - } - } - } - - /// - /// Throws if disposed. - /// - private void ThrowIfDisposed() - { - if (m_disposed) - { - throw new ObjectDisposedException(GetType().Name); - } - } - #endregion - - #region Public Members - /// - /// Gets or sets the handle. - /// - /// The handle. - public IntPtr Handle - { - get { return m_handle; } - set { m_handle = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Gets the server handle. - /// - /// The server handle. - public int ServerHandle - { - get { return m_serverHandle; } - } - - /// - /// Gets or sets the client handle. - /// - /// The client handle. - public int ClientHandle - { - get { return m_clientHandle; } - set { m_clientHandle = value; } - } - - /// - /// Gets or sets a value indicating whether this is active. - /// - /// true if active; otherwise, false. - public bool Active - { - get { return m_active; } - set { m_active = value; } - } - - /// - /// Gets or sets a value indicating whether this is enabled. - /// - /// true if enabled; otherwise, false. - public bool Enabled - { - get { return m_enabled; } - set { m_enabled = value; } - } - - /// - /// Gets or sets the update rate. - /// - /// The update rate. - public int UpdateRate - { - get { return m_updateRate; } - set { m_updateRate = value; } - } - - /// - /// Gets or sets the deadband. - /// - /// The deadband. - public float Deadband - { - get { return m_deadband; } - set { m_deadband = value; } - } - - /// - /// Gets or sets the timebias. - /// - /// The timebias. - public int TimeBias - { - get { return m_timeBias; } - set { m_timeBias = value; } - } - - /// - /// Gets or sets the lcid. - /// - /// The lcid. - public int Lcid - { - get { return m_lcid; } - set { m_lcid = value; } - } - - /// - /// Gets the keep alive time. - /// - /// The keep alive time. - public int KeepAliveTime - { - get { return m_keepAliveTime; } - } - - /// - /// Gets or sets the actual update rate. - /// - /// The actual update rate. - public int ActualUpdateRate - { - get { return m_actualUpdateRate; } - set { m_actualUpdateRate = value; } - } - - /// - /// Gets or sets the subscription. - /// - /// The subscription. - public Subscription Subscription - { - get { return m_subscription; } - - set - { - m_subscription = value; - m_subscription.FastDataChangeCallback = OnDataChange; - } - } - - /// - /// Gets the items. - /// - /// The items. - public Dictionary Items - { - get { return m_itemsByHandle; } - } - - /// - /// Sets the name. - /// - /// Name of the group. - public void SetName(string groupName) - { - TraceState("SetName"); - ThrowIfDisposed(); - - m_manager.SetGroupName(this, groupName); - } - - /// - /// Removes this group from the server. - /// - public void Remove() - { - TraceState("Remove"); - ThrowIfDisposed(); - - m_manager.RemoveGroup(this); - } - - /// - /// Clones the group. - /// - /// Name of the new group. - public ComDaGroup Clone(string groupName) - { - TraceState("Clone", this.m_name, groupName); - ThrowIfDisposed(); - - // create the new group. - ComDaGroup group = m_manager.AddGroup( - groupName, - false, - m_actualUpdateRate, - m_clientHandle, - m_timeBias, - m_deadband, - m_lcid); - - lock (m_lock) - { - // add the items. - for (int ii = 0; ii < m_items.Count; ii++) - { - ComDaGroupItem item = m_items[ii].CloneItem(group); - group.m_itemsByHandle.Add(item.ServerHandle, item); - group.m_items.Add(item); - } - } - - // re-create the items. - group.RecreateItems(); - - // return clone. - return group; - } - - /// - /// Recreates the items. - /// - public void RecreateItems() - { - TraceState("RecreateItems", this.m_name); - ThrowIfDisposed(); - - // create the items on the server. - lock (m_lock) - { - // add the items to the subscription. - for (int ii = 0; ii < m_items.Count; ii++) - { - ComDaGroupItem item = m_items[ii]; - - // check if the item has a different subscription. - if (!Object.ReferenceEquals(item.MonitoredItem.Subscription, m_subscription)) - { - // clone the item if it was attached to discarded subscription. - if (item.MonitoredItem.Subscription != null) - { - m_itemsByMonitoredItem.Remove(item.MonitoredItem.ClientHandle); - - item.MonitoredItem = new MonitoredItem(item.MonitoredItem); - } - AddItemToSubscription(item); - } - } - - // update the server. - try - { - m_subscription.ApplyChanges(); - } - catch (Exception) - { - // TBD - } - } - } - - /// - /// Sets the active state for the group, - /// - /// if set to true the group is activated. - public void SetActive(bool active) - { - TraceState("SetActive", this.m_serverHandle, active); - ThrowIfDisposed(); - - lock (m_lock) - { - // do nothing if no change. - if (m_active == active) - { - CheckUpdateTimerStatus(); - return; - } - - bool areUpdatesRequired = AreUpdatesRequired; - - // turn publishing on. - try - { - m_subscription.SetPublishingMode(active); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e, ResultIds.E_FAIL); - } - - m_active = active; - - // get net monitoring mode. - MonitoringMode monitoringMode = MonitoringMode.Disabled; - - if (m_active) - { - monitoringMode = MonitoringMode.Reporting; - } - - // validate the handles. - int activeItemCount = 0; - List monitoredItems = new List(); - - for (int ii = 0; ii < m_items.Count; ii++) - { - ComDaGroupItem item = m_items[ii]; - - // check if the item is deactivated. - if (!item.Active) - { - continue; - } - - activeItemCount++; - - // flag the last set value for resending. - if (monitoringMode == MonitoringMode.Reporting && item.CacheEntry != null) - { - item.CacheEntry.Changed = true; - } - - // nothing to do if already in the correct state. - if (item.MonitoredItem.Status.MonitoringMode == monitoringMode) - { - continue; - } - - monitoredItems.Add(item.MonitoredItem); - } - - // update the subscription. - if (monitoredItems.Count > 0) - { - try - { - m_subscription.SetMonitoringMode(monitoringMode, monitoredItems); - } - catch (Exception) - { - // ignore errors updating individual items. - } - } - - // resend the contents of the cache. - if (!areUpdatesRequired && AreUpdatesRequired) - { - int cancelId = 0; - Refresh(0, 0, true, out cancelId); - } - - // update timer status. - CheckUpdateTimerStatus(); - } - } - - /// - /// Sets the enabled state for the group. - /// - /// if set to true the group is enabled. - public void SetEnabled(bool enabled) - { - TraceState("SetEnabled", enabled); - ThrowIfDisposed(); - - lock (m_lock) - { - bool areUpdatesRequired = AreUpdatesRequired; - - m_enabled = enabled; - - // resend the contents of the cache. - if (!areUpdatesRequired && AreUpdatesRequired) - { - int cancelId = 0; - Refresh(0, 0, true, out cancelId); - } - - CheckUpdateTimerStatus(); - } - } - - /// - /// Sets the callback. - /// - /// The callback. - public void SetCallback(IComDaGroupCallback callback) - { - TraceState("SetCallback", callback != null); - ThrowIfDisposed(); - - lock (m_lock) - { - bool areUpdatesRequired = AreUpdatesRequired; - - if (m_callback != null) - { - m_callback.Dispose(); - m_callback = null; - } - - m_callback = callback; - - // resend the contents of the cache. - if (!areUpdatesRequired && AreUpdatesRequired) - { - int cancelId = 0; - Refresh(0, 0, true, out cancelId); - } - - CheckUpdateTimerStatus(); - } - } - - /// - /// Sets the keep alive time. - /// - /// The keep alive time. - public int SetKeepAliveTime(int keepAliveTime) - { - TraceState("SetKeepAliveTime", keepAliveTime); - ThrowIfDisposed(); - - lock (m_lock) - { - if (keepAliveTime != 0 && keepAliveTime < m_actualUpdateRate) - { - keepAliveTime = m_actualUpdateRate; - } - - return m_keepAliveTime = keepAliveTime; - } - } - - /// - /// Sets the update rate for the group, - /// - /// The update rate. - /// The revised update rate. - public int SetUpdateRate(int updateRate) - { - TraceState("SetUpdateRate", updateRate); - ThrowIfDisposed(); - - lock (m_lock) - { - // upate the publishing interval. - m_subscription.PublishingInterval = updateRate/2; - - // modify the subscription. - try - { - m_subscription.Modify(); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e, ResultIds.E_FAIL); - } - - int actualUpdateRate = (int)m_subscription.CurrentPublishingInterval*2; - - // restart timer. - if (actualUpdateRate != m_actualUpdateRate) - { - m_actualUpdateRate = actualUpdateRate; - - // adjust keep alive. - if (m_keepAliveTime != 0 && m_keepAliveTime < m_actualUpdateRate) - { - m_keepAliveTime = m_actualUpdateRate; - } - - ScheduleNextUpdate(); - - if (m_updateTimer != null) - { - m_updateTimer.Dispose(); - m_updateTimer = null; - } - - CheckUpdateTimerStatus(); - } - - // update the filter for analog items that have not overriden the deadband. - for (int ii = 0; ii < m_items.Count; ii++) - { - if (m_items[ii].SamplingRate == -1) - { - m_items[ii].MonitoredItem.SamplingInterval = updateRate/2; - } - } - - // update the items on the server. - try - { - m_subscription.ApplyChanges(); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e, ResultIds.E_FAIL); - } - - // return the revised update rate. - return m_actualUpdateRate; - } - } - - /// - /// Sets the deadband for the group, - /// - /// The deadband. - public void SetDeadband(float deadband) - { - TraceState("SetDeadband", deadband); - ThrowIfDisposed(); - - lock (m_lock) - { - this.Deadband = deadband; - - // need the EU Info if the deadband is specified. - m_manager.UpdateItemEuInfo(this, m_items); - - // update filters for all items. - UpdateDeadbandFilters(m_items); - - // update the items on the server. - try - { - m_subscription.ApplyChanges(); - } - catch (Exception e) - { - throw ComUtils.CreateComException(e, ResultIds.E_FAIL); - } - } - } - - /// - /// Creates the items. - /// - /// The requests. - /// if set to true if the items only need to be validated. - public void CreateItems(ComDaCreateItemRequest[] requests, bool validateOnly) - { - TraceState("CreateItems", this.Name, this.Active, this.UpdateRate); - ThrowIfDisposed(); - - // validates the items. - ComDaGroupItem[] items = m_manager.ValidateItems(this, requests); - - // check if nothing more to do. - if (validateOnly) - { - return; - } - - if (this.Deadband > 0) - { - // need the EU Info if the deadband is specified. - m_manager.UpdateItemEuInfo(this, items); - } - - // create the items on the server. - lock (m_lock) - { - // update the filters. - UpdateDeadbandFilters(items); - - // add the monitored items to the group's subscription. - for (int ii = 0; ii < items.Length; ii++) - { - ComDaGroupItem item = items[ii]; - - if (item != null) - { - AddItemToSubscription(item); - } - } - - // update the server. - try - { - m_subscription.ApplyChanges(); - } - catch (Exception e) - { - // set fatal error for remaining items. - for (int ii = 0; ii < items.Length; ii++) - { - ComDaGroupItem item = items[ii]; - - if (items[ii] != null) - { - requests[ii].Error = ComUtils.GetErrorCode(e, ResultIds.E_FAIL); - } - } - - return; - } - - // build results. - for (int ii = 0; ii < items.Length; ii++) - { - // check for valid item. - ComDaGroupItem item = items[ii]; - - if (item == null) - { - continue; - } - - // check for error. - ServiceResult error = item.MonitoredItem.Status.Error; - - if (ServiceResult.IsBad(error)) - { - RemoveItemFromSubscription(item); - requests[ii].Error = ComDaProxy.MapReadStatusToErrorCode(error.StatusCode); - continue; - } - - TraceState( - "ItemCreated", - m_subscription.CurrentPublishingEnabled, - m_subscription.CurrentPublishingInterval, - item.MonitoredItem.Status.MonitoringMode, - item.MonitoredItem.Status.SamplingInterval); - - // save the item. - m_itemsByHandle.Add(item.ServerHandle, item); - m_items.Add(item); - } - - // start the update timer. - CheckUpdateTimerStatus(); - } - } - - /// - /// Deletes the items. - /// - /// The server handles. - /// Any errors. - public int[] DeleteItems(int[] serverHandles) - { - TraceState("DeleteItems", serverHandles.Length); - ThrowIfDisposed(); - - lock (m_lock) - { - // validate the handles. - int[] results = new int[serverHandles.Length]; - ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length]; - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - results[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - items[ii] = item; - RemoveItemFromSubscription(item); - m_itemsByHandle.Remove(serverHandles[ii]); - m_items.Remove(item); - } - - // update the subscription. - try - { - m_subscription.ApplyChanges(); - } - catch (Exception e) - { - SetFatalError(items, results, e, ResultIds.E_FAIL); - } - - // start the update timer. - CheckUpdateTimerStatus(); - - // return any errors. - return results; - } - } - - /// - /// Sets the active state for the items. - /// - /// The server handles. - /// if set to true the items are activated. - /// Any error codes. - public int[] SetActive(int[] serverHandles, bool active) - { - TraceState("SetActive", serverHandles.Length, active); - ThrowIfDisposed(); - - lock (m_lock) - { - // get net monitoring mode. - MonitoringMode monitoringMode = MonitoringMode.Disabled; - - if (m_active && active) - { - monitoringMode = MonitoringMode.Reporting; - } - - // validate the handles. - int[] results = new int[serverHandles.Length]; - ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length]; - List monitoredItems = new List(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - results[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // nothing to do if already in the correct state. - if (item.MonitoredItem.Status.MonitoringMode == monitoringMode) - { - item.Active = active; - results[ii] = ResultIds.S_OK; - continue; - } - - items[ii] = item; - monitoredItems.Add(item.MonitoredItem); - } - - // update the subscription. - try - { - m_subscription.SetMonitoringMode(monitoringMode, monitoredItems); - } - catch (Exception e) - { - SetFatalError(items, results, e, ResultIds.E_FAIL); - } - - // update active state on success - for (int ii = 0; ii < items.Length; ii++) - { - if (items[ii] != null) - { - // clear the last sent value when deactivated. - // this prevents the change filter from suppressing - // updates if the item is reactivated and the value - // has not changed. - if (items[ii].Active && !active) - { - items[ii].LastSentValue = null; - } - - items[ii].Active = active; - } - } - - // return any errors. - return results; - } - } - - /// - /// Sets the client handles. - /// - /// The server handles. - /// The client handles. - /// Any errors. - public int[] SetClientHandles(int[] serverHandles, int[] clientHandles) - { - TraceState("SetClientHandles", serverHandles.Length); - ThrowIfDisposed(); - - lock (m_lock) - { - int[] results = new int[serverHandles.Length]; - ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length]; - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - results[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - item.ClientHandle = clientHandles[ii]; - results[ii] = ResultIds.S_OK; - } - - return results; - } - } - - /// - /// Sets the data types. - /// - /// The server handles. - /// The data types. - /// Any errors. - public int[] SetDataTypes(int[] serverHandles, short[] dataTypes) - { - TraceState("SetDataTypes", serverHandles.Length); - ThrowIfDisposed(); - - lock (m_lock) - { - int[] results = new int[serverHandles.Length]; - ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length]; - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - results[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // validate the datatype. - if (dataTypes[ii] != 0) - { - NodeId dataTypeId = ComUtils.GetDataTypeId(dataTypes[ii]); - - if (NodeId.IsNull(dataTypeId)) - { - results[ii] = ResultIds.E_BADTYPE; - continue; - } - - bool reqTypeIsArray = (dataTypes[ii] & (short)VarEnum.VT_ARRAY) != 0; - bool actualTypeIsArray = (item.CanonicalDataType & (short)VarEnum.VT_ARRAY) != 0; - - if (reqTypeIsArray != actualTypeIsArray) - { - results[ii] = ResultIds.E_BADTYPE; - continue; - } - } - - item.RequestedDataType = dataTypes[ii]; - results[ii] = ResultIds.S_OK; - } - - return results; - } - } - - /// - /// Gets the item attributes. - /// - /// The item attributes. - public OpcRcw.Da.OPCITEMATTRIBUTES[] GetItemAttributes() - { - TraceState("GetItemAttributes", this.m_name); - ThrowIfDisposed(); - - lock (m_lock) - { - m_manager.UpdateItemEuInfo(this, m_items); - - OpcRcw.Da.OPCITEMATTRIBUTES[] attributes = new OpcRcw.Da.OPCITEMATTRIBUTES[m_items.Count]; - - for (int ii = 0; ii < m_items.Count; ii++) - { - ComDaGroupItem item = m_items[ii]; - - attributes[ii].szItemID = item.ItemId; - attributes[ii].szAccessPath = String.Empty; - attributes[ii].hServer = item.ServerHandle; - attributes[ii].hClient = item.ClientHandle; - attributes[ii].bActive = (item.Active)?1:0; - attributes[ii].vtRequestedDataType = item.RequestedDataType; - attributes[ii].vtCanonicalDataType = item.CanonicalDataType; - attributes[ii].dwAccessRights = item.AccessRights; - attributes[ii].dwBlobSize = 0; - attributes[ii].pBlob = IntPtr.Zero; - attributes[ii].dwEUType = (OpcRcw.Da.OPCEUTYPE)item.EuType; - attributes[ii].vEUInfo = item.EuInfo; - } - - return attributes; - } - } - - /// - /// Performs n synchronous read operation. - /// - /// The max age. - /// The server handles. - /// if set to true the read is being done as part of the initial refresh for active items. - /// The client handles (must be allocated by the caller). - /// Any errors. - public DaValue[] SyncRead(uint maxAge, int[] serverHandles, bool isInitialRefresh, int[] clientHandles) - { - TraceState("SyncRead", maxAge, serverHandles.Length); - ThrowIfDisposed(); - - DaValue[] results = new DaValue[serverHandles.Length]; - List items = new List(serverHandles.Length); - ReadValueIdCollection valuesToRead = new ReadValueIdCollection(); - - lock (m_lock) - { - // validate items. - for (int ii = 0; ii < serverHandles.Length; ii++) - { - results[ii] = new DaValue(); - - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - results[ii].Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - if (clientHandles != null) - { - clientHandles[ii] = item.ClientHandle; - } - - // check for cache read. - if (maxAge == UInt32.MaxValue) - { - // inactive items cannot be read from cache. - if (!item.Active || !m_active) - { - results[ii].Quality = OpcRcw.Da.Qualities.OPC_QUALITY_OUT_OF_SERVICE; - results[ii].Timestamp = DateTime.UtcNow; - continue; - } - - // check if waiting for initial data. - if (item.CacheEntry == null) - { - results[ii].Quality = OpcRcw.Da.Qualities.OPC_QUALITY_WAITING_FOR_INITIAL_DATA; - results[ii].Timestamp = DateTime.UtcNow; - continue; - } - - // get the latest value from the cache. - item.CacheEntry.GetLatest(results[ii]); - UpdateReadResult(item, results[ii]); - continue; - } - - // apply max age. - if (maxAge > 0) - { - if (item.CacheEntry != null) - { - if (item.CacheEntry.CacheTimestamp.AddMilliseconds(maxAge) > DateTime.UtcNow) - { - item.CacheEntry.GetLatest(results[ii]); - UpdateReadResult(item, results[ii]); - continue; - } - } - } - - // schedule read from device. - ReadValueId valueToRead = new ReadValueId(); - - valueToRead.NodeId = item.NodeId; - valueToRead.AttributeId = Attributes.Value; - valueToRead.Handle = ii; - - valuesToRead.Add(valueToRead); - items.Add(item); - } - } - - if (valuesToRead.Count == 0) - { - return results; - } - - // read the values from the server. - DaValue[] remoteResults = m_manager.Read(valuesToRead); - - // copy results. - for (int ii = 0; ii < valuesToRead.Count; ii++) - { - int index = (int)valuesToRead[ii].Handle; - - if (isInitialRefresh) - { - UpdateCache(items[ii], remoteResults[ii], isInitialRefresh); - } - - UpdateReadResult(items[ii], remoteResults[ii]); - results[(int)valuesToRead[ii].Handle] = remoteResults[ii]; - } - - return results; - } - - /// - /// Updates the read result by converting the value to the requested data type. - /// - /// The item. - /// The value. - private void UpdateReadResult(ComDaGroupItem item, DaValue value) - { - if (value.Value == null || item.RequestedDataType == (short)VarEnum.VT_EMPTY) - { - return; - } - - object convertedValue = null; - - int error = ComUtils.ChangeTypeForCOM(value.Value, (VarEnum)item.RequestedDataType, out convertedValue); - - if (error < 0) - { - value.Value = null; - value.Error = error; - return; - } - - value.Value = convertedValue; - } - - /// - /// Updates the cache. - /// - /// The item. - /// The value. - /// if set to true the change flag is set to false because the values are sent in the refresh. - private void UpdateCache(ComDaGroupItem item, DaValue value, bool isInitialRefresh) - { - lock (m_lock) - { - - // get sampling rate. - long now = HiResClock.UtcNow.Ticks; - int samplingRate = item.ActualSamplingRate; - - if (item.SamplingRate == -1) - { - samplingRate = m_actualUpdateRate; - } - - // check existing cache contents. - DaValue oldValue = null; - DaCacheValue entry = null; - - if (item.CacheEntry != null) - { - // do not update cache if a newer value exists. - if (item.CacheEntry.Timestamp >= value.Timestamp) - { - /* - TraceState( - "UpdateCache OLD VALUE RECEIVED", - this.m_serverHandle, - item.ServerHandle, - new Variant(item.CacheEntry.Value), - item.CacheEntry.Timestamp.ToString("HH:mm:ss.fff"), - new Variant(value.Value), - value.Timestamp.ToString("HH:mm:ss.fff")); - */ - - return; - } - - oldValue = item.CacheEntry; - - // replace the newest value if sampling interval has not elasped. - - if (!item.BufferEnabled || item.NextUpdateTime > now) - { - // TraceState("UpdateCache ENTRY REPLACED", this.m_serverHandle, item.ServerHandle, samplingRate); - entry = item.CacheEntry; - } - } - - // create a new cache entry. - if (entry == null) - { - entry = new DaCacheValue(); - entry.CacheTimestamp = DateTime.UtcNow; - - if (item.BufferEnabled) - { - entry.NextEntry = item.CacheEntry; - item.NextUpdateTime += samplingRate*TimeSpan.TicksPerMillisecond; - - if (entry.NextEntry != null) - { - // TraceState("UpdateCache ENTRY BUFFERED", this.m_serverHandle, item.ServerHandle, samplingRate); - } - } - - item.CacheEntry = entry; - } - - // check if the value has changed. - bool changed = !isInitialRefresh; - - if (oldValue != null) - { - if (oldValue.Error == value.Error) - { - if (oldValue.Quality == value.Quality) - { - if (Utils.IsEqual(oldValue.Value, value.Value)) - { - changed = false; - } - } - } - } - - // save values. - item.CacheEntry.Value = value.Value; - item.CacheEntry.Quality = value.Quality; - item.CacheEntry.Timestamp = value.Timestamp; - item.CacheEntry.Error = value.Error; - item.CacheEntry.Changed = changed; - - TraceState( - "UpdateCache COMPLETE", - this.m_serverHandle, - item.ServerHandle, - item.ClientHandle, - new Variant(value.Value), - value.Timestamp.ToString("HH:mm:ss.fff"), - item.CacheEntry.Changed); - } - } - - /// - /// Starts an asynchronous read operation. - /// - /// The max age. - /// The transaction id. - /// The server handles. - /// The cancel id. - /// Any errors. - public int[] AsyncRead(uint maxAge, int transactionId, int[] serverHandles, out int cancelId) - { - TraceState("AsyncRead", maxAge, transactionId, serverHandles.Length); - ThrowIfDisposed(); - - cancelId = 0; - - lock (m_lock) - { - int[] results = new int[serverHandles.Length]; - List items = new List(serverHandles.Length); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - results[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - items.Add(item); - } - - if (items.Count > 0) - { - ComDaAsnycReadRequest request = new ComDaAsnycReadRequest(); - - request.CancelId = ++m_transactionCounter; - request.TransactionId = transactionId; - request.MaxAge = maxAge; - request.ServerHandles = new int[items.Count]; - request.ClientHandles = new int[items.Count]; - - for (int ii = 0; ii < items.Count; ii++) - { - request.ServerHandles[ii] = items[ii].ServerHandle; - request.ClientHandles[ii] = items[ii].ClientHandle; - } - - m_requests.Add(request); - cancelId = request.CancelId; - - // create a thread to process the request. - Thread thread = new Thread(OnAsyncRead); - thread.IsBackground = true; - thread.Start(request); - } - - return results; - } - } - - /// - /// Performs n synchronous write operation. - /// - /// The server handles. - /// The values. - /// Any errors. - public int[] SyncWrite(int[] serverHandles, DaValue[] values) - { - TraceState("SyncWrite", serverHandles.Length); - ThrowIfDisposed(); - - int[] results = new int[serverHandles.Length]; - WriteValueCollection valuesToWrite = new WriteValueCollection(); - - lock (m_lock) - { - // validate items. - DaValue convertedValue = new DaValue(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - results[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - // apply the COM type conversion. - DaValue requestedValue = values[ii]; - - if (requestedValue.Value == null) - { - results[ii] = ResultIds.E_BADTYPE; - continue; - } - - if (item.CanonicalDataType != (short)VarEnum.VT_EMPTY) - { - object value = null; - - int error = ComUtils.ChangeTypeForCOM(requestedValue.Value, (VarEnum)item.CanonicalDataType, out value); - - if (error < 0) - { - results[ii] = error; - continue; - } - - // could happen if there is a problem reading the datatype from the server. - if (requestedValue.Value == null) - { - results[ii] = ResultIds.E_BADTYPE; - continue; - } - - // copy all of the attributes into the converted value. - convertedValue.Value = value; - convertedValue.Quality = requestedValue.Quality; - convertedValue.Timestamp = requestedValue.Timestamp; - convertedValue.Error = requestedValue.Error; - - requestedValue = convertedValue; - } - - WriteValue valueToWrite = new WriteValue(); - - valueToWrite.NodeId = item.NodeId; - valueToWrite.AttributeId = Attributes.Value; - valueToWrite.Handle = ii; - - // convert value to UA data type. - try - { - valueToWrite.Value = m_manager.Mapper.GetRemoteDataValue(requestedValue, item.RemoteDataType); - } - 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_manager.Write(valuesToWrite); - - // copy results. - for (int ii = 0; ii < valuesToWrite.Count; ii++) - { - results[(int)valuesToWrite[ii].Handle] = remoteResults[ii]; - } - - return results; - } - - /// - /// Starts an asynchronous write operation. - /// - /// The transaction id. - /// The server handles. - /// The values. - /// The cancel id. - /// Any errors. - public int[] AsyncWrite(int transactionId, int[] serverHandles, DaValue[] values, out int cancelId) - { - TraceState("AsyncWrite", transactionId, serverHandles.Length); - ThrowIfDisposed(); - - cancelId = 0; - - lock (m_lock) - { - int[] results = new int[serverHandles.Length]; - List items = new List(serverHandles.Length); - List valuesToWrite = new List(serverHandles.Length); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - results[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - items.Add(item); - valuesToWrite.Add(values[ii]); - } - - if (items.Count > 0) - { - ComDaAsnycWriteRequest request = new ComDaAsnycWriteRequest(); - - request.CancelId = ++m_transactionCounter; - request.TransactionId = transactionId; - request.ServerHandles = new int[items.Count]; - request.ClientHandles = new int[items.Count]; - request.Values = valuesToWrite.ToArray(); - - for (int ii = 0; ii < items.Count; ii++) - { - request.ServerHandles[ii] = items[ii].ServerHandle; - request.ClientHandles[ii] = items[ii].ClientHandle; - } - - m_requests.Add(request); - cancelId = request.CancelId; - - TraceState("AsyncWrite Queued", transactionId, request.CancelId); - - // create a thread to process the request. - Thread thread = new Thread(OnAsyncWrite); - thread.IsBackground = true; - thread.Start(request); - } - - return results; - } - } - - /// - /// Starts an asynchronous refresh operation. - /// - /// The max age. - /// The transaction id. - /// The cancel id. - public void Refresh(uint maxAge, int transactionId, out int cancelId) - { - Refresh(maxAge, transactionId, false, out cancelId); - } - - /// - /// Starts an asynchronous refresh operation. - /// - /// The max age. - /// The transaction id. - /// True if this refresh is the first update after activation. - /// The cancel id. - private void Refresh(uint maxAge, int transactionId, bool isFirstUpdate, out int cancelId) - { - TraceState("Refresh", maxAge); - ThrowIfDisposed(); - - cancelId = 0; - - lock (m_lock) - { - // no refresh in inactive groups. - if (!m_active) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - // collect active items. - List items = new List(m_items.Count); - - for (int ii = 0; ii < m_items.Count; ii++) - { - ComDaGroupItem item = m_items[ii]; - - if (item.Active) - { - items.Add(item); - } - } - - // no refresh if no active items. - if (items.Count == 0) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - // create the request. - ComDaAsnycReadRequest request = new ComDaAsnycReadRequest(); - - request.CancelId = ++m_transactionCounter; - request.TransactionId = transactionId; - request.IsFirstUpdate = isFirstUpdate; - request.MaxAge = maxAge; - request.IsRefresh = true; - request.ServerHandles = new int[items.Count]; - request.ClientHandles = new int[items.Count]; - - for (int ii = 0; ii < items.Count; ii++) - { - request.ServerHandles[ii] = items[ii].ServerHandle; - request.ClientHandles[ii] = items[ii].ClientHandle; - } - - m_requests.Add(request); - cancelId = request.CancelId; - - // create a thread to process the request. - Thread thread = new Thread(OnAsyncRead); - thread.IsBackground = true; - thread.Start(request); - } - } - - /// - /// Cancels an asynchronous operation. - /// - /// The cancel id. - public bool Cancel(int cancelId) - { - TraceState("Cancel", cancelId); - ThrowIfDisposed(); - - lock (m_lock) - { - for (int ii = 0; ii < m_requests.Count; ii++) - { - if (m_requests[ii].CancelId == cancelId) - { - if (!m_requests[ii].Cancelled) - { - m_requests[ii].Cancelled = true; - return true; - } - - break; - } - } - - return false; - } - } - - /// - /// Sets the deadband for the items. - /// - /// The server handles. - /// The deadbands. - /// Any errors. - public int[] SetItemDeadbands(int[] serverHandles, float[] deadbands) - { - TraceState("SetItemDeadbands", serverHandles.Length); - ThrowIfDisposed(); - - int[] errors = new int[serverHandles.Length]; - ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length]; - int count = 0; - - lock (m_lock) - { - // update the filter for analog items that have not overriden the deadband. - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - if (item.EuType >= 0 && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) - { - errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED; - continue; - } - - if (deadbands[ii] < 0 || deadbands[ii] > 100) - { - errors[ii] = ResultIds.E_INVALIDARG; - continue; - } - - item.Deadband = deadbands[ii]; - items[ii] = item; - count++; - } - } - - if (count == 0) - { - return errors; - } - - // need the EU Info if the deadband is specified. - m_manager.UpdateItemEuInfo(this, items); - - lock (m_lock) - { - // need to check the EU type after updating the EU info. - for (int ii = 0; ii < items.Length; ii++) - { - ComDaGroupItem item = items[ii]; - - if (item != null && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) - { - errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED; - items[ii] = null; - continue; - } - } - - // update filters for selected items. - UpdateDeadbandFilters(items); - - // update the items on the server. - try - { - m_subscription.ApplyChanges(); - } - catch (Exception e) - { - int error = ComUtils.GetErrorCode(e, ResultIds.E_FAIL); - - for (int ii = 0; ii < items.Length; ii++) - { - if (items[ii] != null) - { - errors[ii] = error; - } - } - - return errors; - } - - // check results for monitored items. - for (int ii = 0; ii < items.Length; ii++) - { - ComDaGroupItem item = items[ii]; - - if (item == null) - { - continue; - } - - if (ServiceResult.IsBad(item.MonitoredItem.Status.Error)) - { - item.MonitoredItem.Filter = item.MonitoredItem.Status.Filter; - DataChangeFilter filter = item.MonitoredItem.Filter as DataChangeFilter; - - if (filter != null) - { - item.Deadband = (float)filter.DeadbandValue; - } - - errors[ii] = ResultIds.E_FAIL; - continue; - } - } - - return errors; - } - } - - /// - /// Gets the deadband for the items. - /// - /// The server handles. - /// The deadbands. - /// Any errors. - public int[] GetItemDeadbands(int[] serverHandles, float[] deadbands) - { - TraceState("GetItemDeadbands", serverHandles.Length); - ThrowIfDisposed(); - - int[] errors = new int[serverHandles.Length]; - ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length]; - int count = 0; - - lock (m_lock) - { - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - if (item.EuType >= 0 && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) - { - errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED; - continue; - } - - if (item.Deadband == -1) - { - errors[ii] = ResultIds.E_DEADBANDNOTSET; - continue; - } - - deadbands[ii] = item.Deadband; - - item.Deadband = deadbands[ii]; - items[ii] = item; - count++; - } - } - - if (count == 0) - { - return errors; - } - - // need the EU Info if the deadband is specified. - m_manager.UpdateItemEuInfo(this, items); - - lock (m_lock) - { - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = items[ii]; - - if (item != null) - { - if (item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) - { - errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED; - continue; - } - - deadbands[ii] = item.Deadband; - } - } - } - - return errors; - } - - /// - /// Clears the deadbands for the items. - /// - /// The server handles. - /// Any errors. - public int[] ClearItemDeadbands(int[] serverHandles) - { - TraceState("ClearItemSamplingRates", serverHandles.Length); - ThrowIfDisposed(); - - int[] errors = new int[serverHandles.Length]; - ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length]; - int count = 0; - - lock (m_lock) - { - // update the filter for analog items that have not overriden the deadband. - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - if (item.EuType >= 0 && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) - { - errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED; - continue; - } - - if (item.Deadband == -1) - { - errors[ii] = ResultIds.E_DEADBANDNOTSET; - continue; - } - - items[ii] = item; - item.Deadband = -1; - count++; - } - } - - if (count == 0) - { - return errors; - } - - // need the EU Info if the deadband is specified. - m_manager.UpdateItemEuInfo(this, items); - - lock (m_lock) - { - // need to check the EU type after updating the EU info. - for (int ii = 0; ii < items.Length; ii++) - { - ComDaGroupItem item = items[ii]; - - if (item != null && item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) - { - errors[ii] = ResultIds.E_DEADBANDNOTSUPPORTED; - items[ii] = null; - continue; - } - } - - UpdateDeadbandFilters(items); - - // update the items on the server. - try - { - m_subscription.ApplyChanges(); - } - catch (Exception e) - { - int error = ComUtils.GetErrorCode(e, ResultIds.E_FAIL); - - for (int ii = 0; ii < items.Length; ii++) - { - if (items[ii] != null) - { - errors[ii] = error; - } - } - - return errors; - } - - return errors; - } - } - - /// - /// Sets the sampling rate for the items. - /// - /// The server handles. - /// The sampling rates. - /// The revised sampling rates. - /// Any errors. - public int[] SetItemSamplingRates(int[] serverHandles, int[] samplingRates, int[] revisedSamplingRates) - { - TraceState("SetItemSamplingRates", serverHandles.Length); - ThrowIfDisposed(); - - int[] errors = new int[serverHandles.Length]; - ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length]; - - lock (m_lock) - { - // update the filter for analog items that have not overriden the deadband. - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - item.MonitoredItem.SamplingInterval = (int)(samplingRates[ii]/2); - revisedSamplingRates[ii] = 0; - items[ii] = item; - } - - // update the items on the server. - try - { - m_subscription.ApplyChanges(); - } - catch (Exception e) - { - int error = ComUtils.GetErrorCode(e, ResultIds.E_FAIL); - - for (int ii = 0; ii < items.Length; ii++) - { - if (items[ii] != null) - { - errors[ii] = error; - } - } - - return errors; - } - - // check results for monitored items. - for (int ii = 0; ii < items.Length; ii++) - { - ComDaGroupItem item = items[ii]; - - if (item == null) - { - continue; - } - - if (ServiceResult.IsBad(item.MonitoredItem.Status.Error)) - { - errors[ii] = ResultIds.E_FAIL; - continue; - } - - item.SamplingRate = samplingRates[ii]; - item.ActualSamplingRate = (int)(items[ii].MonitoredItem.Status.SamplingInterval); - - // if 1/2 the sampling rate is accepted then it is possible to guarantee the sampling rate. - if (item.ActualSamplingRate < item.SamplingRate) - { - item.ActualSamplingRate = item.SamplingRate; - } - - // can only guarantee a sampling rate of twice what the UA server can provide. - else - { - item.ActualSamplingRate *= 2; - } - - revisedSamplingRates[ii] = item.ActualSamplingRate; - item.NextUpdateTime = HiResClock.UtcNow.Ticks + item.ActualSamplingRate*TimeSpan.TicksPerMillisecond; - - if (revisedSamplingRates[ii] != samplingRates[ii]) - { - errors[ii] = ResultIds.S_UNSUPPORTEDRATE; - } - - TraceState( - "ItemSamplingUpdated", - this.ServerHandle, - item.ServerHandle, - item.ClientHandle, - m_subscription.CurrentPublishingEnabled, - m_subscription.CurrentPublishingInterval, - item.SamplingRate, - item.MonitoredItem.Status.SamplingInterval); - } - - return errors; - } - } - - /// - /// Gets the sampling rates for the items. - /// - /// The server handles. - /// The sampling rates. - /// Any errors. - public int[] GetItemSamplingRates(int[] serverHandles, int[] samplingRates) - { - TraceState("GetItemSamplingRates", serverHandles.Length); - ThrowIfDisposed(); - - lock (m_lock) - { - int[] errors = new int[serverHandles.Length]; - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - if (item.SamplingRate == -1) - { - errors[ii] = ResultIds.E_RATENOTSET; - continue; - } - - samplingRates[ii] = item.ActualSamplingRate; - } - - return errors; - } - } - - /// - /// Clears the sampling rates for the items. - /// - /// The server handles. - /// Any errors. - public int[] ClearItemSamplingRates(int[] serverHandles) - { - TraceState("ClearItemSamplingRates", serverHandles.Length); - ThrowIfDisposed(); - - int[] errors = new int[serverHandles.Length]; - ComDaGroupItem[] items = new ComDaGroupItem[serverHandles.Length]; - - lock (m_lock) - { - // update the filter for analog items that have not overriden the deadband. - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - if (item.SamplingRate == -1) - { - errors[ii] = ResultIds.E_RATENOTSET; - continue; - } - - item.MonitoredItem.SamplingInterval = (int)(this.UpdateRate/2); - items[ii] = item; - } - - // update the items on the server. - try - { - m_subscription.ApplyChanges(); - } - catch (Exception e) - { - int error = ComUtils.GetErrorCode(e, ResultIds.E_FAIL); - - for (int ii = 0; ii < items.Length; ii++) - { - if (items[ii] != null) - { - errors[ii] = error; - } - } - - return errors; - } - - // check results for monitored items. - for (int ii = 0; ii < items.Length; ii++) - { - ComDaGroupItem item = items[ii]; - - if (item == null) - { - continue; - } - - if (ServiceResult.IsBad(item.MonitoredItem.Status.Error)) - { - errors[ii] = ResultIds.E_FAIL; - continue; - } - - item.SamplingRate = -1; - item.ActualSamplingRate = 0; - item.NextUpdateTime = -1; - } - - return errors; - } - } - - /// - /// Sets whether buffering is enabled for the items. - /// - /// The server handles. - /// Whether buffering is enabled. - /// Any errors. - public int[] SetItemBufferEnabled(int[] serverHandles, int[] bufferEnabled) - { - TraceState("SetItemBufferEnabled", serverHandles.Length); - ThrowIfDisposed(); - - int[] errors = new int[serverHandles.Length]; - - lock (m_lock) - { - // update the filter for analog items that have not overriden the deadband. - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - item.BufferEnabled = bufferEnabled[ii] != 0; - } - - return errors; - } - } - - /// - /// Gets whether buffering is enabled for the items. - /// - /// The server handles. - /// Whether buffering is enabled. - /// Any errors. - public int[] GetItemBufferEnabled(int[] serverHandles, int[] bufferEnabled) - { - TraceState("GetItemBufferEnabled", serverHandles.Length); - ThrowIfDisposed(); - - int[] errors = new int[serverHandles.Length]; - - lock (m_lock) - { - // update the filter for analog items that have not overriden the deadband. - for (int ii = 0; ii < serverHandles.Length; ii++) - { - ComDaGroupItem item = null; - - if (!m_itemsByHandle.TryGetValue(serverHandles[ii], out item)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - bufferEnabled[ii] = (item.BufferEnabled)?1:0; - } - - return errors; - } - } - - /// - /// Updates the cache with quality. - /// - /// The quality. - public void UpdateCacheWithQuality(short quality) - { - lock (m_lock) - { - DateTime now = DateTime.UtcNow; - - foreach (ComDaGroupItem item in m_itemsByHandle.Values) - { - if (null == item.CacheEntry) continue; - DaValue value = new DaValue(); - item.CacheEntry.GetLatest(value); - value.Quality = quality; - value.Timestamp = now; - UpdateCache(item, value, false); - } - } - } - #endregion - - #region Private Methods - /// - /// Updates the deadband filters. - /// - /// The items. - public void UpdateDeadbandFilters(IList items) - { - // update the monitored item filter. - for (int ii = 0; ii < items.Count; ii++) - { - ComDaGroupItem item = items[ii]; - - if (item == null) - { - continue; - } - - if (item.EuType != (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) - { - item.MonitoredItem.Filter = null; - continue; - } - - // do nothing if the filter is not set and is not required. - if (item.MonitoredItem.Filter == null) - { - if (this.Deadband <= 0 && item.Deadband <= 0) - { - continue; - } - } - - DataChangeFilter filter = new DataChangeFilter(); - filter.Trigger = DataChangeTrigger.StatusValue; - - if (this.Deadband <= 0 && item.Deadband <= 0) - { - filter.DeadbandType = (uint)DeadbandType.None; - } - else - { - filter.DeadbandType = (uint)DeadbandType.Percent; - filter.DeadbandValue = this.Deadband; - } - - if (item.Deadband >= 0) - { - filter.DeadbandValue = item.Deadband; - } - - item.MonitoredItem.Filter = filter; - } - } - - /// - /// Gets the session associated with the group. - /// - /// The session. - private Session GetSession() - { - if (m_subscription == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_subscription.Session as Session; - } - - /// - /// Sets the error for all items after an unexpected error occurs. - /// - /// The items in request. - /// The results. - /// The exception. - /// The default error. - private void SetFatalError(ComDaGroupItem[] itemsInRequest, int[] results, Exception e, int defaultError) - { - int error = ComUtils.GetErrorCode(e, defaultError); - - for (int ii = 0; ii < itemsInRequest.Length; ii++) - { - if (itemsInRequest[ii] != null) - { - results[ii] = error; - } - } - } - - /// - /// Checks the update timer status. - /// - private void CheckUpdateTimerStatus() - { - lock (m_lock) - { - if (AreUpdatesRequired) - { - if (m_nextUpdateTime == -1) - { - ScheduleNextUpdate(); - } - - // check if it needs to be started. - if (m_updateTimer == null) - { - // mark all of the cached values for re sending. - for (int ii = 0; ii < m_items.Count; ii++) - { - if (m_items[ii].CacheEntry != null) - { - m_items[ii].CacheEntry.Changed = true; - } - } - - m_updateTimer = new Timer(OnUpdate, null, 0, 50); - } - - return; - } - - // check if the timer needs to stopped. - if (m_updateTimer != null) - { - m_updateTimer.Dispose(); - m_updateTimer = null; - } - - m_nextUpdateTime = -1; - } - } - - /// - /// Gets a value indicating whether updates are required. - /// - /// true if updates are required; otherwise, false. - private bool AreUpdatesRequired - { - get - { - if (m_disposed || !m_active || !m_enabled || m_callback == null) - { - return false; - } - - int activeItemCount = 0; - - for (int ii = 0; ii < m_items.Count; ii++) - { - if (m_items[ii].MonitoredItem.Status.MonitoringMode == MonitoringMode.Reporting) - { - activeItemCount++; - break; - } - } - - if (activeItemCount == 0 && m_keepAliveTime <= 0) - { - return false; - } - - return true; - } - } - - /// - /// Schedules the next update. - /// - private void ScheduleNextUpdate() - { - long now = HiResClock.UtcNow.Ticks; - - if (m_nextUpdateTime > 0) - { - m_nextUpdateTime += m_actualUpdateRate*TimeSpan.TicksPerMillisecond; - } - else - { - m_nextUpdateTime = now + m_actualUpdateRate*TimeSpan.TicksPerMillisecond; - } - - // Utils.Trace("NextUpdateTime={0:mm:ss.fff}, ActualUpdateRate={1}", new DateTime(m_nextUpdateTime), m_actualUpdateRate); - - for (int ii = 0; ii < m_items.Count; ii++) - { - // check if item is being sampled independently. - if (m_items[ii].SamplingRate >= 0) - { - // check if the update time has already passed. - if (m_items[ii].NextUpdateTime < now) - { - m_items[ii].NextUpdateTime = now + m_items[ii].ActualSamplingRate*TimeSpan.TicksPerMillisecond; - } - } - - // turn off item level update time checks. - else - { - m_items[ii].NextUpdateTime = -1; - } - } - } - - /// - /// Called when a data change arrives. - /// - /// The subscription. - /// The notification. - /// The string table. - void OnDataChange(Subscription subscription, DataChangeNotification notification, IList stringTable) - { - try - { - lock (m_lock) - { - for (int jj = 0; jj < notification.MonitoredItems.Count; jj++) - { - uint clientHandle = notification.MonitoredItems[jj].ClientHandle; - - // find item. - ComDaGroupItem item = null; - - if (!m_itemsByMonitoredItem.TryGetValue(clientHandle, out item)) - { - continue; - } - - // convert data change. - DaValue result = m_manager.Mapper.GetLocalDataValue(notification.MonitoredItems[jj].Value); - - // update cache. - UpdateCache(item, result, false); - } - } - } - catch (Exception exception) - { - Utils.Trace("Unexpected error during CacheUpdate. {0}", exception.Message); - } - } - - /// - /// Called when it is time to send an update. - /// - /// The state. - private void OnUpdate(object state) - { - try - { - IComDaGroupCallback callback = null; - List clientHandles = null; - List values = null; - long now = HiResClock.UtcNow.Ticks; - - lock (m_lock) - { - // check if updates are required. - if (!AreUpdatesRequired || m_updateInProgress) - { - TraceState("OnUpdate Skipped"); - return; - } - - // check if enough time has elapsed. - if (m_nextUpdateTime == -1 || m_nextUpdateTime > (now + 50*TimeSpan.TicksPerMillisecond)) - { - return; - } - - // Utils.Trace("NextUpdateTime={0:mm:ss.fff}, CurrentTime={1:mm:ss.fff}", new DateTime(m_nextUpdateTime), new DateTime(now)); - - // collect values to report. - for (int ii = 0; ii < m_items.Count; ii++) - { - ComDaGroupItem item = m_items[ii]; - - if (!item.Active) - { - continue; - } - - if (item.CacheEntry == null || !item.CacheEntry.Changed) - { - continue; - } - - // write buffered values first. - DaValue value = null; - - if (item.CacheEntry.NextEntry != null) - { - Stack stack = new Stack(); - - for (DaCacheValue entry = item.CacheEntry; entry != null; entry = entry.NextEntry) - { - stack.Push(entry); - } - - while (stack.Count > 1) - { - DaCacheValue entry = stack.Pop(); - - value = new DaValue(); - entry.GetLatest(value); - UpdateReadResult(item, value); - - if (item.LastSentValue != null) - { - if (value.Quality == item.LastSentValue.Quality) - { - if (Utils.IsEqual(item.LastSentValue.Value, value.Value)) - { - continue; - } - } - } - - if (clientHandles == null) - { - clientHandles = new List(); - values = new List(); - } - - clientHandles.Add(item.ClientHandle); - values.Add(value); - item.LastSentValue = value; - - /* - TraceState( - "OnUpdate BUFFERED VALUE", - this.m_serverHandle, - item.ServerHandle, - item.ClientHandle, - new Variant(value.Value), - value.Timestamp.ToString("HH:mm:ss.fff"), - item.CacheEntry.Changed); - */ - } - - // clear cache. - item.CacheEntry.NextEntry = null; - } - - // check if enough time has elapsed for this item (used if the sampling rate > update rate). - if (item.NextUpdateTime != -1 && item.NextUpdateTime > now) - { - continue; - } - - // add latest values. - value = new DaValue(); - item.CacheEntry.GetLatest(value); - UpdateReadResult(item, value); - - if (item.LastSentValue != null) - { - if (value.Quality == item.LastSentValue.Quality) - { - if (Utils.IsEqual(item.LastSentValue.Value, value.Value)) - { - item.CacheEntry.Changed = false; - continue; - } - } - } - - if (clientHandles == null) - { - clientHandles = new List(); - values = new List(); - } - - clientHandles.Add(item.ClientHandle); - values.Add(value); - item.LastSentValue = value; - - /* - TraceState( - "OnUpdate LATEST VALUE", - this.m_serverHandle, - item.ServerHandle, - item.ClientHandle, - new Variant(value.Value), - value.Timestamp.ToString("HH:mm:ss.fff"), - item.CacheEntry.Changed); - */ - - // clear change flag. - item.CacheEntry.Changed = false; - } - - // nothing to report unless the keep alive expired. - if (clientHandles == null || clientHandles.Count == 0) - { - if (m_keepAliveTime == 0 || m_lastUpdateTime + m_keepAliveTime*TimeSpan.TicksPerMillisecond > now) - { - ScheduleNextUpdate(); - return; - } - } - - callback = m_callback; - m_updateInProgress = true; - m_lastUpdateTime = now; - - // schedule next update. - ScheduleNextUpdate(); - } - - // send callback. - try - { - callback.ReadCompleted( - this.m_clientHandle, - false, - 0, - 0, - (clientHandles != null) ? clientHandles.ToArray() : new int[0], - (values != null) ? values.ToArray() : new DaValue[0]); - - if (clientHandles.Count > 0) - { - m_manager.SetLastUpdateTime(); - } - - /* - TraceState( - "OnUpdate Completed", - this.m_serverHandle, - (values != null && values.Count > 0)?values[0].Value:"null", - (m_nextUpdateTime-now)/TimeSpan.TicksPerMillisecond); - */ - } - finally - { - lock (m_lock) - { - m_updateInProgress = false; - } - } - } - catch (Exception e) - { - Utils.Trace("Unexpected error during GroupUpdate. {0}", e.Message); - } - } - - /// - /// Called to process an asynchronous read. - /// - private void OnAsyncRead(object state) - { - try - { - TraceState("OnAsyncRead"); - - // find the request. - ComDaAsnycReadRequest request = null; - IComDaGroupCallback callback = null; - - lock (m_lock) - { - // check if dispoed. - if (m_disposed) - { - return; - } - - // find request. - for (int ii = 0; ii < m_requests.Count; ii++) - { - if (Object.ReferenceEquals(state, m_requests[ii])) - { - request = (ComDaAsnycReadRequest)state; - m_requests.RemoveAt(ii); - break; - } - } - - callback = m_callback; - - // request must have been cancelled. - if (request == null || callback == null) - { - return; - } - } - - // report that the cancel succeeded. - if (request.Cancelled) - { - callback.CancelSucceeded(m_clientHandle, request.TransactionId); - TraceState("OnAsyncRead Cancelled", request.TransactionId, request.CancelId); - return; - } - - // check if the initial read after group is activated. - int[] serverHandles = request.ServerHandles; - List itemsToUpdate = null; - - if (request.IsFirstUpdate) - { - lock (m_lock) - { - // need to check if an update has already arrived. - itemsToUpdate = new List(m_items.Count); - - for (int ii = 0; ii < m_items.Count; ii++) - { - ComDaGroupItem item = m_items[ii]; - - if (item.Active) - { - itemsToUpdate.Add(item); - } - } - - // nothing more to do. - if (itemsToUpdate.Count == 0) - { - return; - } - - // revise the handles to read. - serverHandles = new int[itemsToUpdate.Count]; - - for (int ii = 0; ii < itemsToUpdate.Count; ii++) - { - serverHandles[ii] = itemsToUpdate[ii].ServerHandle; - } - } - } - - // read values. - DaValue[] results = SyncRead(request.MaxAge, serverHandles, request.IsRefresh, null); - - // update cache. - if (request.IsFirstUpdate) - { - lock (m_lock) - { - for (int ii = 0; ii < itemsToUpdate.Count; ii++) - { - ComDaGroupItem item = m_items[ii]; - item.LastSentValue = results[ii]; - } - } - } - - // send callback. - callback.ReadCompleted( - this.m_clientHandle, - request.IsRefresh, - request.CancelId, - request.TransactionId, - request.ClientHandles, - results); - - TraceState("OnAsyncRead Completed", request.TransactionId, request.CancelId); - } - catch (Exception e) - { - Utils.Trace("Unexpected error during AsyncRead. {0}", e.Message); - } - } - - /// - /// Called to process an asynchronous write. - /// - private void OnAsyncWrite(object state) - { - try - { - TraceState("OnAsyncWrite"); - - // find the request. - ComDaAsnycWriteRequest request = null; - IComDaGroupCallback callback = null; - - lock (m_lock) - { - // check if dispoed. - if (m_disposed) - { - return; - } - - // find request. - for (int ii = 0; ii < m_requests.Count; ii++) - { - if (Object.ReferenceEquals(state, m_requests[ii])) - { - request = (ComDaAsnycWriteRequest)state; - m_requests.RemoveAt(ii); - break; - } - } - - callback = m_callback; - - // request must have been cancelled. - if (request == null || callback == null) - { - return; - } - } - - // report that the cancel succeeded. - if (request.Cancelled) - { - callback.CancelSucceeded(m_clientHandle, request.TransactionId); - TraceState("OnAsyncWrite Cancelled", request.TransactionId, request.CancelId); - return; - } - - // write values. - int[] results = SyncWrite(request.ServerHandles, request.Values); - - // send callback. - callback.WriteCompleted( - this.m_clientHandle, - request.TransactionId, - request.ClientHandles, - results); - - TraceState("OnAsyncWrite Completed", request.TransactionId, request.CancelId); - } - catch (Exception e) - { - Utils.Trace("Unexpected error during AsyncWrite. {0}", e.Message); - } - } - - private void AddItemToSubscription(ComDaGroupItem item) - { - m_subscription.AddItem(item.MonitoredItem); - m_itemsByMonitoredItem.Add(item.MonitoredItem.ClientHandle, item); - } - - private void RemoveItemFromSubscription(ComDaGroupItem item) - { - m_itemsByMonitoredItem.Remove(item.MonitoredItem.ClientHandle); - m_subscription.RemoveItem(item.MonitoredItem); - } - - /// - /// Dumps the current state of the browser. - /// - private void TraceState(string context, params object[] args) - { - #if TRACESTATE - if ((Utils.TraceMask & Utils.TraceMasks.Information) == 0) - { - return; - } - - StringBuilder buffer = new StringBuilder(); - - buffer.AppendFormat("ComDaGroup::{0}", context); - - if (args != null) - { - buffer.Append("( "); - - for (int ii = 0; ii < args.Length; ii++) - { - if (ii > 0) - { - buffer.Append(", "); - } - - buffer.Append(new Variant(args[ii])); - } - - buffer.Append(" )"); - } - - Utils.Trace("{0}", buffer.ToString()); - #endif - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private bool m_disposed; - private ComDaGroupManager m_manager; - private IntPtr m_handle; - private string m_name; - private int m_serverHandle; - private int m_clientHandle; - private bool m_active; - private bool m_enabled; - private int m_updateRate; - private float m_deadband; - private int m_timeBias; - private int m_lcid; - private int m_actualUpdateRate; - private Subscription m_subscription; - private Dictionary m_itemsByHandle; - private List m_items; - private int m_transactionCounter = 1000; - private List m_requests; - private int m_keepAliveTime; - private IComDaGroupCallback m_callback; - private long m_nextUpdateTime; - private long m_lastUpdateTime; - private Timer m_updateTimer; - private bool m_updateInProgress; - private Dictionary m_itemsByMonitoredItem; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/ComDaGroupItem.cs b/ComIOP/Common/Server/Da/ComDaGroupItem.cs deleted file mode 100644 index c2296846d..000000000 --- a/ComIOP/Common/Server/Da/ComDaGroupItem.cs +++ /dev/null @@ -1,315 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// A class that stores the state of an item in a COM DA group. - /// - public class ComDaGroupItem - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComDaGroupItem(ComDaGroup group, string itemId) - { - m_group = group; - m_itemId = itemId; - m_serverHandle = 0; - m_active = true; - m_euType = -1; - m_samplingRate = -1; - m_bufferEnabled = false; - m_deadband = -1; - } - #endregion - - #region Public Members - /// - /// Gets the group that the item belongs to. - /// - /// The group. - public ComDaGroup Group - { - get { return m_group; } - } - - /// - /// Gets the remote node id. - /// - /// The remote node id. - public NodeId NodeId - { - get { return m_nodeId; } - set { m_nodeId = value; } - } - - /// - /// Gets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - } - - /// - /// Gets or sets the server handle. - /// - /// The server handle. - public int ServerHandle - { - get { return m_serverHandle; } - set { m_serverHandle = value; } - } - - /// - /// Gets or sets the client handle. - /// - /// The client handle. - public int ClientHandle - { - get { return m_clientHandle; } - set { m_clientHandle = value; } - } - - /// - /// Gets or sets a value indicating whether this is active. - /// - /// true if active; otherwise, false. - public bool Active - { - get { return m_active; } - set { m_active = value; } - } - - /// - /// Gets or sets the the requested data type. - /// - /// The type of the requested data type. - public short RequestedDataType - { - get { return m_requestedDataType; } - set { m_requestedDataType = value; } - } - - /// - /// Gets or sets the the canonical data type. - /// - /// The type of the canonical data type. - public short CanonicalDataType - { - get { return m_canonicalDataType; } - set { m_canonicalDataType = value; } - } - - /// - /// Gets or sets the remote data type for the item. - /// - /// The remote data type. - public TypeInfo RemoteDataType - { - get { return m_remoteDataType; } - set { m_remoteDataType = value; } - } - - /// - /// Gets or sets the access rights. - /// - /// The access rights. - public int AccessRights - { - get { return m_accessRights; } - set { m_accessRights = value; } - } - - /// - /// Gets or sets the EU type. - /// - /// The EU type. - public int EuType - { - get { return m_euType; } - set { m_euType = value; } - } - - /// - /// Gets or sets the EU info (HighEU/LowEU for Analog, EnumStrings for Enumerated). - /// - /// The EU info. - public object EuInfo - { - get { return m_euInfo; } - set { m_euInfo = value; } - } - - /// - /// Gets or sets the sampling interval. - /// - /// The sampling interval. - public int SamplingRate - { - get { return m_samplingRate; } - set { m_samplingRate = value; } - } - - /// - /// Gets or sets the actual sampling interval. - /// - /// The actual sampling interval. - public int ActualSamplingRate - { - get { return m_actualSamplingRate; } - set { m_actualSamplingRate = value; } - } - - /// - /// Gets or sets whether buffering is enabled. - /// - /// Whether buffering is enabled. - public bool BufferEnabled - { - get { return m_bufferEnabled; } - set { m_bufferEnabled = value; } - } - - /// - /// Gets or sets the deadband. - /// - /// The deadband. - public float Deadband - { - get { return m_deadband; } - set { m_deadband = value; } - } - - /// - /// Gets or sets the monitored item. - /// - /// The monitored item. - public MonitoredItem MonitoredItem - { - get { return m_monitoredItem; } - set { m_monitoredItem = value; } - } - - /// - /// Gets or sets the cache entry for the item. - /// - /// The cache entry. - public DaCacheValue CacheEntry - { - get { return m_cacheEntry; } - set { m_cacheEntry = value; } - } - - /// - /// Gets or sets the last sent value. - /// - /// The last sent value. - public DaValue LastSentValue - { - get { return m_lastSentValue; } - set { m_lastSentValue = value; } - } - - /// - /// Gets or sets the next update time. - /// - /// The next update time. - public long NextUpdateTime - { - get { return m_nextUpdateTime; } - set { m_nextUpdateTime = value; } - } - - /// - /// Clones the item. - /// - /// The group. - /// The new item. - public ComDaGroupItem CloneItem(ComDaGroup group) - { - ComDaGroupItem copy = new ComDaGroupItem(group, this.ItemId); - - copy.m_nodeId = this.m_nodeId; - copy.m_serverHandle = this.m_serverHandle; - copy.m_clientHandle = this.m_clientHandle; - copy.m_active = this.m_active; - copy.m_requestedDataType = this.m_requestedDataType; - copy.m_canonicalDataType = this.m_canonicalDataType; - copy.m_accessRights = this.m_accessRights; - copy.m_euType = this.m_euType; - copy.m_euInfo = this.m_euInfo; - copy.m_samplingRate = this.m_samplingRate; - copy.m_bufferEnabled = this.m_bufferEnabled; - copy.m_actualSamplingRate = this.m_actualSamplingRate; - copy.m_deadband = this.m_deadband; - - // create new monitored item and use its client handle as the server handle. - copy.m_monitoredItem = new MonitoredItem(this.MonitoredItem); - - return copy; - } - #endregion - - #region Private Fields - private ComDaGroup m_group; - private string m_itemId; - private NodeId m_nodeId; - private int m_serverHandle; - private int m_clientHandle; - private bool m_active; - private short m_requestedDataType; - private short m_canonicalDataType; - private int m_accessRights; - private int m_euType; - private object m_euInfo; - private int m_samplingRate; - private bool m_bufferEnabled; - private int m_actualSamplingRate; - private float m_deadband; - private MonitoredItem m_monitoredItem; - private DaCacheValue m_cacheEntry; - private DaValue m_lastSentValue; - private TypeInfo m_remoteDataType; - private long m_nextUpdateTime; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/ComDaGroupManager.cs b/ComIOP/Common/Server/Da/ComDaGroupManager.cs deleted file mode 100644 index f9caab696..000000000 --- a/ComIOP/Common/Server/Da/ComDaGroupManager.cs +++ /dev/null @@ -1,1105 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// A class that manages the COM DA groups. - /// - public class ComDaGroupManager : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The mapper. - /// The browser. - public ComDaGroupManager(ComNamespaceMapper mapper, ComDaBrowseManager browser) - { - m_mapper = mapper; - m_browser = browser; - m_groups = new List(); - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - lock (m_lock) - { - for (int ii = 0; ii < m_groups.Count; ii++) - { - Utils.SilentDispose(m_groups[ii]); - } - - m_groups.Clear(); - } - } - } - #endregion - - #region Public Members - /// - /// Gets or sets the session. - /// - /// The session. - public Session Session - { - get { return m_session; } - set - { - bool isReplaced = !Object.ReferenceEquals(m_session, value); - m_session = value; - if (isReplaced) OnSessionReplaced(); - } - } - - /// - /// Gets the namespace mapper. - /// - /// The namespace mapper. - public ComNamespaceMapper Mapper - { - get { return m_mapper; } - } - - /// - /// Gets the group count. - /// - /// The group count. - public int GroupCount - { - get - { - lock (m_lock) - { - return m_groups.Count; - } - } - } - - /// - /// Gets the last update time. - /// - /// The last update time. - public DateTime LastUpdateTime - { - get - { - lock (m_lock) - { - return m_lastUpdateTime; - } - } - } - - /// - /// Sets the last update time to the current time. - /// - public void SetLastUpdateTime() - { - lock (m_lock) - { - m_lastUpdateTime = DateTime.UtcNow; - } - } - - /// - /// Gets the group with the specified name. - /// - /// Name of the group. - /// The group. Null if it does not exist. - public ComDaGroup GetGroupByName(string groupName) - { - TraceState("GetGroupByName", groupName); - - lock (m_lock) - { - for (int ii = 0; ii < m_groups.Count; ii++) - { - ComDaGroup group = m_groups[ii]; - - if (group.Name == groupName) - { - return group; - } - } - - return null; - } - } - - /// - /// Gets the group by handle. - /// - /// The server handle. - /// The group. - public ComDaGroup GetGroupByHandle(int serverHandle) - { - TraceState("GetGroupByHandle", serverHandle); - - lock (m_lock) - { - for (int ii = 0; ii < m_groups.Count; ii++) - { - ComDaGroup group = m_groups[ii]; - - if (group.ServerHandle == serverHandle) - { - return group; - } - } - - return null; - } - } - - /// - /// Sets the name. - /// - /// The group. - /// Name of the group. - public void SetGroupName(ComDaGroup group, string groupName) - { - TraceState("SetGroupName", group.Name, groupName); - - if (String.IsNullOrEmpty(groupName)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - lock (m_lock) - { - for (int ii = 0; ii < m_groups.Count; ii++) - { - ComDaGroup target = m_groups[ii]; - - if (target.ServerHandle != group.ServerHandle && target.Name == groupName) - { - throw ComUtils.CreateComException(ResultIds.E_DUPLICATENAME); - } - - group.Name = groupName; - } - } - } - - /// - /// Adds the group. - /// - /// The group name. - /// if set to true the group is active. - /// The update rate. - /// The client handle. - /// The time bias. - /// The deadband. - /// The lcid. - /// The new group. - 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; - } - - /// - /// Removes the group. - /// - /// The group. - public void RemoveGroup(ComDaGroup group) - { - TraceState("RemoveGroup", group.Name); - - lock (m_lock) - { - for (int ii = 0; ii < m_groups.Count; ii++) - { - if (Object.ReferenceEquals(group, m_groups[ii])) - { - m_groups.RemoveAt(ii); - - if (group.Subscription != null && group.Subscription.Session != null) - { - group.Subscription.Session.RemoveSubscription(group.Subscription); - } - } - } - - group.Dispose(); - } - } - - /// - /// Returns the current set of groups. - /// - /// The list of groups. - public ComDaGroup[] GetGroups() - { - TraceState("GetGroups"); - - lock (m_lock) - { - ComDaGroup[] groups = new ComDaGroup[m_groups.Count]; - - for (int ii = 0; ii < m_groups.Count; ii++) - { - groups[ii] = m_groups[ii]; - } - - return groups; - } - } - - /// - /// Updates the EUInfo for the items. - /// - /// The group. - /// The items. Null entries are ignored. - public void UpdateItemEuInfo( - ComDaGroup group, - IList 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(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(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; - } - } - } - - /// - /// Validates the items. - /// - /// The group. - /// The requests. - /// The items. May contain null is validation failed. - 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; - } - - /// - /// Reads the attribute values from the server. - /// - /// The values to read. - /// - /// The values read. - /// - public DaValue[] Read(ReadValueIdCollection valuesToRead) - { - TraceState("Read", valuesToRead.Count); - - // check for valid session. - Session session = m_session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - int masterError = ResultIds.E_FAIL; - DaValue[] results = new DaValue[valuesToRead.Count]; - - if (session != null) - { - try - { - // read the values. - DataValueCollection values = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.Read( - null, - 0, - TimestampsToReturn.Both, - valuesToRead, - out values, - out diagnosticInfos); - - ClientBase.ValidateResponse(values, valuesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToRead); - - // convert the response. - for (int ii = 0; ii < values.Count; ii++) - { - results[ii] = m_mapper.GetLocalDataValue(values[ii]); - } - - // return the results. - return results; - } - catch (Exception e) - { - masterError = ComUtils.GetErrorCode(e, ResultIds.E_FAIL); - } - } - - // report any unexpected errors. - for (int ii = 0; ii < results.Length; ii++) - { - DaValue result = results[ii] = new DaValue(); - result.Error = masterError; - } - - return results; - } - - /// - /// Reads the attribute values from the server. - /// - /// The values to write. - /// The results. - public int[] Write(WriteValueCollection valuesToWrite) - { - TraceState("Write", valuesToWrite.Count); - - // check for valid session. - Session session = m_session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - int masterError = ResultIds.E_FAIL; - int[] errors = new int[valuesToWrite.Count]; - - if (session != null) - { - try - { - // write the values. - StatusCodeCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.Write( - null, - valuesToWrite, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, valuesToWrite); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToWrite); - - // convert the response. - for (int ii = 0; ii < results.Count; ii++) - { - errors[ii] = ComDaProxy.MapWriteStatusToErrorCode(valuesToWrite[ii].Value, results[ii]); - } - - // return the results. - return errors; - } - catch (Exception e) - { - masterError = ComUtils.GetErrorCode(e, ResultIds.E_FAIL); - } - } - - // report any unexpected errors. - for (int ii = 0; ii < errors.Length; ii++) - { - errors[ii] = masterError; - } - - return errors; - } - #endregion - - #region Private Methods - /// - /// Validates the items by reading the attributes required to add them to the group. - /// - /// The session. - /// The group. - /// The requests. - /// The items. - /// The start index. - /// The number of items to process. - 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)NodeClass.Unspecified); - - if (nodeClass != NodeClass.Variable) - { - requests[ii].Error = ResultIds.E_INVALIDITEMID; - continue; - } - - // verify data type. - NodeId dataTypeId = results[first+1].GetValue(null); - - if (dataTypeId == null) - { - requests[ii].Error = ResultIds.E_INVALIDITEMID; - continue; - } - - // get value rank. - int valueRank = results[first+2].GetValue(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(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; - } - } - } - - /// - /// Recovers the session context. - /// - /// The group. - public void RecoverSessionContext(ComDaGroup group) - { - // create a new subscription and copy existing one. - Subscription discardSubscription = group.Subscription; - Subscription subscription = new Subscription(); - subscription.DisplayName = discardSubscription.DisplayName; - subscription.PublishingInterval = discardSubscription.PublishingInterval; - subscription.KeepAliveCount = discardSubscription.KeepAliveCount; - subscription.LifetimeCount = discardSubscription.LifetimeCount; - subscription.MaxNotificationsPerPublish = discardSubscription.MaxNotificationsPerPublish; - subscription.Priority = discardSubscription.Priority; - subscription.PublishingEnabled = discardSubscription.PublishingEnabled; - subscription.DisableMonitoredItemCache = discardSubscription.DisableMonitoredItemCache; - - try - { - discardSubscription.Dispose(); - } - catch (Exception) - { - } - - m_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) - { - m_session.RemoveSubscription(subscription); - throw ComUtils.CreateComException(e, ResultIds.E_FAIL); - } - - // update the group. - group.ActualUpdateRate = (int)(subscription.CurrentPublishingInterval * 2); - group.Subscription = subscription; - group.RecreateItems(); - } - - /// - /// Called when a session is replaced. - /// - public void OnSessionReplaced() - { - lock (m_lock) - { - foreach (ComDaGroup group in m_groups) - { - RecoverSessionContext(group); - } - } - } - - /// - /// Called when a session is removed. - /// - public void OnSessionRemoved() - { - lock (m_lock) - { - if (m_groups.Count <= 0) return; - - foreach (ComDaGroup group in m_groups) - { - group.UpdateCacheWithQuality(OpcRcw.Da.Qualities.OPC_QUALITY_COMM_FAILURE); - } - } - } - - - /// - /// Dumps the current state of the browser. - /// - private void TraceState(string context, params object[] args) - { - #if TRACESTATE - if ((Utils.TraceMask & Utils.TraceMasks.Information) == 0) - { - return; - } - - StringBuilder buffer = new StringBuilder(); - - buffer.AppendFormat("ComDaGroupManager::{0}", context); - - if (args != null) - { - buffer.Append("( "); - - for (int ii = 0; ii < args.Length; ii++) - { - if (ii > 0) - { - buffer.Append(", "); - } - - buffer.Append(new Variant(args[ii])); - } - - buffer.Append(" )"); - } - - Utils.Trace("{0}", buffer.ToString()); - #endif - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private Session m_session; - private ComNamespaceMapper m_mapper; - private ComDaBrowseManager m_browser; - private int m_groupCounter; - private List m_groups; - private DateTime m_lastUpdateTime; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/ComDaProxy.cs b/ComIOP/Common/Server/Da/ComDaProxy.cs deleted file mode 100644 index 8ef153fc6..000000000 --- a/ComIOP/Common/Server/Da/ComDaProxy.cs +++ /dev/null @@ -1,645 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// A base class for classes that implement an OPC COM specification. - /// - public class ComDaProxy : ComProxy - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComDaProxy() - { - m_mapper = new ComNamespaceMapper(); - m_browseCacheManager = new ComDaBrowseCache(m_mapper); - m_browseManager = new ComDaBrowseManager(m_mapper, m_browseCacheManager); - m_groupManager = new ComDaGroupManager(m_mapper, m_browseManager); - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - lock (Lock) - { - Utils.SilentDispose(m_groupManager); - m_groupManager = null; - } - } - - base.Dispose(disposing); - } - #endregion - - #region Overridden Methods - /// - /// Called when a new session is created. - /// - protected override void OnSessionCreated() - { - lock (Lock) - { - // fetch the configuration. - m_configuration = Endpoint.ParseExtension(null); - - if (m_configuration == null) - { - m_configuration = new ComProxyConfiguration(); - } - - // update the mapping and pass the new session to other objects. - m_mapper.Initialize(Session, m_configuration); - m_groupManager.Session = Session; - m_browseCacheManager.BrowseBlockSize = m_configuration.BrowseBlockSize; - - // save the configuration. - Endpoint.UpdateExtension(null, m_configuration); - SaveConfiguration(); - } - } - - /// - /// Called when a session is reconnected. - /// - protected override void OnSessionReconected() - { - // TBD - } - - /// - /// Called when a session is removed. - /// - protected override void OnSessionRemoved() - { - m_groupManager.OnSessionRemoved(); - } - #endregion - - #region Public Methods - /// - /// Gets the group count. - /// - /// The group count. - public int GroupCount - { - get - { - return m_groupManager.GroupCount; - } - } - - /// - /// Gets the last update time. - /// - /// The last update time. - public DateTime LastUpdateTime - { - get - { - return m_groupManager.LastUpdateTime; - } - } - - /// - /// Adds the group. - /// - /// The group name. - /// if set to true the group is active. - /// The update rate. - /// The client handle. - /// The time bias. - /// The deadband. - /// The lcid. - /// The new group. - public ComDaGroup AddGroup( - string groupName, - bool active, - int updateRate, - int clientHandle, - int timeBias, - float deadband, - int lcid) - { - return m_groupManager.AddGroup(groupName, active, updateRate, clientHandle, timeBias, deadband, lcid); - } - - /// - /// Removes the group. - /// - /// The group. - public void RemoveGroup(ComDaGroup group) - { - m_groupManager.RemoveGroup(group); - } - - /// - /// Gets the group with the specified name. - /// - /// Name of the group. - /// The group. Null if it does not exist. - public ComDaGroup GetGroupByName(string groupName) - { - return m_groupManager.GetGroupByName(groupName); - } - - /// - /// Gets the group by handle. - /// - /// The server handle. - /// The group. - public ComDaGroup GetGroupByHandle(int serverHandle) - { - return m_groupManager.GetGroupByHandle(serverHandle); - } - - /// - /// Returns the current set of groups. - /// - /// The list of groups. - public ComDaGroup[] GetGroups() - { - return m_groupManager.GetGroups(); - } - - /// - /// Reads the values for the specified item ids. - /// - /// The item ids. - /// The values. - public DaValue[] Read(string[] itemIds) - { - ReadValueIdCollection valuesToRead = new ReadValueIdCollection(); - - for (int ii = 0; ii < itemIds.Length; ii++) - { - ReadValueId valueToRead = new ReadValueId(); - - valueToRead.NodeId = m_mapper.GetRemoteNodeId(itemIds[ii]); - valueToRead.AttributeId = Attributes.Value; - - valuesToRead.Add(valueToRead); - } - - return m_groupManager.Read(valuesToRead); - } - - /// - /// Writes the values for the specified item ids. - /// - /// The item ids. - /// The values. - /// The results. - 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; - } - #endregion - - #region Browse Implementation - /// - /// Moves the current browse position up. - /// - public void BrowseUp() - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - m_browseManager.BrowseUp(session); - } - - /// - /// Moves the current browse position down. - /// - public void BrowseDown(string targetName) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - m_browseManager.BrowseDown(session, targetName); - } - - /// - /// Moves the current browse position to the specified item. - /// - public void BrowseTo(string itemId) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - m_browseManager.BrowseTo(session, itemId); - } - - /// - /// Browses the current branch. - /// - /// if set to true the return branches. - /// The filter. - /// The data type filter. - /// The access rights filter. - /// The list of names that meet the criteria. - public IList BrowseForNames(bool isBranch, string filter, short dataTypeFilter, int accessRightsFilter) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_browseManager.BrowseForNames( - session, - (isBranch)?BrowseElementFilter.Branch:BrowseElementFilter.Item, - filter, - dataTypeFilter, - accessRightsFilter); - } - - /// - /// Browse for all items below the current branch. - /// - /// The filter. - /// The data type filter. - /// The access rights filter. - /// - /// The list of item ids that meet the criteria. - /// - public IList BrowseForItems(string filter, short dataTypeFilter, int accessRightsFilter) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_browseManager.BrowseFlat( - session, - filter, - dataTypeFilter, - accessRightsFilter); - } - - /// - /// Browses the specified item id. - /// - /// The item id. - /// The continuation point. - /// The max elements returned. - /// The element type mask. - /// The name filter. - /// The revised continuation point. - /// - public IList BrowseForElements( - string itemId, - string continuationPoint, - int maxElementsReturned, - int elementTypeMask, - string nameFilter, - out string revisedContinuationPoint) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_browseManager.BrowseForElements( - session, - itemId, - continuationPoint, - maxElementsReturned, - elementTypeMask, - nameFilter, - out revisedContinuationPoint); - } - - /// - /// Gets the item id for the specified browse element. - /// - /// The name of the browse element. - /// - public string GetItemId(string browseName) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_browseManager.GetItemId(session, browseName); - } - - /// - /// Gets the properties. - /// - /// The item id. - /// The list of properities. - public IList GetProperties(string itemId) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_browseManager.GetAvailableProperties(session, itemId); - } - - /// - /// Gets the properties. - /// - /// The requests. - /// The property ids. - /// The list of properities. - public IList GetProperties(ComDaReadPropertiesRequest[] requests, params int[] propertyIds) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_browseManager.GetPropertyValues(session, requests, propertyIds); - } - - /// - /// Gets the property values. - /// - /// The item id. - /// The property ids. - /// The property values. - public DaValue[] GetPropertyValues(string itemId, int[] propertyIds) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_browseManager.GetPropertyValues(session, itemId, propertyIds); - } - - /// - /// Gets the item ids for the properties. - /// - /// The item id. - /// The property ids. - /// The item ids. - /// Any errors. - public IList GetItemIds(string itemId, int[] propertyIds, out string[] itemIds) - { - Session session = Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_browseManager.GetItemIds(session, itemId, propertyIds, out itemIds); - } - #endregion - - #region Static Functions - /// - /// Converts a StatusCode returned during a Read to an HRESULT. - /// - internal static int MapPropertyReadStatusToErrorCode(StatusCode statusCode) - { - // map good status. - if (StatusCode.IsGood(statusCode)) - { - return ResultIds.S_OK; - } - - // map bad status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadOutOfMemory: { return ResultIds.E_OUTOFMEMORY; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALID_PID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_INVALID_PID; } - case StatusCodes.BadNotReadable: { return ResultIds.E_BADRIGHTS; } - case StatusCodes.BadUserAccessDenied: { return ResultIds.E_ACCESSDENIED; } - case StatusCodes.BadAttributeIdInvalid: { return ResultIds.E_INVALID_PID; } - case StatusCodes.BadTypeMismatch: { return ResultIds.E_BADTYPE; } - } - - return ResultIds.E_FAIL; - } - - // uncertain values for property reads are errors. - return ResultIds.E_FAIL; - } - - /// - /// Converts a StatusCode returned during a Read to an HRESULT. - /// - internal static int MapReadStatusToErrorCode(StatusCode statusCode) - { - // map bad well known status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadOutOfMemory: { return ResultIds.E_OUTOFMEMORY; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALIDITEMID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_UNKNOWNITEMID; } - case StatusCodes.BadNotReadable: { return ResultIds.E_BADRIGHTS; } - case StatusCodes.BadUserAccessDenied: { return ResultIds.E_ACCESSDENIED; } - case StatusCodes.BadAttributeIdInvalid: { return ResultIds.E_INVALIDITEMID; } - case StatusCodes.BadUnexpectedError: { return ResultIds.E_FAIL; } - case StatusCodes.BadInternalError: { return ResultIds.E_FAIL; } - case StatusCodes.BadSessionClosed: { return ResultIds.E_FAIL; } - case StatusCodes.BadTypeMismatch: { return ResultIds.E_BADTYPE; } - } - } - - // all other values are mapped to quality codes. - return ResultIds.S_OK; - } - - /// - /// Converts a StatusCode returned during a Write to an HRESULT. - /// - internal static int MapWriteStatusToErrorCode(DataValue value, StatusCode statusCode) - { - // map bad status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadTypeMismatch: - { - // server may reject a null value without checking the status code. - if (StatusCode.IsBad(value.StatusCode) && value.Value == null) - { - return ResultIds.E_NOTSUPPORTED; - } - - return ResultIds.E_BADTYPE; - } - - case StatusCodes.BadOutOfMemory: { return ResultIds.E_OUTOFMEMORY; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALIDITEMID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_UNKNOWNITEMID; } - case StatusCodes.BadNotWritable: { return ResultIds.E_BADRIGHTS; } - case StatusCodes.BadUserAccessDenied: { return ResultIds.E_ACCESSDENIED; } - case StatusCodes.BadAttributeIdInvalid: { return ResultIds.E_UNKNOWNITEMID; } - case StatusCodes.BadWriteNotSupported: { return ResultIds.E_NOTSUPPORTED; } - case StatusCodes.BadOutOfRange: { return ResultIds.E_RANGE; } - } - - return ResultIds.E_FAIL; - } - - // ignore uncertain and success codes. - return ResultIds.S_OK; - } - #endregion - - #region Private Fields - private static object m_sharedCacheTableLock = new object(); - private ComProxyConfiguration m_configuration; - private ComNamespaceMapper m_mapper; - private ComDaBrowseCache m_browseCacheManager; - private ComDaBrowseManager m_browseManager; - private ComDaGroupManager m_groupManager; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/ComDaReadPropertiesRequest.cs b/ComIOP/Common/Server/Da/ComDaReadPropertiesRequest.cs deleted file mode 100644 index 1bef46a2b..000000000 --- a/ComIOP/Common/Server/Da/ComDaReadPropertiesRequest.cs +++ /dev/null @@ -1,95 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// Specifies the parameters used to create a DA group item. - /// - public class ComDaReadPropertiesRequest - { - #region Public Properties - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the values. - /// - /// The values. - public DaValue[] Values - { - get { return m_values; } - set { m_values = value; } - } - - /// - /// Gets or sets the indexes used to look up the results. - /// - /// The indexes. - public int[] Indexes - { - get { return m_indexes; } - set { m_indexes = value; } - } - - /// - /// Gets or sets the error associated with the operation. - /// - /// The error. - public int Error - { - get { return m_error; } - set { m_error = value; } - } - #endregion - - #region Private Fields - private string m_itemId; - private DaValue[] m_values; - private int[] m_indexes; - private int m_error; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/DaElement.cs b/ComIOP/Common/Server/Da/DaElement.cs deleted file mode 100644 index a40bd89df..000000000 --- a/ComIOP/Common/Server/Da/DaElement.cs +++ /dev/null @@ -1,324 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores information an element in the DA server address space. - /// - public class DaElement - { - #region Public Members - /// - /// Initializes a new instance of the class. - /// - public DaElement() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Gets or sets the parent item id. - /// - /// The parent item id. - public string ParentId - { - get { return m_parentId; } - set { m_parentId = value; } - } - - /// - /// Gets or sets the type of the element. - /// - /// The type of the element. - public DaElementType ElementType - { - get { return m_elementType; } - set { m_elementType = value; } - } - - /// - /// Gets or sets the properties available for the element. - /// - /// The available properties. - public DaProperty[] Properties - { - get { return m_properties; } - set { m_properties = value; } - } - - /// - /// Gets or sets the COM data type for the value. - /// - /// The COM data type for the value. - public short DataType - { - get { return m_dataType; } - set { m_dataType = value; } - } - - /// - /// Gets or sets the access rights for the item. - /// - /// The access rights. - public int AccessRights - { - get { return m_accessRights; } - set { m_accessRights = value; } - } - - /// - /// Gets or sets the scan rate. - /// - /// The scan rate. - public float ScanRate - { - get { return m_scanRate; } - set { m_scanRate = value; } - } - - /// - /// Gets or sets the description. - /// - /// The description. - public string Description - { - get { return m_description; } - set { m_description = value; } - } - - /// - /// Gets or sets the engineering units. - /// - /// The engineering units. - public string EngineeringUnits - { - get { return m_engineeringUnits; } - set { m_engineeringUnits = value; } - } - - /// - /// Gets or sets EUType forthe item. - /// - /// The EUType for the item. - public int EuType - { - get { return m_euType; } - set { m_euType = value; } - } - - /// - /// Gets or sets the EU information for the item. - /// - /// The EU information for the item. - public string[] EuInfo - { - get { return m_euInfo; } - set { m_euInfo = value; } - } - - /// - /// Gets or sets the high EU value. - /// - /// The high EU value. - public double HighEU - { - get { return m_highEU; } - set { m_highEU = value; } - } - - /// - /// Gets or sets the low EU value. - /// - /// The low EU value. - public double LowEU - { - get { return m_lowEU; } - set { m_lowEU = value; } - } - - /// - /// Gets or sets the high IR value. - /// - /// The high IR value. - public double HighIR - { - get { return m_highIR; } - set { m_highIR = value; } - } - - /// - /// Gets or sets the low IR value. - /// - /// The low IR value. - public double LowIR - { - get { return m_lowIR; } - set { m_lowIR = value; } - } - - /// - /// Gets or sets the open label. - /// - /// The open label. - public string OpenLabel - { - get { return m_openLabel; } - set { m_openLabel = value; } - } - - /// - /// Gets or sets the close label. - /// - /// The close label. - public string CloseLabel - { - get { return m_closeLabel; } - set { m_closeLabel = value; } - } - - /// - /// Gets or sets the time zone for the item. - /// - /// The time zone. - public int? TimeZone - { - get { return m_timeZone; } - set { m_timeZone = value; } - } - - /// - /// Returns true if the element supports the specified property. - /// - /// The property id. - /// Rrue if the element supports the specified property. - public bool SupportsProperty(int propertyId) - { - if (m_properties != null) - { - for (int ii = 0; ii < m_properties.Length; ii++) - { - if (propertyId == m_properties[ii].PropertyId) - { - return true; - } - } - } - - return false; - } - #endregion - - #region Private Methods - #endregion - - #region Private Fields - private string m_itemId; - private string m_name; - private string m_parentId; - private DaElementType m_elementType; - private DaProperty[] m_properties; - private short m_dataType; - private int m_accessRights; - private float m_scanRate; - private string m_description; - private string m_engineeringUnits; - private int m_euType; - private string[] m_euInfo; - private double m_highEU; - private double m_lowEU; - private double m_highIR; - private double m_lowIR; - private string m_openLabel; - private string m_closeLabel; - private int? m_timeZone; - #endregion - } - - /// - /// The possible type of elements. - /// - public enum DaElementType - { - /// - /// Unknown element type. - /// - Undefined = 0, - - /// - /// A branch - /// - Branch = 1, - - /// - /// An item. - /// - Item = 2, - - /// - /// An analog item. - /// - AnalogItem = 3, - - /// - /// An enumerated item. - /// - EnumeratedItem = 4, - - /// - /// An digital item. - /// - DigitalItem = 5 - } -} diff --git a/ComIOP/Common/Server/Da/DaProperty.cs b/ComIOP/Common/Server/Da/DaProperty.cs deleted file mode 100644 index 2e63afa29..000000000 --- a/ComIOP/Common/Server/Da/DaProperty.cs +++ /dev/null @@ -1,110 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores information an element in the DA server address space. - /// - public class DaProperty - { - #region Public Members - /// - /// Initializes a new instance of the class. - /// - public DaProperty() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The property id. - public DaProperty(int propertyId) - { - m_propertyId = propertyId; - m_name = PropertyIds.GetDescription(m_propertyId); - m_dataType = (short)PropertyIds.GetVarType(m_propertyId); - } - #endregion - - #region Public Members - /// - /// Gets or sets the property id. - /// - /// The property id. - public int PropertyId - { - get { return m_propertyId; } - set { m_propertyId = value; } - } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - /// - /// Gets or sets the item id. - /// - /// The item id. - public string ItemId - { - get { return m_itemId; } - set { m_itemId = value; } - } - - /// - /// Gets or sets the COM data type. - /// - /// The COM data type for the property. - public short DataType - { - get { return m_dataType; } - set { m_dataType = value; } - } - #endregion - - #region Private Fields - private int m_propertyId; - private string m_name; - private string m_itemId; - private short m_dataType; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/DaValue.cs b/ComIOP/Common/Server/Da/DaValue.cs deleted file mode 100644 index 9ce289d5b..000000000 --- a/ComIOP/Common/Server/Da/DaValue.cs +++ /dev/null @@ -1,194 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Collections.Generic; -using Opc.Ua; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores information an element in the DA server address space. - /// - public class DaValue - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public DaValue() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the value. - /// - /// The value. - public object Value - { - get { return m_value; } - set { m_value = value; } - } - - /// - /// Gets or sets the timestamp. - /// - /// The timestamp. - public DateTime Timestamp - { - get { return m_timestamp; } - set { m_timestamp = value; } - } - - /// - /// Gets or sets the quality. - /// - /// The quality. - public short Quality - { - get { return (short)(m_quality & 0xFFFF); } - set { m_quality = Utils.ToUInt32((int)value); } - } - - /// - /// Gets or sets the quality. - /// - /// The quality. - public uint HdaQuality - { - get { return m_quality; } - set { m_quality = value; } - } - - /// - /// Gets or sets the COM error. - /// - /// The COM error. - public int Error - { - get { return m_error; } - set { m_error = value; } - } - - /// - /// Gets the value. - /// - /// The type of value to return. - /// The value if no error and a valid value exists. The default value for the type otherwise. - public T GetValue() - { - if (m_error < 0) - { - return default(T); - } - - if (typeof(T).IsInstanceOfType(m_value)) - { - return (T)m_value; - } - - return default(T); - } - #endregion - - #region Private Fields - private object m_value; - private uint m_quality; - private DateTime m_timestamp; - private int m_error; - #endregion - } - - /// - /// Stores information an element in the DA server address space. - /// - public class DaCacheValue : DaValue - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public DaCacheValue() - { - } - #endregion - - #region Public Members - /// - /// Gets or sets the cache timestamp. - /// - /// The cache timestamp. - public DateTime CacheTimestamp - { - get { return m_cacheTimestamp; } - set { m_cacheTimestamp = value; } - } - - /// - /// Gets or sets a value indicating whether the value has changed since the last update. - /// - /// true if the value has changed; otherwise, false. - public bool Changed - { - get { return m_changed; } - set { m_changed = value; } - } - - /// - /// Gets or sets the next entry in the cache. - /// - /// The next entry. - public DaCacheValue NextEntry - { - get { return m_nextEntry; } - set { m_nextEntry = value; } - } - - /// - /// Gets the latest value in the cache. - /// - /// The value. - public void GetLatest(DaValue value) - { - value.Value = this.Value; - value.Quality = this.Quality; - value.Timestamp = this.Timestamp; - value.Error = this.Error; - } - #endregion - - #region Private Fields - private DateTime m_cacheTimestamp; - private DaCacheValue m_nextEntry; - private bool m_changed; - #endregion - } -} diff --git a/ComIOP/Common/Server/Da/IComDaGroupCallback.cs b/ComIOP/Common/Server/Da/IComDaGroupCallback.cs deleted file mode 100644 index e6fa2e687..000000000 --- a/ComIOP/Common/Server/Da/IComDaGroupCallback.cs +++ /dev/null @@ -1,85 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// Specifies the parameters for an async request. - /// - public interface IComDaGroupCallback : IDisposable - { - /// - /// Called when a data change or read complete occurs. - /// - /// The group handle. - /// If set to true it is a response to a refresh request. - /// The cancel id. - /// The transaction id. - /// The client handles. - /// The values. - void ReadCompleted( - int groupHandle, - bool isRefresh, - int cancelId, - int transactionId, - int[] clientHandles, - DaValue[] values); - - /// - /// Called when a write complete occurs. - /// - /// The group handle. - /// The transaction id. - /// The client handles. - /// The errors. - void WriteCompleted( - int groupHandle, - int transactionId, - int[] clientHandles, - int[] errors); - - /// - /// Called when a cancel succeeds. - /// - /// The group handle. - /// The transaction id. - void CancelSucceeded( - int groupHandle, - int transactionId); - } -} diff --git a/ComIOP/Common/Server/Hda/ComHdaBrowser.cs b/ComIOP/Common/Server/Hda/ComHdaBrowser.cs deleted file mode 100644 index 76fd658df..000000000 --- a/ComIOP/Common/Server/Hda/ComHdaBrowser.cs +++ /dev/null @@ -1,486 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// A class that implements a COM DA group. - /// - public class ComHdaBrowser : IDisposable - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The server. - /// The browse manager. - public ComHdaBrowser(ComHdaProxy server, ComDaBrowseManager browseManager) - { - m_server = server; - m_browseManager = browseManager; - } - #endregion - - #region IDisposable Members - /// - /// Frees any unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// An overrideable version of the Dispose. - /// - protected virtual void Dispose(bool disposing) - { - m_disposed = true; - } - - /// - /// Throws if disposed. - /// - private void ThrowIfDisposed() - { - if (m_disposed) - { - throw new ObjectDisposedException(GetType().Name); - } - } - #endregion - - #region Public Members - /// - /// Gets or sets the handle. - /// - /// The handle. - public IntPtr Handle - { - get { return m_handle; } - set { m_handle = value; } - } - - /// - /// Sets the attribute filter. - /// - /// The attribute ids. - /// The operators. - /// The values. - /// - public int[] SetAttributeFilter(uint[] attributeIds, int[] operators, object[] values) - { - int[] errors = new int[attributeIds.Length]; - - for (int ii = 0; ii < attributeIds.Length; ii++) - { - // check for supported attribute. - if (!m_server.IsSupportedAttribute(attributeIds[ii])) - { - errors[ii] = ResultIds.E_UNKNOWNATTRID; - continue; - } - - // only support filters on display name. - if (attributeIds[ii] != OpcRcw.Hda.Constants.OPCHDA_ITEMID) - { - errors[ii] = ResultIds.W_NOFILTER; - continue; - } - - // must be a string. - if (!(values[ii] is string)) - { - errors[ii] = ResultIds.E_INVALIDDATATYPE; - continue; - } - - // create the filter. - ItemNameFilter filter = new ItemNameFilter(); - filter.Operator = operators[ii]; - filter.Value = (string)values[ii]; - - if (m_filters == null) - { - m_filters = new List(); - } - - m_filters.Add(filter); - - errors[ii] = ResultIds.S_OK; - } - - return errors; - } - - /// - /// Moves the current browse position up. - /// - public void BrowseUp() - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - m_browseManager.BrowseUp(session); - } - - /// - /// Moves the current browse position down. - /// - public void BrowseDown(string targetName) - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - m_browseManager.BrowseDown(session, targetName); - } - - /// - /// Moves the current browse position to the specified item. - /// - public void BrowseTo(string itemId) - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - m_browseManager.BrowseTo(session, itemId); - } - - /// - /// Browses the current branch. - /// - /// Type of the browse. - /// - /// The list of names that meet the criteria. - /// - public IList Browse(int browseType) - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - string itemId = String.Empty; - string continuationPoint = null; - - ComDaBrowseElement position = m_browseManager.GetBrowsePosition(session); - - if (position != null) - { - itemId = position.ItemId; - } - - IList elements = m_browseManager.BrowseForElements( - session, - itemId, - null, - 0, - (int)BrowseElementFilter.All, - null, - out continuationPoint); - - return ApplyFilters(elements, browseType); - } - - /// - /// Browse for all items below the current branch. - /// - /// - /// The list of item ids that meet the criteria. - /// - public IList BrowseForItems() - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - ComDaBrowseElement position = m_browseManager.GetBrowsePosition(session); - - List elements = new List(); - BrowseForItems(session, position, elements); - - return ApplyFilters(elements, (int)OPCHDA_BROWSETYPE.OPCHDA_FLAT); - } - - /// - /// Gets the item id for the specified browse element. - /// - /// The name of the browse element. - /// - public string GetItemId(string browseName) - { - Session session = m_server.Session; - - if (session == null) - { - throw ComUtils.CreateComException(ResultIds.E_FAIL); - } - - return m_browseManager.GetItemId(session, browseName); - } - #endregion - - #region Private Methods - /// - /// Recursively browses for items. - /// - /// The session. - /// The parent. - /// The hits. - private void BrowseForItems(Session session, ComDaBrowseElement parent, List hits) - { - string itemId = String.Empty; - string continuationPoint = null; - - if (parent != null) - { - itemId = parent.ItemId; - } - - IList elements = m_browseManager.BrowseForElements( - session, - itemId, - null, - 0, - (int)BrowseElementFilter.All, - null, - out continuationPoint); - - for (int ii = 0; ii < elements.Count; ii++) - { - ComDaBrowseElement element = elements[ii]; - - if (element.IsHistoricalItem) - { - hits.Add(element); - } - - if (element.HasChildren) - { - BrowseForItems(session, element, hits); - } - } - } - - /// - /// Applies the filters to the list of names. - /// - /// The elements. - /// Type of the browse. - /// - private IList ApplyFilters(IList elements, int browseType) - { - List names = new List(); - - for (int ii = 0; ii < elements.Count; ii++) - { - ComDaBrowseElement element = elements[ii]; - - if (browseType == (int)OPCHDA_BROWSETYPE.OPCHDA_BRANCH) - { - if (!element.HasChildren) - { - continue; - } - } - - if (browseType == (int)OPCHDA_BROWSETYPE.OPCHDA_LEAF) - { - if (!element.IsHistoricalItem || element.HasChildren) - { - continue; - } - } - - if (browseType == (int)OPCHDA_BROWSETYPE.OPCHDA_ITEMS) - { - if (!element.IsHistoricalItem) - { - continue; - } - } - - if (m_filters != null) - { - for (int jj = 0; jj < m_filters.Count; jj++) - { - if (!MatchFilter(element.BrowseName, m_filters[jj])) - { - continue; - } - } - } - - if (browseType == (int)OPCHDA_BROWSETYPE.OPCHDA_ITEMS || browseType == (int)OPCHDA_BROWSETYPE.OPCHDA_FLAT) - { - names.Add(element.ItemId); - } - else - { - names.Add(element.BrowseName); - } - } - - return names; - } - - /// - /// Return true if the name natches the filter. - /// - /// The name. - /// The filter. - /// - private bool MatchFilter(string name, ItemNameFilter filter) - { - if (String.IsNullOrEmpty(name)) - { - return false; - } - - switch ((OPCHDA_OPERATORCODES)filter.Operator) - { - case OPCHDA_OPERATORCODES.OPCHDA_EQUAL: - { - return name == filter.Value; - } - - case OPCHDA_OPERATORCODES.OPCHDA_GREATER: - { - return name.CompareTo(filter.Value) > 0; - } - - case OPCHDA_OPERATORCODES.OPCHDA_GREATEREQUAL: - { - return name.CompareTo(filter.Value) >= 0; - } - - case OPCHDA_OPERATORCODES.OPCHDA_LESS: - { - return name.CompareTo(filter.Value) < 0; - } - - case OPCHDA_OPERATORCODES.OPCHDA_LESSEQUAL: - { - return name.CompareTo(filter.Value) <= 0; - } - - case OPCHDA_OPERATORCODES.OPCHDA_NOTEQUAL: - { - return name.CompareTo(filter.Value) != 0; - } - } - - return false; - } - - /// - /// Dumps the current state of the browser. - /// - private void TraceState(string context, params object[] args) - { -#if TRACESTATE - if ((Utils.TraceMask & Utils.TraceMasks.Information) == 0) - { - return; - } - - StringBuilder buffer = new StringBuilder(); - - buffer.AppendFormat("ComHdaBrowser::{0}", context); - - if (args != null) - { - buffer.Append("( "); - - for (int ii = 0; ii < args.Length; ii++) - { - if (ii > 0) - { - buffer.Append(", "); - } - - buffer.Append(new Variant(args[ii])); - } - - buffer.Append(" )"); - } - - Utils.Trace("{0}", buffer.ToString()); -#endif - } - #endregion - - /// - /// Stores a filter to use when browsing. - /// - private class ItemNameFilter - { - public int Operator; - public string Value; - } - - #region Private Fields - private object m_lock = new object(); - private bool m_disposed; - private IntPtr m_handle; - private ComHdaProxy m_server; - private List m_filters; - private ComDaBrowseManager m_browseManager; - #endregion - } -} diff --git a/ComIOP/Common/Server/Hda/ComHdaItemManager.cs b/ComIOP/Common/Server/Hda/ComHdaItemManager.cs deleted file mode 100644 index cf3170515..000000000 --- a/ComIOP/Common/Server/Hda/ComHdaItemManager.cs +++ /dev/null @@ -1,770 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores information about an HDA item. - /// - public class HdaItemHandle - { - /// - /// The remote node id. - /// - public NodeId NodeId; - - /// - /// The local HDA server handle. - /// - public int ServerHandle; - - /// - /// The local HDA client handle. - /// - public int ClientHandle; - - /// - /// Any error associated with the handle. - /// - public int Error; - } - - /// - /// A class that implements a COM DA group. - /// - public class ComHdaItemManager - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - /// The object used to map namespace indexes. - public ComHdaItemManager(ComNamespaceMapper mapper) - { - m_mapper = mapper; - m_handles = new Dictionary(); - m_items = new Dictionary(); - } - #endregion - - /// - /// Constructs a ReadValueId for the specified UA attribute. - /// - /// The handle. - /// The ua attribute id. - /// - private ReadValueId Construct(InternalHandle handle, uint uaAttributeId) - { - ReadValueId readValueId = new ReadValueId(); - readValueId.NodeId = handle.NodeId; - readValueId.AttributeId = uaAttributeId; - readValueId.Handle = handle; - return readValueId; - } - - /// - /// Constructs a ReadValueId for the specified UA attribute. - /// - /// The node id. - /// The hda attribute id. - /// The ua attribute id. - /// - private ReadValueId Construct(NodeId nodeId, uint hdaAttributeId, uint uaAttributeId) - { - ReadValueId readValueId = new ReadValueId(); - readValueId.NodeId = nodeId; - readValueId.AttributeId = uaAttributeId; - readValueId.Handle = hdaAttributeId; - return readValueId; - } - - /// - /// Constructs the browse path. - /// - /// The node id. - /// The hda attribute id. - /// The browse paths. - /// - private BrowsePath Construct(NodeId nodeId, uint hdaAttributeId, params string[] browsePaths) - { - BrowsePath browsePath = new BrowsePath(); - browsePath.StartingNode = nodeId; - browsePath.Handle = hdaAttributeId; - - for (int ii = 0; ii < browsePaths.Length; ii++) - { - RelativePathElement element = new RelativePathElement(); - - element.ReferenceTypeId = ReferenceTypeIds.HasChild; - element.IsInverse = false; - element.IncludeSubtypes = true; - element.TargetName = browsePaths[ii]; - - browsePath.RelativePath.Elements.Add(element); - } - - return browsePath; - } - - /// - /// Gets the type of the remote data. - /// - /// The handle. - /// - public TypeInfo GetRemoteDataType(HdaItemHandle handle) - { - InternalHandle handle2 = handle as InternalHandle; - - if (handle2 != null) - { - return handle2.Item.RemoteType; - } - - return TypeInfo.Scalars.Variant; - } - - /// - /// Gets the available attributes for an HDA item. - /// - /// The session. - /// The node id. - /// - private ReadValueIdCollection GetAvailableAttributes(Session session, NodeId nodeId) - { - ReadValueIdCollection supportedAttributes = new ReadValueIdCollection(); - - // add mandatory HDA attributes. - supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_ITEMID, Attributes.DisplayName)); - supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_DATA_TYPE, Attributes.DataType)); - supportedAttributes.Add(Construct(nodeId, ComHdaProxy.INTERNAL_ATTRIBUTE_VALUE_RANK, Attributes.ValueRank)); - supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_DESCRIPTION, Attributes.Description)); - supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_ARCHIVING, Attributes.Historizing)); - - // check if nodes are defined for all optional HDA attributes. - BrowsePathCollection pathsToRead = new BrowsePathCollection(); - - pathsToRead.Add(Construct(nodeId, ComHdaProxy.INTERNAL_ATTRIBUTE_ANNOTATION, Opc.Ua.BrowseNames.Annotations)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_ENG_UNITS, Opc.Ua.BrowseNames.EngineeringUnits)); ; - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_DERIVE_EQUATION, Opc.Ua.BrowseNames.Definition)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_NORMAL_MAXIMUM, Opc.Ua.BrowseNames.EURange)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_NORMAL_MINIMUM, Opc.Ua.BrowseNames.EURange)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_HIGH_ENTRY_LIMIT, Opc.Ua.BrowseNames.InstrumentRange)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_LOW_ENTRY_LIMIT, Opc.Ua.BrowseNames.InstrumentRange)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_STEPPED, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.Stepped)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_MAX_TIME_INT, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.MaxTimeInterval)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_MIN_TIME_INT, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.MinTimeInterval)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_EXCEPTION_DEV, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.ExceptionDeviation)); - pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_EXCEPTION_DEV_TYPE, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.ExceptionDeviationFormat)); - - BrowsePathResultCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.TranslateBrowsePathsToNodeIds( - null, - pathsToRead, - out results, - out diagnosticInfos); - - Session.ValidateResponse(results, pathsToRead); - Session.ValidateDiagnosticInfos(diagnosticInfos, pathsToRead); - - for (int ii = 0; ii < pathsToRead.Count; ii++) - { - uint attributeId = (uint)pathsToRead[ii].Handle; - - // path does not exist. - if (StatusCode.IsBad(results[ii].StatusCode)) - { - continue; - } - - // nothing found. - if (results[ii].Targets.Count == 0) - { - continue; - } - - // choose the first valid target. - for (int jj = 0; jj < results[ii].Targets.Count; jj++) - { - BrowsePathTarget target = results[ii].Targets[jj]; - - if (target.RemainingPathIndex == UInt32.MaxValue && !NodeId.IsNull(target.TargetId) && !target.TargetId.IsAbsolute) - { - supportedAttributes.Add(Construct((NodeId)target.TargetId, attributeId, Attributes.Value)); - break; - } - } - } - - return supportedAttributes; - } - - /// - /// Gets the read value id for the specified attribute. - /// - /// The supported attributes. - /// The attribute id. - /// - private ReadValueId GetReadValueId(ReadValueIdCollection supportedAttributes, uint attributeId) - { - for (int jj = 0; jj < supportedAttributes.Count; jj++) - { - ReadValueId valueToRead = supportedAttributes[jj]; - - if ((uint)valueToRead.Handle == attributeId) - { - return valueToRead; - } - } - - return null; - } - - /// - /// Reads the current values for the specified attributes. - /// - /// The session. - /// The item handle. - /// The attribute ids. - /// - public DaValue[] ReadCurrentValues(Session session, HdaItemHandle itemHandle, uint[] attributeIds) - { - DaValue[] results = new DaValue[attributeIds.Length]; - - // check handle. - InternalHandle handle = itemHandle as InternalHandle; - - if (handle == null) - { - for (int ii = 0; ii < results.Length; ii++) - { - results[ii] = new DaValue(); - results[ii].Error = ResultIds.E_INVALIDHANDLE; - } - - return results; - } - - // look up the supported attributes for an item. - ReadValueIdCollection supportedAttributes = handle.Item.SupportedAttributes; - - if (supportedAttributes == null) - { - handle.Item.SupportedAttributes = supportedAttributes = GetAvailableAttributes(session, handle.NodeId); - } - - // build list of values to read. - ReadValueIdCollection valuesToRead = new ReadValueIdCollection(); - List indexes = new List(); - - for (int ii = 0; ii < attributeIds.Length; ii++) - { - ReadValueId valueToRead = GetReadValueId(supportedAttributes, attributeIds[ii]); - - if (valueToRead == null) - { - results[ii] = new DaValue(); - results[ii].Error = ResultIds.E_INVALIDATTRID; - continue; - } - - valuesToRead.Add(valueToRead); - indexes.Add(ii); - - // need to fetch the value rank as well. - if (attributeIds[ii] == Constants.OPCHDA_DATA_TYPE) - { - valuesToRead.Add(GetReadValueId(supportedAttributes, ComHdaProxy.INTERNAL_ATTRIBUTE_VALUE_RANK)); - indexes.Add(-1); - } - } - - // nothing to do. - if (valuesToRead.Count == 0) - { - return results; - } - - // read values from the UA server. - DataValueCollection values = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.Read( - null, - 0, - TimestampsToReturn.Neither, - valuesToRead, - out values, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(values, valuesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToRead); - - // assign a local handle to all valid items. - for (int ii = 0; ii < valuesToRead.Count; ii++) - { - int index = indexes[ii]; - uint attributeId = (uint)valuesToRead[ii].Handle; - - // check for values which are combined with other values to create the value (e.g. ValueRank). - if (index == -1) - { - continue; - } - - results[index] = GetAttributeValue(session, attributeId, values, ii); - - // only support current value for now. - if (results[index].Error == ResultIds.S_OK) - { - results[index].Error = ResultIds.S_CURRENTVALUE; - } - } - - return results; - } - - /// - /// Reads the node ids used to fetch the history of the specified attributes. - /// - /// The session. - /// The item handle. - /// The attribute ids. - /// The node ids. - /// - public int[] GetAttributeHistoryNodeIds(Session session, HdaItemHandle itemHandle, uint[] attributeIds, out NodeId[] nodeIds) - { - nodeIds = new NodeId[attributeIds.Length]; - int[] results = new int[attributeIds.Length]; - - // check handle. - InternalHandle handle = itemHandle as InternalHandle; - - if (handle == null) - { - for (int ii = 0; ii < results.Length; ii++) - { - results[ii] = ResultIds.E_INVALIDHANDLE; - } - - return results; - } - - // look up the supported attributes for an item. - ReadValueIdCollection supportedAttributes = handle.Item.SupportedAttributes; - - if (supportedAttributes == null) - { - handle.Item.SupportedAttributes = supportedAttributes = GetAvailableAttributes(session, handle.NodeId); - } - - // build list of values to read. - ReadValueIdCollection valuesToRead = new ReadValueIdCollection(); - - for (int ii = 0; ii < attributeIds.Length; ii++) - { - ReadValueId valueToRead = GetReadValueId(supportedAttributes, attributeIds[ii]); - - if (valueToRead == null) - { - results[ii] = ResultIds.E_INVALIDATTRID; - continue; - } - - if (valueToRead.AttributeId == Attributes.Value) - { - nodeIds[ii] = valueToRead.NodeId; - results[ii] = ResultIds.S_OK; - } - else - { - results[ii] = ResultIds.S_NODATA; - } - } - - return results; - } - - /// - /// Gets the annotations property node id. - /// - /// The session. - /// The item handle. - /// - public NodeId GetAnnotationsPropertyNodeId(Session session, HdaItemHandle itemHandle) - { - // check handle. - InternalHandle handle = itemHandle as InternalHandle; - - if (handle == null) - { - return null; - } - - // look up the supported attributes for an item. - ReadValueIdCollection supportedAttributes = handle.Item.SupportedAttributes; - - if (supportedAttributes == null) - { - handle.Item.SupportedAttributes = supportedAttributes = GetAvailableAttributes(session, handle.NodeId); - } - - // check if annotations are supported. - ReadValueId valueToRead = GetReadValueId(supportedAttributes, ComHdaProxy.INTERNAL_ATTRIBUTE_ANNOTATION); - - if (valueToRead == null) - { - return null; - } - - // return node id. - return valueToRead.NodeId; - } - - /// - /// Converts a UA value to an HDA attribute value. - /// - /// The session. - /// The attribute id. - /// The values. - /// The index. - /// - private DaValue GetAttributeValue(Session session, uint attributeId, DataValueCollection values, int index) - { - switch (attributeId) - { - case Constants.OPCHDA_DATA_TYPE: - { - DaValue result = new DaValue(); - DataValue value = values[index]; - - // check for valid node. - if (StatusCode.IsBad(value.StatusCode)) - { - result.Error = ResultIds.E_UNKNOWNITEMID; - return result; - } - - // covert to var type. - NodeId dataTypeId = value.GetValue(DataTypeIds.BaseDataType); - int valueRank = values[index+1].GetValue(ValueRanks.Scalar); - - BuiltInType builtInType = DataTypes.GetBuiltInType(dataTypeId, session.TypeTree); - TypeInfo typeInfo = new TypeInfo(builtInType, valueRank); - short varType = (short)ComUtils.GetVarType(typeInfo); - - result.Value = varType; - result.Quality = ComUtils.GetQualityCode(value.StatusCode); - result.Timestamp = value.ServerTimestamp; - result.Error = ResultIds.S_OK; - - return result; - } - - case Constants.OPCHDA_DESCRIPTION: - { - DataValue value = values[index]; - - if (value.StatusCode == StatusCodes.BadAttributeIdInvalid) - { - DaValue result = new DaValue(); - result.Error = ResultIds.E_INVALIDATTRID; - return result; - } - - return m_mapper.GetLocalDataValue(value); - } - - default: - { - return ComHdaProxy.GetAttributeValue(session, m_mapper, attributeId, values[index]); - } - } - } - - /// - /// Lookups the handle. - /// - /// The server handle. - /// - public HdaItemHandle LookupHandle(int serverHandle) - { - lock (m_lock) - { - InternalHandle handle = null; - - if (!m_handles.TryGetValue(serverHandle, out handle)) - { - return null; - } - - return handle; - } - } - - /// - /// Releases the item handles. - /// - /// The session. - /// The server handles. - /// - public int[] ReleaseItemHandles(Session session, int[] serverHandles) - { - int[] errors = new int[serverHandles.Length]; - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - InternalHandle handle = null; - - lock (m_lock) - { - if (!m_handles.TryGetValue(serverHandles[ii], out handle)) - { - errors[ii] = ResultIds.E_INVALIDHANDLE; - continue; - } - - Utils.Trace("Released Handle: {0} {1}", handle.ServerHandle, handle.NodeId); - m_handles.Remove(handle.ServerHandle); - handle.Item.Refs--; - } - - errors[ii] = ResultIds.S_OK; - } - - return errors; - } - - /// - /// Gets the item handles. - /// - /// The session. - /// The item ids. - /// The client handles. - /// if set to true handles are not created and item ids are only validated. - /// The handles containing any error information. - public HdaItemHandle[] GetItemHandles(Session session, string[] itemIds, int[] clientHandles, bool validateOnly) - { - HdaItemHandle[] handles = new HdaItemHandle[itemIds.Length]; - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); - - for (int ii = 0; ii < itemIds.Length; ii++) - { - InternalHandle handle = new InternalHandle(); - handles[ii] = handle; - - if (clientHandles != null) - { - handle.ClientHandle = clientHandles[ii]; - } - - string itemId = itemIds[ii]; - - if (String.IsNullOrEmpty(itemId)) - { - handle.Error = ResultIds.E_INVALIDITEMID; - continue; - } - - // check if item has already been assigned. - Item item = null; - - if (!validateOnly) - { - lock (m_lock) - { - if (m_items.TryGetValue(itemId, out item)) - { - handle.NodeId = item.NodeId; - handle.ServerHandle = ++m_lastServerHandle; - handle.Item = item; - item.Refs++; - m_handles[handle.ServerHandle] = handle; - Utils.Trace("Created Handle: {0} {1}", handle.ServerHandle, handle.NodeId); - continue; - } - } - } - - // create a new item. - handle.Item = item = new Item(); - item.ItemId = itemId; - handle.Error = ResultIds.S_OK; // assume valid for no - set to an error when detected. - - handle.NodeId = item.NodeId = m_mapper.GetRemoteNodeId(itemId); - - nodesToRead.Add(Construct(handle, Attributes.UserAccessLevel)); - nodesToRead.Add(Construct(handle, Attributes.DisplayName)); - nodesToRead.Add(Construct(handle, Attributes.Description)); - nodesToRead.Add(Construct(handle, Attributes.DataType)); - nodesToRead.Add(Construct(handle, Attributes.ValueRank)); - nodesToRead.Add(Construct(handle, Attributes.Historizing)); - } - - // check if nothing to do. - if (nodesToRead.Count == 0) - { - return handles; - } - - DataValueCollection values = null; - DiagnosticInfoCollection diagnosticInfos = null; - - // read values from the UA server. - session.Read( - null, - 0, - TimestampsToReturn.Neither, - nodesToRead, - out values, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(values, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - - // assign a local handle to all valid items. - NodeIdCollection nodesToRegister = new NodeIdCollection(); - List items = new List(); - - for (int ii = 0; ii < nodesToRead.Count; ii++) - { - InternalHandle handle = (InternalHandle)nodesToRead[ii].Handle; - DataValue value = values[ii]; - Item item = handle.Item; - - // check status codes. - if (StatusCode.IsBad(value.StatusCode)) - { - // description is an optional attribute. - if (nodesToRead[ii].AttributeId != Attributes.Description) - { - handle.Error = ResultIds.E_UNKNOWNITEMID; - } - - continue; - } - - // check access level. - if (nodesToRead[ii].AttributeId == Attributes.UserAccessLevel) - { - byte accessLevel = value.GetValue(AccessLevels.None); - - if ((accessLevel & AccessLevels.HistoryRead) == 0) - { - handle.Error = ResultIds.E_UNKNOWNITEMID; - continue; - } - } - - // save attribute. - switch (nodesToRead[ii].AttributeId) - { - case Attributes.DisplayName: { item.DisplayName = value.GetValue(null); break; } - case Attributes.Description: { item.Description = value.GetValue(null); break; } - case Attributes.DataType: { item.DataType = value.GetValue(null); break; } - case Attributes.ValueRank: { item.ValueRank = value.GetValue(ValueRanks.Scalar); break; } - case Attributes.Historizing: { item.Historizing = value.GetValue(false); break; } - } - - // should have all item metadata when processing the historizing attribute result. - if (nodesToRead[ii].AttributeId == Attributes.Historizing) - { - // check for a fatal error with one or more mandatory attributes. - if (handle.Error != ResultIds.S_OK) - { - continue; - } - - BuiltInType builtInType = DataTypes.GetBuiltInType(item.DataType, session.TypeTree); - item.RemoteType = new TypeInfo(builtInType, item.ValueRank); - - if (!validateOnly) - { - nodesToRegister.Add(item.NodeId); - items.Add(handle); - - lock (m_lock) - { - m_items[handle.Item.ItemId] = handle.Item; - handle.ServerHandle = ++m_lastServerHandle; - handle.NodeId = handle.Item.NodeId; - handle.Item.Refs++; - m_handles[handle.ServerHandle] = handle; - Utils.Trace("Created Handle: {0} {1}", handle.ServerHandle, handle.NodeId); - } - } - } - } - - return handles; - } - - private class InternalHandle : HdaItemHandle - { - public Item Item; - } - - private class Item - { - public string ItemId; - public NodeId NodeId; - public LocalizedText DisplayName; - public LocalizedText Description; - public NodeId DataType; - public int ValueRank; - public bool Historizing; - public ReadValueIdCollection SupportedAttributes; - public int Refs; - public TypeInfo RemoteType; - } - - #region Private Fields - private object m_lock = new object(); - private Dictionary m_items; - private Dictionary m_handles; - private ComNamespaceMapper m_mapper; - private int m_lastServerHandle; - #endregion - } -} diff --git a/ComIOP/Common/Server/Hda/ComHdaProxy.cs b/ComIOP/Common/Server/Hda/ComHdaProxy.cs deleted file mode 100644 index 543a2b76f..000000000 --- a/ComIOP/Common/Server/Hda/ComHdaProxy.cs +++ /dev/null @@ -1,2706 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// A base class for classes that implement an OPC COM specification. - /// - public class ComHdaProxy : ComProxy - { - #region Constructors - /// - /// Initializes a new instance of the class. - /// - public ComHdaProxy() - { - m_mapper = new ComNamespaceMapper(); - m_browseCacheManager = new ComDaBrowseCache(m_mapper); - m_browseManager = new ComDaBrowseManager(m_mapper, m_browseCacheManager); - m_itemManager = new ComHdaItemManager(m_mapper); - m_transactions = new Dictionary(); - } - #endregion - - #region IDisposable Members - /// - /// An overrideable version of the Dispose. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - lock (Lock) - { - // TBD - } - } - - base.Dispose(disposing); - } - #endregion - - #region Overridden Methods - /// - /// Called when a new session is created. - /// - protected override void OnSessionCreated() - { - lock (Lock) - { - // fetch the configuration. - m_configuration = Endpoint.ParseExtension(null); - - if (m_configuration == null) - { - m_configuration = new ComHdaProxyConfiguration(); - } - - Session session = Session; - - // update the mapping and pass the new session to other objects. - m_mapper.Initialize(session, m_configuration); - - // update the aggregate mappings. - UpdateAggregateMappings(session); - - // save the configuration. - Endpoint.UpdateExtension(null, m_configuration); - SaveConfiguration(); - } - } - - /// - /// Called when a session is reconnected. - /// - protected override void OnSessionReconected() - { - // TBD - } - #endregion - - #region HDA Aggregate Support - /// - /// Gets the supported aggregates. - /// - /// - public List GetSupportedAggregates() - { - return m_aggregates; - } - - /// - /// Updates the aggregate mappings. - /// - /// The session. - private void UpdateAggregateMappings(Session session) - { - // get the list of supported aggregates. - NodeId objectId = GetAggregateFunctionsObjectId(session); - - // create the updated mapping set. - NodeIdMappingSet mappingSet = new NodeIdMappingSet(); - mappingSet.MappingType = Opc.Ua.BrowseNames.AggregateFunctions; - mappingSet.Mappings = new NodeIdMappingCollection(); - - List aggregates = GetAggregateFunctions(session, objectId); - - // check for unassigned aggregate ids. - uint maxId = 0x80000000; - - for (int ii = 0; ii < aggregates.Count; ii++) - { - if (aggregates[ii].LocalId != 0) - { - if (maxId < aggregates[ii].LocalId) - { - maxId = aggregates[ii].LocalId; - } - - continue; - } - } - - // assign aggregate ids. - for (int ii = 0; ii < aggregates.Count; ii++) - { - // assign a new id. - if (aggregates[ii].LocalId == 0) - { - aggregates[ii].LocalId = maxId++; - } - - // do not add mapping for built-in annotations. - if (aggregates[ii].LocalId <= (uint)OpcRcw.Hda.OPCHDA_AGGREGATE.OPCHDA_ANNOTATIONS) - { - continue; - } - - NodeIdMapping mapping = new NodeIdMapping(); - - mapping.NodeId = m_mapper.GetLocalItemId(aggregates[ii].RemoteId); - mapping.IntegerId = aggregates[ii].LocalId; - - mappingSet.Mappings.Add(mapping); - } - - // update descriptions. - UpdateAggregateDescriptions(session, aggregates); - - // update configuration. - if (m_configuration.MappingSets == null) - { - m_configuration.MappingSets = new NodeIdMappingSetCollection(); - } - - // replace existing set. - for (int ii = 0; ii < m_configuration.MappingSets.Count; ii++) - { - if (m_configuration.MappingSets[ii].MappingType == Opc.Ua.BrowseNames.AggregateFunctions) - { - m_configuration.MappingSets[ii] = mappingSet; - mappingSet = null; - break; - } - } - - // add a new set. - if (mappingSet != null) - { - // update the configuration. - m_configuration.MappingSets.Add(mappingSet); - - // update the mapping table. - m_mapper.UpdateMappingSet(mappingSet); - } - - m_aggregates = aggregates; - } - - /// - /// Gets the aggregate functions object id. - /// - /// The session. - /// The node id. - private NodeId GetAggregateFunctionsObjectId(Session session) - { - // build the list of browse paths to follow by parsing the relative paths. - BrowsePathCollection browsePaths = m_mapper.GetRemoteBrowsePaths( - Opc.Ua.ObjectIds.Server_ServerCapabilities, - "/HistoryServerCapabilities/AggregateFunctions"); - - // make the call to the server. - BrowsePathResultCollection results; - DiagnosticInfoCollection diagnosticInfos; - - ResponseHeader responseHeader = session.TranslateBrowsePathsToNodeIds( - null, - browsePaths, - out results, - out diagnosticInfos); - - // ensure that the server returned valid results. - Session.ValidateResponse(results, browsePaths); - Session.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); - - NodeId aggregateFunctionsNodeId = Opc.Ua.ObjectIds.Server_ServerCapabilities_AggregateFunctions; - - for (int ii = 0; ii < results.Count; ii++) - { - // check if the start node actually exists. - if (StatusCode.IsBad(results[ii].StatusCode)) - { - Utils.Trace("HistoryServer does not provide the ServerCapabilities object."); - continue; - } - - // an empty list is returned if no node was found. - if (results[ii].Targets.Count == 0) - { - Utils.Trace("HistoryServer does not provide the AggregateFunctions folder."); - continue; - } - - // Multiple matches are possible, however, the node that matches the type model is the - // one we are interested in here. The rest can be ignored. - BrowsePathTarget target = results[ii].Targets[0]; - - if (target.RemainingPathIndex != UInt32.MaxValue || target.TargetId.IsAbsolute) - { - Utils.Trace("HistoryServer does not provide the AggregateFunctions folder."); - continue; - } - - // convert to a local node. - aggregateFunctionsNodeId = ExpandedNodeId.ToNodeId(target.TargetId, session.NamespaceUris); - } - - return aggregateFunctionsNodeId; - } - - /// - /// Gets the aggregate functions object id. - /// - /// The session. - /// The object id. - /// The node id. - private List GetAggregateFunctions(Session session, NodeId objectId) - { - Browser browser = new Browser(session); - - browser.BrowseDirection = BrowseDirection.Forward; - browser.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HierarchicalReferences; - browser.IncludeSubtypes = true; - browser.NodeClassMask = (int)NodeClass.Object; - browser.ResultMask = (uint)(BrowseResultMask.DisplayName | BrowseResultMask.BrowseName | BrowseResultMask.TypeDefinition); - browser.ContinueUntilDone = true; - - ReferenceDescriptionCollection references = browser.Browse(objectId); - - List aggregates = new List(); - - for (int ii = 0; ii < references.Count; ii++) - { - ReferenceDescription reference = references[ii]; - - if (reference.TypeDefinition != Opc.Ua.ObjectTypeIds.AggregateFunctionType) - { - continue; - } - - HdaAggregate aggregate = new HdaAggregate(); - - NodeId remoteId = (NodeId)reference.NodeId; - - aggregate.RemoteId = remoteId; - aggregate.LocalId = ComUtils.GetHdaAggregateId(remoteId); - aggregate.Name = reference.ToString(); - aggregate.Description = null; - - // check for previously mapped ids. - if (aggregate.LocalId == 0) - { - aggregate.LocalId = m_mapper.GetLocalIntegerIdMapping(Opc.Ua.BrowseNames.AggregateFunctions, remoteId); - } - - aggregates.Add(aggregate); - } - - return aggregates; - } - - /// - /// Updates the aggregate descriptions. - /// - /// The session. - /// The aggregates. - private void UpdateAggregateDescriptions(Session session, List aggregates) - { - ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); ; - - for (int ii = 0; ii < aggregates.Count; ii++) - { - HdaAggregate aggregate = aggregates[ii]; - - ReadValueId nodeToRead = new ReadValueId(); - nodeToRead.NodeId = aggregate.RemoteId; - nodeToRead.AttributeId = Attributes.Description; - nodesToRead.Add(nodeToRead); - } - - DataValueCollection values = null; - DiagnosticInfoCollection diagnosticInfos = null; - - // read values from the UA server. - ResponseHeader responseHeader = session.Read( - null, - 0, - TimestampsToReturn.Neither, - nodesToRead, - out values, - out diagnosticInfos); - - // validate response from the UA server. - ClientBase.ValidateResponse(values, nodesToRead); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - - for (int ii = 0; ii < aggregates.Count; ii++) - { - HdaAggregate aggregate = aggregates[ii]; - - if (StatusCode.IsBad(values[ii].StatusCode)) - { - aggregate.Description = null; - continue; - } - - aggregate.Description = values[ii].WrappedValue.ToString(); - } - } - #endregion - - #region HDA Server Support - /// - /// Gets the max return values. - /// - /// The max return values. - public int MaxReturnValues - { - get - { - if (m_configuration == null) - { - return 0; - } - - return m_configuration.MaxReturnValues; - } - } - - /// - /// Creates a new browser. - /// - public ComHdaBrowser CreateBrowser() - { - ThrowIfNotConnected(); - return new ComHdaBrowser(this, m_browseManager); - } - - /// - /// Sets the callback. - /// - /// The callback. - public void SetCallback(IComHdaDataCallback callback) - { - ThrowIfNotConnected(); - - lock (Lock) - { - if (m_callback != null) - { - m_callback.Dispose(); - m_callback = null; - } - - m_callback = callback; - } - } - - /// - /// Determines whether the server supports the specified HDA attribute. - /// - /// The attribute id. - /// - /// true if the server supports the specified HDA attribute; otherwise, false. - /// - public bool IsSupportedAttribute(uint attributeId) - { - switch (attributeId) - { - case OpcRcw.Hda.Constants.OPCHDA_DATA_TYPE: - case OpcRcw.Hda.Constants.OPCHDA_DESCRIPTION: - case OpcRcw.Hda.Constants.OPCHDA_ARCHIVING: - case OpcRcw.Hda.Constants.OPCHDA_ITEMID: - case OpcRcw.Hda.Constants.OPCHDA_ENG_UNITS: - case OpcRcw.Hda.Constants.OPCHDA_DERIVE_EQUATION: - case OpcRcw.Hda.Constants.OPCHDA_NORMAL_MAXIMUM: - case OpcRcw.Hda.Constants.OPCHDA_NORMAL_MINIMUM: - case OpcRcw.Hda.Constants.OPCHDA_HIGH_ENTRY_LIMIT: - case OpcRcw.Hda.Constants.OPCHDA_LOW_ENTRY_LIMIT: - case OpcRcw.Hda.Constants.OPCHDA_STEPPED: - case OpcRcw.Hda.Constants.OPCHDA_MAX_TIME_INT: - case OpcRcw.Hda.Constants.OPCHDA_MIN_TIME_INT: - case OpcRcw.Hda.Constants.OPCHDA_EXCEPTION_DEV: - case OpcRcw.Hda.Constants.OPCHDA_EXCEPTION_DEV_TYPE: - { - return true; - } - } - - return false; - } - - /// - /// Creates handles for the items. - /// - /// The item ids. - /// The client handles. - /// The handle. - public HdaItemHandle[] GetItemHandles(string[] itemIds, int[] clientHandles) - { - Session session = ThrowIfNotConnected(); - return m_itemManager.GetItemHandles(session, itemIds, clientHandles, false); - } - - /// - /// Releases the item handles. - /// - /// The server handles. - /// The error associated with each handle. - public int[] ReleaseItemHandles(int[] serverHandles) - { - Session session = ThrowIfNotConnected(); - return m_itemManager.ReleaseItemHandles(session, serverHandles); - } - - /// - /// Validates the item ids. - /// - /// The item ids. - /// The error associated with each item id. - public int[] ValidateItemIds(string[] itemIds) - { - Session session = ThrowIfNotConnected(); - - HdaItemHandle[] handles = m_itemManager.GetItemHandles(session, itemIds, null, true); - - int[] errors = new int[handles.Length]; - - for (int ii = 0; ii < handles.Length; ii++) - { - errors[ii] = handles[ii].Error; - } - - return errors; - } - #endregion - - #region Read Raw - /// - /// Reads the raw data. - /// - /// The start time. - /// The end time. - /// The num values. - /// if set to true the bounds should be returned. - /// The server handles. - /// The results. - public List ReadRaw( - DateTime startTime, - DateTime endTime, - uint numValues, - bool returnBounds, - int[] serverHandles) - { - Session session = ThrowIfNotConnected(); - - ReadRawModifiedDetails details = new ReadRawModifiedDetails(); - - // create the read requests. - List requests = CreateReadRequests( - session, - startTime, - endTime, - numValues, - returnBounds, - serverHandles, - details); - - ExtensionObject extension = new ExtensionObject(details); - - // fetch all of the values. - if (ReadNext(session, extension, requests, false)) - { - ReadNext(session, extension, requests, true); - } - - return requests; - } - - /// - /// Reads the raw data. - /// - public int[] ReadRaw( - int transactionId, - DateTime startTime, - DateTime endTime, - uint numValues, - bool returnBounds, - int[] serverHandles, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - ReadRawModifiedDetails details = new ReadRawModifiedDetails(); - - // create the read requests. - List requests = CreateReadRequests( - session, - startTime, - endTime, - numValues, - returnBounds, - serverHandles, - details); - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.Read, - transactionId, - new ExtensionObject(details), - requests, - false, - out cancelId); - - // return the initial results. - return errors; - } - - /// - /// Cancels the asynchronous operation. - /// - public int Cancel(int cancelId) - { - lock (Lock) - { - Transaction transaction = null; - - if (!m_transactions.TryGetValue(cancelId, out transaction)) - { - return ResultIds.E_FAIL; - } - - m_transactions.Remove(cancelId); - ThreadPool.QueueUserWorkItem(DoCancel, transaction); - return ResultIds.S_OK; - } - } - - /// - /// Executes an asynchronous cancel operation. - /// - private void DoCancel(object state) - { - Transaction transaction = (Transaction)state; - - try - { - IComHdaDataCallback callback = m_callback; - - if (callback != null) - { - callback.OnCancelComplete(transaction.TransactionId); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error sending cancel callback."); - } - } - - /// - /// Creates the read requests. - /// - private List CreateReadRequests( - Session session, - DateTime startTime, - DateTime endTime, - uint numValues, - bool returnBounds, - int[] serverHandles, - ReadRawModifiedDetails details) - { - // start time or end time must be specified. - if (startTime == DateTime.MinValue && endTime == DateTime.MinValue) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // num values must be specified if start or end time is missing. - if (numValues == 0 && (startTime == DateTime.MinValue || endTime == DateTime.MinValue)) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // can't exceed the limits imposed by the server configuration. - if (m_configuration.MaxReturnValues > 0 && numValues > m_configuration.MaxReturnValues) - { - throw ComUtils.CreateComException(ResultIds.E_MAXEXCEEDED); - } - - details.StartTime = startTime; - details.EndTime = endTime; - details.IsReadModified = false; - details.NumValuesPerNode = numValues; - details.ReturnBounds = returnBounds; - - // build the list of requests. - List requests = new List(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - HdaReadRequest request = new HdaReadRequest(); - requests.Add(request); - - // look up server handle. - request.Handle = m_itemManager.LookupHandle(serverHandles[ii]); - - if (request.Handle == null) - { - request.Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - // initialize request. - request.NodeId = request.Handle.NodeId; - request.ClientHandle = request.Handle.ClientHandle; - } - - return requests; - } - - /// - /// Creates and queues a new transaction. - /// - private int[] CreateTransaction( - TransationType transationType, - int transactionId, - ExtensionObject details, - List requests, - bool asyncReportErrors, - out int cancelId) - { - - lock (Lock) - { - cancelId = ++m_lastCancelId; - - // create the transaction. - ReadRequestTransaction transaction = new ReadRequestTransaction(); - - transaction.TransationType = transationType; - transaction.TransactionId = transactionId; - transaction.CancelId = cancelId; - transaction.Details = details; - transaction.Requests = new List(); - - // keep only the valid requests. - int[] errors = new int[requests.Count]; - - for (int ii = 0; ii < requests.Count; ii++) - { - if (!asyncReportErrors) - { - errors[ii] = requests[ii].Error; - - if (errors[ii] < 0) - { - continue; - } - } - - transaction.Requests.Add(requests[ii]); - } - - // queue the transaction. - if (transaction.Requests.Count > 0) - { - m_transactions.Add(transaction.CancelId, transaction); - ThreadPool.QueueUserWorkItem(DoRead, transaction); - } - - // return the error list. - return errors; - } - } - - /// - /// Executes an asynchronous read operation. - /// - private void DoRead(object state) - { - Session session = null; - ReadRequestTransaction transaction = (ReadRequestTransaction)state; - - try - { - bool done = false; - - while (!done) - { - // check if the transaction is still active. - lock (Lock) - { - if (!m_transactions.ContainsKey(transaction.CancelId)) - { - break; - } - - session = Session; - } - - // check for session error. - if (session == null) - { - for (int ii = 0; ii < transaction.Requests.Count; ii++) - { - transaction.Requests[ii].Error = ResultIds.E_FAIL; - } - - SendCallback(transaction.TransactionId, transaction.TransationType, transaction.Requests); - break; - } - - // fetch next batch. - if (transaction.TransationType == TransationType.ReadAttribute) - { - done = !ReadAttributes(session, transaction.Details, transaction.Requests, false); - } - else - { - done = !ReadNext(session, transaction.Details, transaction.Requests, false); - } - - // send data to client. - SendCallback(transaction.TransactionId, transaction.TransationType, transaction.Requests); - - // remove values that were sent. - for (int ii = 0; ii < transaction.Requests.Count; ii++) - { - transaction.Requests[ii].Values.Clear(); - - if (transaction.Requests[ii].ModificationInfos != null) - { - transaction.Requests[ii].ModificationInfos.Clear(); - } - } - } - - // release continuation points. - if (!done && session != null) - { - ReadNext(session, transaction.Details, transaction.Requests, true); - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error reading history."); - } - finally - { - // remove transaction. - lock (Lock) - { - m_transactions.Remove(transaction.CancelId); - } - } - } - - /// - /// Sends the callback for a read request. - /// - private bool SendCallback( - int transactionId, - TransationType transactionType, - List requests) - { - try - { - IComHdaDataCallback callback = m_callback; - - if (callback == null) - { - return false; - } - - switch (transactionType) - { - case TransationType.Read: - { - callback.OnReadComplete(transactionId, requests); - break; - } - - case TransationType.ReadModified: - { - callback.OnReadModifiedComplete(transactionId, requests); - break; - } - - case TransationType.ReadAttribute: - { - callback.OnReadAttributeComplete(transactionId, requests); - break; - } - - case TransationType.ReadAnnotation: - { - callback.OnReadAnnotations(transactionId, requests); - break; - } - } - - return true; - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error sending callback to HDA client."); - return false; - } - } - #endregion - - #region Read Modified - /// - /// Reads the modified data. - /// - public List ReadModified( - DateTime startTime, - DateTime endTime, - uint numValues, - int[] serverHandles) - { - Session session = ThrowIfNotConnected(); - - ReadRawModifiedDetails details = new ReadRawModifiedDetails(); - - // create the read requests. - List requests = CreateReadRequests( - session, - startTime, - endTime, - numValues, - false, - serverHandles, - details); - - details.IsReadModified = true; - - for (int ii = 0; ii < requests.Count; ii++) - { - requests[ii].ModificationInfos = new List(); - } - - ExtensionObject extension = new ExtensionObject(details); - - // fetch all of the values. - if (ReadNext(session, extension, requests, false)) - { - ReadNext(session, extension, requests, true); - } - - return requests; - } - - /// - /// Reads the modified data. - /// - public int[] ReadModified( - int transactionId, - DateTime startTime, - DateTime endTime, - uint numValues, - int[] serverHandles, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - ReadRawModifiedDetails details = new ReadRawModifiedDetails(); - - // create the read requests. - List requests = CreateReadRequests( - session, - startTime, - endTime, - numValues, - false, - serverHandles, - details); - - details.IsReadModified = true; - - for (int ii = 0; ii < requests.Count; ii++) - { - requests[ii].ModificationInfos = new List(); - } - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.ReadModified, - transactionId, - new ExtensionObject(details), - requests, - false, - out cancelId); - - // return the initial results. - return errors; - } - #endregion - - #region Read Processed - /// - /// Reads the processed data. - /// - public List ReadProcessed( - DateTime startTime, - DateTime endTime, - long resampleInterval, - int[] serverHandles, - uint[] aggregateIds) - { - Session session = ThrowIfNotConnected(); - - // create the read requests. - ReadProcessedDetails details = new ReadProcessedDetails(); - - List requests = CreateReadRequests( - session, - startTime, - endTime, - resampleInterval, - serverHandles, - aggregateIds, - details); - - ExtensionObject extension = new ExtensionObject(details); - - // fetch all of the values. - if (ReadNext(session, extension, requests, false)) - { - ReadNext(session, extension, requests, true); - } - - - return requests; - } - - /// - /// Reads the processed data. - /// - public int[] ReadProcessed( - int transactionId, - DateTime startTime, - DateTime endTime, - long resampleInterval, - int[] serverHandles, - uint[] aggregateIds, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - // create the read requests. - ReadProcessedDetails details = new ReadProcessedDetails(); - - List requests = CreateReadRequests( - session, - startTime, - endTime, - resampleInterval, - serverHandles, - aggregateIds, - details); - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.Read, - transactionId, - new ExtensionObject(details), - requests, - false, - out cancelId); - - // return the initial results. - return errors; - } - - /// - /// Creates the read requests. - /// - private List CreateReadRequests( - Session session, - DateTime startTime, - DateTime endTime, - double resampleInterval, - int[] serverHandles, - uint[] aggregateIds, - ReadProcessedDetails details) - { - // start time or end time must be specified. - if (startTime == DateTime.MinValue || endTime == DateTime.MinValue || startTime == endTime || resampleInterval < 0) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // check the number of intervals. - if (m_configuration.MaxReturnValues > 0 && resampleInterval != 0) - { - long range = Math.Abs(((endTime - startTime).Ticks)); - - if (range/(TimeSpan.TicksPerMillisecond*resampleInterval) > m_configuration.MaxReturnValues) - { - throw ComUtils.CreateComException(ResultIds.E_MAXEXCEEDED); - } - } - - details.StartTime = startTime; - details.EndTime = endTime; - details.ProcessingInterval = resampleInterval; - - // build the list of requests. - List requests = new List(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - HdaReadRequest request = new HdaReadRequest(); - requests.Add(request); - - // initialize request. - request.AggregateId = aggregateIds[ii]; - - // look up server handle. - request.Handle = m_itemManager.LookupHandle(serverHandles[ii]); - - if (request.Handle == null) - { - request.Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - // set node id to use. - request.NodeId = request.Handle.NodeId; - request.ClientHandle = request.Handle.ClientHandle; - - // check aggregate. - NodeId aggregateId = ComUtils.GetHdaAggregateId(aggregateIds[ii]); - - if (aggregateId == null) - { - aggregateId = m_mapper.GetRemoteIntegerIdMapping(Opc.Ua.BrowseNames.AggregateFunctions, aggregateIds[ii]); - } - - if (aggregateId == null) - { - request.Error = ResultIds.E_NOT_AVAIL; - continue; - } - - details.AggregateType.Add(aggregateId); - } - - return requests; - } - #endregion - - #region Advise Processed - #endregion - - #region Read At Time - /// - /// Reads the data at the specified times. - /// - public List ReadAtTime( - DateTime[] timestamps, - int[] serverHandles) - { - Session session = ThrowIfNotConnected(); - - // create the read requests. - ReadAtTimeDetails details = new ReadAtTimeDetails(); - - List requests = CreateReadRequests( - session, - timestamps, - serverHandles, - details); - - ExtensionObject extension = new ExtensionObject(details); - - // fetch all of the values. - if (ReadNext(session, extension, requests, false)) - { - ReadNext(session, extension, requests, true); - } - - return requests; - } - - /// - /// Reads the data at the specified times. - /// - public int[] ReadAtTime( - int transactionId, - DateTime[] timestamps, - int[] serverHandles, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - // create the read requests. - ReadAtTimeDetails details = new ReadAtTimeDetails(); - - List requests = CreateReadRequests( - session, - timestamps, - serverHandles, - details); - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.Read, - transactionId, - new ExtensionObject(details), - requests, - false, - out cancelId); - - // return the initial results. - return errors; - } - - /// - /// Creates the read requests. - /// - private List CreateReadRequests( - Session session, - DateTime[] timestamps, - int[] serverHandles, - ReadAtTimeDetails details) - { - if (m_configuration.MaxReturnValues > 0 && timestamps.Length > m_configuration.MaxReturnValues) - { - throw ComUtils.CreateComException(ResultIds.E_MAXEXCEEDED); - } - - details.ReqTimes.AddRange(timestamps); - - // build the list of requests. - List requests = new List(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - HdaReadRequest request = new HdaReadRequest(); - requests.Add(request); - - // look up server handle. - request.Handle = m_itemManager.LookupHandle(serverHandles[ii]); - - if (request.Handle == null) - { - request.Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - // set node id to use. - request.NodeId = request.Handle.NodeId; - request.ClientHandle = request.Handle.ClientHandle; - } - - return requests; - } - #endregion - - #region Read Annotations - /// - /// Reads the annotations. - /// - public List ReadAnnotations( - DateTime startTime, - DateTime endTime, - int[] serverHandles) - { - Session session = ThrowIfNotConnected(); - - // create the read requests. - ReadRawModifiedDetails details = new ReadRawModifiedDetails(); - - List requests = CreateReadRequests( - session, - startTime, - endTime, - serverHandles, - details); - - ExtensionObject extension = new ExtensionObject(details); - - // fetch all of the values. - if (ReadNext(session, extension, requests, false)) - { - ReadNext(session, extension, requests, true); - } - - return requests; - } - - /// - /// Reads the annotations. - /// - public int[] ReadAnnotations( - int transactionId, - DateTime startTime, - DateTime endTime, - int[] serverHandles, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - // create the read requests. - ReadRawModifiedDetails details = new ReadRawModifiedDetails(); - - List requests = CreateReadRequests( - session, - startTime, - endTime, - serverHandles, - details); - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.ReadAnnotation, - transactionId, - new ExtensionObject(details), - requests, - false, - out cancelId); - - // return the initial results. - return errors; - } - - /// - /// Creates the read requests. - /// - private List CreateReadRequests( - Session session, - DateTime startTime, - DateTime endTime, - int[] serverHandles, - ReadRawModifiedDetails details) - { - if (startTime == DateTime.MinValue || endTime == DateTime.MinValue) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // specify the parameters for the request. - details.StartTime = startTime; - details.EndTime = endTime; - details.IsReadModified = false; - details.NumValuesPerNode = 0; - details.ReturnBounds = false; - - // build the list of requests. - List requests = new List(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - HdaReadRequest request = new HdaReadRequest(); - requests.Add(request); - - // initialize request. - request.AttributeId = INTERNAL_ATTRIBUTE_ANNOTATION; - - // look up server handle. - request.Handle = m_itemManager.LookupHandle(serverHandles[ii]); - - if (request.Handle == null) - { - request.Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - request.ClientHandle = request.Handle.ClientHandle; - - // look up annotation property. - NodeId annotationsId = m_itemManager.GetAnnotationsPropertyNodeId(session, request.Handle); - - if (NodeId.IsNull(annotationsId)) - { - request.Error = ResultIds.S_NODATA; - continue; - } - - // set node id. - request.NodeId = annotationsId; - } - - return requests; - } - #endregion - - #region Read Attributes - /// - /// Reads the attributes. - /// - public List ReadAttributes( - DateTime startTime, - DateTime endTime, - int serverHandle, - uint[] attributeIds) - { - Session session = ThrowIfNotConnected(); - - // create the read requests. - ReadRawModifiedDetails details = new ReadRawModifiedDetails(); - - List requests = CreateReadRequests( - session, - startTime, - endTime, - serverHandle, - attributeIds, - details); - - ExtensionObject extension = new ExtensionObject(details); - - // fetch all of the values. - if (ReadAttributes(session, extension, requests, false)) - { - ReadNext(session, extension, requests, true); - } - - return requests; - } - - /// - /// Reads the attributes. - /// - public int[] ReadAttributes( - int transactionId, - DateTime startTime, - DateTime endTime, - int serverHandle, - uint[] attributeIds, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - // create the read requests. - ReadRawModifiedDetails details = new ReadRawModifiedDetails(); - - List requests = CreateReadRequests( - session, - startTime, - endTime, - serverHandle, - attributeIds, - details); - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.ReadAttribute, - transactionId, - new ExtensionObject(details), - requests, - true, - out cancelId); - - // return the initial results. - return errors; - } - - /// - /// Creates the read requests. - /// - private List CreateReadRequests( - Session session, - DateTime startTime, - DateTime endTime, - int serverHandle, - uint[] attributeIds, - ReadRawModifiedDetails details) - { - if (startTime == DateTime.MinValue) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // check for the special case where current values are requested. - if (endTime == DateTime.MinValue && startTime.AddSeconds(10) < DateTime.UtcNow) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - // specify the parameters for the request. - details.StartTime = startTime; - details.EndTime = endTime; - details.IsReadModified = false; - details.NumValuesPerNode = 0; - details.ReturnBounds = true; - - // look up server handle. - HdaItemHandle handle = m_itemManager.LookupHandle(serverHandle); - - if (handle == null) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDHANDLE); - } - - // get the node ids for the requested attributes. - NodeId[] nodeIds = null; - - int[] errors = m_itemManager.GetAttributeHistoryNodeIds( - session, - handle, - attributeIds, - out nodeIds); - - // build the list of requests. - List requests = new List(); - - for (int ii = 0; ii < attributeIds.Length; ii++) - { - HdaReadRequest request = new HdaReadRequest(); - requests.Add(request); - - // initialize request. - request.Handle = handle; - request.AttributeId = attributeIds[ii]; - - if (request.Handle == null) - { - request.Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - request.ClientHandle = request.Handle.ClientHandle; - - // check for errors. - if (errors[ii] != ResultIds.S_OK) - { - request.Error = errors[ii]; - request.IsComplete = true; - continue; - } - - request.NodeId = nodeIds[ii]; - } - - return requests; - } - - /// - /// Reads the historical or current value for attributes. - /// - private bool ReadAttributes( - Session session, - ExtensionObject extension, - List requests, - bool releaseContinuationPoints) - { - ReadRawModifiedDetails details = extension.Body as ReadRawModifiedDetails; - - if (details == null) - { - return false; - } - - // check if reading historical values. - if (details.EndTime != DateTime.MinValue) - { - return ReadNext(session, extension, requests, false); - } - - HdaItemHandle handle = null; - List attributeIds = new List(); - List indexes = new List(); - - // build the list of requests. - for (int ii = 0; ii < requests.Count; ii++) - { - HdaReadRequest request = requests[ii]; - - if (request.Error < 0) - { - continue; - } - - // handle should be the same for all. - if (handle == null) - { - handle = request.Handle; - } - - attributeIds.Add(request.AttributeId); - indexes.Add(ii); - } - - // check if nothing to do. - if (attributeIds.Count == 0) - { - return false; - } - - // reads the current values for all requested attributes. - DaValue[] values = m_itemManager.ReadCurrentValues(session, handle, attributeIds.ToArray()); - - // build the list of requests. - for (int ii = 0; ii < attributeIds.Count; ii++) - { - HdaReadRequest request = requests[indexes[ii]]; - - if (values[ii].Error < 0) - { - request.Error = values[ii].Error; - } - else - { - request.Values = new List(); - request.Values.Add(values[ii]); - } - - request.IsComplete = true; - } - - return false; - } - #endregion - - #region Update Raw - /// - /// Updates the history. - /// - public int[] UpdateRaw( - PerformUpdateType updateType, - int[] serverHandles, - DaValue[] values) - { - Session session = ThrowIfNotConnected(); - - // create the update requests. - List requests = CreateUpdateRequests( - session, - updateType, - serverHandles, - values); - - // update the server. - return UpdateHistory(session, requests, true); - } - - /// - /// Updates the history. - /// - public int[] UpdateRaw( - int transactionId, - PerformUpdateType updateType, - int[] serverHandles, - DaValue[] values, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - // create the update requests. - List requests = CreateUpdateRequests( - session, - updateType, - serverHandles, - values); - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.Update, - transactionId, - requests, - out cancelId); - - // return the initial results. - return errors; - } - - /// - /// Creates the update requests. - /// - private List CreateUpdateRequests( - Session session, - PerformUpdateType updateType, - int[] serverHandles, - DaValue[] values) - { - List requests = new List(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - HdaUpdateRequest request = new HdaUpdateRequest(); - requests.Add(request); - - // find handle. - request.Handle = m_itemManager.LookupHandle(serverHandles[ii]); - - if (request.Handle == null) - { - request.Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - request.ClientHandle = request.Handle.ClientHandle; - - // check if nothing to do. - DaValue value = values[ii]; - - if (value == null) - { - request.Error = ResultIds.E_FAIL; - continue; - } - - // specify the parameters for the request. - UpdateDataDetails details = new UpdateDataDetails(); - - details.NodeId = request.Handle.NodeId; - details.PerformInsertReplace = updateType; - - DataValue value2 = m_mapper.GetRemoteDataValue(value, m_itemManager.GetRemoteDataType(request.Handle)); - - value2.SourceTimestamp = value.Timestamp; - value2.StatusCode = ComUtils.GetHdaQualityCode(value.HdaQuality); - - details.UpdateValues.Add(value2); - - request.Details = new ExtensionObject(details); - } - - return requests; - } - - /// - /// Calls the server and updates the history. - /// - private int[] UpdateHistory( - Session session, - List requests, - bool checkOperationError) - { - int[] errors = new int[requests.Count]; - - // build list of nodes to update. - ExtensionObjectCollection nodesToUpdate = new ExtensionObjectCollection(); - List indexes = new List(); - - for (int ii = 0; ii < requests.Count; ii++) - { - if (requests[ii].Error < 0) - { - errors[ii] = requests[ii].Error; - continue; - } - - // check if nothing to do. - if (requests[ii].Details == null) - { - continue; - } - - nodesToUpdate.Add(requests[ii].Details); - indexes.Add(ii); - } - - if (nodesToUpdate.Count == 0) - { - return errors; - } - - // call the server. - HistoryUpdateResultCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.HistoryUpdate( - null, - nodesToUpdate, - out results, - out diagnosticInfos); - - Session.ValidateResponse(results, nodesToUpdate); - Session.ValidateDiagnosticInfos(diagnosticInfos, nodesToUpdate); - - // process results. - for (int ii = 0; ii < nodesToUpdate.Count; ii++) - { - HdaUpdateRequest request = requests[indexes[ii]]; - - request.Error = MapUpdateStatusToErrorCode(results[ii].StatusCode); - - if (checkOperationError) - { - if (StatusCode.IsGood(results[ii].StatusCode)) - { - request.Error = MapUpdateStatusToErrorCode(results[ii].OperationResults[0]); - } - } - - errors[indexes[ii]] = request.Error; - } - - return errors; - } - - /// - /// Creates and queues a new transaction. - /// - private int[] CreateTransaction( - TransationType transationType, - int transactionId, - List requests, - out int cancelId) - { - - lock (Lock) - { - cancelId = ++m_lastCancelId; - - // create the transaction. - UpdateRequestTransaction transaction = new UpdateRequestTransaction(); - - transaction.TransationType = transationType; - transaction.TransactionId = transactionId; - transaction.CancelId = cancelId; - transaction.Requests = new List(); - - // keep only the valid requests. - int[] errors = new int[requests.Count]; - - for (int ii = 0; ii < requests.Count; ii++) - { - errors[ii] = requests[ii].Error; - - if (errors[ii] < 0) - { - continue; - } - - transaction.Requests.Add(requests[ii]); - } - - // queue the transaction. - if (transaction.Requests.Count > 0) - { - m_transactions.Add(transaction.CancelId, transaction); - ThreadPool.QueueUserWorkItem(DoUpdate, transaction); - } - - // return the error list. - return errors; - } - } - - /// - /// Executes an asynchronous update operation. - /// - private void DoUpdate(object state) - { - Session session = null; - UpdateRequestTransaction transaction = (UpdateRequestTransaction)state; - - try - { - // check if the transaction is still active. - lock (Lock) - { - if (!m_transactions.ContainsKey(transaction.CancelId)) - { - return; - } - - session = Session; - } - - // check for session error. - if (session == null) - { - for (int ii = 0; ii < transaction.Requests.Count; ii++) - { - transaction.Requests[ii].Error = ResultIds.E_FAIL; - } - - SendCallback(transaction.TransactionId, transaction.TransationType, transaction.Requests); - return; - } - - // send request to the server. - try - { - switch (transaction.TransationType) - { - case TransationType.Update: - { - UpdateHistory(session, transaction.Requests, true); - break; - } - - case TransationType.DeleteAtTime: - case TransationType.DeleteRaw: - case TransationType.InsertAnnotation: - { - UpdateHistory(session, transaction.Requests, false); - break; - } - } - } - - // handle network error. - catch (Exception) - { - for (int ii = 0; ii < transaction.Requests.Count; ii++) - { - transaction.Requests[ii].Error = ResultIds.E_FAIL; - } - } - - // send data to client. - SendCallback(transaction.TransactionId, transaction.TransationType, transaction.Requests); - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error updating history."); - } - finally - { - // remove transaction. - lock (Lock) - { - m_transactions.Remove(transaction.CancelId); - } - } - } - - /// - /// Sends the callback for a read request. - /// - private bool SendCallback( - int transactionId, - TransationType transactionType, - List requests) - { - try - { - IComHdaDataCallback callback = m_callback; - - if (callback == null) - { - return false; - } - - switch (transactionType) - { - case TransationType.Update: - case TransationType.DeleteRaw: - case TransationType.DeleteAtTime: - { - callback.OnUpdateComplete(transactionId, requests); - break; - } - - case TransationType.InsertAnnotation: - { - callback.OnInsertAnnotations(transactionId, requests); - break; - } - } - - return true; - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error sending callback to HDA client."); - return false; - } - } - #endregion - - #region Delete At Time - /// - /// Deletes the data at the specified times. - /// - public int[] DeleteAtTime( - DateTime[] timestamps, - int[] serverHandles) - { - Session session = ThrowIfNotConnected(); - - // create the delete requests. - List requests = CreateUpdateRequests( - session, - timestamps, - serverHandles); - - // delete the values. - return UpdateHistory(session, requests, false); - } - - /// - /// Deletes the data at the specified times. - /// - public int[] DeleteAtTime( - int transactionId, - DateTime[] timestamps, - int[] serverHandles, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - // create the read requests. - List requests = CreateUpdateRequests( - session, - timestamps, - serverHandles); - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.DeleteAtTime, - transactionId, - requests, - out cancelId); - - // return the initial results. - return errors; - } - - /// - /// Creates the update requests. - /// - private List CreateUpdateRequests( - Session session, - DateTime[] timestamps, - int[] serverHandles) - { - List requests = new List(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - HdaUpdateRequest request = new HdaUpdateRequest(); - requests.Add(request); - - // find handle. - request.Handle = m_itemManager.LookupHandle(serverHandles[ii]); - - if (request.Handle == null) - { - request.Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - request.ClientHandle = request.Handle.ClientHandle; - - // specify the parameters for the request. - DeleteAtTimeDetails details = new DeleteAtTimeDetails(); - - details.NodeId = request.Handle.NodeId; - details.ReqTimes.AddRange(timestamps); - - request.Details = new ExtensionObject(details); - } - - return requests; - } - #endregion - - #region Delete Raw - /// - /// Deletes the raw data. - /// - public int[] DeleteRaw( - DateTime startTime, - DateTime endTime, - int[] serverHandles) - { - Session session = ThrowIfNotConnected(); - - // create the delete requests. - List requests = CreateUpdateRequests( - session, - startTime, - endTime, - serverHandles); - - // delete the values. - return UpdateHistory(session, requests, false); - } - - /// - /// Deletes the raw data. - /// - public int[] DeleteRaw( - int transactionId, - DateTime startTime, - DateTime endTime, - int[] serverHandles, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - ReadRawModifiedDetails details = new ReadRawModifiedDetails(); - - // create the delete requests. - List requests = CreateUpdateRequests( - session, - startTime, - endTime, - serverHandles); - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.DeleteRaw, - transactionId, - requests, - out cancelId); - - // return the initial results. - return errors; - } - - /// - /// Creates the update requests. - /// - private List CreateUpdateRequests( - Session session, - DateTime startTime, - DateTime endTime, - int[] serverHandles) - { - if (startTime == DateTime.MinValue || endTime == DateTime.MinValue) - { - throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); - } - - List requests = new List(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - HdaUpdateRequest request = new HdaUpdateRequest(); - requests.Add(request); - - // find handle. - request.Handle = m_itemManager.LookupHandle(serverHandles[ii]); - - if (request.Handle == null) - { - request.Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - request.ClientHandle = request.Handle.ClientHandle; - - // specify the parameters for the request. - DeleteRawModifiedDetails details = new DeleteRawModifiedDetails(); - - details.NodeId = request.Handle.NodeId; - details.IsDeleteModified = false; - details.StartTime = startTime; - details.EndTime = endTime; - - request.Details = new ExtensionObject(details); - } - - return requests; - } - #endregion - - #region Insert Annotations - /// - /// Inserts the annotations. - /// - public int[] InsertAnnotations( - int[] serverHandles, - DateTime[] timestamps, - Annotation[][] annotations) - { - Session session = ThrowIfNotConnected(); - - // create the update requests. - List requests = CreateUpdateRequests( - session, - serverHandles, - timestamps, - annotations); - - // update the server. - return UpdateHistory(session, requests, false); - } - - /// - /// Inserts the annotations. - /// - public int[] InsertAnnotations( - int transactionId, - int[] serverHandles, - DateTime[] timestamps, - Annotation[][] annotations, - out int cancelId) - { - Session session = ThrowIfNotConnected(); - - // create the update requests. - List requests = CreateUpdateRequests( - session, - serverHandles, - timestamps, - annotations); - - // queue the transaction. - int[] errors = CreateTransaction( - TransationType.InsertAnnotation, - transactionId, - requests, - out cancelId); - - // return the initial results. - return errors; - } - - /// - /// Creates the update requests. - /// - private List CreateUpdateRequests( - Session session, - int[] serverHandles, - DateTime[] timestamps, - Annotation[][] annotations) - { - List requests = new List(); - - for (int ii = 0; ii < serverHandles.Length; ii++) - { - HdaUpdateRequest request = new HdaUpdateRequest(); - requests.Add(request); - - // find handle. - request.Handle = m_itemManager.LookupHandle(serverHandles[ii]); - - if (request.Handle == null) - { - request.Error = ResultIds.E_INVALIDHANDLE; - continue; - } - - request.ClientHandle = request.Handle.ClientHandle; - - // check if nothing to do. - Annotation[] list = annotations[ii]; - - if (list == null || list.Length == 0) - { - request.Error = ResultIds.S_OK; - continue; - } - - // get the annotations proprerty. - NodeId annotationsId = m_itemManager.GetAnnotationsPropertyNodeId(session, request.Handle); - - if (NodeId.IsNull(annotationsId)) - { - request.Error = ResultIds.E_FAIL; - continue; - } - - // specify the parameters for the request. - UpdateDataDetails details = new UpdateDataDetails(); - - details.NodeId = annotationsId; - details.PerformInsertReplace = PerformUpdateType.Insert; - - for (int jj = 0; jj < list.Length; jj++) - { - DataValue value = new DataValue(); - value.WrappedValue = new ExtensionObject(list[jj]); - value.SourceTimestamp = timestamps[ii]; - details.UpdateValues.Add(value); - } - - request.Details = new ExtensionObject(details); - } - - return requests; - } - #endregion - - #region Private Methods - /// - /// Reads the next batch of values from the server. - /// - private bool ReadNext( - Session session, - ExtensionObject details, - List requests, - bool releaseContinuationPoints) - { - // get the value. - HistoryReadValueIdCollection nodesToRead = new HistoryReadValueIdCollection(); - - for (int ii = 0; ii < requests.Count; ii++) - { - HdaReadRequest request = requests[ii]; - - if (request.IsComplete || request.Error < 0) - { - continue; - } - - if (NodeId.IsNull(request.NodeId)) - { - request.Error = ResultIds.S_NODATA; - continue; - } - - HistoryReadValueId nodeToRead = new HistoryReadValueId(); - nodeToRead.NodeId = request.NodeId; - nodeToRead.ContinuationPoint = request.ContinuationPoint; - nodeToRead.Handle = request; - nodesToRead.Add(nodeToRead); - } - - // check if something to do. - if (nodesToRead.Count == 0) - { - return false; - } - - HistoryReadResultCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - session.HistoryRead( - null, - details, - TimestampsToReturn.Source, - releaseContinuationPoints, - nodesToRead, - out results, - out diagnosticInfos); - - Session.ValidateResponse(results, nodesToRead); - Session.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - - // check if nothing more to do. - if (releaseContinuationPoints) - { - return false; - } - - // process results. - bool continuationPoints = false; - - for (int ii = 0; ii < nodesToRead.Count; ii++) - { - HdaReadRequest request = (HdaReadRequest)nodesToRead[ii].Handle; - - if (request.Values == null) - { - request.Values = new List(); - } - - request.Error = ProcessReadResults( - session, - results[ii], - request.AttributeId, - request.Values, - request.ModificationInfos); - - request.ContinuationPoint = results[ii].ContinuationPoint; - - // check if continuation point provided. - if (request.ContinuationPoint != null && request.ContinuationPoint.Length > 0) - { - request.Error = ResultIds.S_MOREDATA; - continuationPoints = true; - } - else - { - request.IsComplete = true; - } - } - - return continuationPoints; - } - - /// - /// Processes the results of a history read operation. - /// - private int ProcessReadResults( - Session session, - HistoryReadResult result, - uint attributeId, - List values, - List modificationInfos) - { - // check for item level error. - int error = MapReadStatusToErrorCode(result.StatusCode); - - if (error < 0) - { - return error; - } - - // check if no data found. - if (result.StatusCode == StatusCodes.GoodNoData) - { - return ResultIds.S_NODATA; - } - - // extract the history data. - HistoryData data = ExtensionObject.ToEncodeable(result.HistoryData) as HistoryData; - - if (data == null) - { - return ResultIds.E_FAIL; - } - - // check for modified data. - HistoryModifiedData modifiedData = data as HistoryModifiedData; - - if (modificationInfos != null) - { - if (modifiedData == null) - { - return ResultIds.E_FAIL; - } - - modificationInfos.AddRange(modifiedData.ModificationInfos); - } - - // convert the values. - for (int ii = 0; ii < data.DataValues.Count; ii++) - { - DaValue value = GetAttributeValue(session, m_mapper, attributeId, data.DataValues[ii]); - values.Add(value); - - // ensure matching modification info record exists. - if (modificationInfos != null) - { - if (modifiedData == null || ii >= modifiedData.ModificationInfos.Count) - { - modificationInfos.Add(new ModificationInfo()); - } - else - { - modificationInfos.Add(modifiedData.ModificationInfos[ii]); - } - } - } - - // check if no data found. - if (result.StatusCode == StatusCodes.GoodMoreData) - { - return ResultIds.S_MOREDATA; - } - - return ResultIds.S_OK; - } - #endregion - - #region Static Functions - /// - /// Converts a UA value to an HDA attribute value. - /// - /// The session. - /// The mapper. - /// The attribute id. - /// The value. - /// - internal static DaValue GetAttributeValue(Session session, ComNamespaceMapper mapper, uint attributeId, DataValue value) - { - switch (attributeId) - { - case INTERNAL_ATTRIBUTE_ANNOTATION: - { - DaValue result = new DaValue(); - - Annotation annotation = value.GetValue(null); - - if (annotation == null) - { - result.Error = ResultIds.E_BADTYPE; - return result; - } - - result.Value = annotation; - result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode); - result.Timestamp = value.SourceTimestamp; - result.Error = ResultIds.S_OK; - - return result; - } - - case Constants.OPCHDA_ENG_UNITS: - { - DaValue result = new DaValue(); - - EUInformation engineeringUnits = value.GetValue(null); - - if (engineeringUnits == null) - { - result.Error = ResultIds.E_INVALIDATTRID; - return result; - } - - if (engineeringUnits.DisplayName != null) - { - result.Value = engineeringUnits.DisplayName.Text; - } - - result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode); - result.Timestamp = value.SourceTimestamp; - result.Error = ResultIds.S_OK; - - return result; - } - - case Constants.OPCHDA_HIGH_ENTRY_LIMIT: - case Constants.OPCHDA_NORMAL_MAXIMUM: - { - DaValue result = new DaValue(); - - Range range = value.GetValue(null); - - if (range == null) - { - result.Error = ResultIds.E_INVALIDATTRID; - return result; - } - - result.Value = range.High; - result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode); - result.Timestamp = value.SourceTimestamp; - result.Error = ResultIds.S_OK; - - return result; - } - - case Constants.OPCHDA_LOW_ENTRY_LIMIT: - case Constants.OPCHDA_NORMAL_MINIMUM: - { - DaValue result = new DaValue(); - - Range range = value.GetValue(null); - - if (range == null) - { - result.Error = ResultIds.E_INVALIDATTRID; - return result; - } - - result.Value = range.Low; - result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode); - result.Timestamp = value.SourceTimestamp; - result.Error = ResultIds.S_OK; - - return result; - } - - case Constants.OPCHDA_MAX_TIME_INT: - case Constants.OPCHDA_MIN_TIME_INT: - { - DaValue result = new DaValue(); - - int error = ComHdaProxy.MapReadStatusToErrorCode(value.StatusCode); - - if (error < 0) - { - result.Error = error; - return result; - } - - // need to support the VT_CY type. - result.Value = (decimal)value.GetValue(0); - result.HdaQuality = ComUtils.GetHdaQualityCode(value.StatusCode); - result.Timestamp = value.SourceTimestamp; - result.Error = ResultIds.S_OK; - - return result; - } - - default: - case Constants.OPCHDA_ITEMID: - case Constants.OPCHDA_ARCHIVING: - case Constants.OPCHDA_STEPPED: - case Constants.OPCHDA_EXCEPTION_DEV: - case Constants.OPCHDA_EXCEPTION_DEV_TYPE: - case Constants.OPCHDA_DERIVE_EQUATION: - { - return mapper.GetLocalDataValue(value); - } - } - } - - /// - /// Converts a StatusCode returned during a Read to an HRESULT. - /// - internal static int MapPropertyReadStatusToErrorCode(StatusCode statusCode) - { - // map good status. - if (StatusCode.IsGood(statusCode)) - { - return ResultIds.S_OK; - } - - // map bad status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadOutOfMemory: { return ResultIds.E_OUTOFMEMORY; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALID_PID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_INVALID_PID; } - case StatusCodes.BadNotReadable: { return ResultIds.E_BADRIGHTS; } - case StatusCodes.BadUserAccessDenied: { return ResultIds.E_ACCESSDENIED; } - case StatusCodes.BadAttributeIdInvalid: { return ResultIds.E_INVALID_PID; } - case StatusCodes.BadTypeMismatch: { return ResultIds.E_BADTYPE; } - } - - return ResultIds.E_FAIL; - } - - // uncertain values for property reads are errors. - return ResultIds.E_FAIL; - } - - /// - /// Converts a StatusCode returned during a Read to an HRESULT. - /// - internal static int MapReadStatusToErrorCode(StatusCode statusCode) - { - // map bad well known status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadOutOfMemory: { return ResultIds.E_OUTOFMEMORY; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALIDITEMID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_UNKNOWNITEMID; } - case StatusCodes.BadNotReadable: { return ResultIds.E_BADRIGHTS; } - case StatusCodes.BadUserAccessDenied: { return ResultIds.E_ACCESSDENIED; } - case StatusCodes.BadAttributeIdInvalid: { return ResultIds.E_INVALIDITEMID; } - case StatusCodes.BadUnexpectedError: { return ResultIds.E_FAIL; } - case StatusCodes.BadInternalError: { return ResultIds.E_FAIL; } - case StatusCodes.BadSessionClosed: { return ResultIds.E_FAIL; } - case StatusCodes.BadTypeMismatch: { return ResultIds.E_BADTYPE; } - } - } - - // all other values are mapped to quality codes. - return ResultIds.S_OK; - } - - /// - /// Converts a StatusCode returned during a HistoryUpdate to an HRESULT. - /// - internal static int MapUpdateStatusToErrorCode(StatusCode statusCode) - { - // map bad status codes. - if (StatusCode.IsBad(statusCode)) - { - switch (statusCode.Code) - { - case StatusCodes.BadOutOfMemory: { return ResultIds.E_OUTOFMEMORY; } - case StatusCodes.BadNodeIdInvalid: { return ResultIds.E_INVALIDITEMID; } - case StatusCodes.BadNodeIdUnknown: { return ResultIds.E_UNKNOWNITEMID; } - case StatusCodes.BadNotWritable: { return ResultIds.E_BADRIGHTS; } - case StatusCodes.BadUserAccessDenied: { return ResultIds.E_ACCESSDENIED; } - case StatusCodes.BadHistoryOperationInvalid: { return ResultIds.E_NOTSUPPORTED; } - case StatusCodes.BadHistoryOperationUnsupported: { return ResultIds.E_NOTSUPPORTED; } - case StatusCodes.BadOutOfRange: { return ResultIds.E_RANGE; } - case StatusCodes.BadEntryExists: { return ResultIds.E_DATAEXISTS; } - case StatusCodes.BadNoEntryExists: { return ResultIds.E_NODATAEXISTS; } - } - - return ResultIds.E_FAIL; - } - - // ignore uncertain and success codes. - return ResultIds.S_OK; - } - #endregion - - #region Transaction Class - /// - /// The parameters for an asynchronous transaction. - /// - private class Transaction - { - public TransationType TransationType; - public int TransactionId; - public int CancelId; - } - #endregion - - #region ReadRequestTransaction Class - /// - /// The parameters for a read request. - /// - private class ReadRequestTransaction : Transaction - { - public ExtensionObject Details; - public List Requests; - } - #endregion - - #region UpdateRequestTransaction Class - /// - /// The parameters for an update request. - /// - private class UpdateRequestTransaction : Transaction - { - public List Requests; - } - #endregion - - #region TransationType Enumeration - /// - /// The possible transaction types. - /// - private enum TransationType - { - Read, - ReadModified, - ReadAttribute, - ReadAnnotation, - Update, - DeleteRaw, - DeleteAtTime, - InsertAnnotation, - Cancel - } - #endregion - - #region Private Fields - internal const uint INTERNAL_ATTRIBUTE_ANNOTATION = 1000; - internal const uint INTERNAL_ATTRIBUTE_VALUE_RANK = 1001; - - private ComHdaProxyConfiguration m_configuration; - private ComNamespaceMapper m_mapper; - private ComDaBrowseCache m_browseCacheManager; - private ComDaBrowseManager m_browseManager; - private ComHdaItemManager m_itemManager; - private List m_aggregates; - private IComHdaDataCallback m_callback; - private Dictionary m_transactions; - private int m_lastCancelId; - #endregion - } -} diff --git a/ComIOP/Common/Server/Hda/ComHdaProxyConfiguration.cs b/ComIOP/Common/Server/Hda/ComHdaProxyConfiguration.cs deleted file mode 100644 index ff9f6553d..000000000 --- a/ComIOP/Common/Server/Hda/ComHdaProxyConfiguration.cs +++ /dev/null @@ -1,88 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.ServiceModel; -using System.Runtime.Serialization; -using System.Collections.Generic; -using Opc.Ua.Server; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores the configuration for UA that wraps a COM server. - /// - [DataContract(Namespace = Namespaces.ComInterop)] - public class ComHdaProxyConfiguration : ComProxyConfiguration - { - #region Constructors - /// - /// The default constructor. - /// - public ComHdaProxyConfiguration() - { - Initialize(); - } - - /// - /// Initializes the object during deserialization. - /// - [OnDeserializing()] - private void Initialize(StreamingContext context) - { - Initialize(); - } - - /// - /// Sets private members to default values. - /// - private void Initialize() - { - m_maxReturnValues = 2000; - } - #endregion - - #region Public Properties - /// - /// Gets or sets the max return values. - /// - /// The max return values. - [DataMember(Order=1)] - public int MaxReturnValues - { - get { return m_maxReturnValues; } - set { m_maxReturnValues = value; } - } - #endregion - - #region Private Members - private int m_maxReturnValues; - #endregion - } -} diff --git a/ComIOP/Common/Server/Hda/HdaAggregate.cs b/ComIOP/Common/Server/Hda/HdaAggregate.cs deleted file mode 100644 index 693e93ffe..000000000 --- a/ComIOP/Common/Server/Hda/HdaAggregate.cs +++ /dev/null @@ -1,69 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores information about an HDA aggregate. - /// - public class HdaAggregate - { - /// - /// The UA aggregate id. - /// - public NodeId RemoteId; - - /// - /// The proxy assigned identifier for the aggregate, - /// - public uint LocalId; - - /// - /// The name of the aggregate. - /// - public string Name; - - /// - /// The descriptions of the aggregate. - /// - public string Description; - } -} diff --git a/ComIOP/Common/Server/Hda/HdaReadRequest.cs b/ComIOP/Common/Server/Hda/HdaReadRequest.cs deleted file mode 100644 index 30b857839..000000000 --- a/ComIOP/Common/Server/Hda/HdaReadRequest.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores information about an HDA read request. - /// - public class HdaReadRequest - { - /// - /// The handle for the requested item. - /// - public HdaItemHandle Handle; - - /// - /// The node id to read. - /// - public NodeId NodeId; - - /// - /// The client handle. - /// - public int ClientHandle; - - /// - /// The attribute being read. - /// - public uint AttributeId; - - /// - /// The aggregate used to calculate the results. - /// - public uint AggregateId; - - /// - /// Any error associated with the item. - /// - public int Error; - - /// - /// Any error associated with the item. - /// - public List Values; - - /// - /// Metadata associated with the values. - /// - public List ModificationInfos; - - /// - /// A continuation point returned by the server. - /// - public byte[] ContinuationPoint; - - /// - /// A flag that indicates that all data has been read. - /// - public bool IsComplete; - } -} diff --git a/ComIOP/Common/Server/Hda/HdaUpdateRequest.cs b/ComIOP/Common/Server/Hda/HdaUpdateRequest.cs deleted file mode 100644 index 793773064..000000000 --- a/ComIOP/Common/Server/Hda/HdaUpdateRequest.cs +++ /dev/null @@ -1,69 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; -using Opc.Ua.Client; -using OpcRcw.Hda; - -namespace Opc.Ua.Com.Server -{ - /// - /// Stores information about an HDA update request. - /// - public class HdaUpdateRequest - { - /// - /// The handle for the requested item. - /// - public HdaItemHandle Handle; - - /// - /// The client handle. - /// - public int ClientHandle; - - /// - /// The details of the request. - /// - public ExtensionObject Details; - - /// - /// Any error associated with the item. - /// - public int Error; - } -} diff --git a/ComIOP/Common/Server/Hda/IComHdaDataCallback.cs b/ComIOP/Common/Server/Hda/IComHdaDataCallback.cs deleted file mode 100644 index c184e059a..000000000 --- a/ComIOP/Common/Server/Hda/IComHdaDataCallback.cs +++ /dev/null @@ -1,100 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Client; - -namespace Opc.Ua.Com.Server -{ - /// - /// Used to report asynchronous events produced by an HDA server. - /// - public interface IComHdaDataCallback : IDisposable - { - /// - /// Called when a data change operation completes. - /// - void OnDataChange( - int transactionId, - List results); - - /// - /// Called when a read operation completes. - /// - void OnReadComplete( - int transactionId, - List results); - - /// - /// Called when a read modified operation completes. - /// - void OnReadModifiedComplete( - int transactionId, - List results); - - /// - /// Called when a read attributes operation completes. - /// - void OnReadAttributeComplete( - int transactionId, - List results); - - /// - /// Called when a read annotations operation completes. - /// - void OnReadAnnotations( - int transactionId, - List results); - - /// - /// Called when an insert annotations operation completes. - /// - void OnInsertAnnotations( - int transactionId, - List results); - - /// - /// Called when a update operation completes. - /// - void OnUpdateComplete( - int transactionId, - List results); - - /// - /// Called when a cancel operation completes. - /// - void OnCancelComplete(int transactionId); - } -} diff --git a/ComIOP/Common/UA COM Interop Library.csproj b/ComIOP/Common/UA COM Interop Library.csproj deleted file mode 100644 index fd74cbf77..000000000 --- a/ComIOP/Common/UA COM Interop Library.csproj +++ /dev/null @@ -1,291 +0,0 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {24D3C616-ED4C-4AF9-B529-7B418EC8ACC4} - Library - Properties - Opc.Ua.Com - Opc.Ua.ComInterop - false - - - - - 3.5 - - - true - v4.8 - http://localhost/Opc.Ua.ComInterop/ - true - Web - true - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - - - - true - full - false - ..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - false - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - - - AnyCPU - false - - - - - - - 3.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - - - Code - - - - - - Code - - - - Code - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - - Code - - - - Code - - - - - - Code - - - Code - - - Code - - - Code - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - true - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - false - - - False - .NET Framework 3.5 SP1 - false - - - - - - - - - - - - - - 1.5.374.126 - - - 1.5.374.126 - - - 1.5.374.126 - - - - - - - - - - - \ No newline at end of file diff --git a/ComIOP/Common/app.config b/ComIOP/Common/app.config deleted file mode 100644 index c8a008bed..000000000 --- a/ComIOP/Common/app.config +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ComIOP/README.md b/ComIOP/README.md deleted file mode 100644 index 3c36aaee2..000000000 --- a/ComIOP/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# OPC Foundation UA .Net Standard Library COM Server Wrapper - -## Introduction -This OPC UA COM Server Wrapper is designed to map OPC Classic server information to OPC UA to help vendors migrate to OPC UA based systems while still being able to access information from existing OPC Classic systems. -For more information please refer of the OPC Unified Architecture specification: -- for OPC Data Access (DA) refer to the OPC UA specification, Part 8: Data Access, ANNEX A -- for OPC Alarms and Events (AE) refer to the OPC UA specification, Part 9: Alarms & Conditions, ANNEX D -- for OPC Historical Data Access (HDA) refer to the OPC UA specification, Part 11: Historical Access, ANNEX A - -## How to build and run the Windows OPC COM Server Wrapper -1. Start the OPC Classic Server. -2. Open the solution **UA COM Interop.sln** with VisualStudio. -3. Choose the **UA COM Server Wrapper** project in the Solution Explorer and set it with a right click as `Startup Project`. -4. Enter the `ServerUrl` for the OPC Classic Server DA, AE and HDA connection in the configuration file: **Opc.Ua.ComServerWrapper.Config.xml**. -5. Hit `F5` to build and execute the sample. -5. Connect to the **UA COM Server Wrapper** with a OPC UA Client to access the namespace of the OPC Classic Server. - - - diff --git a/ComIOP/Wrapper/Common/COpcArray.h b/ComIOP/Wrapper/Common/COpcArray.h deleted file mode 100644 index 18f275f4d..000000000 --- a/ComIOP/Wrapper/Common/COpcArray.h +++ /dev/null @@ -1,250 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcArray_H -#define _COpcArray_H - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "COpcString.h" - -//============================================================================== -// CLASS: COpcList -// PURPOSE: Defines a indexable array template class. - -template -class COpcArray -{ - OPC_CLASS_NEW_DELETE_ARRAY() - - public: - - //========================================================================== - // Constructor - COpcArray(UINT uSize = 0) - : - m_pData(NULL), - m_uSize(0) - { - SetSize(uSize); - } - - //========================================================================== - // Copy Constructor - COpcArray(const COpcArray& cArray) - : - m_pData(NULL), - m_uSize(0) - { - *this = cArray; - } - - //========================================================================== - // Destructor - ~COpcArray() - { - RemoveAll(); - } - - //========================================================================== - // Assignment - COpcArray& operator=(const COpcArray& cArray) - { - SetSize(cArray.m_uSize); - - for (UINT ii = 0; ii < cArray.m_uSize; ii++) - { - m_pData[ii] = cArray[ii]; - } - - return *this; - } - - //========================================================================== - // GetSize - UINT GetSize() const - { - return m_uSize; - } - - //========================================================================== - // GetData - TYPE* GetData() const - { - return m_pData; - } - - //========================================================================== - // SetSize - void SetSize(UINT uNewSize) - { - if (uNewSize == 0) - { - RemoveAll(); - return; - } - - TYPE* pData = new TYPE[uNewSize]; - - for (UINT ii = 0; ii < uNewSize && ii < m_uSize; ii++) - { - pData[ii] = m_pData[ii]; - } - - if (m_pData != NULL) - { - delete [] m_pData; - } - - m_pData = pData; - m_uSize = uNewSize; - } - - //========================================================================== - // RemoveAll - void RemoveAll() - { - if (m_pData != NULL) - { - delete [] m_pData; - } - - m_uSize = 0; - m_pData = NULL; - } - - //========================================================================== - // operator[] - TYPE& operator[](UINT uIndex) - { - OPC_ASSERT(uIndex < m_uSize); - return m_pData[uIndex]; - } - - const TYPE& operator[](UINT uIndex) const - { - OPC_ASSERT(uIndex < m_uSize); - return m_pData[uIndex]; - } - - //========================================================================== - // SetAtGrow - void SetAtGrow(UINT uIndex, const TYPE& newElement) - { - if (uIndex+1 > m_uSize) - { - SetSize(uIndex+1); - } - - m_pData[uIndex] = newElement; - } - - //========================================================================== - // Append - void Append(const TYPE& newElement) - { - SetAtGrow(m_uSize, newElement); - } - - //========================================================================== - // InsertAt - void InsertAt(UINT uIndex, const TYPE& newElement, UINT uCount = 1) - { - OPC_ASSERT(uIndex < m_uSize); - - UINT uNewSize = m_uSize+uCount; - TYPE* pData = new TYPE[uNewSize]; - - UINT ii = 0; - - for (ii = 0; ii < uIndex; ii++) - { - pData[ii] = m_pData[ii]; - } - - for (ii = uIndex; ii < uCount; ii++) - { - pData[ii] = newElement; - } - - for (ii = uIndex+uCount; ii < uNewSize; ii++) - { - pData[ii] = m_pData[ii-uCount]; - } - - delete [] m_pData; - m_pData = pData; - m_uSize = uNewSize; - } - - //========================================================================== - // RemoveAt - void RemoveAt(UINT uIndex, UINT uCount = 1) - { - OPC_ASSERT(uIndex < m_uSize); - - UINT uNewSize = m_uSize-uCount; - TYPE* pData = new TYPE[uNewSize]; - - UINT ii = 0; - - for (ii = 0; ii < uIndex; ii++) - { - pData[ii] = m_pData[ii]; - } - - for (ii = uIndex+uCount; ii < m_uSize; ii++) - { - pData[ii-uCount] = m_pData[ii]; - } - - delete [] m_pData; - m_pData = pData; - m_uSize = uNewSize; - } - -private: - - TYPE* m_pData; - UINT m_uSize; -}; - -//============================================================================== -// TYPE: COpcStringArray -// PURPOSE: An array of strings. - -typedef COpcArray COpcStringArray; - -#ifndef OPCUTILS_EXPORTS -template class OPCUTILS_API COpcArray; -#endif - -#endif //ndef _COpcArray_H diff --git a/ComIOP/Wrapper/Common/COpcBrowseElement.cpp b/ComIOP/Wrapper/Common/COpcBrowseElement.cpp deleted file mode 100644 index d0750e0a7..000000000 --- a/ComIOP/Wrapper/Common/COpcBrowseElement.cpp +++ /dev/null @@ -1,423 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcBrowseElement.h" - -//============================================================================ -// Local Declarations - -#define DEFAULT_SEPARATOR _T("/") - -//============================================================================ -// COpcBrowseElement - -// Constructor -COpcBrowseElement::COpcBrowseElement(COpcBrowseElement* pParent) -{ - Init(); - m_pParent = pParent; -} - -// Init -void COpcBrowseElement::Init() -{ - m_pParent = NULL; - m_cItemID = OPC_EMPTY_STRING; - m_cName = OPC_EMPTY_STRING; - m_cSeparator = OPC_EMPTY_STRING; -} - -// Clear -void COpcBrowseElement::Clear() -{ - while (m_cChildren.GetCount() > 0) - { - COpcBrowseElement* pNode = m_cChildren.RemoveHead(); - pNode->Clear(); - delete pNode; - } - - m_cChildren.RemoveAll(); - - Init(); -} - -// GetName -COpcString COpcBrowseElement::GetName() const -{ - return m_cName; -} - -// GetItemID -COpcString COpcBrowseElement::GetItemID() const -{ - if (m_cItemID.IsEmpty()) - { - COpcString cItemID; - - if (m_pParent != NULL) - { - cItemID += m_pParent->GetItemID(); - - if (!cItemID.IsEmpty()) - { - cItemID += m_pParent->GetSeparator(); - } - } - - cItemID += m_cName; - - return cItemID; - } - - return m_cItemID; -} - -// GetBrowsePath -COpcString COpcBrowseElement::GetBrowsePath() const -{ - COpcString cPath; - - if (m_pParent != NULL) - { - cPath += m_pParent->GetBrowsePath(); - cPath += m_pParent->GetSeparator(); - } - - cPath += m_cName; - - return cPath; -} - -// GetSeparator -COpcString COpcBrowseElement::GetSeparator() const -{ - // inheirit separator from parent if not provided. - if (m_cSeparator.IsEmpty()) - { - // use default separator if top level node. - if (m_pParent == NULL) - { - return DEFAULT_SEPARATOR; - } - - return m_pParent->GetSeparator(); - } - - return m_cSeparator; -} - -// GetChild -COpcBrowseElement* COpcBrowseElement::GetChild(UINT uIndex) const -{ - if (uIndex > m_cChildren.GetCount()) - { - return NULL; - } - - OPC_POS pos = m_cChildren.GetHeadPosition(); - - for (UINT ii = 0; pos != NULL; ii++) - { - COpcBrowseElement* pNode = m_cChildren.GetNext(pos); - - if (ii == uIndex) - { - return pNode; - } - } - - return NULL; -} -/* -// Browse -void COpcBrowseElement::Browse( - OPCBROWSETYPE eType, - const COpcString& cPath, - COpcStringList& cNodes -) -{ - if (eType != OPC_FLAT) - { - OPC_POS pos = m_cChildren.GetHeadPosition(); - - while (pos != NULL) - { - COpcBrowseElement* pNode = m_cChildren.GetNext(pos); - - // add child to list. - cNodes.AddTail(pNode->GetName()); - } - } - - else - { - OPC_POS pos = m_cChildren.GetHeadPosition(); - - while (pos != NULL) - { - COpcBrowseElement* pNode = m_cChildren.GetNext(pos); - - // add child to list. - cNodes.AddTail(cPath + pNode->GetName()); - - // recursively browse children. - if (pNode->m_cChildren.GetCount() > 0) - { - pNode->Browse(eType, cPath + pNode->GetName() + GetSeparator(), cNodes); - } - } - } -} -*/ - -// Find -COpcBrowseElement* COpcBrowseElement::Find(const COpcString& cPath) -{ - // remove leading separator - if it exists. - COpcString cPrefix = GetSeparator(); - COpcString cLocalPath = cPath; - - while (cLocalPath.Find(GetSeparator()) == 0) - { - cLocalPath = cLocalPath.SubStr(cPrefix.GetLength()); - } - - // recursively search children. - OPC_POS pos = m_cChildren.GetHeadPosition(); - - while (pos != NULL) - { - COpcBrowseElement* pChild = m_cChildren.GetNext(pos); - - // check for a child with an exact name match. - if (cLocalPath == pChild->m_cName) - { - return pChild; - } - - // check if the path starts with the child name. - COpcString cPrefix = pChild->m_cName + pChild->GetSeparator(); - - // check for a child with an exact name match plus trailing separator. - if (cLocalPath == cPrefix) - { - return pChild; - } - - UINT uIndex = cLocalPath.Find(cPrefix); - - // search the child node if there is a match. - if (uIndex == 0) - { - cLocalPath = cLocalPath.SubStr(cPrefix.GetLength()); - return pChild->Find(cLocalPath); - } - } - - return NULL; -} - -// CreateInstance -COpcBrowseElement* COpcBrowseElement::CreateInstance() -{ - return new COpcBrowseElement(this); -} - -// Insert -COpcBrowseElement* COpcBrowseElement::Insert(const COpcString& cPath) -{ - COpcString cName = cPath; - COpcString cSubPath = OPC_EMPTY_STRING; - - // check if multiple levels have been specified. - do - { - UINT uIndex = cName.Find(GetSeparator()); - - if (uIndex == -1) - { - break; - } - - cSubPath = cName.SubStr(uIndex + GetSeparator().GetLength()); - cName = cName.SubStr(0, uIndex); - - if (!cName.IsEmpty()) - { - break; - } - - cName = cSubPath; - } - while (!cSubPath.IsEmpty()); - - // invalid path specified. - if (cName.IsEmpty()) - { - return NULL; - } - - // find out if node already exists. - COpcBrowseElement* pNode = NULL; - - OPC_POS pos = m_cChildren.GetHeadPosition(); - - while (pos != NULL) - { - pNode = m_cChildren.GetNext(pos); - - if (pNode->m_cName == cName) - { - // return existing node. - if (cSubPath.IsEmpty()) - { - return pNode; - } - - // insert sub-path into existing node. - return pNode->Insert(cSubPath); - } - } - - // create new node. - pNode = CreateInstance(); - pNode->m_cName = cName; - OPC_ASSERT(!pNode->m_cName.IsEmpty()); - - COpcBrowseElement* pChild = pNode; - - if (!cSubPath.IsEmpty()) - { - pChild = pNode->Insert(cSubPath); - - if (pChild == NULL) - { - delete pNode; - return NULL; - } - } - - m_cChildren.AddTail(pNode); - return pChild; -} - -// Insert -COpcBrowseElement* COpcBrowseElement::Insert(const COpcString& cPath, const COpcString& cItemID) -{ - COpcBrowseElement* pChild = Insert(cPath); - - if (pChild != NULL) - { - pChild->m_cItemID = cItemID; - } - - return pChild; -} - -// Remove -void COpcBrowseElement::Remove() -{ - // tell parent to destroy branch. - if (m_pParent != NULL) - { - m_pParent->Remove(m_cName); - return; - } - - delete this; -} - -// Remove -bool COpcBrowseElement::Remove(const COpcString& cName) -{ - // find child node. - OPC_POS pos = m_cChildren.GetHeadPosition(); - - while (pos != NULL) - { - COpcBrowseElement* pChild = m_cChildren[pos]; - - // remove child node from list and delete it. - if (pChild->GetName() == cName) - { - m_cChildren.RemoveAt(pos); - - pChild->Clear(); - delete pChild; - - return true; - } - - m_cChildren.GetNext(pos); - } - - return false; -} - -// Browse -void COpcBrowseElement::Browse( - const COpcString& cPath, - bool bFlat, - COpcStringList& cNodes -) -{ - if (!bFlat) - { - OPC_POS pos = m_cChildren.GetHeadPosition(); - - while (pos != NULL) - { - COpcBrowseElement* pNode = m_cChildren.GetNext(pos); - - // add child to list. - cNodes.AddTail(pNode->GetName()); - } - } - - else - { - OPC_POS pos = m_cChildren.GetHeadPosition(); - - while (pos != NULL) - { - COpcBrowseElement* pNode = m_cChildren.GetNext(pos); - - // add child to list. - cNodes.AddTail(cPath + pNode->GetName()); - - // recursively browse children. - if (pNode->m_cChildren.GetCount() > 0) - { - pNode->Browse(cPath + pNode->GetName() + GetSeparator(), bFlat, cNodes); - } - } - } -} diff --git a/ComIOP/Wrapper/Common/COpcBrowseElement.h b/ComIOP/Wrapper/Common/COpcBrowseElement.h deleted file mode 100644 index f84de16fc..000000000 --- a/ComIOP/Wrapper/Common/COpcBrowseElement.h +++ /dev/null @@ -1,137 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcBrowseElement_H_ -#define _COpcBrowseElement_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "COpcString.h" -#include "COpcList.h" - -//============================================================================ -// TYPE: COpcBrowseElementList -// PURPOSE: A ordered list of server namespace elements. - -class COpcBrowseElement; -typedef COpcList COpcBrowseElementList; - -//============================================================================ -// CLASS: COpcBrowseElement -// PURPOSE: Describes an element in the server namespace. - -class COpcBrowseElement -{ - OPC_CLASS_NEW_DELETE() - -public: - - //======================================================================== - // Public Operators - - // Constructor - COpcBrowseElement(COpcBrowseElement* pParent); - - // Destructor - ~COpcBrowseElement() { Clear(); } - - //======================================================================== - // Public Methods - - // Init - void Init(); - - // Clear - void Clear(); - - // GetName - COpcString GetName() const; - - // GetItemID - COpcString GetItemID() const; - - // GetBrowsePath - COpcString GetBrowsePath() const; - - // GetSeparator - COpcString GetSeparator() const; - - // GetParent - COpcBrowseElement* GetParent() const { return m_pParent; } - - // GetChild - COpcBrowseElement* GetChild(UINT uIndex) const; - - // Browse - void Browse( - const COpcString& cPath, - bool bFlat, - COpcStringList& cNodes - ); - - // Find - COpcBrowseElement* Find(const COpcString& cPath); - - // Insert - COpcBrowseElement* Insert(const COpcString& cPath); - - // Insert - COpcBrowseElement* Insert( - const COpcString& cPath, - const COpcString& cItemID - ); - - // Remove - void Remove(); - - // Remove - bool Remove(const COpcString& cName); - -protected: - - //======================================================================== - // Protected Methods - - // CreateInstance - virtual COpcBrowseElement* CreateInstance(); - - //======================================================================== - // Protected Members - - COpcBrowseElement* m_pParent; - COpcString m_cItemID; - COpcString m_cName; - COpcString m_cSeparator; - - COpcBrowseElementList m_cChildren; -}; - -#endif // _COpcBrowseElement_H_ diff --git a/ComIOP/Wrapper/Common/COpcCPContainer.cpp b/ComIOP/Wrapper/Common/COpcCPContainer.cpp deleted file mode 100644 index 6002893e1..000000000 --- a/ComIOP/Wrapper/Common/COpcCPContainer.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcCPContainer.h" -#include "COpcEnumCPs.h" - -//============================================================================== -// COpcCPContainer - -// Constructor -COpcCPContainer::COpcCPContainer() -{ -} - -// Destructor -COpcCPContainer::~COpcCPContainer() -{ - // release the connection points. - OPC_POS pos = m_cCPs.GetHeadPosition(); - - while (pos != NULL) - { - m_cCPs.GetNext(pos)->Release(); - } -} - -// RegisterInterface -void COpcCPContainer::RegisterInterface(const IID& tInterface) -{ - // constructor adds one reference. - COpcConnectionPoint* pCP = new COpcConnectionPoint(tInterface, this); - m_cCPs.AddTail(pCP); -} - -// UnregisterInterface -void COpcCPContainer::UnregisterInterface(const IID& tInterface) -{ - OPC_POS pos = m_cCPs.GetHeadPosition(); - - while (pos != NULL) - { - COpcConnectionPoint* pCP = m_cCPs[pos]; - - if (pCP->GetInterface() == tInterface) - { - m_cCPs.RemoveAt(pos); - pCP->Delete(); - break; - } - - m_cCPs.GetNext(pos); - } -} - -// GetCallback -HRESULT COpcCPContainer::GetCallback(const IID& tInterface, IUnknown** ippCallback) -{ - COpcConnectionPoint* pCP = NULL; - - OPC_POS pos = m_cCPs.GetHeadPosition(); - - while (pos != NULL) - { - pCP = m_cCPs.GetNext(pos); - - if (pCP->GetInterface() == tInterface) - { - IUnknown* ipUnknown = pCP->GetCallback(); - - if (ipUnknown != NULL) - { - return ipUnknown->QueryInterface(tInterface, (void**)ippCallback); - } - } - } - - return E_FAIL; -} - -// IsConnected -bool COpcCPContainer::IsConnected(const IID& tInterface) -{ - COpcConnectionPoint* pCP = NULL; - - OPC_POS pos = m_cCPs.GetHeadPosition(); - - while (pos != NULL) - { - pCP = m_cCPs.GetNext(pos); - - if (pCP->GetInterface() == tInterface) - { - return pCP->IsConnected(); - } - } - - return false; -} - -//============================================================================== -// IConnectionPointContainer - -// EnumConnectionPoints -HRESULT COpcCPContainer::EnumConnectionPoints(IEnumConnectionPoints** ppEnum) -{ - // invalid arguments. - if (ppEnum == NULL) - { - return E_POINTER; - } - - // create enumeration object. - COpcEnumCPs* pEnumCPs = new COpcEnumCPs(m_cCPs); - - if (pEnumCPs == NULL) - { - return E_OUTOFMEMORY; - } - - // query for enumeration interface. - HRESULT hResult = pEnumCPs->QueryInterface(IID_IEnumConnectionPoints, (void**)ppEnum); - - // release local reference. - pEnumCPs->Release(); - - return hResult; -} - -// FindConnectionPoint -HRESULT COpcCPContainer::FindConnectionPoint(REFIID riid, IConnectionPoint** ppCP) -{ - // invalid arguments. - if (ppCP == NULL) - { - return E_POINTER; - } - - // search for connection point. - OPC_POS pos = m_cCPs.GetHeadPosition(); - - while (pos != NULL) - { - COpcConnectionPoint* pCP = m_cCPs.GetNext(pos); - - if (pCP->GetInterface() == riid) - { - return pCP->QueryInterface(IID_IConnectionPoint, (void**)ppCP); - } - } - - // connection point not found. - return CONNECT_E_NOCONNECTION; -} diff --git a/ComIOP/Wrapper/Common/COpcCPContainer.h b/ComIOP/Wrapper/Common/COpcCPContainer.h deleted file mode 100644 index 3ad2c6028..000000000 --- a/ComIOP/Wrapper/Common/COpcCPContainer.h +++ /dev/null @@ -1,107 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcCPContainer_H_ -#define _COpcCPContainer_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcList.h" -#include "COpcConnectionPoint.h" - -//============================================================================== -// CLASS: COpcConnectionPointList -// PURPOSE: Stores a list of connection points. - -typedef COpcList COpcConnectionPointList; -template class OPCUTILS_API COpcList; - -//============================================================================== -// CLASS: COpcCPContainer -// PURPOSE: Implements the IConnectionPointContainer interface. -// NOTES: - -class OPCUTILS_API COpcCPContainer : public IConnectionPointContainer -{ -public: - - //========================================================================== - // Operators - - // Constructor - COpcCPContainer(); - - // Destructor - ~COpcCPContainer(); - - //========================================================================== - // IConnectionPointContainer - - // EnumConnectionPoints - STDMETHODIMP EnumConnectionPoints(IEnumConnectionPoints** ppEnum); - - // FindConnectionPoint - STDMETHODIMP FindConnectionPoint(REFIID riid, IConnectionPoint** ppCP); - - //========================================================================== - // Public Methods - - // OnAdvise - virtual void OnAdvise(REFIID riid, DWORD dwCookie) {} - - // OnUnadvise - virtual void OnUnadvise(REFIID riid, DWORD dwCookie) {} - -protected: - - //========================================================================== - // Protected Methods - - // RegisterInterface - void RegisterInterface(const IID& tInterface); - - // UnregisterInterface - void UnregisterInterface(const IID& tInterface); - - // GetCallback - HRESULT GetCallback(const IID& tInterface, IUnknown** ippCallback); - - // IsConnected - bool IsConnected(const IID& tInterface); - - //========================================================================== - // Protected Members - - COpcConnectionPointList m_cCPs; -}; - -#endif // _COpcCPContainer_H_ diff --git a/ComIOP/Wrapper/Common/COpcClassFactory.cpp b/ComIOP/Wrapper/Common/COpcClassFactory.cpp deleted file mode 100644 index ea15b287b..000000000 --- a/ComIOP/Wrapper/Common/COpcClassFactory.cpp +++ /dev/null @@ -1,717 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcClassFactory.h" -#include "COpcString.h" -#include "OpcRegistry.h" - -#include "ntsecapi.h" -// #include "DCOM Config/dcomperm.h" - -//============================================================================ -// Local Functions - -// InstallService -static bool InstallService( - LPCTSTR szServiceName, - LPCTSTR szServiceDescription, - LPCTSTR tsFilePath -) -{ - bool bResult = false; - - SC_HANDLE hSCM = NULL; - SC_HANDLE hService = NULL; - - TRY - { - // open service control manager. - hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - - if (hSCM == NULL) - { - THROW_(bResult, false); - } - - SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_QUERY_CONFIG); - - // check if sevice already installed. - if (hService != NULL) - { - GOTOFINALLY(); - } - - // create service. - hService = CreateService( - hSCM, - szServiceName, - szServiceDescription, - SERVICE_ALL_ACCESS, - SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, - SERVICE_ERROR_NORMAL, - tsFilePath, - NULL, - NULL, - _T("RPCSS\0"), - NULL, - NULL); - - if (hService == NULL) - { - THROW_(bResult, false); - } - } - CATCH - { - } - - FINALLY - - if (hService != NULL) CloseServiceHandle(hService); - if (hService != NULL) CloseServiceHandle(hSCM); - - return bResult; -} - -// UninstallService -static void UninstallService(LPCTSTR szServiceName) -{ - SC_HANDLE hSCM = NULL; - SC_HANDLE hService = NULL; - - TRY - { - // open service control manager. - hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - - if (hSCM == NULL) - { - GOTOFINALLY(); - } - - hService = OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE); - - // check if sevice already uninstalled. - if (hService == NULL) - { - GOTOFINALLY(); - } - - // send control message to service - ignore errors. - SERVICE_STATUS cStatus; - ZeroMemory(&cStatus, sizeof(cStatus)); - ControlService(hService, SERVICE_CONTROL_STOP, &cStatus); - - // mark service for deletion. - DeleteService(hService); - } - CATCH - { - } - - FINALLY - - if (hService != NULL) CloseServiceHandle(hService); - if (hService != NULL) CloseServiceHandle(hSCM); - -} - -// UnregisterApplication -static void UnregisterApplication( - const COpcString& cModuleName, - const COpcString& cApplicationName, - const GUID& cAppID -) -{ - COpcString cSubKey; - - // uninstall service. - UninstallService(cApplicationName); - - // delete exe sub key. - cSubKey = _T("AppID\\") + cModuleName + _T(".exe"); - OpcRegDeleteKey(HKEY_CLASSES_ROOT, cSubKey); - - // delete app id sub key. - cSubKey = _T("AppID\\") + (COpcString)cAppID; - OpcRegDeleteKey(HKEY_CLASSES_ROOT, cSubKey); -} - -// RegisterApplication -static HRESULT RegisterApplication( - const COpcString& cModuleName, - const COpcString& cModulePath, - const COpcString& cApplicationName, - const COpcString& cApplicationDescription, - const GUID& cAppID, - bool bService, - bool bEveryone -) -{ - HRESULT hResult = S_OK; - - TRY - { - // create exe sub key. - COpcString cSubKey = _T("AppID\\") + cModuleName + _T(".exe"); - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, (COpcString)cAppID)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // create app id sub key. - cSubKey = _T("AppID\\") + (COpcString)cAppID; - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, (cApplicationDescription.IsEmpty())?cApplicationName:cApplicationDescription)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - /* - // Set application LaunchPermission and AccessPermission to "Everyone". - if (bEveryone) - { - // create authenication sub key. - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, _T("AuthenticationLevel"), (DWORD)1)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // check for OSes earlier than XP SP2 - if (IsLegacySecurityModel()) - { - static BYTE pEveryone[] = { - 0x01,0x00,0x04,0x80,0x34,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x14,0x00,0x00,0x00,0x02,0x00,0x20,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x18,0x00, - 0x01,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x01,0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x15,0x00,0x00,0x00, - 0xa0,0x5f,0x84,0x1f,0x5e,0x2e,0x6b,0x49,0xce,0x12,0x03,0x03,0xf4,0x01,0x00,0x00, - 0x01,0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x15,0x00,0x00,0x00,0xa0,0x5f,0x84,0x1f, - 0x5e,0x2e,0x6b,0x49,0xce,0x12,0x03,0x03,0xf4,0x01,0x00,0x00}; - - // create launch permission sub key. - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, _T("LaunchPermission"), pEveryone, sizeof(pEveryone))) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // create access permission sub key. - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, _T("AccessPermission"), pEveryone, sizeof(pEveryone))) - { - THROW_(hResult, SELFREG_E_CLASS); - } - } - - // use the APIs to set permissions for OSes later than or equal XP S2. - else - { - DWORD dwResult = ChangeAppIDAccessACL( - (LPTSTR)(LPCTSTR)(COpcString)cAppID, - _T("Everyone"), - TRUE, - TRUE, - COM_RIGHTS_EXECUTE_LOCAL | COM_RIGHTS_EXECUTE_REMOTE | COM_RIGHTS_EXECUTE); - - if (dwResult != ERROR_SUCCESS) - { - // could not set access permissions. - THROW_(hResult, SELFREG_E_CLASS); - } - - dwResult = ChangeAppIDLaunchAndActivateACL( - (LPTSTR)(LPCTSTR)(COpcString)cAppID, - _T("Everyone"), - TRUE, - TRUE, - COM_RIGHTS_ACTIVATE_LOCAL | COM_RIGHTS_EXECUTE_LOCAL | COM_RIGHTS_ACTIVATE_REMOTE | COM_RIGHTS_EXECUTE_REMOTE | COM_RIGHTS_EXECUTE); - - if (dwResult != ERROR_SUCCESS) - { - // could hResult set launch and activate permissions. - THROW_(hResult, SELFREG_E_CLASS); - } - } - } - */ - - // register as a service. - if (bService) - { - // set service application parameters. - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, _T("LocalService"), cApplicationName)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, _T("ServiceParameters"), _T("-Service"))) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // install service. - hResult = InstallService(cApplicationName, cApplicationDescription, cModulePath); - - if (FAILED(hResult)) - { - THROW(); - } - } - } - CATCH - { - UnregisterApplication(cModuleName, cApplicationName, cAppID); - } - - return hResult; -} - -// GetModuleInfo -static HRESULT GetModuleInfo( - HINSTANCE hModule, - COpcString& cPath, - COpcString& cName, - COpcString& cExtension -) -{ - // initialize return parameters. - cPath.Empty(); - cName.Empty(); - cExtension.Empty(); - - // lookup the module path. - TCHAR tsModulePath[MAX_PATH+1]; - memset(tsModulePath, 0, sizeof(tsModulePath)); - - DWORD dwResult = GetModuleFileName(hModule, tsModulePath, MAX_PATH); - - if (dwResult == 0) - { - return E_UNEXPECTED; - } - - cPath = tsModulePath; - - // parse module name. - cName = tsModulePath; - - int iIndex = cName.ReverseFind(_T("\\")); - - if (iIndex != -1) - { - cName = cName.SubStr(iIndex+1); - } - - // parse extension. - iIndex = cName.ReverseFind(_T(".")); - - if (iIndex != -1) - { - cExtension = cName.SubStr(iIndex+1).ToUpper(); - cName = cName.SubStr(0, iIndex); - } - - // check for valid values. - if (cName.IsEmpty() || cExtension.IsEmpty()) - { - return E_UNEXPECTED; - } - - return S_OK; -} - -//============================================================================ -// OpcGetClassObject - -HRESULT OpcGetClassObject( - REFCLSID rclsid, - REFIID riid, - LPVOID* ppv, - const TOpcClassTableEntry* pClasses) -{ - // find the class factory for a COM server. - for (int ii = 0; pClasses[ii].tsClassName != NULL; ii++) - { - if (*(pClasses[ii].pClsid) == rclsid) - { - // create the class factory - adds a reference. - COpcClassFactory* pFactory = new COpcClassFactory(&(pClasses[ii])); - - // query for the desired interface - adds another reference. - HRESULT hResult = pFactory->QueryInterface(riid, ppv); - - // release the local reference. - pFactory->Release(); - - return hResult; - } - } - - // clsid was not found in module. - return CLASS_E_CLASSNOTAVAILABLE; -} - -//============================================================================ -// OpcRegisterClassObjects - -OPCUTILS_API HRESULT OpcRegisterClassObjects( - const TOpcClassTableEntry* pClasses, - DWORD dwContext, - DWORD dwFlags, - DWORD* pdwRegister) -{ - HRESULT hResult = S_OK; - - // register each server in the table. - for (int ii = 0; pClasses[ii].tsClassName != NULL; ii++) - { - IUnknown* ipUnknown = NULL; - - // create the class factory - adds a reference. - COpcClassFactory* pFactory = new COpcClassFactory(&(pClasses[ii])); - - // query for the IUnknown interface - adds another reference. - hResult = pFactory->QueryInterface(IID_IUnknown, (void**)&ipUnknown); - - // release the local reference. - pFactory->Release(); - - if (FAILED(hResult)) - { - return hResult; - } - - // register the class factory. - hResult = CoRegisterClassObject( - *(pClasses[ii].pClsid), - ipUnknown, - dwContext, - dwFlags, - &(pdwRegister[ii])); - - // release the local reference again. - ipUnknown->Release(); - - if (FAILED(hResult)) - { - return hResult; - } - } - - // success. - return S_OK; -} - -//============================================================================ -// OpcRevokeClassObjects - -OPCUTILS_API HRESULT OpcRevokeClassObjects( - const TOpcClassTableEntry* pClasses, - DWORD* pdwRegister) -{ - // unregister each server in the table. - for (int ii = 0; pClasses[ii].tsClassName != NULL; ii++) - { - CoRevokeClassObject(pdwRegister[ii]); - } - - // success. - return S_OK; -} - -//============================================================================ -// OpcRegisterServer - -HRESULT OpcRegisterServer( - HINSTANCE hModule, - LPCTSTR tsVendorName, - LPCTSTR tsApplicationName, - LPCTSTR tsApplicationDescription, - const GUID& cAppID, - bool bService, - const TOpcClassTableEntry* pClasses, - const TClassCategories* pCategories, - bool bEveryone) -{ - - HRESULT hResult = S_OK; - - TRY - { - // get module information. - COpcString cModulePath; - COpcString cModuleName; - COpcString cModuleExtension; - - hResult = GetModuleInfo(hModule, cModulePath, cModuleName, cModuleExtension); - - if (FAILED(hResult)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // determine if registering an out of process server. - bool bIsExe = (cModuleExtension == _T("EXE")); - - // register application - if (cAppID != GUID_NULL) - { - hResult = RegisterApplication( - cModuleName, - cModulePath, - tsApplicationName, - tsApplicationDescription, - cAppID, - bService, - bEveryone - ); - - if (FAILED(hResult)) - { - THROW(); - } - } - - // construct type library path - COpcString cTypeLib(cModulePath); - - // register type library - ITypeLib* ipTypeLib = NULL; - hResult = LoadTypeLibEx((LPCWSTR)cTypeLib, REGKIND_REGISTER, &ipTypeLib); - - if (SUCCEEDED(hResult)) - { - ipTypeLib->Release(); - } - - hResult = S_OK; - - // add clsid and prog id registy keys for each class. - for (UINT ii = 0; pClasses[ii].tsClassName != NULL; ii++) - { - COpcString cSubKey; - COpcString cValue; - - // create clsid string. - COpcString cClsid; - cClsid.FromGuid(*(pClasses[ii].pClsid)); - - // create version independent prog id. - COpcString cVersionIndependentProgID; - - cVersionIndependentProgID += tsVendorName; - cVersionIndependentProgID += _T("."); - cVersionIndependentProgID += pClasses[ii].tsClassName; - - // create prog id. - COpcString cProgID; - - cProgID += cVersionIndependentProgID; - cProgID += _T("."); - cProgID += pClasses[ii].tsClassVersion; - - // determine class description. - COpcString cClassDescription = pClasses[ii].tsClassDescription; - - if (cClassDescription.IsEmpty()) - { - cClassDescription = cProgID; - } - - // set description in clsid sub key. - cSubKey = _T("CLSID\\") + cClsid; - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, cClassDescription)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // register application. - if (cAppID != GUID_NULL) - { - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, _T("AppID"), (COpcString)cAppID)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - } - - // set the prog id sub key. - cSubKey = _T("CLSID\\") + cClsid + _T("\\ProgID"); - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, cProgID)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // set the version independent prog id sub key. - cSubKey = _T("CLSID\\") + cClsid + _T("\\VersionIndependentProgID"); - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, cVersionIndependentProgID)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // set LocalServer32 or InprocServer32 sub key. - cSubKey = _T("CLSID\\"); - cSubKey += cClsid; - cSubKey += (bIsExe)?_T("\\LocalServer32"):_T("\\InprocServer32"); - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, cModulePath)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // set threading model. - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, _T("ThreadingModel"), _T("Free"))) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // set description in prog id sub key. - cSubKey = cProgID; - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, cClassDescription)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // set clsid in prog id sub key. - cSubKey = cProgID + _T("\\CLSID"); - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, cClsid)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // set description in version independent prog id sub key. - cSubKey = cVersionIndependentProgID; - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, cClassDescription)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // set clsid in version independent prog id sub key. - cSubKey = cVersionIndependentProgID + _T("\\CLSID"); - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, cClsid)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - - // set current version prog id in version independent prog id sub key. - cSubKey = cVersionIndependentProgID + _T("\\CurVer"); - - if (!OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, cProgID)) - { - THROW_(hResult, SELFREG_E_CLASS); - } - } - - // add categories. - for (ii = 0; pCategories[ii].pClsid != NULL; ii++) - { - RegisterClsidInCategory(*(pCategories[ii].pClsid), *(pCategories[ii].pCategory), pCategories[ii].szDescription); - } - } - CATCH - { - OpcUnregisterServer(hModule, tsVendorName, tsApplicationName, cAppID, pClasses, pCategories); - } - - return hResult; -} - -//============================================================================ -// OpcUnregisterServer - -HRESULT OpcUnregisterServer( - HINSTANCE hModule, - LPCTSTR tsVendorName, - LPCTSTR tsApplicationName, - const GUID& cAppID, - const TOpcClassTableEntry* pClasses, - const TClassCategories* pCategories -) -{ - // remove categories. - for (int ii = 0; pCategories[ii].pClsid != NULL; ii++) - { - UnregisterClsidInCategory(*(pCategories[ii].pClsid), *(pCategories[ii].pCategory)); - } - - // remove clsid and prog id registy keys for each class. - for (ii = 0; pClasses[ii].tsClassName != NULL; ii++) - { - COpcString cSubKey; - - // delete clsid sub key. - COpcString cClsid; - cClsid.FromGuid(*(pClasses[ii].pClsid)); - - cSubKey = _T("CLSID\\") + cClsid; - OpcRegDeleteKey(HKEY_CLASSES_ROOT, cSubKey); - - // delete version independent prog id. - COpcString cVersionIndependentProgID; - - cVersionIndependentProgID += tsVendorName; - cVersionIndependentProgID += _T("."); - cVersionIndependentProgID += pClasses[ii].tsClassName; - - cSubKey = cVersionIndependentProgID; - OpcRegDeleteKey(HKEY_CLASSES_ROOT, cSubKey); - - // delete prog id. - COpcString cProgID; - - cProgID += cVersionIndependentProgID; - cProgID += _T("."); - cProgID += pClasses[ii].tsClassVersion; - - cSubKey = cProgID; - OpcRegDeleteKey(HKEY_CLASSES_ROOT, cSubKey); - } - - // unregister application. - COpcString cModulePath; - COpcString cModuleName; - COpcString cModuleExtension; - - HRESULT hResult = GetModuleInfo(hModule, cModulePath, cModuleName, cModuleExtension); - - if (SUCCEEDED(hResult)) - { - UnregisterApplication(cModuleName, tsApplicationName, cAppID); - } - - return S_OK; -} diff --git a/ComIOP/Wrapper/Common/COpcClassFactory.h b/ComIOP/Wrapper/Common/COpcClassFactory.h deleted file mode 100644 index ea718d439..000000000 --- a/ComIOP/Wrapper/Common/COpcClassFactory.h +++ /dev/null @@ -1,301 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcClassFactory_H -#define _COpcClassFactory_H - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "OpcCategory.h" -#include "COpcCriticalSection.h" - -//============================================================================== -// TYPE: OpcCreateInstanceProc -// PURPOSE: Declares a function to create instances of COM servers. -// NOTES: - -typedef HRESULT (__stdcall PfnOpcCreateInstance)(IUnknown**, const CLSID*); - -//============================================================================== -// STRUCT: TOpcClassTableEntry -// PURPOSE: An element in the module class table. -// NOTES: - -struct TOpcClassTableEntry -{ - const CLSID* pClsid; - LPCTSTR tsClassName; - LPCTSTR tsClassVersion; - LPCTSTR tsClassDescription; - PfnOpcCreateInstance* pfnCreateInstance; -}; - - -//============================================================================== -// CLASS: COpcClassFactory -// PURPOSE: Implements the IClassFactory interface. -// NOTES: - -class OPCUTILS_API COpcClassFactory : public IClassFactory -{ - OPC_CLASS_NEW_DELETE(); - -public: - - //========================================================================== - // Operators - - // Constructor - inline COpcClassFactory(const TOpcClassTableEntry* pClassInfo) - { - m_ulRefs = 1; - m_ulLocks = 0; - m_pClassInfo = pClassInfo; - } - - // Destructor - inline ~COpcClassFactory() - { - OPC_ASSERT(m_ulRefs == 0 && m_ulLocks == 0); - } - - //========================================================================== - // IUnknown - - // QueryInterface - STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppInterface) - { - if (ppInterface == NULL) return E_POINTER; - - if (iid == IID_IClassFactory || iid == IID_IUnknown) - { - AddRef(); - *ppInterface = dynamic_cast(this); - return S_OK; - } - - return E_NOINTERFACE; - } - - // AddRef - STDMETHODIMP_(ULONG) AddRef() - { - COpcLock cLock(m_cLock); - ULONG ulRefs = ++m_ulRefs; - return ulRefs; - } - - // Release - STDMETHODIMP_(ULONG) Release() - { - COpcLock cLock(m_cLock); - - OPC_ASSERT(m_ulRefs > 0); - - ULONG ulRefs = --m_ulRefs; - - if (ulRefs == 0 && m_ulLocks == 0) - { - cLock.Unlock(); - delete this; - } - - return ulRefs; - } - - //========================================================================== - // IClassFactory - - // CreateInstance - STDMETHODIMP CreateInstance( - IUnknown* pUnkOuter, - REFIID riid, - void** ppvObject) - { - *ppvObject = NULL; - - // aggregation is not supported. - if (pUnkOuter != NULL) - { - return CLASS_E_NOAGGREGATION; - } - - OPC_ASSERT(m_pClassInfo != NULL && m_pClassInfo->pfnCreateInstance != NULL); - - // create instance - adds one reference. - IUnknown* ipUnknown = NULL; - - HRESULT hResult = m_pClassInfo->pfnCreateInstance(&ipUnknown, m_pClassInfo->pClsid); - - if (FAILED(hResult)) - { - return hResult; - } - - // query desired interface - adds another reference. - hResult = ipUnknown->QueryInterface(riid, ppvObject); - - if (FAILED(hResult)) - { - ipUnknown->Release(); - return hResult; - } - - // release one reference. - ipUnknown->Release(); - return S_OK; - } - - // LockServer - STDMETHODIMP LockServer(BOOL fLock) - { - COpcLock cLock(m_cLock); - - if (fLock) - { - m_ulLocks++; - return S_OK; - } - - OPC_ASSERT(m_ulLocks > 0); - - ULONG ulLocks = --m_ulLocks; - - if (ulLocks == 0 && m_ulRefs == 0) - { - cLock.Unlock(); - delete this; - } - - return S_OK; - } - -private: - - COpcCriticalSection m_cLock; - ULONG m_ulRefs; - ULONG m_ulLocks; - const TOpcClassTableEntry* m_pClassInfo; -}; - -//============================================================================== -// FUNCTION: OpcGetClassObject -// PURPOSE: Gets the class factory for the specified COM server. -// NOTES: - -OPCUTILS_API HRESULT OpcGetClassObject( - REFCLSID rclsid, - REFIID riid, - LPVOID* ppv, - const TOpcClassTableEntry* pClasses); - -//============================================================================== -// FUNCTION: OpcRegisterClassObject -// PURPOSE: Registers COM servers for use as an EXE server. -// NOTES: - -OPCUTILS_API HRESULT OpcRegisterClassObjects( - const TOpcClassTableEntry* pClasses, - DWORD dwContext, - DWORD dwFlags, - DWORD* pdwRegister); - -//============================================================================== -// FUNCTION: OpcRevokeClassObject -// PURPOSE: Unregisters COM servers for use as an EXE server. -// NOTES: - -OPCUTILS_API HRESULT OpcRevokeClassObjects( - const TOpcClassTableEntry* pClasses, - DWORD* pdwRegister); - -//============================================================================== -// FUNCTION: OpcRegisterServer -// PURPOSE: Registers COM servers for the module. -// NOTES: - -OPCUTILS_API HRESULT OpcRegisterServer( - HINSTANCE hModule, - LPCTSTR tsVendorName, - LPCTSTR tsApplicationName, - LPCTSTR tsApplicationDescription, - const GUID& cAppID, - bool bService, - const TOpcClassTableEntry* pClasses, - const TClassCategories* pCategories, - bool bEveryone); - -//============================================================================== -// FUNCTION: OpcUnregisterServer -// PURPOSE: Unregisters COM servers for the module. -// NOTES: - -OPCUTILS_API HRESULT OpcUnregisterServer( - HINSTANCE hModule, - LPCTSTR tsVendorName, - LPCTSTR tsApplicationName, - const GUID& cAppID, - const TOpcClassTableEntry* pClasses, - const TClassCategories* pCategories); - -//============================================================================== -// MACRO: OPC_BEGIN_CLASS_MAP -// PURPOSE: Starts the COM class table. -// NOTES: - -#define OPC_BEGIN_CLASS_TABLE() \ -\ -static HINSTANCE g_hModule = NULL; \ -static const TOpcClassTableEntry g_pClassTable[] = { - -//============================================================================== -// MACRO: OPC_CLASS_ENTRY -// PURPOSE: Adds a class to the COM class table. -// NOTES: - -#define OPC_CLASS_TABLE_ENTRY(xClass, xClassName, xClassVersion, xClassDescription) \ -{ \ - &(__uuidof(xClassName)), \ - _T(#xClassName), \ - _T(#xClassVersion), \ - _T(xClassDescription), \ - (PfnOpcCreateInstance*)xClass::CreateInstance \ -}, - -//============================================================================== -// MACRO: OPC_END_CLASS_MAP -// PURPOSE: Completes the COM class table. -// NOTES: - -#define OPC_END_CLASS_TABLE() {&CLSID_NULL, NULL, NULL, NULL, NULL}}; - -#endif // _COpcClassFactory_H diff --git a/ComIOP/Wrapper/Common/COpcComModule.cpp b/ComIOP/Wrapper/Common/COpcComModule.cpp deleted file mode 100644 index b6841b449..000000000 --- a/ComIOP/Wrapper/Common/COpcComModule.cpp +++ /dev/null @@ -1,1406 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcComModule.h" -#include "COpcTextReader.h" -#include "OpcRegistry.h" -#include "COpcSecurity.h" -#include "COpcList.h" -#include "COpcMap.h" -#include "COpcXmlDocument.h" - -//============================================================================== -// Static Data - -static COpcComModule* g_pModule = NULL; - -//============================================================================== -// Local Declarations - -#define OPCREG_CONFIG_INFO _T("ConfigInfo") -#define OPCREG_SELFREG_INFO _T("SelfRegInfo") -#define OPCREG_VENDOR_NAME _T("VendorName") -#define OPCREG_APPLICATION_NAME _T("ApplicationName") -#define OPCREG_APPLICATION_DESCRIPTION _T("ApplicationDescription") -#define OPCREG_APPID _T("AppID") -#define OPCREG_CLASS_NAME _T("ClassName") -#define OPCREG_CLASS_DESCRIPTION _T("ClassDescription") -#define OPCREG_CLASS_VERSION _T("ClassVersion") -#define OPCREG_CLSID _T("CLSID") -#define OPCREG_ALLOW_EVERYONE_ACCESS _T("AllowEveryoneAccess") -#define OPCREG_SERVER_WRAPPER _T("ServerWrapper") - -//============================================================================== -// ServiceMain - -static void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) -{ - OPC_ASSERT(g_pModule != NULL); - - g_pModule->ServiceMain(dwArgc, lpszArgv); -} - -//============================================================================== -// EventHandler - -static void WINAPI EventHandler(DWORD fdwControl) -{ - OPC_ASSERT(g_pModule != NULL); - - g_pModule->EventHandler(fdwControl); -} - -//============================================================================== -// ExitProcess - -void COpcComModule::ExitProcess(DWORD dwExitCode) -{ - OPC_ASSERT(g_pModule != NULL); - - g_pModule->m_cServiceStatus.dwWin32ExitCode = dwExitCode; - - PostThreadMessage(g_pModule->m_dwThread, WM_QUIT, 0, 0); -} - -//============================================================================== -// OpcWinMain - -OPCUTILS_API DWORD OpcWinMain( - COpcComModule* pModule, - HINSTANCE hInstance, - LPTSTR lpCmdLine -) -{ - OPC_ASSERT(pModule != NULL); - - g_pModule = pModule; - - DWORD dwResult = g_pModule->WinMain(hInstance, lpCmdLine); - - g_pModule = NULL; - - return dwResult; -} - -//============================================================================== -// OpcExtractSelfRegInfo - -HRESULT OpcExtractSelfRegInfo(IXMLDOMElement* ipRoot, IXMLDOMElement** ippInfo) -{ - BSTR bstrName = NULL; - IXMLDOMElement* ipElement = NULL; - - *ippInfo = NULL; - - HRESULT hResult = S_OK; - - TRY - { - hResult = ipRoot->get_firstChild((IXMLDOMNode**)&ipElement); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = ipElement->get_nodeName(&bstrName); - - if (FAILED(hResult)) - { - THROW(); - } - - if (((COpcString)bstrName) == OPCREG_SELFREG_INFO) - { - hResult = ipRoot->removeChild(ipElement, (IXMLDOMNode**)ippInfo); - - if (FAILED(hResult)) - { - THROW(); - } - } - } - CATCH_FINALLY - { - if (bstrName != NULL) SysFreeString(bstrName); - if (ipElement != NULL) ipElement->Release(); - } - - return hResult; -} - -//============================================================================== -// OpcInsertSelfRegInfo - -HRESULT OpcInsertSelfRegInfo(IXMLDOMElement* ipRoot, IXMLDOMElement* ipInfo) -{ - IXMLDOMElement* ipElement = NULL; - IXMLDOMElement* ipResult = NULL; - - HRESULT hResult = S_OK; - - TRY - { - VARIANT_BOOL bHasChildren = VARIANT_FALSE; - - hResult = ipRoot->hasChildNodes(&bHasChildren); - - if (FAILED(hResult)) - { - THROW(); - } - - if (bHasChildren == VARIANT_TRUE) - { - hResult = ipRoot->get_firstChild((IXMLDOMNode**)&ipElement); - - if (FAILED(hResult)) - { - THROW(); - } - - VARIANT vRefChild; - vRefChild.vt = VT_UNKNOWN; - vRefChild.punkVal = ipElement; - - hResult = ipRoot->insertBefore(ipInfo, vRefChild, (IXMLDOMNode**)&ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - } - else - { - hResult = ipRoot->appendChild(ipInfo, (IXMLDOMNode**)&ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - } - } - CATCH_FINALLY - { - if (ipElement != NULL) ipElement->Release(); - if (ipResult != NULL) ipResult->Release(); - } - - return hResult; -} - -//============================================================================== -// COpcComModule - -// Constructor -COpcComModule::COpcComModule( - const COpcString& cVendorName, - const COpcString& cApplicationName, - const COpcString& cApplicationDescription, - const GUID& cAppID, - const TOpcClassTableEntry* pClasses, - const TClassCategories* pCategories, - bool bIsWrapper -) -: - m_cAppID(cAppID) -{ - m_cVendorName = cVendorName; - m_cApplicationName = cApplicationName; - m_cApplicationDescription = cApplicationDescription; - - m_pClasses = (TOpcClassTableEntry*)pClasses; - m_pCategories = (TClassCategories*)pCategories; - m_bRegFromFile = false; - - m_bWrapper = bIsWrapper; - m_pWrappedClasses = NULL; - - m_hModule = NULL; - m_dwThread = NULL; - m_hServiceStatus = NULL; - - memset(&m_cServiceStatus, 0, sizeof(m_cServiceStatus)); -} - -// Destructor -COpcComModule::~COpcComModule() -{ - if (m_bRegFromFile) - { - FreeClassTable(m_pClasses); - OpcFree(m_pCategories); - CoUninitialize(); - } -} - - -// GetConfigParam -bool COpcComModule::GetConfigParam(const COpcString& cName, COpcString& cValue) -{ - return m_cParameters.Lookup(cName, cValue); -} - -// WinMain -DWORD COpcComModule::WinMain( - HINSTANCE hInstance, - LPTSTR lpCmdLine -) -{ - m_hModule = hInstance; - - // need to extract the executable name from the command line. - WCHAR* pchCommandLine = GetCommandLine(); - BOOL isQuoted = FALSE; - - if (*pchCommandLine == '"') - { - isQuoted = TRUE; - pchCommandLine++; - } - - while (*pchCommandLine != '\0') - { - // check for quotes. - if (isQuoted) - { - if (*pchCommandLine == '"') - { - pchCommandLine++; - break; - } - } - - // check for whitespace. - else - { - if (iswspace(*pchCommandLine)) - { - pchCommandLine++; - break; - } - } - - pchCommandLine++; - } - - // skip trailing whitespace. - while (iswspace(*pchCommandLine)) - { - pchCommandLine++; - } - - // parse command line arguments. - COpcText cText; - COpcTextReader cReader(pchCommandLine); - - // skip until first command flag - if any. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L"-/"); - - if (cReader.GetNext(cText)) - { - // read first command flag. - cText.SetType(COpcText::NonWhitespace); - cText.SetEofDelim(); - - if (cReader.GetNext(cText)) - { - COpcString cFlags = ((COpcString&)cText).ToLower(); - - // register module as local server. - if (cFlags== _T("regserver")) return RegisterServer(false); - - // register module as service. - if (cFlags== _T("service")) return RegisterServer(true); - - // unregister module. - if (cFlags == _T("unregserver")) return UnregisterServer(); - } - } - - // check for service key in registry. - LPTSTR tsValue; - - bool bService = OpcRegGetValue( - HKEY_CLASSES_ROOT, - _T("AppID\\") + (COpcString)m_cAppID, - _T("LocalService"), - &tsValue); - - - // enter the main execution loop when running as an EXE server. - if (!bService) - { - Run(); - } - - // start the service main thread when running as a service. - else - { - OpcFree(tsValue); - - // initialize status structure. - m_cServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - m_cServiceStatus.dwCurrentState = SERVICE_STOPPED; - m_cServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; - m_cServiceStatus.dwWin32ExitCode = 0; - m_cServiceStatus.dwServiceSpecificExitCode = 0; - m_cServiceStatus.dwCheckPoint = 0; - m_cServiceStatus.dwWaitHint = 0; - - SERVICE_TABLE_ENTRY* pServices = new SERVICE_TABLE_ENTRY[2]; - - pServices[0].lpServiceName = (LPTSTR)(LPCTSTR)m_cApplicationName; - pServices[0].lpServiceProc = ::ServiceMain; - pServices[1].lpServiceName = NULL; - pServices[1].lpServiceProc = NULL; - - // notify the server control manager. - if (!StartServiceCtrlDispatcher(pServices)) - { - delete [] pServices; - return -1; - } - - delete [] pServices; - } - - return m_cServiceStatus.dwWin32ExitCode; -} - -// ServiceMain -void COpcComModule::ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) -{ - // register handler for service control events. - m_hServiceStatus = RegisterServiceCtrlHandler(m_cApplicationName, ::EventHandler); - - if (m_hServiceStatus == NULL) - { - return; - } - - // update service state. - m_cServiceStatus.dwCurrentState = SERVICE_START_PENDING; - SetServiceStatus(m_hServiceStatus, &m_cServiceStatus); - - m_cServiceStatus.dwWin32ExitCode = S_OK; - m_cServiceStatus.dwCheckPoint = 0; - m_cServiceStatus.dwWaitHint = 0; - - // enter the main execution loop. - Run(); - - // update service state. - m_cServiceStatus.dwCurrentState = SERVICE_STOPPED; - SetServiceStatus(m_hServiceStatus, &m_cServiceStatus); -} - -// EventHandler -void COpcComModule::EventHandler(DWORD fdwControl) -{ - switch (fdwControl) - { - case SERVICE_CONTROL_STOP: - { - // update service state. - m_cServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus(m_hServiceStatus, &m_cServiceStatus); - - // post quit message. - PostThreadMessage(m_dwThread, WM_QUIT, 0, 0); - break; - } - - default: - { - // do nothing. - break; - } - } -} - -// Run -void COpcComModule::Run() -{ - HRESULT hResult = S_OK; - - // record service control thread. - m_dwThread = GetCurrentThreadId(); - - // intialize thread as free threaded service. - hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED); - - if (FAILED(hResult)) - { - return; - } - - // create a NULL DACL which will allow access to everyone. - COpcSecurity cSecurity; - - hResult = cSecurity.InitializeFromThreadToken(); - - if (FAILED(hResult)) - { - return; - } - - // initialize security. - hResult = CoInitializeSecurity( - cSecurity, - -1, - NULL, - NULL, - RPC_C_AUTHN_LEVEL_PKT, - RPC_C_IMP_LEVEL_IMPERSONATE, - NULL, - EOAC_NONE, - NULL); - - if (FAILED(hResult)) - { - // security may have already been initialized when registering classes from config file. - if (hResult != RPC_E_TOO_LATE) - { - return; - } - } - - DWORD pdwRegister[256]; - - // register class objects. - hResult = OpcRegisterClassObjects( - m_pClasses, - CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, - REGCLS_MULTIPLEUSE, - pdwRegister); - - if (FAILED(hResult)) - { - return; - } - - // check if a wrapper process. - if (m_bWrapper) - { - // load classes from registry. - m_pWrappedClasses = GetClassesFromRegistry(m_pClasses); - - // register class objects for wrapped classes. - if (m_pWrappedClasses != NULL) - { - OpcRegisterClassObjects( - m_pWrappedClasses, - CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, - REGCLS_MULTIPLEUSE, - pdwRegister); - } - } - - // update service state. - m_cServiceStatus.dwCurrentState = SERVICE_RUNNING; - - if (m_hServiceStatus != NULL) - { - SetServiceStatus(m_hServiceStatus, &m_cServiceStatus); - } - - TRY - { - // enter message loop. - MSG cMsg; - while (GetMessage(&cMsg, 0, 0, 0)) DispatchMessage(&cMsg); - } - CATCH - { - } - - // revoke wrapped classes. - if (m_pWrappedClasses != NULL) - { - OpcRevokeClassObjects(m_pWrappedClasses, pdwRegister); - } - - // unregister class objects. - OpcRevokeClassObjects(m_pClasses, pdwRegister); - - // unregister com libraries. - CoUninitialize(); -} - -// RegisterServer -HRESULT COpcComModule::RegisterServer(bool bService) -{ - COpcString cValue; - bool bEveryone = GetConfigParam(OPCREG_ALLOW_EVERYONE_ACCESS, cValue); - - return OpcRegisterServer( - m_hModule, - m_cVendorName, - m_cApplicationName, - m_cApplicationDescription, - m_cAppID, - bService, - m_pClasses, - m_pCategories, - bEveryone); -} - -// UnregisterServer -HRESULT COpcComModule::UnregisterServer() -{ - return OpcUnregisterServer( - m_hModule, - m_cVendorName, - m_cApplicationName, - m_cAppID, - m_pClasses, - m_pCategories); -} - -// RegisterFromFiles -HRESULT COpcComModule::RegisterFromFiles(HINSTANCE hModule) -{ - CoInitializeEx(NULL, COINIT_MULTITHREADED); - - // create a NULL DACL which will allow access to everyone. - COpcSecurity cSecurity; - - HRESULT hResult = cSecurity.InitializeFromThreadToken(); - - if (FAILED(hResult)) - { - return hResult; - } - - // initialize security. - hResult = CoInitializeSecurity( - cSecurity, - -1, - NULL, - NULL, - RPC_C_AUTHN_LEVEL_PKT, - RPC_C_IMP_LEVEL_IMPERSONATE, - NULL, - EOAC_NONE, - NULL); - - if (FAILED(hResult)) - { - return hResult; - } - - // ================= - // TJF - skip GetClassesFromFiles and just use the hard-coded configuration - // defined by macros 'OPC_CLASS_TABLE_ENTRY' & 'OPC_CATEGORY_TABLE_ENTRY'. Not clear - // at this point how to support multiple CoClasses from XML file - m_bRegFromFile = false; - return S_OK; - // ================= - - - COpcString cVendorName; - COpcString cApplicationName; - COpcString cApplicationDescription; - GUID cAppID; - - // get classes from config file(s). - TOpcClassTableEntry* pClassesFromFile = GetClassesFromFiles( - hModule, - m_pClasses, - cVendorName, - cApplicationName, - cApplicationDescription, - cAppID - ); - - // check for error reading from file - use defaults. - if (pClassesFromFile == NULL) - { - m_bRegFromFile = false; - return S_OK; - } - - m_cVendorName = cVendorName; - m_cApplicationName = cApplicationName; - m_cApplicationDescription = cApplicationDescription; - m_cAppID = cAppID; - - // check if the server wraps other servers. - COpcString cWrapper; - - if (GetConfigParam(OPCREG_SERVER_WRAPPER, cWrapper)) - { - m_bWrapper = (cWrapper.ToLower() == _T("true")); - } - - // replace the class and category tables with the auto generated ones. - for (UINT uClassCount = 0; pClassesFromFile[uClassCount].tsClassName != NULL; uClassCount++); - for (UINT uCategoryCount = 0; m_pCategories[uCategoryCount].pClsid != NULL; uCategoryCount++); - - TClassCategories* pCategoriesFromFile = OpcArrayAlloc(TClassCategories, uClassCount*uCategoryCount+1); - memset(pCategoriesFromFile, 0, (uClassCount*uCategoryCount+1)*sizeof(TClassCategories)); - - UINT uIndex = 0; - - for (UINT ii = 0; pClassesFromFile[ii].tsClassName != NULL; ii++) - { - for (UINT jj = 0; m_pCategories[jj].pClsid != NULL; jj++) - { - pCategoriesFromFile[uIndex].pClsid = pClassesFromFile[ii].pClsid; - pCategoriesFromFile[uIndex].pCategory = m_pCategories[jj].pCategory; - uIndex++; - } - } - - m_pClasses = pClassesFromFile; - m_pCategories = pCategoriesFromFile; - m_bRegFromFile = true; - - return S_OK; -} - -// InsertSelfRegInfo -HRESULT COpcComModule::InsertSelfRegInfo( - COpcXmlElement& cRoot, - const TOpcClassTableEntry* pClasses -) -{ - BSTR bstrName = NULL; - BSTR bstrNamespace = NULL; - - IXMLDOMElement* ipInfo = NULL; - IXMLDOMDocument* ipDocument = NULL; - - HRESULT hResult = S_OK; - - TRY - { - IXMLDOMElement* ipRoot = cRoot; - - HRESULT hResult = ipRoot->get_ownerDocument(&ipDocument); - - if (FAILED(hResult)) - { - THROW(); - } - - VARIANT vNodeType; - vNodeType.vt = VT_I4; - vNodeType.lVal = NODE_ELEMENT; - - BSTR bstrName = SysAllocString((COpcString)OPCREG_SELFREG_INFO); - BSTR bstrNamespace = SysAllocString((COpcString)OPCXML_NS_OPC); - - hResult = ipDocument->createNode(vNodeType, bstrName, bstrNamespace, (IXMLDOMNode**)&ipInfo); - - if (FAILED(hResult)) - { - THROW(); - } - - COpcXmlElement cElement = ipInfo; - - // save the default information. - WRITE_ELEMENT(OPCREG_VENDOR_NAME, m_cVendorName); - WRITE_ELEMENT(OPCREG_APPLICATION_NAME, m_cApplicationName); - WRITE_ELEMENT(OPCREG_APPLICATION_DESCRIPTION, m_cApplicationDescription); - WRITE_ELEMENT(OPCREG_APPID, m_cAppID); - WRITE_ELEMENT(OPCREG_CLASS_NAME, (COpcString)pClasses[0].tsClassName); - WRITE_ELEMENT(OPCREG_CLASS_DESCRIPTION, (COpcString)pClasses[0].tsClassDescription); - WRITE_ELEMENT(OPCREG_CLASS_VERSION, (COpcString)pClasses[0].tsClassVersion); - WRITE_ELEMENT(OPCREG_CLSID, *(pClasses[0].pClsid)); - - OpcInsertSelfRegInfo(ipRoot, ipInfo); - } - CATCH_FINALLY - { - SysFreeString(bstrName); - SysFreeString(bstrNamespace); - - if (ipInfo != NULL) ipInfo->Release(); - if (ipDocument != NULL) ipDocument->Release(); - } - - return hResult; -} - -// GetClassesFromFiles -TOpcClassTableEntry* COpcComModule::GetClassesFromFiles( - HINSTANCE hModule, - const TOpcClassTableEntry* pClasses, - COpcString& cVendorName, - COpcString& cApplicationName, - COpcString& cApplicationDescription, - GUID& cAppID -) -{ - // lookup the module path. - TCHAR tsPath[MAX_PATH+1]; - memset(tsPath, 0, sizeof(tsPath)); - - GetModuleFileName(hModule, tsPath, MAX_PATH); - - // split into components. - TCHAR tsDrive[_MAX_DRIVE]; - TCHAR tsDir[_MAX_DIR]; - TCHAR tsName[_MAX_FNAME]; - TCHAR tsExtention[_MAX_EXT]; - - _tsplitpath(tsPath, tsDrive, tsDir, tsName, tsExtention); - - // construct config file parh. - COpcString cConfigFile; - - cConfigFile += tsDrive; - cConfigFile += tsDir; - cConfigFile += tsName; - cConfigFile += OPCREG_CONFIG_FILE_SUFFIX; - - // load the XML document. - COpcXmlDocument cDocument; - - if (!cDocument.Load(cConfigFile)) - { - return NULL; - } - - COpcXmlElement cRoot = cDocument.GetRoot(); - - // nothing more to do document is not valid. - if (cRoot == NULL) - { - return NULL; - } - - // populate the configuration parameters table. - cRoot.GetAttributes(m_cParameters); - - // find the registration element. - COpcXmlElement cElement = cRoot.GetChild(OPCREG_SELFREG_INFO); - - if (cElement == NULL) - { - // insert default self registration info. - HRESULT hResult = InsertSelfRegInfo(cRoot, pClasses); - - // persist the configuration with the self registration info. - if (SUCCEEDED(hResult)) - { - cDocument.Save(); - }; - } - - // nothing more to do if self reg info was not found. - if (cElement == NULL) - { - return NULL; - } - - // read registration information from the XML document. - COpcString cClassName; - COpcString cClassDescription; - COpcString cClassVersion; - CLSID cClsid = GUID_NULL; - - READ_ELEMENT(OPCREG_VENDOR_NAME, cVendorName); - READ_ELEMENT(OPCREG_APPLICATION_NAME, cApplicationName); - READ_ELEMENT(OPCREG_APPLICATION_DESCRIPTION, cApplicationDescription); - READ_ELEMENT(OPCREG_APPID, cAppID); - READ_ELEMENT(OPCREG_CLASS_NAME, cClassName); - READ_ELEMENT(OPCREG_CLASS_DESCRIPTION, cClassDescription); - READ_ELEMENT(OPCREG_CLASS_VERSION, cClassVersion); - READ_ELEMENT(OPCREG_CLSID, cClsid); - - // check that all require information has been provided. - if ( - cVendorName.IsEmpty() || - cAppID == GUID_NULL || - cClassName.IsEmpty() || - cClsid == GUID_NULL - ) - { - return NULL; - } - - // default application name as class name. - if (cApplicationName.IsEmpty()) - { - cApplicationName = cClassName; - } - - // default application description as class description. - if (cApplicationDescription.IsEmpty()) - { - cApplicationDescription = cClassDescription; - } - - // re-allocate class table dynamically, - TOpcClassTableEntry* pClassesFromFile = OpcArrayAlloc(TOpcClassTableEntry, 2); - memset(pClassesFromFile, 0, sizeof(TOpcClassTableEntry)*2); - - pClassesFromFile[0].tsClassName = OpcStrDup((LPCTSTR)cClassName); - pClassesFromFile[0].tsClassDescription = OpcStrDup((LPCTSTR)cClassDescription); - pClassesFromFile[0].tsClassVersion = OpcStrDup((LPCTSTR)cClassVersion); - pClassesFromFile[0].pClsid = (CLSID*)OpcAlloc(sizeof(CLSID)); - *((CLSID*)(pClassesFromFile[0].pClsid)) = cClsid; - pClassesFromFile[0].pfnCreateInstance = pClasses[0].pfnCreateInstance; - - return pClassesFromFile; -} - -// 899A3076-F94E-4695-9DF8-0ED25B02BDBA -static const GUID CATID_PseudoComServers = {0x899A3076, 0xF94E, 0x4695, { 0x9D, 0xF8, 0x0E, 0xD2, 0x5B, 0x02, 0xBD, 0xBA } }; - -// GetClassesFromRegistry map -TOpcClassTableEntry* COpcComModule::GetClassesFromRegistry( - const TOpcClassTableEntry* pClasses -) -{ - // read registration information from the XML document. - COpcString cClassName; - COpcString cClassDescription; - COpcString cClassVersion; - CLSID cClsid = GUID_NULL; - - CreatorsMap creatorsByCategory; - HRESULT hResult = GetHostCreatorsByCategory (pClasses, creatorsByCategory); - if (FAILED(hResult)) - { - return NULL; - } - - COpcList cClsids; - - hResult = OpcEnumServersInCategory(NULL, CATID_PseudoComServers, &cClsids); - - if (FAILED(hResult)) - { - return NULL; - } - - UINT uCount = cClsids.GetCount(); - - if (uCount == 0) - { - return NULL; - } - - // re-allocate class table dynamically, - TOpcClassTableEntry* pClassesFromFile = OpcArrayAlloc(TOpcClassTableEntry, uCount+1); - memset(pClassesFromFile, 0, sizeof(TOpcClassTableEntry)*(uCount+1)); - - OPC_POS pos = cClsids.GetHeadPosition(); - - for (UINT ii = 0; pos != NULL; ii++) - { - CLSID cClsid = cClsids.GetNext(pos); - PfnOpcCreateInstance* pCreator = NULL; - - COpcString cSubKey(_T("CLSID\\")); - cSubKey += (COpcString)cClsid; - cSubKey += _T("\\ProgID"); - - LPTSTR tsProgID = NULL; - bool bResult = OpcRegGetValue(HKEY_CLASSES_ROOT, cSubKey, NULL, &tsProgID); - - if (bResult) - { - pCreator = FindHostCreatorByCategory(creatorsByCategory, cClsid); - - pClassesFromFile[ii].tsClassName = OpcStrDup(tsProgID); - pClassesFromFile[ii].tsClassDescription = OpcStrDup(tsProgID); - pClassesFromFile[ii].tsClassVersion = NULL; - pClassesFromFile[ii].pClsid = (CLSID*)OpcAlloc(sizeof(CLSID)); - *((CLSID*)(pClassesFromFile[ii].pClsid)) = cClsid; - if (pCreator) - pClassesFromFile[ii].pfnCreateInstance = pCreator; - else - pClassesFromFile[ii].pfnCreateInstance = pClasses[0].pfnCreateInstance; - - OpcFree(tsProgID); - } - } - - return pClassesFromFile; -} - -// FreeClassTable -void COpcComModule::FreeClassTable(TOpcClassTableEntry* ppClassesFromFile) -{ - for (UINT ii = 0; ppClassesFromFile[ii].tsClassName != NULL; ii++) - { - OpcFree((LPTSTR)ppClassesFromFile[ii].tsClassName); - OpcFree((LPTSTR)ppClassesFromFile[ii].tsClassDescription); - OpcFree((LPTSTR)ppClassesFromFile[ii].tsClassVersion); - OpcFree((CLSID*)ppClassesFromFile[ii].pClsid); - } - - OpcFree(ppClassesFromFile); -} - - -//============================================================================== -// OpcServerRegInfo - -HRESULT OpcServerRegInfo( - const COpcString& cSrcFile, - COpcString& cVendorName, - COpcString& cApplicationName, - COpcString& cApplicationDescription, - GUID& cAppID, - COpcString& cClassName, - COpcString& cClassDescription, - COpcString& cClassVersion, - GUID& cClsid -) -{ - HRESULT hResult = S_OK; - - TRY - { - // load the configuration file. - COpcXmlDocument cConfigDocument; - - if (!cConfigDocument.Load(cSrcFile)) - { - THROW_(hResult, E_FAIL); - } - - // find the existing self registration element. - COpcXmlElement cElement = cConfigDocument.GetRoot().GetChild(OPCREG_SELFREG_INFO); - - if (cElement == NULL) - { - THROW_(hResult, E_FAIL); - } - - READ_ELEMENT(OPCREG_VENDOR_NAME, cVendorName); - READ_ELEMENT(OPCREG_APPLICATION_NAME, cApplicationName); - READ_ELEMENT(OPCREG_APPLICATION_DESCRIPTION, cApplicationDescription); - READ_ELEMENT(OPCREG_APPID, cAppID); - READ_ELEMENT(OPCREG_CLASS_NAME, cClassName); - READ_ELEMENT(OPCREG_CLASS_DESCRIPTION, cClassDescription); - READ_ELEMENT(OPCREG_CLASS_VERSION, cClassVersion); - READ_ELEMENT(OPCREG_CLSID, cClsid); - } - CATCH - { - } - - return hResult; -} - -//============================================================================== -// OpcCopyServer - -HRESULT OpcCopyServer( - const COpcString& cSrcPath, - const COpcString& cDstPath, - const COpcString& cVendorName, - const COpcString& cApplicationName, - const COpcString& cApplicationDescription, - const GUID& cAppID, - const COpcString& cClassName, - const COpcString& cClassDescription, - const COpcString& cClassVersion, - const GUID& cClsid -) -{ - // parse the source path. - COpcString cSrcBase = cSrcPath; - - int iIndex = cSrcBase.ReverseFind(OPCREG_CONFIG_FILE_SUFFIX); - - if (iIndex == -1) - { - return E_INVALIDARG; - } - - cSrcBase = cSrcBase.SubStr(0, iIndex); - - // parse the destination path. - COpcString cDstBase = cDstPath; - - iIndex = cDstBase.ReverseFind(OPCREG_CONFIG_FILE_SUFFIX); - - if (iIndex != -1) - { - cDstBase = cDstBase.SubStr(0, iIndex); - } - - HRESULT hResult = S_OK; - - TRY - { - // load the configuration file. - COpcString cConfigFile; - - cConfigFile += cSrcBase; - cConfigFile += OPCREG_CONFIG_FILE_SUFFIX; - - // parse the document. - COpcXmlDocument cConfigDocument; - - if (!cConfigDocument.Load(cConfigFile)) - { - THROW_(hResult, E_FAIL); - } - - // find the existing self registration element. - COpcXmlElement cElement = cConfigDocument.GetRoot().GetChild(OPCREG_SELFREG_INFO); - - if (cElement == NULL) - { - cElement = cConfigDocument.GetRoot().AddChild(OPCREG_SELFREG_INFO); - } - - WRITE_ELEMENT(OPCREG_VENDOR_NAME, cVendorName); - WRITE_ELEMENT(OPCREG_APPLICATION_NAME, cApplicationName); - WRITE_ELEMENT(OPCREG_APPLICATION_DESCRIPTION, cApplicationDescription); - WRITE_ELEMENT(OPCREG_APPID, cAppID); - WRITE_ELEMENT(OPCREG_CLASS_NAME, cClassName); - WRITE_ELEMENT(OPCREG_CLASS_DESCRIPTION, cClassDescription); - WRITE_ELEMENT(OPCREG_CLASS_VERSION, cClassVersion); - WRITE_ELEMENT(OPCREG_CLSID, cClsid); - - // save the document. - cConfigFile = cDstBase; - cConfigFile += OPCREG_CONFIG_FILE_SUFFIX; - - if (!cConfigDocument.Save(cConfigFile)) - { - THROW_(hResult, E_FAIL); - } - - // copy the COM server executable binary file. - CopyFile((COpcString)(cSrcBase + _T(".exe")), (COpcString)(cDstBase + _T(".exe")), FALSE); - } - CATCH - { - } - - return hResult; -} - -// OpcGetModuleName -COpcString OpcGetModuleName() -{ - COpcString cConfigPath; - - // get executable path. - TCHAR tsPath[MAX_PATH+1]; - memset(tsPath, 0, sizeof(tsPath)); - - DWORD dwResult = GetModuleFileName(NULL, tsPath, MAX_PATH); - - if (dwResult == 0) - { - return cConfigPath; - } - - cConfigPath = tsPath; - - // remove directory. - int iIndex = cConfigPath.ReverseFind(_T("\\")); - - if (iIndex != -1) - { - cConfigPath = cConfigPath.SubStr(iIndex+1); - } - - // remove extension. - iIndex = cConfigPath.ReverseFind(_T(".")); - - if (iIndex != -1) - { - cConfigPath = cConfigPath.SubStr(0, iIndex); - } - - return cConfigPath; -} - -// OpcGetModulePath -COpcString OpcGetModulePath() -{ - COpcString cConfigPath; - - // get executable path. - TCHAR tsPath[MAX_PATH+1]; - memset(tsPath, 0, sizeof(tsPath)); - - DWORD dwResult = GetModuleFileName(NULL, tsPath, MAX_PATH); - - if (dwResult == 0) - { - return cConfigPath; - } - - cConfigPath = tsPath; - - // remove file name. - int iIndex = cConfigPath.ReverseFind(_T("\\")); - - if (iIndex != -1) - { - cConfigPath = cConfigPath.SubStr(0, iIndex); - } - - return cConfigPath; -} - -// OpcGetModuleVersion -bool OpcGetModuleVersion(OpcVersionInfo& cInfo) -{ - // initialize output parameters. - cInfo.cFileDescription.Empty(); - cInfo.wMajorVersion = 0; - cInfo.wMinorVersion = 0; - cInfo.wBuildNumber = 0; - cInfo.wRevisionNumber = 0; - - // get module path. - TCHAR tsModuleName[MAX_PATH+1]; - memset(tsModuleName, 0, sizeof(tsModuleName)); - - DWORD dwResult = GetModuleFileName(NULL, tsModuleName, sizeof(tsModuleName)); - - if (dwResult == 0) - { - return false; - } - - // get the size of the version info blob. - DWORD dwSize = GetFileVersionInfoSize(tsModuleName, NULL); - - if (dwSize == 0) - { - return false; - } - - // allocate space for the version info blob. - BYTE* pBuffer = OpcArrayAlloc(BYTE, dwSize); - memset(pBuffer, 0, dwSize); - - // get the version info blob. - if (GetFileVersionInfo(tsModuleName, NULL, dwSize, pBuffer)) - { - // get the base version info. - UINT uInfoSize = 0; - VS_FIXEDFILEINFO* pInfo = NULL; - - if (VerQueryValue(pBuffer, _T("\\"), (void**)&pInfo, &uInfoSize)) - { - cInfo.wMajorVersion = (WORD)((pInfo->dwFileVersionMS>>16)&0x00FF); - cInfo.wMinorVersion = (WORD)(pInfo->dwFileVersionMS&0x00FF); - cInfo.wBuildNumber = (WORD)((pInfo->dwFileVersionLS>>16)&0x00FF); - cInfo.wRevisionNumber = (WORD)(pInfo->dwFileVersionLS&0x00FF); - } - - UINT uTranslateSize = 0; - struct LANGANDCODEPAGE { WORD wLanguage; WORD wCodePage; }* pTranslate = NULL; - - // read the list of languages and code pages. - if (VerQueryValue(pBuffer, - _T("\\VarFileInfo\\Translation"), - (void**)&pTranslate, - &uTranslateSize)) - { - TCHAR tsSubBlock[MAX_PATH+1]; - memset(tsSubBlock, 0, sizeof(tsSubBlock)); - - _stprintf( - tsSubBlock, - _T("\\StringFileInfo\\%04x%04x\\FileDescription"), - pTranslate->wLanguage, - pTranslate->wCodePage - ); - - TCHAR* pBlock = NULL; - UINT uBlockSize = 0; - - if (VerQueryValue(pBuffer, tsSubBlock, (void**)&pBlock, &uTranslateSize)) - { - cInfo.cFileDescription = pBlock; - } - } - } - - // free the buffer. - OpcFree(pBuffer); - - return true; -} - -// 132B3E2B-0E92-4816-972B-E42AA9532529 -static const GUID CATID_ComDllServerHost = {0x132B3E2B, 0x0E92, 0x4816, { 0x97, 0x2B, 0xE4, 0x2A, 0xA9, 0x53, 0x25, 0x29 } }; - -// GetHostCreatorsByCategory -HRESULT GetHostCreatorsByCategory (const TOpcClassTableEntry* pClasses, CreatorsMap& creatorsByCategory) -{ - HRESULT hResult = S_OK; - ICatInformation* ipInfo = NULL; - IEnumCATID* penumCATID = NULL; - - TRY - { - // create component category manager. - hResult = CoCreateInstance( - CLSID_StdComponentCategoriesMgr, - NULL, - CLSCTX_INPROC_SERVER, - IID_ICatInformation, - (void**)&ipInfo - ); - - if (FAILED(hResult)) - { - THROW(); - } - - creatorsByCategory.RemoveAll(); - - for (UINT i = 0; pClasses[i].tsClassName != NULL; i++) - { - hResult = ipInfo->EnumImplCategoriesOfClass(*(pClasses[i].pClsid), &penumCATID); - - if (FAILED(hResult)) - { - THROW(); - } - - do - { - ULONG ulFetched = 0; - CATID catid = GUID_NULL; - - hResult = penumCATID->Next(1, &catid, &ulFetched); - - if (ulFetched == 1 && (catid != CATID_ComDllServerHost)) - { - creatorsByCategory[catid] = pClasses[i].pfnCreateInstance; - } - } - while (hResult == S_OK); - - if (FAILED(hResult)) - { - THROW(); - } - } - - // error while enumerating clsids. - if (FAILED(hResult)) - { - THROW(); - } - } - CATCH - { - creatorsByCategory.RemoveAll(); - } - FINALLY - { - if (penumCATID != NULL) penumCATID->Release(); - if (ipInfo != NULL) ipInfo->Release(); - } - - return hResult; - -} - -// FindHostCreatorByCategory -PfnOpcCreateInstance* FindHostCreatorByCategory(const CreatorsMap& creatorsByCategory, const GUID& cClsid) -{ - - HRESULT hResult = S_OK; - ICatInformation* ipInfo = NULL; - IEnumCATID* penumCATID = NULL; - PfnOpcCreateInstance* pCreator = NULL; - - TRY - { - // create component category manager. - hResult = CoCreateInstance( - CLSID_StdComponentCategoriesMgr, - NULL, - CLSCTX_INPROC_SERVER, - IID_ICatInformation, - (void**)&ipInfo - ); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = ipInfo->EnumImplCategoriesOfClass(cClsid, &penumCATID); - - do - { - ULONG ulFetched = 0; - CATID catid = GUID_NULL; - - hResult = penumCATID->Next(1, &catid, &ulFetched); - - if (ulFetched == 1 && (catid != CATID_PseudoComServers)) - { - if (creatorsByCategory.Lookup(catid, pCreator)) - { - break; - } - } - } - while (hResult == S_OK); - - if (FAILED(hResult)) - { - THROW(); - } - - // error while enumerating clsids. - if (FAILED(hResult)) - { - THROW(); - } - } - CATCH - { - pCreator = NULL; - } - FINALLY - { - if (penumCATID != NULL) penumCATID->Release(); - if (ipInfo != NULL) ipInfo->Release(); - } - - return pCreator; -} diff --git a/ComIOP/Wrapper/Common/COpcComModule.h b/ComIOP/Wrapper/Common/COpcComModule.h deleted file mode 100644 index 7fd1c81ef..000000000 --- a/ComIOP/Wrapper/Common/COpcComModule.h +++ /dev/null @@ -1,372 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcComModule_H_ -#define _COpcComModule_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcString.h" -#include "COpcMap.h" -#include "COpcCriticalSection.h" -#include "COpcClassFactory.h" -#include "COpcXmlElement.h" - -//============================================================================== -// CLASS: COpcComModule -// PURPOSE: Manages initialization and registration of a COM ComModule. - -class OPCUTILS_API COpcComModule -{ - OPC_CLASS_NEW_DELETE() - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcComModule( - const COpcString& cVendorName, - const COpcString& cApplicationName, - const COpcString& cApplicationDescription, - const GUID& cAppID, - const TOpcClassTableEntry* pClasses, - const TClassCategories* pCategories, - bool bIsWrapper - ); - - // Destructor - ~COpcComModule(); - - //========================================================================== - // Public Methods - - // ExitProcess - static void ExitProcess(DWORD dwExitCode); - - // WinMain - virtual DWORD WinMain( - HINSTANCE hInstance, - LPTSTR lpCmdLine - ); - - // ServiceMain - void ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv); - - // EventHandler - void EventHandler(DWORD fdwControl); - - // RegisterFromFiles - HRESULT RegisterFromFiles(HINSTANCE hModule); - - // GetConfigParam - bool GetConfigParam(const COpcString& cName, COpcString& cValue); - -protected: - - //========================================================================== - // Protected Methods - - // RegisterServer - HRESULT RegisterServer(bool bService); - - // UnregisterServer - HRESULT UnregisterServer(); - - // Run - void Run(); - - // GetClassesFromFiles - TOpcClassTableEntry* GetClassesFromFiles( - HINSTANCE hModule, - const TOpcClassTableEntry* pClasses, - COpcString& cVendorName, - COpcString& cApplicationName, - COpcString& cApplicationDescription, - GUID& cAppID - ); - - // GetClassesFromRegistry - TOpcClassTableEntry* GetClassesFromRegistry( - const TOpcClassTableEntry* pClasses); - - // FreeClassTable - void FreeClassTable(TOpcClassTableEntry* ppClassesFromFile); - - // InsertSelfRegInfo - HRESULT InsertSelfRegInfo( - COpcXmlElement& cRoot, - const TOpcClassTableEntry* pClasses - ); - - //========================================================================== - // Protected Members - - HINSTANCE m_hModule; - - COpcString m_cVendorName; - COpcString m_cApplicationName; - COpcString m_cApplicationDescription; - GUID m_cAppID; - - TOpcClassTableEntry* m_pClasses; - TClassCategories* m_pCategories; - bool m_bRegFromFile; - bool m_bEveryone; - COpcStringMap m_cParameters; - - bool m_bWrapper; - TOpcClassTableEntry* m_pWrappedClasses; - - DWORD m_dwThread; - SERVICE_STATUS m_cServiceStatus; - SERVICE_STATUS_HANDLE m_hServiceStatus; -}; - - -//============================================================================== -// FUNCTION: OpcWinMain -// PURPOSE: The main entry point for the executable. - -extern COpcComModule& OpcGetModule(); - -//============================================================================== -// FUNCTION: OpcWinMain -// PURPOSE: The main entry point for the executable. - -OPCUTILS_API DWORD OpcWinMain( - COpcComModule* pModule, - HINSTANCE hInstance, - LPTSTR lpCmdLine -); - -//============================================================================== -// MACRO: OPC_DECLARE_APPLICATION -// PURPOSE: Declares the vendor name, the application name and the description. - -#define OPC_DECLARE_APPLICATION(xVendor, xName, xDescription, xIsWrapperProcess) \ -static const LPCTSTR g_tsVendorName = _T(#xVendor); \ -static const LPCTSTR g_tsApplicationName = _T(#xName); \ -static const LPCTSTR g_tsApplicationDescription = _T(xDescription); \ -static const bool g_bIsWrapperProcess = xIsWrapperProcess; - -//============================================================================== -// MACRO: OPC_IMPLEMENT_LOCAL_SERVER -// PURPOSE: Declares required functions for a local COM server module. - -#define OPC_IMPLEMENT_LOCAL_SERVER(l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ -static const GUID g_cAppID = {l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; \ -static COpcComModule* g_pModule = NULL; \ -COpcComModule& OpcGetModule() { return *g_pModule; } - -//============================================================================== -// MACRO: OPC_START_LOCAL_SERVER -// PURPOSE: Starts the main execution loop for an EXE COM server. - -#define OPC_START_LOCAL_SERVER(xInstance, xCmdLine) \ -{ \ - g_pModule = new COpcComModule( \ - g_tsVendorName, \ - g_tsApplicationName, \ - g_tsApplicationDescription, \ - g_cAppID, \ - g_pClassTable, \ - g_pCategoryTable, \ - g_bIsWrapperProcess); \ -\ - DWORD dwResult = OpcWinMain(g_pModule, xInstance, xCmdLine); \ -\ - delete g_pModule; \ - g_pModule = NULL; \ -\ - return dwResult; \ -} - -//============================================================================== -// MACRO: OPC_START_LOCAL_SERVER_EX -// PURPOSE: Starts the main execution loop for an EXE COM server that uses configuration files. - -#define OPC_START_LOCAL_SERVER_EX(xInstance, xCmdLine) \ -{ \ - COpcComModule* pModule = new COpcComModule( \ - g_tsVendorName, \ - g_tsApplicationName, \ - g_tsApplicationDescription, \ - g_cAppID, \ - g_pClassTable, \ - g_pCategoryTable, \ - g_bIsWrapperProcess); \ -\ - pModule->RegisterFromFiles(xInstance); \ -\ - DWORD dwResult = OpcWinMain(pModule, xInstance, xCmdLine); \ -\ - delete pModule; \ - return dwResult; \ -} - -//============================================================================== -// MACRO: OPC_START_INPROC_SERVER -// PURPOSE: Intializes a DLL COM server. - -#define OPC_START_INPROC_SERVER(xInstance, xReason) \ -{ \ - if (xReason == DLL_PROCESS_ATTACH) g_hModule = xInstance; \ -} - -//============================================================================== -// MACRO: OPC_IMPLEMENT_INPROC_SERVER -// PURPOSE: Declares required functions for an in process COM server module. - -#define OPC_IMPLEMENT_INPROC_SERVER() \ -STDAPI DllCanUnloadNow(void) { return S_FALSE; } \ -STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { return OpcGetClassObject(rclsid, riid, ppv, g_pClassTable); } \ -\ -STDAPI DllRegisterServer(void) \ -{ \ - return OpcRegisterServer( \ - g_hModule, \ - g_tsVendorName, \ - NULL, \ - NULL, \ - GUID_NULL, \ - false, \ - g_pClassTable, \ - g_pCategoryTable, \ - false); \ -} \ -\ -STDAPI DllUnregisterServer(void) \ -{ \ - return OpcUnregisterServer( \ - g_hModule, \ - g_tsVendorName, \ - NULL, \ - GUID_NULL, \ - g_pClassTable, \ - g_pCategoryTable); \ -} - -//============================================================================== -// MACRO: OPCREG_CONFIG_FILE_SUFFIX -// PURPOSE: Declares the suffix used by COM server configuration files. - -#define OPCREG_CONFIG_FILE_SUFFIX _T(".config.xml") - -//============================================================================== -// FUNCTION: OpcExtractSelfRegInfo -// PURPOSE: Removes the self registration information from an XML document. - -OPCUTILS_API HRESULT OpcExtractSelfRegInfo(IXMLDOMElement* ipRoot, IXMLDOMElement** ippInfo); - -//============================================================================== -// FUNCTION: OpcInsertSelfRegInfo -// PURPOSE: Inserts the self registration information into an XML document. - -OPCUTILS_API HRESULT OpcInsertSelfRegInfo(IXMLDOMElement* ipRoot, IXMLDOMElement* ipInfo); - -//============================================================================== -// FUNCTION: OpcGetModuleName -// PURPOSE: Returns the name of the current executable. - -OPCUTILS_API COpcString OpcGetModuleName(); - -//============================================================================== -// FUNCTION: OpcGetModulePath -// PURPOSE: Returns the full file path of the current executable. - -OPCUTILS_API COpcString OpcGetModulePath(); - -//============================================================================== -// STRUCTURE: OpcVersionInfo -// PURPOSE: Stores information extracted from the version info resource. - -// OpcVersionInfo -struct OPCUTILS_API OpcVersionInfo -{ - COpcString cFileDescription; - WORD wMajorVersion; - WORD wMinorVersion; - WORD wBuildNumber; - WORD wRevisionNumber; - - // Constructor - OpcVersionInfo() - { - wMajorVersion = 0; - wMinorVersion = 0; - wBuildNumber = 0; - wRevisionNumber = 0; - } - - // Copy Constructor - OpcVersionInfo(const OpcVersionInfo& cInfo) - { - cFileDescription = cInfo.cFileDescription; - wMajorVersion = cInfo.wMajorVersion; - wMinorVersion = cInfo.wMinorVersion; - wBuildNumber = cInfo.wBuildNumber; - wRevisionNumber = cInfo.wRevisionNumber; - } -}; - -//============================================================================== -// FUNCTION: OpcGetModuleVersion -// PURPOSE: Looks up the version resource block for the current executable. - -OPCUTILS_API bool OpcGetModuleVersion(OpcVersionInfo& cInfo); - -//============================================================================== - -struct CATIDcmp -{ - bool operator()(const CATID c1, CATID c2) const - { return (c1.Data1 < c2.Data1); } // simplistic comparison -- assumes 'Data1' fields are unique -}; - -typedef COpcMap CreatorsMap; - -//============================================================================== -// FUNCTION: GetHostCreatorsByCategory -// PURPOSE: Associates a classfactory creator function with each category supported by -// the hosting process. - -OPCUTILS_API HRESULT GetHostCreatorsByCategory (const TOpcClassTableEntry* pClasses, CreatorsMap& creatorsByCategory); - -//============================================================================== -// FUNCTION: FindHostCreatorByCategory -// PURPOSE: Returns the classfactory creator function appropriate for the Pseudoserver with CLSID 'cClsid'. - -OPCUTILS_API PfnOpcCreateInstance* FindHostCreatorByCategory(const CreatorsMap& creatorsByCategory, const GUID& cClsid); - -#endif // _COpcComModule_H_ diff --git a/ComIOP/Wrapper/Common/COpcComObject.h b/ComIOP/Wrapper/Common/COpcComObject.h deleted file mode 100644 index d521f1d31..000000000 --- a/ComIOP/Wrapper/Common/COpcComObject.h +++ /dev/null @@ -1,256 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcComObject_H -#define _COpcComObject_H - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" - -//============================================================================== -// TITLE: COpcComObject.h -// PURPOSE: Defines the base class for COM servers -// NOTES: - -class OPCUTILS_API COpcComObject -{ - OPC_CLASS_NEW_DELETE_ARRAY(); - -public: - - //========================================================================== - // Operators - - // Constructor - COpcComObject() - { - // set the reference count to one - calling function must release. - m_ulRefs = 1; - } - - // Destructor - virtual ~COpcComObject() - { - OPC_ASSERT(m_ulRefs == 0); - } - - //========================================================================== - // Public Methods - - // InternalAddRef - // - // Description - // - // Adds a reference to the COM server. - // - // Return Codes - // - // The current number of references. - - virtual ULONG InternalAddRef() - { - return InterlockedIncrement((LONG*)&m_ulRefs); - } - - // InternalRelease - // - // Description - // - // Removes a reference to the COM server. If the reference reaches zero - // it calls FinalRelease() and deletes the instance. - // - // Return Codes - // - // The current number of references. - - virtual ULONG InternalRelease() - { - ULONG ulRefs = InterlockedDecrement((LONG*)&m_ulRefs); - - if (ulRefs == 0) - { - if (FinalRelease()) - { - delete this; - } - - return 0; - } - - return ulRefs; - } - - // InternalQueryInterface - // - // Description - // - // An pure virtual method that the COM server's interface map implements. - // The inteface map macro's add a stub QueryInterface implmentation - // that call this function. It calls AddRef() so the client must call - // Release() on the returned interface. - // - // Parameters; - // - // iid The desired interface IID. - // ppInterface The returned interface. - // - // Return Codes - // - // S_OK if the interface is supported - // E_NOINTERFACE if not. - - virtual HRESULT InternalQueryInterface(REFIID iid, LPVOID* ppInterface) = 0; - - // FinalConstruct - // - // Description - // - // A function called by the class factory after creating the object. - // The COM server does any server specific initialization. - // - // Return Codes - // - // S_OK if intialization succeeded. - - virtual HRESULT FinalConstruct() - { - return S_OK; - } - - // FinalRelease - // - // Description - // - // A function called by release after the reference count drops to zero - // before deleting the object. The COM server does any server specific - // uninitialization. - // - - virtual bool FinalRelease() - { - // returning false would stop the caller from explicitly deleting the object. - return true; - } - -private: - - //========================================================================== - // Private Members - - ULONG m_ulRefs; -}; - -//============================================================================== -// MACRO: OPC_BEGIN_INTERFACE_TABLE -// PURPOSE: Starts the COM server's interface table. -// NOTES: - -#define OPC_BEGIN_INTERFACE_TABLE(xClass) \ -private: \ -\ -const CLSID* m_pClsid; \ -\ -protected: \ -\ -REFCLSID GetCLSID() { return *m_pClsid; } \ -\ -public: \ -\ -static HRESULT __stdcall CreateInstance(IUnknown** ippUnknown, const CLSID* pClsid) \ -{ \ - if (ippUnknown == NULL) return E_POINTER; \ - *ippUnknown = NULL; \ -\ - xClass* pObject = new xClass(); \ -\ - pObject->m_pClsid = pClsid; \ -\ - HRESULT hResult = pObject->FinalConstruct(); \ -\ - if (FAILED(hResult)) \ - { \ - pObject->Release(); \ - return hResult; \ - } \ -\ - hResult = pObject->QueryInterface(IID_IUnknown, (void**)ippUnknown); \ - pObject->Release(); \ - return hResult; \ -} \ -\ -virtual HRESULT InternalQueryInterface(REFIID iid, LPVOID* ppInterface) \ -{ \ - if (ppInterface == NULL) return E_POINTER; \ - *ppInterface = NULL; - -//============================================================================== -// MACRO: OPC_INTERFACE_ENTRY -// PURPOSE: Adds an interface to the COM server's interface table. -// NOTES: - -#define OPC_INTERFACE_ENTRY(xInterface) \ -\ -if (iid == __uuidof(xInterface) || iid == IID_IUnknown) \ -{ \ - *ppInterface = (dynamic_cast(this)); \ - AddRef(); \ - return S_OK; \ -} - -//============================================================================== -// MACRO: OPC_AGGREGATE_OBJECT -// PURPOSE: Adds an interface to the COM server's interface table. -// NOTES: - -#define OPC_AGGREGATE_OBJECT(xObject) \ -\ -if (xObject != NULL) \ -{ \ - return xObject->QueryInterface(iid, ppInterface); \ -} - -//============================================================================== -// MACRO: OPC_END_INTERFACE_TABLE -// PURPOSE: Completes the COM server's interface table. -// NOTES: - -#define OPC_END_INTERFACE_TABLE() \ -return E_NOINTERFACE; } \ -\ -STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppInterface) {return InternalQueryInterface(iid, ppInterface);} \ -STDMETHODIMP_(ULONG) AddRef() {return InternalAddRef();} \ -STDMETHODIMP_(ULONG) Release() {return InternalRelease();} - -#define OPC_END_INTERFACE_TABLE_DEBUG() \ -return E_NOINTERFACE; } - -#endif // _COpcComObject_H diff --git a/ComIOP/Wrapper/Common/COpcCommon.cpp b/ComIOP/Wrapper/Common/COpcCommon.cpp deleted file mode 100644 index 715936093..000000000 --- a/ComIOP/Wrapper/Common/COpcCommon.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcCommon.h" - -//============================================================================== -// Local Declarations - -#define MAX_ERROR_STRING 1024 - -#define LOCALE_ENGLISH_US MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) -#define LOCALE_ENGLISH_NEUTRAL MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), SORT_DEFAULT) - -//============================================================================== -// COpcCommon - -COpcCommon::COpcCommon() -{ - m_dwLcid = LOCALE_SYSTEM_DEFAULT; - m_cClientName = _T(""); -} - -// Destructor -COpcCommon::~COpcCommon() -{ - // do nothing. -} - -// SetLocaleID -HRESULT COpcCommon::SetLocaleID(LCID dwLcid) -{ - // check that the locale is supported. - switch (dwLcid) - { - case LOCALE_ENGLISH_US: - case LOCALE_ENGLISH_NEUTRAL: - case LOCALE_NEUTRAL: - case LOCALE_INVARIANT: - case LOCALE_SYSTEM_DEFAULT: - case LOCALE_USER_DEFAULT: - { - m_dwLcid = dwLcid; - return S_OK; - } - - default: - { - const LCID* pLcids = GetAvailableLocaleIDs(); - - if (pLcids != NULL) - { - for (int ii = 0; pLcids[ii] != NULL; ii++) - { - if (pLcids[ii] == dwLcid) - { - m_dwLcid = dwLcid; - return S_OK; - } - } - } - - break; - } - } - - // locale not available - return error. - return E_INVALIDARG; -} - -// GetLocaleID -HRESULT COpcCommon::GetLocaleID(LCID* pdwLcid) -{ - // invalid arguments - return error. - if (pdwLcid == NULL) - { - return E_INVALIDARG; - } - - *pdwLcid = m_dwLcid; - return S_OK; -} - -// QueryAvailableLocaleIDs -HRESULT COpcCommon::QueryAvailableLocaleIDs(DWORD* pdwCount, LCID** pdwLcid) -{ - // invalid arguments - return error. - if (pdwCount == NULL || pdwLcid == NULL) - { - return E_INVALIDARG; - } - - // always supports english and neutral cultures. - *pdwCount = 4; - - // get additional locales. - const LCID* pLcids = GetAvailableLocaleIDs(); - - // count the available locales. - if (pLcids != NULL) - { - for (int ii = 0; pLcids[ii] != NULL; ii++) (*pdwCount)++; - } - - // allocate array. - *pdwLcid = (LCID*)CoTaskMemAlloc((*pdwCount)*sizeof(LCID)); - - // add default locales. - (*pdwLcid)[0] = LOCALE_ENGLISH_US; - (*pdwLcid)[1] = LOCALE_ENGLISH_NEUTRAL; - (*pdwLcid)[2] = LOCALE_NEUTRAL; - (*pdwLcid)[3] = LOCALE_INVARIANT; - - DWORD temp = GetSystemDefaultLCID(); - - // add additional locales. - if (pLcids != NULL) - { - for (int ii = 0; pLcids[ii] != NULL; ii++) (*pdwLcid)[ii+4] = pLcids[ii]; - } - - // everything ok. - return S_OK; -} - -// GetErrorString -HRESULT COpcCommon::GetErrorString(HRESULT dwError, LPWSTR* ppString) -{ - return GetErrorString(dwError, m_dwLcid, ppString); -} - -// GetErrorString -COpcString COpcCommon::GetErrorString( - const COpcString& cModuleName, - HRESULT hError -) -{ - COpcString cString; - LPWSTR pString = NULL; - - HRESULT hResult = COpcCommon::GetErrorString(cModuleName, hError, LOCALE_NEUTRAL, &pString); - - if (SUCCEEDED(hResult)) - { - cString = pString; - OpcFree(pString); - } - - return cString; -} - -// FormatMessage -static bool FormatMessage( - LANGID langID, - DWORD dwCode, - LPCTSTR szModuleName, - TCHAR* tsBuffer, - DWORD dwLength -) -{ - // attempt to load string from module message table. - DWORD dwResult = FormatMessage( - FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, - ::GetModuleHandle(szModuleName), - dwCode, - langID, - tsBuffer, - dwLength-1, - NULL - ); - - // attempt to load string from system message table. - if (dwResult == 0) - { - dwResult = FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dwCode, - langID, - tsBuffer, - dwLength-1, - NULL - ); - } - - return (dwResult != 0); -} - -// GetErrorString -HRESULT COpcCommon::GetErrorString( - LPCTSTR szModuleName, - HRESULT dwError, - LCID dwLocale, - LPWSTR* ppString -) -{ - // check arguments. - if (ppString == NULL) - { - return E_INVALIDARG; - } - - *ppString = NULL; - - LANGID langID = LANGIDFROMLCID(dwLocale); - - // lookup languages for 'special' locales. - switch (dwLocale) - { - case LOCALE_SYSTEM_DEFAULT: - { - langID = GetSystemDefaultLangID(); - break; - } - - case LOCALE_USER_DEFAULT: - { - langID = GetUserDefaultLangID(); - break; - } - - case LOCALE_INVARIANT: - { - langID = LANGIDFROMLCID(LOCALE_NEUTRAL); - break; - } - } - - // initialize buffer for message. - TCHAR tsMsg[MAX_ERROR_STRING+1]; - memset(tsMsg, 0, sizeof(tsMsg)); - - if (!FormatMessage(langID, dwError, szModuleName, tsMsg, MAX_ERROR_STRING+1)) - { - // check if the locale explicitly requested a particular language. - if (dwLocale == LOCALE_SYSTEM_DEFAULT || dwLocale == LOCALE_USER_DEFAULT) - { - // try to load message using special locales. - if (!FormatMessage(LANGIDFROMLCID(dwLocale), dwError, szModuleName, tsMsg, MAX_ERROR_STRING+1)) - { - // use US english if a default locale was requested but language is not supported by server. - if (!FormatMessage(LANGIDFROMLCID(LOCALE_ENGLISH_US), dwError, szModuleName, tsMsg, MAX_ERROR_STRING+1)) - { - return E_INVALIDARG; - } - } - } - else - { - // return US english for variants for english. - if (PRIMARYLANGID(langID) == LANG_ENGLISH) - { - if (!FormatMessage(LANGIDFROMLCID(LOCALE_ENGLISH_US), dwError, szModuleName, tsMsg, MAX_ERROR_STRING+1)) - { - return E_INVALIDARG; - } - } - - // locale is not supported at all. - else - { - return E_INVALIDARG; - } - } - } - - COpcString cMsg = tsMsg; - - // remove trailing \r\n. - if (cMsg.ReverseFind(_T("\r\n")) == (int)(cMsg.GetLength()-2)) - { - cMsg = cMsg.SubStr(0, cMsg.GetLength()-2); - } - - // allocate string for return. - *ppString = OpcStrDup((LPCWSTR)cMsg); - - return S_OK; -} - -// SetClientName -HRESULT COpcCommon::SetClientName(LPCWSTR szName) -{ - m_cClientName = szName; - return S_OK; -} diff --git a/ComIOP/Wrapper/Common/COpcCommon.h b/ComIOP/Wrapper/Common/COpcCommon.h deleted file mode 100644 index 9d10a3f78..000000000 --- a/ComIOP/Wrapper/Common/COpcCommon.h +++ /dev/null @@ -1,133 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcCommon_H_ -#define _COpcCommon_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "opccomn.h" - -#include "OpcDefs.h" -#include "COpcString.h" - -//============================================================================== -// FUNCTION: OPCXX_MESSAGE_MODULE_NAME -// PURPOSE: Names for modules that contain text for standard OPC messages. - -#define OPC_MESSAGE_MODULE_NAME_AE _T("opc_aeps") -#define OPC_MESSAGE_MODULE_NAME_BATCH _T("opcbc_ps") -#define OPC_MESSAGE_MODULE_NAME_DA _T("opcproxy") -#define OPC_MESSAGE_MODULE_NAME_DX _T("opcdxps") -#define OPC_MESSAGE_MODULE_NAME_HDA _T("opchda_ps") -#define OPC_MESSAGE_MODULE_NAME_SEC _T("opcsec_ps") -#define OPC_MESSAGE_MODULE_NAME_CMD _T("opccmdps") - -//============================================================================== -// CLASS: COpcCommon -// PURPOSE: Implements the IOPCCommon interface. -// NOTES: - -class OPCUTILS_API COpcCommon : public IOPCCommon -{ -public: - - //========================================================================== - // Operators - - // Constructor - COpcCommon(); - - // Destructor - ~COpcCommon(); - - //========================================================================== - // Public Methods - - // GetErrorString - static COpcString GetErrorString( - const COpcString& cModuleName, - HRESULT hResult - ); - - // GetErrorString - static STDMETHODIMP GetErrorString( - LPCTSTR szModuleName, - HRESULT dwError, - LCID dwLocale, - LPWSTR* ppString - ); - - //========================================================================== - // IOPCCommon - - // SetLocaleID - STDMETHODIMP SetLocaleID(LCID dwLcid); - - // GetLocaleID - STDMETHODIMP GetLocaleID(LCID *pdwLcid); - - // QueryAvailableLocaleIDs - STDMETHODIMP QueryAvailableLocaleIDs(DWORD* pdwCount, LCID** pdwLcid); - - // GetErrorString - STDMETHODIMP GetErrorString(HRESULT dwError, LPWSTR* ppString); - - // SetClientName - STDMETHODIMP SetClientName(LPCWSTR szName); - -protected: - - //========================================================================== - // Protected Methods - - // GetLocaleID - LCID GetLocaleID() const { return m_dwLcid; } - - // GetClientName - const COpcString& GetClientName() const { return m_cClientName; } - - // GetAvailableLocaleIDs - virtual const LCID* GetAvailableLocaleIDs() { return NULL; } - - // GetErrorString - virtual STDMETHODIMP GetErrorString(HRESULT dwError, LCID dwLocale, LPWSTR* ppString) = 0; - -private: - - //========================================================================== - // Private Members - - LCID m_dwLcid; - COpcString m_cClientName; -}; - -#endif // _COpcCommon_H_ diff --git a/ComIOP/Wrapper/Common/COpcConnectionPoint.cpp b/ComIOP/Wrapper/Common/COpcConnectionPoint.cpp deleted file mode 100644 index 660811dc0..000000000 --- a/ComIOP/Wrapper/Common/COpcConnectionPoint.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcConnectionPoint.h" -#include "COpcCPContainer.h" - -#include "opcda.h" - -//============================================================================== -// COpcConnectionPoint - -// Constructor -COpcConnectionPoint::COpcConnectionPoint() -{ - m_tInterface = GUID_NULL; - m_pContainer = NULL; - m_ipCallback = NULL; - m_dwCookie = NULL; - m_bFetched = false; -} - -// Constructor -COpcConnectionPoint::COpcConnectionPoint(const IID& tIid, COpcCPContainer* pContainer) -{ - m_tInterface = tIid; - m_pContainer = pContainer; - m_ipCallback = NULL; - m_dwCookie = NULL; - m_bFetched = false; -} - -// Destructor -COpcConnectionPoint::~COpcConnectionPoint() -{ - if (m_ipCallback != NULL) m_ipCallback->Release(); -} - -// Delete -bool COpcConnectionPoint::Delete() -{ - COpcLock cLock(*this); - - if (m_ipCallback != NULL) - { - m_ipCallback->Release(); - m_ipCallback = NULL; - } - - m_pContainer = NULL; - - cLock.Unlock(); - - // return false if reference still exist. - return (Release() == 0); -} - -//============================================================================== -// IConnectionPoint - -// GetConnectionInterface -HRESULT COpcConnectionPoint::GetConnectionInterface(IID* pIID) -{ - COpcLock cLock(*this); - - if (pIID == NULL) - { - return E_INVALIDARG; - } - - *pIID = m_tInterface; - return S_OK; -} - -// GetConnectionPointContainer -HRESULT COpcConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer** ppCPC) -{ - COpcLock cLock(*this); - - if (ppCPC == NULL) - { - return E_INVALIDARG; - } - - if (m_pContainer != NULL) - { - return m_pContainer->QueryInterface(IID_IConnectionPointContainer, (void**)ppCPC); - } - - return E_FAIL; -} - -// Advise -HRESULT COpcConnectionPoint::Advise(IUnknown* pUnkSink, DWORD* pdwCookie) -{ - COpcLock cLock(*this); - - // invalid arguments. - if (pUnkSink == NULL || pdwCookie == NULL) - { - return E_POINTER; - } - - *pdwCookie = NULL; - - // check if an callback already exists. - if (m_ipCallback != NULL) - { - return CONNECT_E_ADVISELIMIT; - } - - // get the connection callback interface. - HRESULT hResult = pUnkSink->QueryInterface(m_tInterface, (void**)&m_ipCallback); - - if (FAILED(hResult)) - { - return hResult; - } - - // use interface as a unique id. - m_dwCookie = (DWORD)m_ipCallback; - *pdwCookie = m_dwCookie; - - // notify the container. - COpcCPContainer* pContainer = m_pContainer; - - if (pContainer != NULL) - { - pContainer->AddRef(); - } - - DWORD dwCookie = m_dwCookie; - - cLock.Unlock(); - - if (pContainer != NULL) - { - pContainer->OnAdvise(m_tInterface, dwCookie); - pContainer->Release(); - } - - return S_OK; -} - -// Unadvise -HRESULT COpcConnectionPoint::Unadvise(DWORD dwCookie) -{ - COpcLock cLock(*this); - - // not a valid connection id. - if (m_dwCookie != dwCookie || m_ipCallback == NULL) - { - return CONNECT_E_NOCONNECTION; - } - - m_ipCallback->Release(); - - // notify the container. - COpcCPContainer* pContainer = m_pContainer; - - if (pContainer != NULL) - { - pContainer->AddRef(); - } - - m_ipCallback = NULL; - m_dwCookie = NULL; - - cLock.Unlock(); - - if (pContainer != NULL) - { - pContainer->OnUnadvise(m_tInterface, dwCookie); - pContainer->Release(); - } - - return S_OK; -} - -// EnumConnections -HRESULT COpcConnectionPoint::EnumConnections(IEnumConnections** ppEnum) -{ - COpcLock cLock(*this); - - // invalid arguments. - if (ppEnum == NULL) - { - return E_POINTER; - } - - // no separate object required since one and only one callback exists. - return QueryInterface(IID_IEnumConnections, (void**)ppEnum); -} - -//============================================================================== -// FUNCTION: OpcConnect -// PURPOSE: Establishes a connection to the server. - -OPCUTILS_API HRESULT OpcConnect( - IUnknown* ipSource, - IUnknown* ipSink, - REFIID riid, - DWORD* pdwConnection) -{ - HRESULT hResult = S_OK; - - IConnectionPoint* pCP = NULL; - IConnectionPointContainer* ipCPC = NULL; - IUnknown* ipCallback = NULL; - - TRY - { - // check for valid arguments. - if (ipSource == NULL || ipSink == NULL || pdwConnection == NULL) - { - THROW_(hResult, E_POINTER); - } - - // query for container. - hResult = ipSource->QueryInterface(IID_IConnectionPointContainer, (void**)&ipCPC); - - if (FAILED(hResult)) - { - THROW(); - } - - // find connection point. - hResult = ipCPC->FindConnectionPoint(riid, &pCP); - - if (FAILED(hResult)) - { - THROW(); - } - - // query for interface. - hResult = ipSink->QueryInterface(riid, (void**)&ipCallback); - - if (FAILED(hResult)) - { - THROW(); - } - - // connect - hResult = pCP->Advise(ipCallback, pdwConnection); - - if (FAILED(hResult)) - { - THROW(); - } - } - CATCH_FINALLY - { - if (pCP != NULL) pCP->Release(); - if (ipCPC != NULL) ipCPC->Release(); - if (ipCallback != NULL) ipCallback->Release(); - } - - return hResult; -} - -//============================================================================== -// FUNCTION: OpcDisconnect -// PURPOSE: Closes a connection to the server. - -OPCUTILS_API HRESULT OpcDisconnect( - IUnknown* ipSource, - REFIID riid, - DWORD dwConnection) -{ - HRESULT hResult = S_OK; - - IConnectionPoint* pCP = NULL; - IConnectionPointContainer* ipCPC = NULL; - - TRY - { - // check for valid arguments. - if (ipSource == NULL) - { - THROW_(hResult, E_POINTER); - } - - // query for container. - hResult = ipSource->QueryInterface(IID_IConnectionPointContainer, (void**)&ipCPC); - - if (FAILED(hResult)) - { - THROW(); - } - - // find connection point. - hResult = ipCPC->FindConnectionPoint(riid, &pCP); - - if (FAILED(hResult)) - { - THROW(); - } - - // disconnect - hResult = pCP->Unadvise(dwConnection); - - if (FAILED(hResult)) - { - THROW(); - } - } - CATCH_FINALLY - { - if (pCP != NULL) pCP->Release(); - if (ipCPC != NULL) ipCPC->Release(); - } - - return hResult; -} diff --git a/ComIOP/Wrapper/Common/COpcConnectionPoint.h b/ComIOP/Wrapper/Common/COpcConnectionPoint.h deleted file mode 100644 index a08a506a4..000000000 --- a/ComIOP/Wrapper/Common/COpcConnectionPoint.h +++ /dev/null @@ -1,140 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcConnectionPoint_H_ -#define _COpcConnectionPoint_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "ocidl.h" - -#include "OpcDefs.h" -#include "COpcComObject.h" -#include "COpcCriticalSection.h" - -class COpcCPContainer; - -//============================================================================== -// CLASS: COpcConnectionPoint -// PURPOSE: Implements the IConnectionPoint interface. -// NOTES: - -class OPCUTILS_API COpcConnectionPoint -: - public COpcComObject, - public COpcSynchObject, - public IConnectionPoint -{ - OPC_BEGIN_INTERFACE_TABLE(COpcConnectionPoint) - OPC_INTERFACE_ENTRY(IConnectionPoint) - OPC_END_INTERFACE_TABLE() - - OPC_CLASS_NEW_DELETE() - -public: - - //========================================================================== - // Operators - - // Constructor - COpcConnectionPoint(); - - // Constructor - COpcConnectionPoint(const IID& tIid, COpcCPContainer* pContainer); - - // Destructor - ~COpcConnectionPoint(); - - //========================================================================== - // IConnectionPoint - - // GetConnectionInterface - STDMETHODIMP GetConnectionInterface(IID* pIID); - - // GetConnectionPointContainer - STDMETHODIMP GetConnectionPointContainer(IConnectionPointContainer** ppCPC); - - // Advise - STDMETHODIMP Advise(IUnknown* pUnkSink, DWORD* pdwCookie); - - // Unadvise - STDMETHODIMP Unadvise(DWORD dwCookie); - - // EnumConnections - STDMETHODIMP EnumConnections(IEnumConnections** ppEnum); - - //========================================================================== - // Public Methods - - // GetCallback - IUnknown* GetCallback() { return m_ipCallback; } - - // GetInterface - const IID& GetInterface() { return m_tInterface; } - - // Delete - bool Delete(); - - // IsConnected - bool IsConnected() { return (m_dwCookie != NULL); } - -private: - - //========================================================================== - // Private Members - - IID m_tInterface; - COpcCPContainer* m_pContainer; - IUnknown* m_ipCallback; - DWORD m_dwCookie; - bool m_bFetched; -}; - -//============================================================================== -// FUNCTION: OpcConnect -// PURPOSE: Establishes a connection to the server. - -OPCUTILS_API HRESULT OpcConnect( - IUnknown* ipSource, - IUnknown* ipSink, - REFIID riid, - DWORD* pdwConnection); - -//============================================================================== -// FUNCTION: OpcDisconnect -// PURPOSE: Closes a connection to the server. - -OPCUTILS_API HRESULT OpcDisconnect( - IUnknown* ipSource, - REFIID riid, - DWORD dwConnection); - -#endif // _COpcConnectionPoint_H_ diff --git a/ComIOP/Wrapper/Common/COpcCriticalSection.h b/ComIOP/Wrapper/Common/COpcCriticalSection.h deleted file mode 100644 index e3ac85c17..000000000 --- a/ComIOP/Wrapper/Common/COpcCriticalSection.h +++ /dev/null @@ -1,198 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcCriticalSection_H_ -#define _COpcCriticalSection_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" - -//============================================================================== -// TITLE: COpcCriticalSection.h -// PURPOSE: Implements a wrapper for a critical section. -// NOTES: - -class OPCUTILS_API COpcCriticalSection -{ - OPC_CLASS_NEW_DELETE(); - -public: - - //========================================================================== - // Operators - - // Constructor - inline COpcCriticalSection() - { - m_ulLocks = 0; - m_dwThread = -1; - - InitializeCriticalSection(&m_csLock); - } - - // Destructor - inline ~COpcCriticalSection() - { - DeleteCriticalSection(&m_csLock); - } - - //========================================================================== - // Public Methods - - // Lock - inline void Lock() - { - EnterCriticalSection(&m_csLock); - - if (m_dwThread == -1) - { - m_dwThread = GetCurrentThreadId(); - } - - OPC_ASSERT(m_dwThread == GetCurrentThreadId()); - - m_ulLocks++; - } - - // Unlock - inline void Unlock() - { - OPC_ASSERT(m_dwThread == GetCurrentThreadId()); - OPC_ASSERT(m_ulLocks > 0); - - m_ulLocks--; - - if (m_ulLocks == 0) - { - m_dwThread = -1; - } - - LeaveCriticalSection(&m_csLock); - } - - // HasLock - inline bool HasLock() - { - return (m_dwThread == GetCurrentThreadId()); - } - -private: - - //=========================================================================== - // Private Members - - CRITICAL_SECTION m_csLock; - DWORD m_dwThread; - ULONG m_ulLocks; -}; - -//============================================================================== -// TITLE: COpcLock.h -// PURPOSE: Implements a class that leaves a critical section when destroyed. -// NOTES: - -class COpcLock -{ -public: - - //========================================================================== - // Operators - - // Constructor - inline COpcLock(const COpcCriticalSection& cLock) - : - m_pLock(NULL) - { - m_pLock = (COpcCriticalSection*)&cLock; - m_pLock->Lock(); - m_uLocks = 1; - } - - // Destructor - inline ~COpcLock() - { - while (m_uLocks > 0) Unlock(); - } - - //========================================================================== - // Public Methods - - inline void Unlock() - { - OPC_ASSERT(m_uLocks > 0); - - m_uLocks--; - - if (m_uLocks == 0) - { - m_pLock->Unlock(); - } - } - - inline void Lock() - { - if (m_uLocks == 0) - { - m_pLock->Lock(); - } - - m_uLocks++; - } - -private: - - UINT m_uLocks; - COpcCriticalSection* m_pLock; -}; - -//============================================================================== -// TITLE: COpcSynchObject.h -// PURPOSE: A base class that adds a critical section to a class. - -class COpcSynchObject -{ - -public: - - // Cast - operator COpcCriticalSection&() { return m_cLock; } - operator const COpcCriticalSection&() const { return m_cLock; } - - // HasLock - bool HasLock() { return m_cLock.HasLock(); } - -private: - - COpcCriticalSection m_cLock; -}; - -#endif // _COpcCriticalSection_H_ diff --git a/ComIOP/Wrapper/Common/COpcEnumCPs.cpp b/ComIOP/Wrapper/Common/COpcEnumCPs.cpp deleted file mode 100644 index 0f693aa81..000000000 --- a/ComIOP/Wrapper/Common/COpcEnumCPs.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcEnumCPs.h" - -// Constructor -COpcEnumCPs::COpcEnumCPs() -{ - Reset(); -} - -// Constructor -COpcEnumCPs::COpcEnumCPs(const COpcConnectionPointList& cCPs) -{ - // copy connection points. - OPC_POS pos = cCPs.GetHeadPosition(); - - while (pos != NULL) - { - COpcConnectionPoint* pCP = cCPs.GetNext(pos); - - m_cCPs.AddTail(pCP); - pCP->AddRef(); - } - - // set pointer to start of list. - Reset(); -} - -// Destructor -COpcEnumCPs::~COpcEnumCPs() -{ - // release connection points. - OPC_POS pos = m_cCPs.GetHeadPosition(); - - while (pos != NULL) - { - m_cCPs.GetNext(pos)->Release(); - } -} - -//============================================================================== -// IEnumConnectionPoints - -// Next -HRESULT COpcEnumCPs::Next( - ULONG cConnections, - LPCONNECTIONPOINT* ppCP, - ULONG* pcFetched -) -{ - // invalid arguments - return error. - if (pcFetched == NULL) - { - return E_INVALIDARG; - } - - *pcFetched = 0; - - // trivial case - return nothing. - if (cConnections == 0) - { - return S_OK; - } - - // read connection points. - for (ULONG ii = 0; ii < cConnections; ii++) - { - // end of list reached before count reached. - if (m_pos == NULL) - { - *pcFetched = ii; - return S_FALSE; - } - - ppCP[ii] = m_cCPs.GetNext(m_pos); - - // client must release the reference. - ppCP[ii]->AddRef(); - } - - *pcFetched = ii; - return S_OK; -} - -// Skip -HRESULT COpcEnumCPs::Skip(ULONG cConnections) -{ - // skip connection points. - OPC_POS pos = m_cCPs.GetHeadPosition(); - - for (ULONG ii = 0; ii < cConnections; ii++) - { - // end of list reached before count reached. - if (m_pos == NULL) - { - return S_FALSE; - } - - m_cCPs.GetNext(m_pos); - } - - return S_OK; -} - -// Reset -HRESULT COpcEnumCPs::Reset() -{ - m_pos = m_cCPs.GetHeadPosition(); - return S_OK; -} - -// Clone -HRESULT COpcEnumCPs::Clone(IEnumConnectionPoints** ppEnum) -{ - // create a new enumeration object. - COpcEnumCPs* ipEnum = new COpcEnumCPs(); - - // copy connection points. - OPC_POS pos = m_cCPs.GetHeadPosition(); - - while (pos != NULL) - { - COpcConnectionPoint* pCP = m_cCPs[pos]; - - ipEnum->m_cCPs.AddTail(pCP); - - // clone must release the reference. - pCP->AddRef(); - - // save the current location. - if (pos == m_pos) - { - ipEnum->m_pos = ipEnum->m_cCPs.GetTailPosition(); - } - - m_cCPs.GetNext(pos); - } - - // query interface. - HRESULT hResult = ipEnum->QueryInterface(IID_IEnumConnectionPoints, (void**)ppEnum); - - // release local reference. - ipEnum->Release(); - - return hResult; -} diff --git a/ComIOP/Wrapper/Common/COpcEnumCPs.h b/ComIOP/Wrapper/Common/COpcEnumCPs.h deleted file mode 100644 index 2423dd989..000000000 --- a/ComIOP/Wrapper/Common/COpcEnumCPs.h +++ /dev/null @@ -1,99 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcEnumCPs_H_ -#define _COpcEnumCPs_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcComObject.h" -#include "COpcCPContainer.h" - -//============================================================================== -// CLASS: COpcEnumCPs -// PURPOSE: Implements the IEnumConnectionPoints interface. -// NOTES: - -class OPCUTILS_API COpcEnumCPs -: - public COpcComObject, - public IEnumConnectionPoints -{ - OPC_BEGIN_INTERFACE_TABLE(COpcEnumCPs) - OPC_INTERFACE_ENTRY(IEnumConnectionPoints) - OPC_END_INTERFACE_TABLE() - - OPC_CLASS_NEW_DELETE() - -public: - - //========================================================================== - // Operators - - // Constructor - COpcEnumCPs(); - - // Constructor - COpcEnumCPs(const COpcList& cCPs); - - // Destructor - ~COpcEnumCPs(); - - //========================================================================== - // IEnumConnectionPoints - - // Next - STDMETHODIMP Next( - ULONG cConnections, - LPCONNECTIONPOINT* ppCP, - ULONG* pcFetched - ); - - // Skip - STDMETHODIMP Skip(ULONG cConnections); - - // Reset - STDMETHODIMP Reset(); - - // Clone - STDMETHODIMP Clone(IEnumConnectionPoints** ppEnum); - -private: - - //========================================================================== - // Private Members - - OPC_POS m_pos; - COpcConnectionPointList m_cCPs; -}; - -#endif // _COpcEnumCPs_H_ diff --git a/ComIOP/Wrapper/Common/COpcEnumString.cpp b/ComIOP/Wrapper/Common/COpcEnumString.cpp deleted file mode 100644 index 1a235d807..000000000 --- a/ComIOP/Wrapper/Common/COpcEnumString.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcEnumString.h" - -//============================================================================== -// COpcEnumString - -COpcEnumString::COpcEnumString() -{ - m_uIndex = 0; - m_uCount = 0; - m_pStrings = NULL; -} - -// Constructor -COpcEnumString::COpcEnumString(UINT uCount, LPWSTR*& pStrings) -{ - m_uIndex = 0; - m_uCount = uCount; - m_pStrings = pStrings; - - // take ownership of memory. - pStrings = NULL; -} - -// Destructor -COpcEnumString::~COpcEnumString() -{ - for (UINT ii = 0; ii < m_uCount; ii++) - { - OpcFree(m_pStrings[ii]); - } - - OpcFree(m_pStrings); -} - -//============================================================================== -// IEnumString - -// Next -HRESULT COpcEnumString::Next( - ULONG celt, - LPOLESTR* rgelt, - ULONG* pceltFetched) -{ - // check for invalid arguments. - if (rgelt == NULL || pceltFetched == NULL) - { - return E_INVALIDARG; - } - - *pceltFetched = NULL; - - // all strings already returned. - if (m_uIndex >= m_uCount) - { - return S_FALSE; - } - - // copy strings. - for (UINT ii = m_uIndex; ii < m_uCount && *pceltFetched < celt; ii++) - { - rgelt[*pceltFetched] = (LPWSTR)CoTaskMemAlloc((wcslen(m_pStrings[ii])+1)*sizeof(WCHAR)); - - if (m_pStrings[ii] == NULL) - { - rgelt[*pceltFetched] = NULL; - } - else - { - wcscpy(rgelt[*pceltFetched], m_pStrings[ii]); - } - - (*pceltFetched)++; - } - - // no enough strings left. - if (*pceltFetched < celt) - { - m_uIndex = m_uCount; - return S_FALSE; - } - - m_uIndex = ii; - return S_OK; -} - -// Skip -HRESULT COpcEnumString::Skip(ULONG celt) -{ - if (m_uIndex + celt > m_uCount) - { - m_uIndex = m_uCount; - return S_FALSE; - } - - m_uIndex += celt; - return S_OK; -} - -// Reset -HRESULT COpcEnumString::Reset() -{ - m_uIndex = 0; - return S_OK; -} - -// Clone -HRESULT COpcEnumString::Clone(IEnumString** ppEnum) -{ - // check for invalid arguments. - if (ppEnum == NULL) - { - return E_INVALIDARG; - } - - // allocate enumerator. - COpcEnumString* pEnum = new COpcEnumString(); - - // copy strings. - pEnum->m_pStrings = OpcArrayAlloc(LPWSTR, m_uCount); - - for (UINT ii = 0; ii < m_uCount; ii++) - { - pEnum->m_pStrings[ii] = OpcArrayAlloc(WCHAR, wcslen(m_pStrings[ii])+1); - wcscpy(pEnum->m_pStrings[ii], m_pStrings[ii]); - } - - // set index. - pEnum->m_uIndex = m_uIndex; - pEnum->m_uCount = m_uCount; - - HRESULT hResult = pEnum->QueryInterface(IID_IEnumString, (void**)ppEnum); - - // release local reference. - pEnum->Release(); - - return hResult; -} diff --git a/ComIOP/Wrapper/Common/COpcEnumString.h b/ComIOP/Wrapper/Common/COpcEnumString.h deleted file mode 100644 index 5c179e1f0..000000000 --- a/ComIOP/Wrapper/Common/COpcEnumString.h +++ /dev/null @@ -1,100 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcEnumStrings_H_ -#define _COpcEnumStrings_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcComObject.h" -#include "COpcList.h" -#include "COpcString.h" - -//============================================================================== -// CLASS: COpcEnumString -// PURPOSE: A class to implement the IEnumString interface. -// NOTES: - -class OPCUTILS_API COpcEnumString -: - public COpcComObject, - public IEnumString -{ - OPC_BEGIN_INTERFACE_TABLE(COpcEnumString) - OPC_INTERFACE_ENTRY(IEnumString) - OPC_END_INTERFACE_TABLE() - - OPC_CLASS_NEW_DELETE() - -public: - - //========================================================================== - // Operators - - // Constructor - COpcEnumString(); - - // Constructor - COpcEnumString(UINT uCount, LPWSTR*& pStrings); - - // Destructor - ~COpcEnumString(); - - //========================================================================== - // IEnumConnectionPoints - - // Next - STDMETHODIMP Next( - ULONG celt, - LPOLESTR* rgelt, - ULONG* pceltFetched); - - // Skip - STDMETHODIMP Skip(ULONG celt); - - // Reset - STDMETHODIMP Reset(); - - // Clone - STDMETHODIMP Clone(IEnumString** ppEnum); - -private: - - //========================================================================== - // Private Members - - UINT m_uIndex; - UINT m_uCount; - LPWSTR* m_pStrings; -}; - -#endif // _COpcEnumStrings_H_ diff --git a/ComIOP/Wrapper/Common/COpcEnumUnknown.cpp b/ComIOP/Wrapper/Common/COpcEnumUnknown.cpp deleted file mode 100644 index 4e42a610a..000000000 --- a/ComIOP/Wrapper/Common/COpcEnumUnknown.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcEnumUnknown.h" - -//============================================================================== -// COpcEnumUnknown - -COpcEnumUnknown::COpcEnumUnknown() -{ - m_uIndex = 0; - m_uCount = 0; - m_pUnknowns = NULL; -} - -// Constructor -COpcEnumUnknown::COpcEnumUnknown(UINT uCount, IUnknown**& pUnknowns) -{ - m_uIndex = 0; - m_uCount = uCount; - m_pUnknowns = pUnknowns; - - // take ownership of memory. - pUnknowns = NULL; -} - -// Destructor -COpcEnumUnknown::~COpcEnumUnknown() -{ - for (UINT ii = 0; ii < m_uCount; ii++) - { - if (m_pUnknowns[ii] != NULL) m_pUnknowns[ii]->Release(); - } - - OpcFree(m_pUnknowns); -} - -//============================================================================== -// IEnumUnknown - -// Next -HRESULT COpcEnumUnknown::Next( - ULONG celt, - IUnknown** rgelt, - ULONG* pceltFetched -) -{ - // check for invalid arguments. - if (rgelt == NULL || pceltFetched == NULL) - { - return E_INVALIDARG; - } - - *pceltFetched = NULL; - - // all strings already returned. - if (m_uIndex >= m_uCount) - { - return S_FALSE; - } - - // copy strings. - for (UINT ii = m_uIndex; ii < m_uCount && *pceltFetched < celt; ii++) - { - rgelt[*pceltFetched] = m_pUnknowns[ii]; - if (m_pUnknowns[ii] != NULL) m_pUnknowns[ii]->AddRef(); - (*pceltFetched)++; - } - - // no enough strings left. - if (*pceltFetched < celt) - { - m_uIndex = m_uCount; - return S_FALSE; - } - - m_uIndex = ii; - return S_OK; -} - -// Skip -HRESULT COpcEnumUnknown::Skip(ULONG celt) -{ - if (m_uIndex + celt > m_uCount) - { - m_uIndex = m_uCount; - return S_FALSE; - } - - m_uIndex += celt; - return S_OK; -} - -// Reset -HRESULT COpcEnumUnknown::Reset() -{ - m_uIndex = 0; - return S_OK; -} - -// Clone -HRESULT COpcEnumUnknown::Clone(IEnumUnknown** ppEnum) -{ - // check for invalid arguments. - if (ppEnum == NULL) - { - return E_INVALIDARG; - } - - // allocate enumerator. - COpcEnumUnknown* pEnum = new COpcEnumUnknown(); - - // copy strings. - pEnum->m_pUnknowns = OpcArrayAlloc(IUnknown*, m_uCount); - - for (UINT ii = 0; ii < m_uCount; ii++) - { - pEnum->m_pUnknowns[ii] = m_pUnknowns[ii]; - if (m_pUnknowns[ii] != NULL) m_pUnknowns[ii]->AddRef(); - } - - // set index. - pEnum->m_uIndex = m_uIndex; - pEnum->m_uCount = m_uCount; - - HRESULT hResult = pEnum->QueryInterface(IID_IEnumUnknown, (void**)ppEnum); - - // release local reference. - pEnum->Release(); - - return hResult; -} diff --git a/ComIOP/Wrapper/Common/COpcEnumUnknown.h b/ComIOP/Wrapper/Common/COpcEnumUnknown.h deleted file mode 100644 index b5dbc4134..000000000 --- a/ComIOP/Wrapper/Common/COpcEnumUnknown.h +++ /dev/null @@ -1,101 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcEnumUnknowns_H_ -#define _COpcEnumUnknowns_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcComObject.h" -#include "COpcList.h" -#include "COpcString.h" - -//============================================================================== -// CLASS: COpcEnumUnknown -// PURPOSE: A class to implement the IEnumUnknown interface. -// NOTES: - -class OPCUTILS_API COpcEnumUnknown -: - public COpcComObject, - public IEnumUnknown -{ - OPC_BEGIN_INTERFACE_TABLE(COpcEnumUnknown) - OPC_INTERFACE_ENTRY(IEnumUnknown) - OPC_END_INTERFACE_TABLE() - - OPC_CLASS_NEW_DELETE() - -public: - - //========================================================================== - // Operators - - // Constructor - COpcEnumUnknown(); - - // Constructor - COpcEnumUnknown(UINT uCount, IUnknown**& pUnknowns); - - // Destructor - ~COpcEnumUnknown(); - - //========================================================================== - // IEnumConnectionPoints - - // Next - STDMETHODIMP Next( - ULONG celt, - IUnknown** rgelt, - ULONG* pceltFetched - ); - - // Skip - STDMETHODIMP Skip(ULONG celt); - - // Reset - STDMETHODIMP Reset(); - - // Clone - STDMETHODIMP Clone(IEnumUnknown** ppEnum); - -private: - - //========================================================================== - // Private Members - - UINT m_uIndex; - UINT m_uCount; - IUnknown** m_pUnknowns; -}; - -#endif // _COpcEnumUnknowns_H_ diff --git a/ComIOP/Wrapper/Common/COpcFile.cpp b/ComIOP/Wrapper/Common/COpcFile.cpp deleted file mode 100644 index d1db1191d..000000000 --- a/ComIOP/Wrapper/Common/COpcFile.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcFile.h" - -//============================================================================== -// COpcFile - -// Constructor -COpcFile::COpcFile() -{ - m_hFile = INVALID_HANDLE_VALUE; - m_hMapping = NULL; - m_pView = NULL; - m_bReadOnly = false; -} - -// Destructor -COpcFile::~COpcFile() -{ - Close(); -} - -// Create -bool COpcFile::Create(const COpcString& cFileName) -{ - // check if file has aleady been opened. - if (m_hFile != INVALID_HANDLE_VALUE) - { - return false; - } - - // create a new file. - m_hFile = CreateFile( - cFileName, - GENERIC_READ | GENERIC_WRITE, - NULL, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - - // check for error. - if (m_hFile == INVALID_HANDLE_VALUE) - { - return false; - } - - return true; -} - -// Open -bool COpcFile::Open(const COpcString& cFileName, bool bReadOnly) -{ - // check if file has aleady been opened. - if (m_hFile != INVALID_HANDLE_VALUE) - { - return false; - } - - m_bReadOnly = bReadOnly; - - // create a new file. - m_hFile = CreateFile( - cFileName, - (bReadOnly)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE), - NULL, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - - // check for error. - if (m_hFile == INVALID_HANDLE_VALUE) - { - return false; - } - - return true; -} - -// Close -void COpcFile::Close() -{ - if (m_hFile != INVALID_HANDLE_VALUE) - { - UnmapViewOfFile(m_pView); - CloseHandle(m_hMapping); - CloseHandle(m_hFile); - - m_hFile = INVALID_HANDLE_VALUE; - m_hMapping = NULL; - m_pView = NULL; - } -} - -// Read -UINT COpcFile::Read(BYTE* pBuffer, UINT uSize) -{ - // check if file has been opened. - if (m_hFile == INVALID_HANDLE_VALUE) - { - return 0; - } - - // intialize buffer. - memset(pBuffer, 0, uSize); - - // read into buffer. - DWORD dwBytesRead = 0; - - BOOL bResult = ReadFile( - m_hFile, - pBuffer, - uSize, - &dwBytesRead, - NULL - ); - - // check for error. - if (!bResult) - { - return 0; - } - - // return number of bytes read. - return (UINT)dwBytesRead; -} - -// Write -UINT COpcFile::Write(BYTE* pBuffer, UINT uSize) -{ - // check if file has been opened. - if (m_hFile == INVALID_HANDLE_VALUE) - { - return 0; - } - - // write from buffer. - DWORD dwBytesWritten = 0; - - BOOL bResult = WriteFile( - m_hFile, - pBuffer, - uSize, - &dwBytesWritten, - NULL - ); - - // check for error. - if (!bResult) - { - return 0; - } - - // return number of bytes read. - return (UINT)dwBytesWritten; -} - -// GetFileSize -UINT COpcFile::GetFileSize() -{ - return (UINT)::GetFileSize(m_hFile, NULL); -} - -// GetLastModified -FILETIME COpcFile::GetLastModified() -{ - FILETIME ftLastModified = { 0, 0 }; - ::GetFileTime(m_hFile, NULL, NULL, &ftLastModified); - return ftLastModified; -} - -// GetMemoryMapping -BYTE* COpcFile::GetMemoryMapping() -{ - // check if the mapping already exists. - if (m_hMapping != NULL && m_pView != NULL) - { - return m_pView; - } - - // create the file mapping. - m_hMapping = CreateFileMapping( - m_hFile, - NULL, - (m_bReadOnly)?PAGE_READONLY:PAGE_READWRITE, - NULL, - NULL, - NULL - ); - - if (m_hMapping == NULL) - { - return NULL; - } - - // create a view of the mapping in memory. - m_pView = (BYTE*)MapViewOfFile( - m_hMapping, - (m_bReadOnly)?FILE_MAP_READ:FILE_MAP_WRITE, - 0, - 0, - 0 - ); - - if (m_pView == NULL) - { - return NULL; - } - - // return a pointer to the memory view of the file. - return m_pView; -} diff --git a/ComIOP/Wrapper/Common/COpcFile.h b/ComIOP/Wrapper/Common/COpcFile.h deleted file mode 100644 index e619cb212..000000000 --- a/ComIOP/Wrapper/Common/COpcFile.h +++ /dev/null @@ -1,96 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcFile_H_ -#define _COpcFile_H_ - -#include "COpcString.h" - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -//============================================================================== -// CLASS: COpcFile -// PURPOSE Facilitiates manipulation of XML Elements, - -class COpcFile -{ - OPC_CLASS_NEW_DELETE(); - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcFile(); - - // Destructor - ~COpcFile(); - - //========================================================================== - // Public Methods - - // Create - bool Create(const COpcString& cFileName); - - // Open - bool Open(const COpcString& cFileName, bool bReadOnly = true); - - // Close - void Close(); - - // Read - UINT Read(BYTE* pBuffer, UINT uSize); - - // Write - UINT Write(BYTE* pBuffer, UINT uSize); - - // GetFileSize - UINT GetFileSize(); - - // GetLastModified - FILETIME GetLastModified(); - - // GetMemoryMapping - BYTE* GetMemoryMapping(); - -private: - - //========================================================================== - // Private Members - - HANDLE m_hFile; - HANDLE m_hMapping; - BYTE* m_pView; - bool m_bReadOnly; -}; - -#endif // _COpcFile_H_ diff --git a/ComIOP/Wrapper/Common/COpcList.h b/ComIOP/Wrapper/Common/COpcList.h deleted file mode 100644 index 86fa7df47..000000000 --- a/ComIOP/Wrapper/Common/COpcList.h +++ /dev/null @@ -1,595 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcList_H_ -#define _COpcList_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcString.h" - -//============================================================================== -// TYPE: OPC_POS -// PURPOSE: A position when enumerating the list. - -#ifndef _OPC_POS -#define _OPC_POS -typedef struct TOpcPos{}* OPC_POS; -#endif //_OPC_POS - -//============================================================================== -// CLASS: COpcList -// PURPOSE: Defines a linked list template class. - -template -class COpcList -{ - OPC_CLASS_NEW_DELETE_ARRAY() - -public: - - //========================================================================== - // Constructor - COpcList(UINT uBlockSize = 10) - { - m_uCount = 0; - m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL; - m_pBlocks = NULL; - m_uBlockSize = uBlockSize; - } - - //========================================================================== - // Copy Constructor - COpcList(const COpcList& cList) - { - m_uCount = 0; - m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL; - m_pBlocks = NULL; - m_uBlockSize = cList.m_uBlockSize; - - *this = cList; - } - - //========================================================================== - // Destructor - ~COpcList() - { - RemoveAll(); - } - - //========================================================================== - // Assignment - COpcList& operator=(const COpcList& cList) - { - RemoveAll(); - - m_uBlockSize = cList.m_uBlockSize; - - OPC_POS pos = cList.GetHeadPosition(); - - while (pos != NULL) - { - AddTail(cList.GetNext(pos)); - } - - return *this; - } - - //========================================================================== - // GetCount - UINT GetCount() const - { - return m_uCount; - } - - //========================================================================== - // IsEmpty - BOOL IsEmpty() const - { - return (m_uCount == 0); - } - - //========================================================================== - // GetBlockSize - UINT GetBlockSize() const - { - return m_uBlockSize; - } - - //========================================================================== - // GetHead - TYPE& GetHead() - { - OPC_ASSERT(m_pNodeHead != NULL); - return m_pNodeHead->data; - } - - TYPE GetHead() const - { - OPC_ASSERT(m_pNodeHead != NULL); - return m_pNodeHead->data; - } - - //========================================================================== - // GetTail - TYPE& GetTail() - { - OPC_ASSERT(m_pNodeTail != NULL); - return m_pNodeTail->data; - } - - TYPE GetTail() const - { - OPC_ASSERT(m_pNodeTail != NULL); - return m_pNodeTail->data; - } - - //========================================================================== - // RemoveHead - TYPE RemoveHead() - { - OPC_ASSERT(m_pNodeHead != NULL); // don't call on empty list !!! - - CVsNode* pOldNode = m_pNodeHead; - TYPE returnValue = pOldNode->data; - - m_pNodeHead = pOldNode->pNext; - - if (m_pNodeHead != NULL) - { - m_pNodeHead->pPrev = NULL; - } - else - { - m_pNodeTail = NULL; - } - - FreeNode(pOldNode); - return returnValue; - } - - //========================================================================== - // RemoveTail - TYPE RemoveTail() - { - OPC_ASSERT(m_pNodeTail != NULL); // don't call on empty list !!! - - CVsNode* pOldNode = m_pNodeTail; - TYPE returnValue = pOldNode->data; - - m_pNodeTail = pOldNode->pPrev; - - if (m_pNodeTail != NULL) - { - m_pNodeTail->pNext = NULL; - } - else - { - m_pNodeHead = NULL; - } - - FreeNode(pOldNode); - return returnValue; - } - - //========================================================================== - // AddHead - OPC_POS AddHead(const TYPE& newElement) - { - CVsNode* pNewNode = NewNode(NULL, m_pNodeHead); - pNewNode->data = newElement; - - if (m_pNodeHead != NULL) - { - m_pNodeHead->pPrev = pNewNode; - } - else - { - m_pNodeTail = pNewNode; - } - - m_pNodeHead = pNewNode; - return (OPC_POS) pNewNode; - } - - void AddHead(COpcList* pNewList) - { - OPC_ASSERT(pNewList != NULL); - - // add a list of same elements to head (maintain order) - OPC_POS pos = pNewList->GetTailPosition(); - - while (pos != NULL) - { - AddHead(pNewList->GetPrev(pos)); - } - } - - //========================================================================== - // AddTail - OPC_POS AddTail(const TYPE& newElement) - { - CVsNode* pNewNode = NewNode(m_pNodeTail, NULL); - pNewNode->data = newElement; - - if (m_pNodeTail != NULL) - { - m_pNodeTail->pNext = pNewNode; - } - else - { - m_pNodeHead = pNewNode; - } - - m_pNodeTail = pNewNode; - return (OPC_POS) pNewNode; - } - - void AddTail(COpcList* pNewList) - { - OPC_ASSERT(pNewList != NULL); - - // add a list of same elements - OPC_POS pos = pNewList->GetHeadPosition(); - - while (pos != NULL) - { - AddTail(pNewList->GetNext(pos)); - } - } - - //========================================================================== - // RemoveAll - void RemoveAll() - { - CVsBlock* pBlock = m_pBlocks; - CVsBlock* pNext = NULL; - - while (pBlock != NULL) - { - pNext = pBlock->pNext; - delete pBlock; - pBlock = pNext; - } - - m_uCount = 0; - m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL; - m_pBlocks = NULL; - } - - //========================================================================== - // GetHeadPosition - OPC_POS GetHeadPosition() const - { - return (OPC_POS)m_pNodeHead; - } - - //========================================================================== - // GetTailPosition - OPC_POS GetTailPosition() const - { - return (OPC_POS)m_pNodeTail; - } - - //========================================================================== - // GetNext - TYPE& GetNext(OPC_POS& rPosition) // return *Position++ - { - OPC_ASSERT(rPosition != NULL); - CVsNode* pNode = (CVsNode*) rPosition; - rPosition = (OPC_POS) pNode->pNext; - return pNode->data; - } - - TYPE GetNext(OPC_POS& rPosition) const // return *Position++ - { - OPC_ASSERT(rPosition != NULL); - CVsNode* pNode = (CVsNode*) rPosition; - rPosition = (OPC_POS) pNode->pNext; - return pNode->data; - } - - //========================================================================== - // GetPrev - TYPE& GetPrev(OPC_POS& rPosition) // return *Position-- - { - CVsNode* pNode = (CVsNode*) rPosition; - rPosition = (OPC_POS) pNode->pPrev; - return pNode->data; - } - - TYPE GetPrev(OPC_POS& rPosition) const // return *Position-- - { - CVsNode* pNode = (CVsNode*) rPosition; - rPosition = (OPC_POS) pNode->pPrev; - return pNode->data; - } - - //========================================================================== - // GetAt - TYPE& GetAt(OPC_POS position) - { - CVsNode* pNode = (CVsNode*) position; - return pNode->data; - } - - TYPE GetAt(OPC_POS position) const - { - CVsNode* pNode = (CVsNode*) position; - return pNode->data; - } - - //========================================================================== - // operator[] - TYPE& operator[](OPC_POS position) - { - return GetAt(position); - } - - TYPE operator[](OPC_POS position) const - { - return GetAt(position); - } - - //========================================================================== - // SetAt - void SetAt(OPC_POS pos, const TYPE& newElement) - { - CVsNode* pNode = (CVsNode*)pos; - pNode->data = newElement; - } - - //========================================================================== - // RemoveAt - void RemoveAt(OPC_POS position) - { - CVsNode* pOldNode = (CVsNode*) position; - - // remove pOldNode from list - if (pOldNode == m_pNodeHead) - { - m_pNodeHead = pOldNode->pNext; - } - else - { - pOldNode->pPrev->pNext = pOldNode->pNext; - } - if (pOldNode == m_pNodeTail) - { - m_pNodeTail = pOldNode->pPrev; - } - else - { - pOldNode->pNext->pPrev = pOldNode->pPrev; - } - - FreeNode(pOldNode); - } - - //========================================================================== - // InsertBefore - OPC_POS InsertBefore(OPC_POS position, const TYPE& newElement) - { - if (position == NULL) - return AddHead(newElement); // insert before nothing -> head of the list - - // Insert it before position - CVsNode* pOldNode = (CVsNode*) position; - CVsNode* pNewNode = NewNode(pOldNode->pPrev, pOldNode); - pNewNode->data = newElement; - - if (pOldNode->pPrev != NULL) - { - pOldNode->pPrev->pNext = pNewNode; - } - else - { - OPC_ASSERT(pOldNode == m_pNodeHead); - m_pNodeHead = pNewNode; - } - - pOldNode->pPrev = pNewNode; - return (OPC_POS) pNewNode; - } - - //========================================================================== - // InsertAfter - OPC_POS InsertAfter(OPC_POS position, const TYPE& newElement) - { - if (position == NULL) - return AddTail(newElement); // insert after nothing -> tail of the list - - // Insert it before position - CVsNode* pOldNode = (CVsNode*) position; - CVsNode* pNewNode = NewNode(pOldNode, pOldNode->pNext); - pNewNode->data = newElement; - - if (pOldNode->pNext != NULL) - { - pOldNode->pNext->pPrev = pNewNode; - } - else - { - OPC_ASSERT(pOldNode == m_pNodeTail); - m_pNodeTail = pNewNode; - } - - pOldNode->pNext = pNewNode; - return (OPC_POS) pNewNode; - } - - //========================================================================== - // Find - helper functions (note: O(n) speed) - OPC_POS Find(const TYPE& searchValue, OPC_POS startAfter = NULL) const - { - CVsNode* pNode = (CVsNode*)startAfter; - - if (pNode == NULL) - { - pNode = m_pNodeHead; // start at head - } - else - { - pNode = pNode->pNext; // start after the one specified - } - - for (; pNode != NULL; pNode = pNode->pNext) - { - if (pNode->data == searchValue) - { - return (OPC_POS)pNode; - } - } - - return NULL; - } - - //========================================================================== - // FindIndex - defaults to starting at the HEAD, return NULL if not found - OPC_POS FindIndex(UINT nIndex) const - { - if (nIndex >= m_uCount || nIndex < 0) - { - return NULL; // went too far - } - - CVsNode* pNode = m_pNodeHead; - - while (nIndex--) - { - pNode = pNode->pNext; - } - - return (OPC_POS)pNode; - } - - protected: - - //========================================================================== - // CVsNode - struct CVsNode - { - OPC_CLASS_NEW_DELETE_ARRAY() - - CVsNode* pNext; - CVsNode* pPrev; - TYPE data; - }; - - //========================================================================== - // CVsBlock - class CVsBlock - { - OPC_CLASS_NEW_DELETE_ARRAY() - - public: - - CVsBlock(UINT uBlockSize) - { - pNodes = new CVsNode[uBlockSize]; - } - - ~CVsBlock() - { - delete [] pNodes; - } - - CVsBlock* pNext; - CVsNode* pNodes; - }; - - //========================================================================== - // NewNode - CVsNode* NewNode(CVsNode* pPrev, CVsNode* pNext) - { - if (m_pNodeFree == NULL) - { - CVsBlock* pBlock = new CVsBlock(m_uBlockSize); - - for (UINT ii = 0; ii < m_uBlockSize; ii++) - { - pBlock->pNodes[ii].pNext = m_pNodeFree; - m_pNodeFree = &(pBlock->pNodes[ii]); - } - - pBlock->pNext = m_pBlocks; - m_pBlocks = pBlock; - } - - OPC_ASSERT(m_pNodeFree != NULL); - - CVsNode* pNode = m_pNodeFree; - m_pNodeFree = m_pNodeFree->pNext; - pNode->pPrev = pPrev; - pNode->pNext = pNext; - - m_uCount++; - OPC_ASSERT(m_uCount > 0); // make sure we don't overflow - - return pNode; - } - - //========================================================================== - // FreeNode - void FreeNode(CVsNode* pNode) - { - pNode->pNext = m_pNodeFree; - m_pNodeFree = pNode; - m_uCount--; - OPC_ASSERT(m_uCount >= 0); // make sure we don't underflow - - // if no more elements, cleanup completely - if (m_uCount == 0) - RemoveAll(); - } - - //========================================================================== - // Members - CVsNode* m_pNodeHead; - CVsNode* m_pNodeTail; - UINT m_uCount; - CVsNode* m_pNodeFree; - CVsBlock* m_pBlocks; - UINT m_uBlockSize; -}; - -//============================================================================== -// TYPE: COpcStringList -// PURPOSE: A list of strings. - -typedef COpcList COpcStringList; - -#ifndef OPCUTILS_EXPORTS -template class OPCUTILS_API COpcList; -#endif - -#endif //ndef _COpcList_H_ diff --git a/ComIOP/Wrapper/Common/COpcMap.h b/ComIOP/Wrapper/Common/COpcMap.h deleted file mode 100644 index 8ace44c07..000000000 --- a/ComIOP/Wrapper/Common/COpcMap.h +++ /dev/null @@ -1,631 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcMap_H_ -#define _COpcMap_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcString.h" - -//============================================================================== -// TYPE: OPC_POS -// PURPOSE: A position when enumerating the hash table. - -#ifndef _OPC_POS -#define _OPC_POS -typedef struct TOpcPos{}* OPC_POS; -#endif //_OPC_POS - -//============================================================================== -// CLASS: COpcMap -// PURPOSE: Defines a hash table template class. - -template -class COpcMap -{ - OPC_CLASS_NEW_DELETE_ARRAY() - -public: - - //========================================================================== - // COpcEntry - class COpcEntry - { - OPC_CLASS_NEW_DELETE_ARRAY() - - public: - - COpcEntry* pNext; - KEY cKey; - VALUE cValue; - UINT uHash; - - COpcEntry() : pNext(NULL), uHash(0) {} - }; - - //========================================================================== - // COpcBlock - class COpcBlock - { - OPC_CLASS_NEW_DELETE_ARRAY() - - public: - - COpcBlock(UINT uBlockSize) - : - pNext(NULL), - pEntries(NULL) - { - pEntries = new COpcEntry[uBlockSize]; - } - - ~COpcBlock() - { - delete [] pEntries; - } - - COpcBlock* pNext; - COpcEntry* pEntries; - }; - -public: - - //========================================================================== - // Constructor - COpcMap(int nBlockSize = 10, int uTableSize = 17) - : - m_pUnusedEntries(NULL), - m_uCount(0), - m_pBlocks(NULL), - m_uBlockSize(nBlockSize), - m_ppHashTable(NULL), - m_uTableSize(0) - { - InitHashTable(uTableSize); - } - - //========================================================================== - // Copy Constructor - COpcMap(const COpcMap& cMap) - : - m_pUnusedEntries(NULL), - m_uCount(0), - m_pBlocks(NULL), - m_uBlockSize(cMap.m_uBlockSize), - m_ppHashTable(NULL), - m_uTableSize(0) - { - *this = cMap; - } - - //========================================================================== - // Destructor - ~COpcMap() - { - RemoveAll(); - delete [] m_ppHashTable; - } - - //========================================================================== - // Assignment - COpcMap& operator=(const COpcMap& cMap) - { - InitHashTable(cMap.m_uTableSize); - - KEY cKey; - VALUE cValue; - OPC_POS pos = cMap.GetStartPosition(); - - while (pos != NULL) - { - cMap.GetNextAssoc(pos, cKey, cValue); - SetAt(cKey, cValue); - } - - return *this; - } - - //========================================================================== - // GetCount - int GetCount() const - { - return m_uCount; - } - - //========================================================================== - // IsEmpty - bool IsEmpty() const - { - return (m_uCount == 0); - } - - //========================================================================== - // Lookup - return false if not there - bool Lookup(const KEY& cKey, VALUE** ppValue = NULL) const - { - COpcEntry* pEntry = Find(cKey); - - if (pEntry == NULL) - { - return false; - } - - if (ppValue != NULL) - { - *ppValue = &(pEntry->cValue); - } - - return true; - } - - //========================================================================== - // Lookup - return false if not there - bool Lookup(const KEY& cKey, VALUE& cValue) const - { - COpcEntry* pEntry = Find(cKey); - - if (pEntry == NULL) - { - return false; - } - - cValue = pEntry->cValue; - return true; - } - - //========================================================================== - // Lookup - and add if not there - VALUE& operator[](const KEY& cKey) - { - COpcEntry* pEntry = Find(cKey); - - if (pEntry == NULL) - { - pEntry = NewEntry(cKey); - } - - return pEntry->cValue; - } - - //========================================================================== - // SetAt - add a new (key, value) pair - void SetAt(const KEY& cKey, const VALUE& cValue) - { - (*this)[cKey] = cValue; - } - - //========================================================================== - // RemoveKey - removing existing (key, ?) pair - bool RemoveKey(const KEY& cKey) - { - UINT uBin = HashKey(cKey)%m_uTableSize; - COpcEntry* pEntry = m_ppHashTable[uBin]; - COpcEntry* pPrev = NULL; - - while (pEntry != NULL) - { - if (pEntry->cKey == cKey) - { - if (pPrev == NULL) - { - m_ppHashTable[uBin] = pEntry->pNext; - } - else - { - pPrev->pNext = pEntry->pNext; - } - - FreeEntry(pEntry); - return true; - } - - pPrev = pEntry; - pEntry = pEntry->pNext; - } - - return false; - } - - //========================================================================== - // RemoveAll - void RemoveAll() - { - COpcBlock* pBlock = m_pBlocks; - COpcBlock* pNext = NULL; - - while (pBlock != NULL) - { - pNext = pBlock->pNext; - delete pBlock; - pBlock = pNext; - } - - m_uCount = 0; - m_pUnusedEntries = NULL; - m_pBlocks = NULL; - memset(m_ppHashTable, 0, m_uTableSize*sizeof(COpcEntry*)); - } - - //========================================================================== - // GetStartPosition - OPC_POS GetStartPosition() const - { - UINT uBin = 0; - - while (uBin < m_uTableSize && m_ppHashTable[uBin] == NULL) - { - uBin++; - } - - if (uBin == m_uTableSize) - { - return (OPC_POS)NULL; - } - - return (OPC_POS)m_ppHashTable[uBin]; - } - - //========================================================================== - // GetNextAssoc - void GetNextAssoc(OPC_POS& pos, KEY& cKey) const - { - COpcEntry* pEntry = (COpcEntry*)pos; - OPC_ASSERT(pos != NULL); - - cKey = pEntry->cKey; - - pos = GetNextAssoc(pos); - } - - //========================================================================== - // GetNextAssoc - void GetNextAssoc(OPC_POS& pos, KEY& cKey, VALUE& cValue) const - { - COpcEntry* pEntry = (COpcEntry*)pos; - OPC_ASSERT(pos != NULL); - - cKey = pEntry->cKey; - cValue = pEntry->cValue; - - pos = GetNextAssoc(pos); - } - - //========================================================================== - // GetNextAssoc - void GetNextAssoc(OPC_POS& pos, KEY& cKey, VALUE*& pValue) const - { - COpcEntry* pEntry = (COpcEntry*)pos; - OPC_ASSERT(pos != NULL); - - cKey = pEntry->cKey; - pValue = &(pEntry->cValue); - - pos = GetNextAssoc(pos); - } - - //========================================================================== - // IsValid - bool IsValid(OPC_POS pos) const - { - COpcBlock* pBlock = m_pBlocks; - - while (pBlock != NULL) - { - for (UINT ii = 0; ii < m_uBlockSize; ii++) - { - if (pos == (OPC_POS)&(pBlock->pEntries[ii])) - { - return true; - } - } - - pBlock = pBlock->pNext; - } - - return false; - } - - //========================================================================== - // GetPosition - OPC_POS GetPosition(const KEY& cKey) const - { - return (OPC_POS)Find(cKey); - } - - //========================================================================== - // GetKey - const KEY& GetKey(OPC_POS pos) const - { - OPC_ASSERT(IsValid(pos)); - return ((COpcEntry*)pos)->cKey; - } - - //========================================================================== - // GetValue - VALUE& GetValue(OPC_POS pos) - { - OPC_ASSERT(IsValid(pos)); - return ((COpcEntry*)pos)->cValue; - } - - //========================================================================== - // GetValue - const VALUE& GetValue(OPC_POS pos) const - { - OPC_ASSERT(IsValid(pos)); - return ((COpcEntry*)pos)->cValue; - } - - //========================================================================== - // GetBlockSize - UINT GetBlockSize() const - { - return m_uBlockSize; - } - - //========================================================================== - // GetHashTableSize - UINT GetHashTableSize() const - { - return m_uTableSize; - } - - //========================================================================== - // InitHashTable - void InitHashTable(UINT uTableSize) - { - COpcEntry* pEntries = NULL; - - for (UINT ii = 0; ii < m_uTableSize; ii++) - { - COpcEntry* pEntry = m_ppHashTable[ii]; - COpcEntry* pNext = NULL; - - while (pEntry != NULL) - { - pNext = pEntry->pNext; - pEntry->pNext = pEntries; - pEntries = pEntry; - pEntry = pNext; - } - } - - delete [] m_ppHashTable; - - m_uTableSize = uTableSize; - m_ppHashTable = new COpcEntry*[m_uTableSize]; - memset(m_ppHashTable, 0, m_uTableSize*sizeof(COpcEntry*)); - - COpcEntry* pEntry = pEntries; - COpcEntry* pNext = NULL; - - while (pEntry != NULL) - { - pNext = pEntry->pNext; - - UINT uBin = (pEntry->uHash)%m_uTableSize; - pEntry->pNext = m_ppHashTable[uBin]; - m_ppHashTable[uBin] = pEntry; - - pEntry = pNext; - } - } - -private: - - //========================================================================== - // Find - COpcEntry* Find(const KEY& cKey) const - { - UINT uBin = HashKey(cKey)%m_uTableSize; - COpcEntry* pEntry = m_ppHashTable[uBin]; - - while (pEntry != NULL) - { - if (pEntry->cKey == cKey) - { - return pEntry; - } - - pEntry = pEntry->pNext; - } - - return NULL; - } - - //========================================================================== - // NewEntry - COpcEntry* NewEntry(const KEY& cKey) - { - // optimize hash table size. - if (m_uTableSize < 1.2*m_uCount) - { - InitHashTable(2*m_uCount); - } - - // create a new block if necessary. - if (m_pUnusedEntries == NULL) - { - COpcBlock* pBlock = new COpcBlock(m_uBlockSize); - - for (UINT ii = 0; ii < m_uBlockSize; ii++) - { - pBlock->pEntries[ii].pNext = m_pUnusedEntries; - m_pUnusedEntries = &(pBlock->pEntries[ii]); - } - - pBlock->pNext = m_pBlocks; - m_pBlocks = pBlock; - } - - OPC_ASSERT(m_pUnusedEntries != NULL); - - // remove entry from unused entry list. - COpcEntry* pEntry = m_pUnusedEntries; - m_pUnusedEntries = m_pUnusedEntries->pNext; - - // insert entry into hash table. - pEntry->cKey = cKey; - pEntry->uHash = HashKey(cKey); - - UINT uBin = pEntry->uHash%m_uTableSize; - pEntry->pNext = m_ppHashTable[uBin]; - m_ppHashTable[uBin] = pEntry; - - m_uCount++; - - return pEntry; - } - - //========================================================================== - // FreeEntry - void FreeEntry(COpcEntry* pEntry) - { - // return to unused entries list - pEntry->pNext = m_pUnusedEntries; - m_pUnusedEntries = pEntry; - m_uCount--; - OPC_ASSERT(m_uCount >= 0); // make sure we don't underflow - - // if no more elements, cleanup completely - if (m_uCount == 0) - { - RemoveAll(); - } - } - - //========================================================================== - // GetNextAssoc - OPC_POS GetNextAssoc(OPC_POS pos) const - { - COpcEntry* pEntry = (COpcEntry*)pos; - OPC_ASSERT(pos != NULL); - - if (pEntry->pNext == NULL) - { - UINT uBin = pEntry->uHash%m_uTableSize; - - do - { - uBin++; - } - while (uBin < m_uTableSize && m_ppHashTable[uBin] == NULL); - - if (uBin == m_uTableSize) - { - return (OPC_POS)NULL; - } - - return (OPC_POS)m_ppHashTable[uBin]; - } - - return (OPC_POS)pEntry->pNext; - } - - //========================================================================== - // Members - COpcEntry** m_ppHashTable; - UINT m_uTableSize; - UINT m_uCount; - COpcEntry* m_pUnusedEntries; - COpcBlock* m_pBlocks; - UINT m_uBlockSize; -}; - - -//============================================================================== -// FUNCTION: HashKey -// PURPOSE: Default hash key generator. -template -inline UINT HashKey(const KEY& cKey) -{ - return ((UINT)(void*)(DWORD)cKey) >> 4; -} - -//============================================================================== -// FUNCTION: HashKey -// PURPOSE: String hash key generator. -template<> -inline UINT HashKey (const LPCTSTR& tsKey) -{ - LPCTSTR key = tsKey; - if (key == NULL) return -1; - - UINT nHash = 0; - while (*key) - nHash = (nHash<<5) + nHash + *key++; - return nHash; -} - -//============================================================================== -// FUNCTION: HashKey -// PURPOSE: String object hash key generator. -template<> -inline UINT HashKey (const COpcString& cKey) -{ - LPCTSTR key = cKey; - if (key == NULL) return -1; - - UINT nHash = 0; - while (*key) - nHash = (nHash<<5) + nHash + *key++; - return nHash; -} - -//============================================================================== -// FUNCTION: HashKey -// PURPOSE: GUID hash key generator. -template<> -inline UINT HashKey (const GUID& cKey) -{ - UINT nHash = 0; - - nHash ^= cKey.Data1; - nHash ^= (cKey.Data2<<16 | cKey.Data3); - nHash ^= ((cKey.Data4[0]<<24) | (cKey.Data4[1]<<16) |(cKey.Data4[2]<<8) | (cKey.Data4[3])); - nHash ^= ((cKey.Data4[4]<<24) | (cKey.Data4[5]<<16) |(cKey.Data4[6]<<8) | (cKey.Data4[7])); - - return nHash; -} - -//============================================================================== -// TYPE: COpcStringMap -// PURPOSE: A string to string map. - -typedef COpcMap COpcStringMap; - -//#ifndef OPCUTILS_EXPORTS -template class OPCUTILS_API COpcMap; -//#endif - -#endif //ndef _COpcMap_H_ diff --git a/ComIOP/Wrapper/Common/COpcSecurity.cpp b/ComIOP/Wrapper/Common/COpcSecurity.cpp deleted file mode 100644 index 87daf7519..000000000 --- a/ComIOP/Wrapper/Common/COpcSecurity.cpp +++ /dev/null @@ -1,940 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcSecurity.h" - -#define OPCTRY(x) try{x;} catch(...) {} -#define OPCASSERT(expr) _ASSERTE(expr) - -//============================================================================== -// COpcSecurity - -COpcSecurity::COpcSecurity() -{ - m_pSD = NULL; - m_pOwner = NULL; - m_pGroup = NULL; - m_pDACL = NULL; - m_pSACL= NULL; -} - -COpcSecurity::~COpcSecurity() -{ - if (m_pSD) - delete m_pSD; - if (m_pOwner) - free(m_pOwner); - if (m_pGroup) - free(m_pGroup); - if (m_pDACL) - free(m_pDACL); - if (m_pSACL) - free(m_pSACL); -} - -HRESULT COpcSecurity::Initialize() -{ - if (m_pSD) - { - delete m_pSD; - m_pSD = NULL; - } - if (m_pOwner) - { - free(m_pOwner); - m_pOwner = NULL; - } - if (m_pGroup) - { - free(m_pGroup); - m_pGroup = NULL; - } - if (m_pDACL) - { - free(m_pDACL); - m_pDACL = NULL; - } - if (m_pSACL) - { - free(m_pSACL); - m_pSACL = NULL; - } - - OPCTRY(m_pSD = new SECURITY_DESCRIPTOR); - if (m_pSD == NULL) - return E_OUTOFMEMORY; - - if (!InitializeSecurityDescriptor(m_pSD, SECURITY_DESCRIPTOR_REVISION)) - { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - delete m_pSD; - m_pSD = NULL; - OPCASSERT(FALSE); - return hr; - } - // Set the DACL to allow EVERYONE - SetSecurityDescriptorDacl(m_pSD, TRUE, NULL, FALSE); - return S_OK; -} - -HRESULT COpcSecurity::InitializeFromProcessToken(BOOL bDefaulted) -{ - PSID pUserSid = NULL; - PSID pGroupSid = NULL; - HRESULT hr; - - Initialize(); - hr = GetProcessSids(&pUserSid, &pGroupSid); - if (SUCCEEDED(hr)) - { - hr = SetOwner(pUserSid, bDefaulted); - if (SUCCEEDED(hr)) - hr = SetGroup(pGroupSid, bDefaulted); - } - if (pUserSid != NULL) - free(pUserSid); - if (pGroupSid != NULL) - free(pGroupSid); - return hr; -} - -HRESULT COpcSecurity::InitializeFromThreadToken(BOOL bDefaulted, BOOL bRevertToProcessToken) -{ - PSID pUserSid = NULL; - PSID pGroupSid = NULL; - HRESULT hr; - - Initialize(); - hr = GetThreadSids(&pUserSid, &pGroupSid); - if (HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken) - hr = GetProcessSids(&pUserSid, &pGroupSid); - if (SUCCEEDED(hr)) - { - hr = SetOwner(pUserSid, bDefaulted); - if (SUCCEEDED(hr)) - hr = SetGroup(pGroupSid, bDefaulted); - } - if (pUserSid != NULL) - free(pUserSid); - if (pGroupSid != NULL) - free(pGroupSid); - return hr; -} - -HRESULT COpcSecurity::SetOwner(PSID pOwnerSid, BOOL bDefaulted) -{ - OPCASSERT(m_pSD); - - // Mark the SD as having no owner - if (!SetSecurityDescriptorOwner(m_pSD, NULL, bDefaulted)) - { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - return hr; - } - - if (m_pOwner) - { - free(m_pOwner); - m_pOwner = NULL; - } - - // If they asked for no owner don't do the copy - if (pOwnerSid == NULL) - return S_OK; - - // Make a copy of the Sid for the return value - DWORD dwSize = GetLengthSid(pOwnerSid); - - m_pOwner = (PSID) malloc(dwSize); - if (m_pOwner == NULL) - return E_OUTOFMEMORY; - if (!CopySid(dwSize, m_pOwner, pOwnerSid)) - { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - free(m_pOwner); - m_pOwner = NULL; - return hr; - } - - OPCASSERT(IsValidSid(m_pOwner)); - - if (!SetSecurityDescriptorOwner(m_pSD, m_pOwner, bDefaulted)) - { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - free(m_pOwner); - m_pOwner = NULL; - return hr; - } - - return S_OK; -} - -HRESULT COpcSecurity::SetGroup(PSID pGroupSid, BOOL bDefaulted) -{ - OPCASSERT(m_pSD); - - // Mark the SD as having no Group - if (!SetSecurityDescriptorGroup(m_pSD, NULL, bDefaulted)) - { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - return hr; - } - - if (m_pGroup) - { - free(m_pGroup); - m_pGroup = NULL; - } - - // If they asked for no Group don't do the copy - if (pGroupSid == NULL) - return S_OK; - - // Make a copy of the Sid for the return value - DWORD dwSize = GetLengthSid(pGroupSid); - - m_pGroup = (PSID) malloc(dwSize); - if (m_pGroup == NULL) - return E_OUTOFMEMORY; - if (!CopySid(dwSize, m_pGroup, pGroupSid)) - { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - free(m_pGroup); - m_pGroup = NULL; - return hr; - } - - OPCASSERT(IsValidSid(m_pGroup)); - - if (!SetSecurityDescriptorGroup(m_pSD, m_pGroup, bDefaulted)) - { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - free(m_pGroup); - m_pGroup = NULL; - return hr; - } - - return S_OK; -} - -HRESULT COpcSecurity::Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask) -{ - HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask); - if (SUCCEEDED(hr)) - SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE); - return hr; -} - -HRESULT COpcSecurity::Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask) -{ - HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask); - if (SUCCEEDED(hr)) - SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE); - return hr; -} - -HRESULT COpcSecurity::Revoke(LPCTSTR pszPrincipal) -{ - HRESULT hr = RemovePrincipalFromACL(m_pDACL, pszPrincipal); - if (SUCCEEDED(hr)) - SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE); - return hr; -} - -HRESULT COpcSecurity::GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid) -{ - BOOL bRes; - HRESULT hr; - HANDLE hToken = NULL; - if (ppUserSid) - *ppUserSid = NULL; - if (ppGroupSid) - *ppGroupSid = NULL; - bRes = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); - if (!bRes) - { - // Couldn't open process token - hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - return hr; - } - hr = GetTokenSids(hToken, ppUserSid, ppGroupSid); - CloseHandle(hToken); - return hr; -} - -HRESULT COpcSecurity::GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid, BOOL bOpenAsSelf) -{ - BOOL bRes; - HRESULT hr; - HANDLE hToken = NULL; - if (ppUserSid) - *ppUserSid = NULL; - if (ppGroupSid) - *ppGroupSid = NULL; - bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken); - if (!bRes) - { - // Couldn't open thread token - hr = HRESULT_FROM_WIN32(GetLastError()); - return hr; - } - hr = GetTokenSids(hToken, ppUserSid, ppGroupSid); - CloseHandle(hToken); - return hr; -} - -HRESULT COpcSecurity::GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid) -{ - DWORD dwSize; - HRESULT hr; - PTOKEN_USER ptkUser = NULL; - PTOKEN_PRIMARY_GROUP ptkGroup = NULL; - - if (ppUserSid) - *ppUserSid = NULL; - if (ppGroupSid) - *ppGroupSid = NULL; - - if (ppUserSid) - { - // Get length required for TokenUser by specifying buffer length of 0 - GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize); - hr = GetLastError(); - if (hr != ERROR_INSUFFICIENT_BUFFER) - { - // Expected ERROR_INSUFFICIENT_BUFFER - OPCASSERT(FALSE); - hr = HRESULT_FROM_WIN32(hr); - goto failed; - } - - ptkUser = (TOKEN_USER*) malloc(dwSize); - if (ptkUser == NULL) - { - hr = E_OUTOFMEMORY; - goto failed; - } - // Get Sid of process token. - if (!GetTokenInformation(hToken, TokenUser, ptkUser, dwSize, &dwSize)) - { - // Couldn't get user info - hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - goto failed; - } - - // Make a copy of the Sid for the return value - dwSize = GetLengthSid(ptkUser->User.Sid); - - PSID pSid; - pSid = (PSID) malloc(dwSize); - if (pSid == NULL) - { - hr = E_OUTOFMEMORY; - goto failed; - } - if (!CopySid(dwSize, pSid, ptkUser->User.Sid)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - goto failed; - } - - OPCASSERT(IsValidSid(pSid)); - *ppUserSid = pSid; - free(ptkUser); - } - if (ppGroupSid) - { - // Get length required for TokenPrimaryGroup by specifying buffer length of 0 - GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize); - hr = GetLastError(); - if (hr != ERROR_INSUFFICIENT_BUFFER) - { - // Expected ERROR_INSUFFICIENT_BUFFER - OPCASSERT(FALSE); - hr = HRESULT_FROM_WIN32(hr); - goto failed; - } - - ptkGroup = (TOKEN_PRIMARY_GROUP*) malloc(dwSize); - if (ptkGroup == NULL) - { - hr = E_OUTOFMEMORY; - goto failed; - } - // Get Sid of process token. - if (!GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize)) - { - // Couldn't get user info - hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - goto failed; - } - - // Make a copy of the Sid for the return value - dwSize = GetLengthSid(ptkGroup->PrimaryGroup); - - PSID pSid; - pSid = (PSID) malloc(dwSize); - if (pSid == NULL) - { - hr = E_OUTOFMEMORY; - goto failed; - } - if (!CopySid(dwSize, pSid, ptkGroup->PrimaryGroup)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - goto failed; - } - - OPCASSERT(IsValidSid(pSid)); - - *ppGroupSid = pSid; - free(ptkGroup); - } - - return S_OK; - -failed: - if (ptkUser) - free(ptkUser); - if (ptkGroup) - free (ptkGroup); - return hr; -} - - -HRESULT COpcSecurity::GetCurrentUserSID(PSID *ppSid) -{ - HANDLE tkHandle; - - if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle)) - { - TOKEN_USER *tkUser; - DWORD tkSize; - DWORD sidLength; - - // Call to get size information for alloc - GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize); - tkUser = (TOKEN_USER *) malloc(tkSize); - if (tkUser == NULL) - return E_OUTOFMEMORY; - - // Now make the real call - if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize)) - { - sidLength = GetLengthSid(tkUser->User.Sid); - *ppSid = (PSID) malloc(sidLength); - if (*ppSid == NULL) - return E_OUTOFMEMORY; - - memcpy(*ppSid, tkUser->User.Sid, sidLength); - CloseHandle(tkHandle); - - free(tkUser); - return S_OK; - } - else - { - free(tkUser); - return HRESULT_FROM_WIN32(GetLastError()); - } - } - return HRESULT_FROM_WIN32(GetLastError()); -} - - -HRESULT COpcSecurity::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid) -{ - HRESULT hr; - LPTSTR pszRefDomain = NULL; - DWORD dwDomainSize = 0; - DWORD dwSidSize = 0; - SID_NAME_USE snu; - - // Call to get size info for alloc - LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu); - - hr = GetLastError(); - if (hr != ERROR_INSUFFICIENT_BUFFER) - return HRESULT_FROM_WIN32(hr); - - OPCTRY(pszRefDomain = new TCHAR[dwDomainSize]); - if (pszRefDomain == NULL) - return E_OUTOFMEMORY; - - *ppSid = (PSID) malloc(dwSidSize); - if (*ppSid != NULL) - { - if (!LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu)) - { - free(*ppSid); - *ppSid = NULL; - delete[] pszRefDomain; - return HRESULT_FROM_WIN32(GetLastError()); - } - delete[] pszRefDomain; - return S_OK; - } - delete[] pszRefDomain; - return E_OUTOFMEMORY; -} - - -HRESULT COpcSecurity::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD) -{ - PACL pDACL = NULL; - PACL pSACL = NULL; - BOOL bDACLPresent, bSACLPresent; - BOOL bDefaulted; - PACL m_pDACL = NULL; - ACCESS_ALLOWED_ACE* pACE; - HRESULT hr; - PSID pUserSid; - PSID pGroupSid; - - hr = Initialize(); - if(FAILED(hr)) - return hr; - - // get the existing DACL. - if (!GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted)) - goto failed; - - if (bDACLPresent) - { - if (pDACL) - { - // allocate new DACL. - m_pDACL = (PACL) malloc(pDACL->AclSize); - if (m_pDACL == NULL) - { - hr = E_OUTOFMEMORY; - goto failedMemory; - } - - // initialize the DACL - if (!InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION)) - goto failed; - - // copy the ACES - for (int i = 0; i < pDACL->AceCount; i++) - { - if (!GetAce(pDACL, i, (void **)&pACE)) - goto failed; - - if (!AddAccessAllowedAce(m_pDACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart))) - goto failed; - } - - if (!IsValidAcl(m_pDACL)) - goto failed; - } - - // set the DACL - if (!SetSecurityDescriptorDacl(m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, bDefaulted)) - goto failed; - } - - // get the existing SACL. - if (!GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted)) - goto failed; - - if (bSACLPresent) - { - if (pSACL) - { - // allocate new SACL. - m_pSACL = (PACL) malloc(pSACL->AclSize); - if (m_pSACL == NULL) - { - hr = E_OUTOFMEMORY; - goto failedMemory; - } - - // initialize the SACL - if (!InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION)) - goto failed; - - // copy the ACES - for (int i = 0; i < pSACL->AceCount; i++) - { - if (!GetAce(pSACL, i, (void **)&pACE)) - goto failed; - - if (!AddAccessAllowedAce(m_pSACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart))) - goto failed; - } - - if (!IsValidAcl(m_pSACL)) - goto failed; - } - - // set the SACL - if (!SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, bDefaulted)) - goto failed; - } - - if (!GetSecurityDescriptorOwner(m_pSD, &pUserSid, &bDefaulted)) - goto failed; - - if (FAILED(SetOwner(pUserSid, bDefaulted))) - goto failed; - - if (!GetSecurityDescriptorGroup(m_pSD, &pGroupSid, &bDefaulted)) - goto failed; - - if (FAILED(SetGroup(pGroupSid, bDefaulted))) - goto failed; - - if (!IsValidSecurityDescriptor(m_pSD)) - goto failed; - - return hr; - -failed: - hr = HRESULT_FROM_WIN32(hr); - -failedMemory: - if (m_pDACL) - { - free(m_pDACL); - m_pDACL = NULL; - } - if (m_pSD) - { - free(m_pSD); - m_pSD = NULL; - } - return hr; -} - -HRESULT COpcSecurity::AttachObject(HANDLE hObject) -{ - HRESULT hr; - DWORD dwSize = 0; - PSECURITY_DESCRIPTOR pSD = NULL; - - GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION, pSD, 0, &dwSize); - - hr = GetLastError(); - if (hr != ERROR_INSUFFICIENT_BUFFER) - return HRESULT_FROM_WIN32(hr); - - pSD = (PSECURITY_DESCRIPTOR) malloc(dwSize); - if (pSD == NULL) - return E_OUTOFMEMORY; - - if (!GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - free(pSD); - return hr; - } - - hr = Attach(pSD); - free(pSD); - return hr; -} - - -HRESULT COpcSecurity::CopyACL(PACL pDest, PACL pSrc) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - LPVOID pAce; - ACE_HEADER *aceHeader; - - if (pSrc == NULL) - return S_OK; - - if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) - return HRESULT_FROM_WIN32(GetLastError()); - - // Copy all of the ACEs to the new ACL - for (UINT i = 0; i < aclSizeInfo.AceCount; i++) - { - if (!GetAce(pSrc, i, &pAce)) - return HRESULT_FROM_WIN32(GetLastError()); - - aceHeader = (ACE_HEADER *) pAce; - - if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize)) - return HRESULT_FROM_WIN32(GetLastError()); - } - - return S_OK; -} - -HRESULT COpcSecurity::AddAccessDeniedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - int aclSize; - DWORD returnValue; - PSID principalSID; - PACL oldACL, newACL = NULL; - - oldACL = *ppAcl; - - returnValue = GetPrincipalSID(pszPrincipal, &principalSID); - if (FAILED(returnValue)) - return returnValue; - - aclSizeInfo.AclBytesInUse = 0; - if (*ppAcl != NULL) - GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation); - - aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD); - - OPCTRY(newACL = (PACL) new BYTE[aclSize]); - if (newACL == NULL) - return E_OUTOFMEMORY; - - if (!InitializeAcl(newACL, aclSize, ACL_REVISION)) - { - free(principalSID); - return HRESULT_FROM_WIN32(GetLastError()); - } - - if (!AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID)) - { - free(principalSID); - return HRESULT_FROM_WIN32(GetLastError()); - } - - returnValue = CopyACL(newACL, oldACL); - if (FAILED(returnValue)) - { - free(principalSID); - return returnValue; - } - - *ppAcl = newACL; - - if (oldACL != NULL) - free(oldACL); - free(principalSID); - return S_OK; -} - - -HRESULT COpcSecurity::AddAccessAllowedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - int aclSize; - DWORD returnValue; - PSID principalSID; - PACL oldACL, newACL = NULL; - - oldACL = *ppAcl; - - returnValue = GetPrincipalSID(pszPrincipal, &principalSID); - if (FAILED(returnValue)) - return returnValue; - - aclSizeInfo.AclBytesInUse = 0; - if (*ppAcl != NULL) - GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation); - - aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD); - - OPCTRY(newACL = (PACL) new BYTE[aclSize]); - if (newACL == NULL) - return E_OUTOFMEMORY; - - if (!InitializeAcl(newACL, aclSize, ACL_REVISION)) - { - free(principalSID); - return HRESULT_FROM_WIN32(GetLastError()); - } - - returnValue = CopyACL(newACL, oldACL); - if (FAILED(returnValue)) - { - free(principalSID); - return returnValue; - } - - if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID)) - { - free(principalSID); - return HRESULT_FROM_WIN32(GetLastError()); - } - - *ppAcl = newACL; - - if (oldACL != NULL) - free(oldACL); - free(principalSID); - return S_OK; -} - - -HRESULT COpcSecurity::RemovePrincipalFromACL(PACL pAcl, LPCTSTR pszPrincipal) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - ULONG i; - LPVOID ace; - ACCESS_ALLOWED_ACE *accessAllowedAce; - ACCESS_DENIED_ACE *accessDeniedAce; - SYSTEM_AUDIT_ACE *systemAuditAce; - PSID principalSID; - DWORD returnValue; - ACE_HEADER *aceHeader; - - returnValue = GetPrincipalSID(pszPrincipal, &principalSID); - if (FAILED(returnValue)) - return returnValue; - - GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation); - - for (i = 0; i < aclSizeInfo.AceCount; i++) - { - if (!GetAce(pAcl, i, &ace)) - { - free(principalSID); - return HRESULT_FROM_WIN32(GetLastError()); - } - - aceHeader = (ACE_HEADER *) ace; - - if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) - { - accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace; - - if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart)) - { - DeleteAce(pAcl, i); - free(principalSID); - return S_OK; - } - } else - - if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE) - { - accessDeniedAce = (ACCESS_DENIED_ACE *) ace; - - if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart)) - { - DeleteAce(pAcl, i); - free(principalSID); - return S_OK; - } - } else - - if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE) - { - systemAuditAce = (SYSTEM_AUDIT_ACE *) ace; - - if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart)) - { - DeleteAce(pAcl, i); - free(principalSID); - return S_OK; - } - } - } - free(principalSID); - return S_OK; -} - - -HRESULT COpcSecurity::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken) -{ - HRESULT hr; - TOKEN_PRIVILEGES tpPrevious; - TOKEN_PRIVILEGES tp; - DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); - LUID luid; - HANDLE hTokenUsed; - - // if no token specified open process token - if (hToken == 0) - { - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - return hr; - } - } - else - hTokenUsed = hToken; - - if (!LookupPrivilegeValue(NULL, privilege, &luid )) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - if (hToken == 0) - CloseHandle(hTokenUsed); - return hr; - } - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = 0; - - if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - if (hToken == 0) - CloseHandle(hTokenUsed); - return hr; - } - - tpPrevious.PrivilegeCount = 1; - tpPrevious.Privileges[0].Luid = luid; - - if (bEnable) - tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); - else - tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes); - - if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tpPrevious, cbPrevious, NULL, NULL)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - OPCASSERT(FALSE); - if (hToken == 0) - CloseHandle(hTokenUsed); - return hr; - } - return S_OK; -} diff --git a/ComIOP/Wrapper/Common/COpcSecurity.h b/ComIOP/Wrapper/Common/COpcSecurity.h deleted file mode 100644 index 2b5e74409..000000000 --- a/ComIOP/Wrapper/Common/COpcSecurity.h +++ /dev/null @@ -1,88 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcSecurity_H_ -#define _COpcSecurity_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" - -//============================================================================== -// CLASS: COpcSecurity -// PURPOSE: Encapsulates details of security implementations. - -class OPCUTILS_API COpcSecurity -{ -public: - COpcSecurity(); - ~COpcSecurity(); - -public: - - HRESULT Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD); - HRESULT AttachObject(HANDLE hObject); - HRESULT Initialize(); - HRESULT InitializeFromProcessToken(BOOL bDefaulted = FALSE); - HRESULT InitializeFromThreadToken(BOOL bDefaulted = FALSE, BOOL bRevertToProcessToken = TRUE); - HRESULT SetOwner(PSID pOwnerSid, BOOL bDefaulted = FALSE); - HRESULT SetGroup(PSID pGroupSid, BOOL bDefaulted = FALSE); - HRESULT Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask); - HRESULT Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask); - HRESULT Revoke(LPCTSTR pszPrincipal); - - // utility functions - // Any PSID you get from these functions should be free()ed - static HRESULT SetPrivilege(LPCTSTR Privilege, BOOL bEnable = TRUE, HANDLE hToken = NULL); - static HRESULT GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid); - static HRESULT GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid = NULL); - static HRESULT GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid = NULL, BOOL bOpenAsSelf = FALSE); - static HRESULT CopyACL(PACL pDest, PACL pSrc); - static HRESULT GetCurrentUserSID(PSID *ppSid); - static HRESULT GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid); - static HRESULT AddAccessAllowedACEToACL(PACL *Acl, LPCTSTR pszPrincipal, DWORD dwAccessMask); - static HRESULT AddAccessDeniedACEToACL(PACL *Acl, LPCTSTR pszPrincipal, DWORD dwAccessMask); - static HRESULT RemovePrincipalFromACL(PACL Acl, LPCTSTR pszPrincipal); - - operator PSECURITY_DESCRIPTOR() - { - return m_pSD; - } - -public: - PSECURITY_DESCRIPTOR m_pSD; - PSID m_pOwner; - PSID m_pGroup; - PACL m_pDACL; - PACL m_pSACL; -}; - -#endif //ndef _COpcSecurity_H_ diff --git a/ComIOP/Wrapper/Common/COpcSortedArray.h b/ComIOP/Wrapper/Common/COpcSortedArray.h deleted file mode 100644 index c740bcacc..000000000 --- a/ComIOP/Wrapper/Common/COpcSortedArray.h +++ /dev/null @@ -1,514 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcSortedArray_H -#define _COpcSortedArray_H - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "COpcString.h" - -//============================================================================== -// CLASS: COpcList -// PURPOSE: Defines a indexable array template class. - -template -class COpcSortedArray -{ - OPC_CLASS_NEW_DELETE_ARRAY() - -public: - - //========================================================================== - // Constructor - COpcSortedArray(UINT uCapacity = 0, UINT uBlockSize = 16) - : - m_pKeys(NULL), - m_pValues(NULL), - m_uCapacity(0), - m_uCount(0), - m_uBlockSize(uBlockSize) - { - SetCapacity(uCapacity); - } - - //========================================================================== - // Copy Constructor - COpcSortedArray(const COpcSortedArray& cArray) - : - m_pKeys(NULL), - m_pValues(NULL), - m_uCapacity(0), - m_uCount(0) - { - *this = cArray; - } - - //========================================================================== - // Destructor - ~COpcSortedArray() - { - RemoveAll(); - } - - //========================================================================== - // Assignment - COpcSortedArray& operator=(const COpcSortedArray& cArray) - { - RemoveAll(); - - SetCapacity(cArray.m_uCapacity); - - for (UINT ii = 0; ii < cArray.m_uCount; ii++) - { - m_pKeys[ii] = cArray.m_pKeys[ii]; - m_pValues[ii] = cArray.m_pValues[ii]; - } - - return *this; - } - - //========================================================================== - // GetCapacity - UINT GetCapacity() const - { - return m_uCapacity; - } - - //========================================================================== - // SetCapacity - void SetCapacity(UINT uNewCapacity) - { - if (uNewCapacity == 0) - { - RemoveAll(); - return; - } - - KEY* pKeys = new KEY[uNewCapacity]; - VALUE* pValues = new VALUE[uNewCapacity]; - - for (UINT ii = 0; ii < uNewCapacity && ii < m_uCount; ii++) - { - pKeys[ii] = m_pKeys[ii]; - pValues[ii] = m_pValues[ii]; - } - - if (m_pKeys != NULL) - { - delete [] m_pKeys; - } - - if (m_pValues != NULL) - { - delete [] m_pValues; - } - - m_pKeys = pKeys; - m_pValues = pValues; - m_uCapacity = uNewCapacity; - - if (m_uCount > uNewCapacity) - { - m_uCount = uNewCapacity; - } - } - - //========================================================================== - // RemoveAll - void RemoveAll() - { - if (m_pKeys != NULL) - { - delete [] m_pKeys; - m_pKeys = NULL; - } - - if (m_pValues != NULL) - { - delete [] m_pValues; - m_pValues = NULL; - } - - m_uCapacity = 0; - m_uCount = 0; - } - - //========================================================================== - // Append - bool Append(const KEY& cKey, const VALUE& cValue) - { - // used to bulk load pre-sorted values into the array. - if (m_uCount > 0) - { - if (m_pKeys[m_uCount-1] > cKey) - { - return false; - } - } - - // increase capacity as required. - if (m_uCapacity <= m_uCount) - { - SetCapacity(m_uCapacity + m_uBlockSize); - } - - // add to end of list. - m_pKeys[m_uCount] = cKey; - m_pValues[m_uCount] = cValue; - - m_uCount++; - - // ok. - return true; - } - - //========================================================================== - // GetCount - UINT GetCount() const - { - return m_uCount; - } - - //========================================================================== - // operator[] - VALUE& operator[](UINT uIndex) - { - OPC_ASSERT(uIndex < m_uCount); - return m_pValues[uIndex]; - } - - const VALUE& operator[](UINT uIndex) const - { - OPC_ASSERT(uIndex < m_uCount); - return m_pValues[uIndex]; - } - - //========================================================================== - // GetKey - const KEY& GetKey(UINT uIndex) const - { - OPC_ASSERT(uIndex < m_uCount); - return m_pKeys[uIndex]; - } - - //========================================================================== - // GetLastValue - const VALUE& GetLastValue() const - { - OPC_ASSERT(m_uCount > 0); - return m_pValues[m_uCount-1]; - } - - //========================================================================== - // IsValidIndex - bool IsValidIndex(UINT uIndex) const - { - return (uIndex < m_uCount); - } - - //========================================================================== - // FindIndex - UINT FindIndex(const KEY& cKey) - { - // check for empty list. - if (m_uCount == 0 || cKey < m_pKeys[0] || cKey > m_pKeys[m_uCount-1]) - { - return -1; - } - - // find key. - UINT uLower = 0; - UINT uUpper = 0; - - if (FindBounds(cKey, uLower, uUpper)) - { - return uLower; - } - - return -1; - } - - //========================================================================== - // FindIndexBefore - UINT FindIndexBefore(const KEY& cKey) - { - // check for empty list. - if (m_uCount == 0 || cKey < m_pKeys[0]) - { - return -1; - } - - UINT uLower = 0; - UINT uUpper = 0; - - if (FindBounds(cKey, uLower, uUpper)) - { - return uUpper; - } - - return uLower; - } - - //========================================================================== - // FindIndexAfter - UINT FindIndexAfter(const KEY& cKey) - { - // check for empty list. - if (m_uCount == 0 || cKey > m_pKeys[m_uCount-1]) - { - return -1; - } - - UINT uLower = 0; - UINT uUpper = 0; - - if (FindBounds(cKey, uLower, uUpper)) - { - return uLower; - } - - return uUpper; - } - - //========================================================================== - // Insert - UINT Insert(const KEY& cKey, const VALUE& cValue) - { - // increase capacity as required. - if (m_uCapacity <= m_uCount) - { - SetCapacity(m_uCapacity + m_uBlockSize); - } - - // find location in array. - UINT uLower = 0; - UINT uUpper = 0; - - bool bKeyExists = FindBounds(cKey, uLower, uUpper); - - // insert at end of array. - if (uUpper == -1) - { - m_pKeys[m_uCount] = cKey; - m_pValues[m_uCount] = cValue; - - // increment count. - m_uCount++; - - // return new index. - return m_uCount-1; - } - - // determine index of new value. - UINT uIndex = (bKeyExists)?uUpper+1:uUpper; - - // shift values after the value up one index. - for (UINT ii = m_uCount; ii > uIndex; ii--) - { - m_pKeys[ii] = m_pKeys[ii-1]; - m_pValues[ii] = m_pValues[ii-1]; - } - - // add key/value to array. - m_pKeys[uIndex] = cKey; - m_pValues[uIndex] = cValue; - - // increment count. - m_uCount++; - - // return new index. - return uIndex; - } - - //========================================================================== - // RemoveAt - void RemoveAt(UINT uIndex, UINT uCount = 1) - { - if (uIndex < m_uCount && uCount > 0) - { - // adjust the count. - if (uCount > m_uCount-uIndex) - { - uCount = m_uCount-uIndex; - } - - // shift values after the value down one index. - for (UINT ii = uIndex; ii < m_uCount-uCount; ii++) - { - m_pKeys[ii] = m_pKeys[ii+uCount]; - m_pValues[ii] = m_pValues[ii+uCount]; - } - - // decrement count. - m_uCount -= uCount; - } - } - - //========================================================================== - // FindBounds - bool FindBounds(const KEY& cTarget, UINT& uLower, UINT& uUpper) - { - uLower = -1; - uUpper = -1; - - // check if no values exists. - if (m_uCount == 0) - { - return false; - } - - // check if target is before first value. - if (cTarget < m_pKeys[0]) - { - uLower = -1; - uUpper = 0; - return false; - } - - // check if target is after last value. - if (cTarget > m_pKeys[m_uCount-1]) - { - uLower = m_uCount-1; - uUpper = -1; - return false; - } - - // check if target is the last value. - if (cTarget == m_pKeys[m_uCount-1]) - { - uLower = uUpper = m_uCount-1; - - // adjust lower bound to beginning duplicate keys. - while (uLower > 0 && m_pKeys[uLower-1] == cTarget) - { - uLower--; - } - - return true; - } - - // start with full range of data. - uLower = 0; - uUpper = m_uCount-1; - - // narrow the bounds as much as possible. - while (uUpper - uLower > 1 && cTarget != m_pKeys[uLower]) - { - // split the range in half and discard the half that the key does not belong to. - UINT uBound = uUpper - (uUpper-uLower)/2; - - // keep the lower range. - if (KeyInRange(uLower, uBound, cTarget)) - { - uUpper = uBound; - } - - // keep the upper range. - else - { - uLower = uBound; - } - } - - // a value at the key does not exist. - if (cTarget != m_pKeys[uLower]) - { - return false; - } - - // adjust upper bound end of range of duplicate keys. - uUpper = uLower; - - while (uUpper < m_uCount-1 && m_pKeys[uUpper+1] == cTarget) - { - uUpper++; - } - - // adjust lower bound to beginning duplicate timestamps. - while (uLower > 0 && m_pKeys[uLower-1] == cTarget) - { - uLower--; - } - - // a value at the time does exist. - return true; - } - -private: - - //========================================================================== - // KeyInRange - bool KeyInRange(UINT uLower, UINT uUpper, const KEY& cTarget) - { - // ensure upper bound is a valid index. - if (uUpper > m_uCount) - { - uUpper = m_uCount-1; - } - - // check if lower bound is a valid index. - if (uLower >= m_uCount || uUpper < uLower) - { - return false; - } - - // check if target is within range. - if (m_pKeys[uLower] <= cTarget) - { - if (m_pKeys[uUpper] > cTarget || (m_pKeys[uLower] == cTarget && m_pKeys[uLower] == m_pKeys[uUpper])) - { - return true; - } - } - - // target is not within range. - return false; - } - - KEY* m_pKeys; - VALUE* m_pValues; - UINT m_uCapacity; - UINT m_uCount; - UINT m_uBlockSize; -}; - -//============================================================================== -// VALUE: COpcStringArray -// PURPOSE: An array of strings. - -typedef COpcSortedArray COpcSortedStringArray; - -#ifndef OPCUTILS_EXPORTS -template class OPCUTILS_API COpcSortedArray; -#endif - -#endif //ndef _COpcSortedArray_H diff --git a/ComIOP/Wrapper/Common/COpcString.cpp b/ComIOP/Wrapper/Common/COpcString.cpp deleted file mode 100644 index 3cf454309..000000000 --- a/ComIOP/Wrapper/Common/COpcString.cpp +++ /dev/null @@ -1,905 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcString.h" - -//============================================================================== -// Local Declarations - -#define GUID_STR_LENGTH 38 - -//============================================================================== -// COpcString - -// Constructor -COpcString::COpcString() -{ - m_pBuf = NULL; -} - -// Constructor -COpcString::COpcString(LPCSTR szStr) -{ - m_pBuf = NULL; - Set(szStr); -} - -// Constructor -COpcString::COpcString(LPCWSTR wszStr) -{ - m_pBuf = NULL; - Set(wszStr); -} - -// Copy Constructor -COpcString::COpcString(const COpcString& cStr) -{ - m_pBuf = NULL; - Set(cStr); -} - -COpcString::COpcString(const GUID& cGuid) -{ - m_pBuf = NULL; - FromGuid(cGuid); -} - -// Destructor -COpcString::~COpcString() -{ - Free(); -} - -// Cast -COpcString::operator LPCSTR() const -{ - TStrBuf* pBuf = (TStrBuf*)this->m_pBuf; - - if (pBuf == NULL) - { - return NULL; - } - - #ifdef _UNICODE - if (pBuf->szStr == NULL) - { - ((LPSTR)pBuf->szStr) = ToMultiByte(pBuf->wszStr); - } - #endif - - return pBuf->szStr; -} - -// Cast -COpcString::operator LPCWSTR() const -{ - TStrBuf* pBuf = (TStrBuf*)this->m_pBuf; - - if (pBuf == NULL) - { - return NULL; - } - - #ifndef _UNICODE - if (pBuf->wszStr == NULL) - { - ((LPWSTR)pBuf->wszStr) = ToUnicode(pBuf->szStr); - } - #endif - - return pBuf->wszStr; -} - -// Assignment -COpcString& COpcString::operator=(const COpcString& cStr) -{ - Set(cStr); - return *this; -} - -// Index -TCHAR& COpcString::operator[](UINT uIndex) -{ - #ifdef _UNICODE - OpcFree(m_pBuf->szStr); - m_pBuf->szStr = NULL; - #else - OpcFree(m_pBuf->wszStr); - m_pBuf->wszStr = NULL; - #endif - - OPC_ASSERT(uIndex < GetLength()); - return ((LPTSTR)((LPCTSTR)*this))[uIndex]; -} - -// Index -TCHAR COpcString::operator[](UINT uIndex) const -{ - OPC_ASSERT(uIndex < GetLength()); - return ((LPCTSTR)*this)[uIndex]; -} - -// Append -COpcString& COpcString::operator+=(const COpcString& cStr) -{ - UINT uLength1 = GetLength(); - UINT uLength2 = uLength1 + cStr.GetLength(); - - // check for buffer overflow. - if (uLength2 < uLength1) - { - Empty(); - return *this; - } - - TStrBuf* pBuf = Alloc(uLength2); - - if (pBuf == NULL) - { - Empty(); - return *this; - } - - #ifdef _UNICODE - - if ((LPCWSTR)*this != NULL) - { - wcscpy(pBuf->wszStr, (LPCWSTR)*this); - } - - if ((LPCWSTR)(COpcString&)cStr != NULL) - { - wcscat(pBuf->wszStr, (LPCWSTR)(COpcString&)cStr); - } - - #else - - if ((LPCSTR)*this != NULL) - { - strcpy(pBuf->szStr, (LPCSTR)*this); - } - - if ((LPCSTR)(COpcString&)cStr != NULL) - { - strcat(pBuf->szStr, (LPCSTR)(COpcString&)cStr); - } - - #endif - - Free(); - m_pBuf = pBuf; - return *this; -} - -// Compare -int COpcString::Compare(const COpcString& cStr) const -{ - // check for self references. - if (&cStr == this) return 0; - if (cStr.m_pBuf == m_pBuf) return 0; - - // check for null. - if (cStr.m_pBuf == NULL) return +1; - if (m_pBuf == NULL) return -1; - - // compare strings. - #ifdef _UNICODE - return wcscmp((LPCWSTR)*this, (LPCWSTR)(COpcString&)cStr); - #else - return strcmp((LPCSTR)*this, (LPCSTR)(COpcString&)cStr); - #endif -} - -// Addition -COpcString operator+(const COpcString& cStr1, LPCSTR szStr2) -{ - COpcString cStr(cStr1); - cStr += szStr2; - return cStr; -} - -// Addition -COpcString operator+(const COpcString& cStr1, LPCWSTR wszStr2) -{ - COpcString cStr(cStr1); - cStr += wszStr2; - return cStr; -} - -// Addition -COpcString operator+(const COpcString& cStr1, const COpcString& cStr2) -{ - COpcString cStr(cStr1); - cStr += cStr2; - return cStr; -} - -// Addition -COpcString operator+(LPCSTR szStr1, const COpcString& cStr2) -{ - COpcString cStr(szStr1); - cStr += cStr2; - return cStr; -} - -// Addition -COpcString operator+(LPCWSTR wszStr1, const COpcString& cStr2) -{ - COpcString cStr(wszStr1); - cStr += cStr2; - return cStr; -} - -// IsEmpty -bool COpcString::IsEmpty() const -{ - return (m_pBuf == NULL); -} - -// GetLength -UINT COpcString::GetLength() const -{ - if (m_pBuf == NULL) - { - return 0; - } - - #ifdef _UNICODE - return wcslen(m_pBuf->wszStr); - #else - return strlen(m_pBuf->szStr); - #endif -} - -// GetBuffer -LPTSTR COpcString::GetBuffer() -{ - if (m_pBuf == NULL) - { - // set it to a zero length string. - Set(OPC_EMPTY_STRING); - } - - #ifdef _UNICODE - OpcFree(m_pBuf->szStr); - m_pBuf->szStr = NULL; - return m_pBuf->wszStr; - #else - OpcFree(m_pBuf->wszStr); - m_pBuf->wszStr = NULL; - return m_pBuf->szStr; - #endif -} - -// SetBuffer -void COpcString::SetBuffer(UINT uLength) -{ - Free(); - m_pBuf = Alloc(uLength); -} - -// Free -void COpcString::Free() -{ - if (m_pBuf != NULL) - { - LONG lRefs = InterlockedDecrement((LONG*)&m_pBuf->uRefs); - - if (lRefs == 0) - { - OpcFree(m_pBuf->szStr); - OpcFree(m_pBuf->wszStr); - OpcFree(m_pBuf); - } - - m_pBuf = NULL; - } -} - -// Set -void COpcString::Set(LPCSTR szStr) -{ - Free(); - - if (szStr == NULL || strlen(szStr) == 0) - { - return; - } - - m_pBuf = (TStrBuf*)OpcAlloc(sizeof(TStrBuf)); - m_pBuf->uRefs = 1; - - #ifdef _UNICODE - m_pBuf->szStr = NULL; - m_pBuf->wszStr = ToUnicode(szStr); - #else - m_pBuf->szStr = Clone(szStr); - m_pBuf->wszStr = NULL; - #endif -} - -// Set -void COpcString::Set(LPCWSTR wszStr) -{ - Free(); - - if (wszStr == NULL || wcslen(wszStr) == 0) - { - return; - } - - m_pBuf = (TStrBuf*)OpcAlloc(sizeof(TStrBuf)); - m_pBuf->uRefs = 1; - - #ifdef _UNICODE - m_pBuf->szStr = NULL; - m_pBuf->wszStr = Clone(wszStr); - #else - m_pBuf->szStr = ToMultiByte(wszStr); - m_pBuf->wszStr = NULL; - #endif -} - -// Set -void COpcString::Set(const COpcString& cStr) -{ - // check for self references. - if (&cStr == this) return; - if (cStr.m_pBuf == m_pBuf) return; - - Free(); - - m_pBuf = cStr.m_pBuf; - - if (m_pBuf != NULL) - { - InterlockedIncrement((LONG*)&m_pBuf->uRefs); - } -} - -// Find -int COpcString::Find(LPCTSTR tsTarget) const -{ - LPCTSTR tsStr = (LPCTSTR)*this; - - if (tsStr == NULL || tsTarget == NULL || _tcslen(tsTarget) == 0) - { - return -1; - } - - int iLength = _tcslen(tsTarget); - int iLast = _tcslen(tsStr) - iLength + 1; - - for (int ii = 0; ii < iLast; ii++) - { - if (_tcsncmp(tsStr+ii, tsTarget, iLength) == 0) - { - return ii; - } - } - - return -1; -} - -// ReverseFind -int COpcString::ReverseFind(LPCTSTR tsTarget) const -{ - LPCTSTR tsStr = (LPCTSTR)*this; - - if (tsStr == NULL || tsTarget == NULL || _tcslen(tsTarget) == 0) - { - return -1; - } - - int iLength = _tcslen(tsTarget); - int iLast = _tcslen(tsStr) - iLength; - - for (int ii = iLast; ii >=0; ii--) - { - if (_tcsncmp(tsStr+ii, tsTarget, iLength) == 0) - { - return ii; - } - } - - return -1; -} - -// SubStr -COpcString COpcString::SubStr(UINT uStart, UINT uCount) const -{ - COpcString cStr; - - UINT uLength = GetLength(); - - if (uCount == 0 || uStart >= uLength) - { - return cStr; - } - - uLength = (uCount == -1 || uCount > uLength)?uLength-uStart:uCount; - - cStr.SetBuffer(uLength); - _tcsncpy(cStr.GetBuffer(), ((LPCTSTR)*this)+uStart, uLength); - - return cStr; -} - -// Trim -COpcString& COpcString::Trim() -{ - if (m_pBuf == NULL) - { - return *this; - } - - UINT uStart = 0; - UINT uEnd = GetLength(); - - // remove leading whitespace. - for (UINT ii = 0; ii < uEnd; ii++) - { - if (!_istspace((*this)[ii])) - { - uStart = ii; - break; - } - } - - // string only contained whitespace. - if (uStart == uEnd) - { - Empty(); - return *this; - } - - // remove trailing whitespace - for (ii = uEnd-1; ii >= uStart; ii--) - { - if (!_istspace((*this)[ii])) - { - uEnd = ii+1; - break; - } - } - - // update string. - *this = SubStr(uStart, uEnd - uStart); - - return *this; -} - -// ToLower -COpcString COpcString::ToLower(UINT uIndex) -{ - COpcString cCopy = *this; - - if (cCopy.m_pBuf == NULL) - { - return cCopy; - } - - #ifdef _UNICODE - OpcFree(cCopy.m_pBuf->szStr); - cCopy.m_pBuf->szStr = NULL; - #else - OpcFree(cCopy.m_pBuf->wszStr); - cCopy.m_pBuf->wszStr = NULL; - #endif - - UINT uLength = cCopy.GetLength(); - - if (uIndex == -1) - { - for (UINT ii = 0; ii < uLength; ii++) - { - #ifdef _UNICODE - if (iswupper(cCopy.m_pBuf->wszStr[ii])) cCopy.m_pBuf->wszStr[ii] = towlower(cCopy.m_pBuf->wszStr[ii]); - #else - if (isupper(cCopy.m_pBuf->szStr[ii])) cCopy.m_pBuf->szStr[ii] = tolower(cCopy.m_pBuf->szStr[ii]); - #endif - } - - return *this; - } - - if (uIndex < uLength) - { - #ifdef _UNICODE - if (iswupper(cCopy.m_pBuf->wszStr[uIndex])) cCopy.m_pBuf->wszStr[uIndex] = towlower(cCopy.m_pBuf->wszStr[uIndex]); - #else - if (isupper(cCopy.m_pBuf->szStr[uIndex])) cCopy.m_pBuf->szStr[uIndex] = tolower(cCopy.m_pBuf->szStr[uIndex]); - #endif - } - - return cCopy; -} - -// ToUpper -COpcString COpcString::ToUpper(UINT uIndex) -{ - COpcString cCopy = *this; - - if (cCopy.m_pBuf == NULL) - { - return *this; - } - - #ifdef _UNICODE - OpcFree(cCopy.m_pBuf->szStr); - cCopy.m_pBuf->szStr = NULL; - #else - OpcFree(cCopy.m_pBuf->wszStr); - cCopy.m_pBuf->wszStr = NULL; - #endif - - UINT uLength = cCopy.GetLength(); - - if (uIndex == -1) - { - for (UINT ii = 0; ii < uLength; ii++) - { - #ifdef _UNICODE - if (iswlower(cCopy.m_pBuf->wszStr[ii])) cCopy.m_pBuf->wszStr[ii] = towupper(cCopy.m_pBuf->wszStr[ii]); - #else - if (islower(cCopy.m_pBuf->szStr[ii])) cCopy.m_pBuf->szStr[ii] = toupper(cCopy.m_pBuf->szStr[ii]); - #endif - } - - return *this; - } - - if (uIndex < uLength) - { - #ifdef _UNICODE - if (iswlower(cCopy.m_pBuf->wszStr[uIndex])) cCopy.m_pBuf->wszStr[uIndex] = towupper(cCopy.m_pBuf->wszStr[uIndex]); - #else - if (islower(cCopy.m_pBuf->szStr[uIndex]))cCopy.m_pBuf->szStr[uIndex] = toupper(cCopy.m_pBuf->szStr[uIndex]); - #endif - } - - return cCopy; -} - -// Alloc -COpcString::TStrBuf* COpcString::Alloc(UINT uLength) -{ - if (uLength == 0) - { - return NULL; - } - - TStrBuf* pBuf = (TStrBuf*)OpcAlloc(sizeof(TStrBuf)); - pBuf->uRefs = 1; - - #ifdef _UNICODE - pBuf->szStr = NULL; - pBuf->wszStr = OpcArrayAlloc(WCHAR, uLength+1); - memset(pBuf->wszStr, 0, (uLength+1)*sizeof(WCHAR)); - #else - pBuf->szStr = OpcArrayAlloc(CHAR, uLength+1); - pBuf->wszStr = NULL; - memset(pBuf->szStr, 0, (uLength+1)*sizeof(CHAR)); - #endif - - return pBuf; -} - -// Clone -LPSTR COpcString::Clone(LPCSTR szStr) -{ - if (szStr == NULL || strlen(szStr) == 0) - { - return NULL; - } - - LPSTR szCopy = OpcArrayAlloc(CHAR, strlen(szStr)+1); - strcpy(szCopy, szStr); - - return szCopy; -} - -// Clone -LPWSTR COpcString::Clone(LPCWSTR wszStr) -{ - if (wszStr == NULL || wcslen(wszStr) == 0) - { - return NULL; - } - - LPWSTR wszCopy = OpcArrayAlloc(WCHAR, wcslen(wszStr)+1); - wcscpy(wszCopy, wszStr); - - return wszCopy; -} - -// ToMultiByte -LPSTR COpcString::ToMultiByte(LPCWSTR wszStr, int iwszLen) -{ - if (wszStr == NULL || wcslen(wszStr) == 0) - { - return NULL; - } - - int iLength = WideCharToMultiByte( - CP_UTF8, - 0, - wszStr, - iwszLen, - NULL, - 0, - NULL, - NULL - ); - - if (iLength == 0) - { - return NULL; - } - - LPSTR szStr = OpcArrayAlloc(CHAR, iLength+1); - - iLength = WideCharToMultiByte( - CP_UTF8, - 0, - wszStr, - iwszLen, - szStr, - iLength+1, - NULL, - NULL - ); - - if (iLength == 0) - { - OpcFree(szStr); - return NULL; - } - - szStr[iLength] = '\0'; - return szStr; -} - -// ToUnicode -LPWSTR COpcString::ToUnicode(LPCSTR szStr, int iszLen) -{ - if (szStr == NULL || strlen(szStr) == 0) - { - return NULL; - } - - int iLength = MultiByteToWideChar( - CP_UTF8, - 0, - szStr, - iszLen, - NULL, - 0 - ); - - if (iLength == 0) - { - return NULL; - } - - LPWSTR wszStr = OpcArrayAlloc(WCHAR, iLength+1); - - iLength = MultiByteToWideChar( - CP_UTF8, - 0, - szStr, - iszLen, - wszStr, - iLength+1 - ); - - if (iLength == 0) - { - OpcFree(wszStr); - return NULL; - } - - wszStr[iLength] = L'\0'; - return wszStr; -} - -// ConvertULONG -static bool ConvertULONG(LPCSTR szStr, ULONG& ulValue) -{ - static const CHAR szHexDigits[] = "0123456789ABCDEF"; - - ulValue = 0; - - for (int ii = 0; szStr[ii] != '\0'; ii++) - { - CHAR zDigit = szStr[ii]; - - if (!isxdigit(zDigit)) - { - return false; - } - - if (islower(zDigit)) - { - zDigit = toupper(zDigit); - } - - for (int jj = 0; szHexDigits[jj] != '\0'; jj++) - { - if (szHexDigits[jj] == zDigit) - { - ulValue *= 16; - ulValue += jj; - break; - } - } - } - - return true; -} - -// ToGuid -bool COpcString::ToGuid(GUID& tGuid) const -{ - tGuid = GUID_NULL; - - // check for invalid guid string. - LPCSTR szStr = (LPCSTR)*this; - - if (szStr == NULL || strlen(szStr) != GUID_STR_LENGTH) - { - return false; - } - - ULONG ulBuf = 0; - CHAR szBuf[GUID_STR_LENGTH]; - - // convert first 32 bits. - strncpy(szBuf, szStr+1, 8); - szBuf[8] = '\0'; - - if (!ConvertULONG(szBuf, ulBuf)) - { - return false; - } - - tGuid.Data1 = (DWORD)ulBuf; - - // convert next 16 bits. - strncpy(szBuf, szStr+10, 4); - szBuf[4] = '\0'; - - if (!ConvertULONG(szBuf, ulBuf)) - { - return false; - } - - tGuid.Data2 = (WORD)ulBuf; - - // convert next 16 bits. - strncpy(szBuf, szStr+15, 4); - szBuf[4] = '\0'; - - if (!ConvertULONG(szBuf, ulBuf)) - { - return false; - } - - tGuid.Data3 = (WORD)ulBuf; - - // convert next 8 bits. - strncpy(szBuf, szStr+20, 2); - szBuf[2] = '\0'; - - if (!ConvertULONG(szBuf, ulBuf)) - { - return false; - } - - tGuid.Data4[0] = (BYTE)ulBuf; - - // convert next 8 bits. - strncpy(szBuf, szStr+22, 2); - szBuf[2] = '\0'; - - if (!ConvertULONG(szBuf, ulBuf)) - { - return false; - } - - tGuid.Data4[1] = (BYTE)ulBuf; - - // convert next 48 bits. - for (int ii = 2; ii < 8; ii++) - { - strncpy(szBuf, szStr+21+ii*2, 2); - szBuf[2] = '\0'; - - if (!ConvertULONG(szBuf, ulBuf)) - { - return false; - } - - tGuid.Data4[ii] = (BYTE)ulBuf; - } - - return true; -} - -// FromGuid -void COpcString::FromGuid(const GUID& tGuid) -{ - WCHAR wszBuf[GUID_STR_LENGTH+1]; - memset(wszBuf, 0, sizeof(wszBuf)); - StringFromGUID2(tGuid, wszBuf, GUID_STR_LENGTH+1); - Set(wszBuf); -} - -/* -// OpcStrMatch -bool OpcMatch(const COpcString& cString, const COpcString& cPattern) -{ - if (cPattern.IsEmpty()) return true; - - UINT uIndex = cPattern.Find(_T("*")); - - // must match exactly. - if (uIndex == -1) - { - return (cString == cPattern); - } - - COpcString cText = cPattern.SubStr(0, uIndex); - - // must match start of string. - if (uIndex > 0) - { - if (cString.Find(cText) != 0) - { - return false; - } - } - - cText = cPattern.SubStr(uIndex+1); - - // must match end of string. - if (!cText.IsEmpty()) - { - uIndex = cString.ReverseFind(cText); - - if (uIndex == -1 || (cString.GetLength() - uIndex) > cText.GetLength()) - { - return false; - } - } - - return true; -} -*/ diff --git a/ComIOP/Wrapper/Common/COpcString.h b/ComIOP/Wrapper/Common/COpcString.h deleted file mode 100644 index a7c855f72..000000000 --- a/ComIOP/Wrapper/Common/COpcString.h +++ /dev/null @@ -1,217 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcString_H_ -#define _COpcString_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" - -#define OPC_EMPTY_STRING _T("") - -//============================================================================== -// Class: COpcString -// PURPOSE: Implements a string class. - -class OPCUTILS_API COpcString -{ - OPC_CLASS_NEW_DELETE_ARRAY(); - -public: - - //========================================================================== - // Operators - - // Constructor - COpcString(); - COpcString(LPCSTR szStr); - COpcString(LPCWSTR wszStr); - COpcString(const GUID& cGuid); - - // Copy Constructor - COpcString(const COpcString& cStr); - - // Destructor - ~COpcString(); - - // Cast - operator LPCSTR() const; - operator LPCWSTR() const; - - // Assignment - COpcString& operator=(const COpcString& cStr); - - // Append - COpcString& operator+=(const COpcString& cStr); - - // Index - TCHAR& operator[](UINT uIndex); - TCHAR operator[](UINT uIndex) const; - - // Comparison - int Compare(const COpcString& cStr) const; - - bool operator==(LPCSTR szStr) const {return (Compare(szStr) == 0);} - bool operator<=(LPCSTR szStr) const {return (Compare(szStr) <= 0);} - bool operator <(LPCSTR szStr) const {return (Compare(szStr) < 0);} - bool operator!=(LPCSTR szStr) const {return (Compare(szStr) != 0);} - bool operator >(LPCSTR szStr) const {return (Compare(szStr) > 0);} - bool operator>=(LPCSTR szStr) const {return (Compare(szStr) >= 0);} - - bool operator==(LPCWSTR szStr) const {return (Compare(szStr) == 0);} - bool operator<=(LPCWSTR szStr) const {return (Compare(szStr) <= 0);} - bool operator <(LPCWSTR szStr) const {return (Compare(szStr) < 0);} - bool operator!=(LPCWSTR szStr) const {return (Compare(szStr) != 0);} - bool operator >(LPCWSTR szStr) const {return (Compare(szStr) > 0);} - bool operator>=(LPCWSTR szStr) const {return (Compare(szStr) >= 0);} - - bool operator==(const COpcString& szStr) const {return (Compare(szStr) == 0);} - bool operator<=(const COpcString& szStr) const {return (Compare(szStr) <= 0);} - bool operator <(const COpcString& szStr) const {return (Compare(szStr) < 0);} - bool operator!=(const COpcString& szStr) const {return (Compare(szStr) != 0);} - bool operator >(const COpcString& szStr) const {return (Compare(szStr) > 0);} - bool operator>=(const COpcString& szStr) const {return (Compare(szStr) >= 0);} - - // Addition - OPCUTILS_API friend COpcString operator+(const COpcString& cStr1, LPCSTR szStr2); - OPCUTILS_API friend COpcString operator+(const COpcString& cStr1, LPCWSTR wszStr2); - OPCUTILS_API friend COpcString operator+(const COpcString& cStr1, const COpcString& cStr2); - OPCUTILS_API friend COpcString operator+(LPCSTR szStr1, const COpcString& cStr2); - OPCUTILS_API friend COpcString operator+(LPCWSTR wszStr1, const COpcString& cStr2); - - //========================================================================== - // Public Methods - - // GetLength - UINT GetLength() const; - - // IsEmpty - bool IsEmpty() const; - - // Empty - void Empty() {Free();} - - // ToGuid - bool ToGuid(GUID& tGuid) const; - - // FromGuid - void FromGuid(const GUID& tGuid); - - // GetBuffer - LPTSTR GetBuffer(); - - // SetBuffer - void SetBuffer(UINT uLength); - - // Find - int Find(LPCTSTR tsTarget) const; - - // ReverseFind - int ReverseFind(LPCTSTR tsTarget) const; - - // SubStr - COpcString SubStr(UINT uStart, UINT uCount = -1) const; - - // Trim - COpcString& Trim(); - - // ToLower - COpcString ToLower(UINT uIndex = -1); - - // ToUpper - COpcString ToUpper(UINT uIndex = -1); - - // Clone - static LPSTR Clone(LPCSTR szStr); - - // Clone - static LPWSTR Clone(LPCWSTR wszStr); - - // ToMultiByte - static LPSTR ToMultiByte(LPCWSTR wszStr, int iwszLen = -1); - - // ToUnicode - static LPWSTR ToUnicode(LPCSTR szStr, int iszLen = -1); - -private: - - // TStrBuf - struct TStrBuf - { - UINT uRefs; - LPSTR szStr; - LPWSTR wszStr; - }; - - //========================================================================== - // Private Methods - - // Set - void Set(LPCSTR szStr); - - // Set - void Set(LPCWSTR wszStr); - - // Set - void Set(const COpcString& cStr); - - // Free - void Free(); - - // Alloc - static TStrBuf* Alloc(UINT uLength); - - //========================================================================== - // Private Members - - TStrBuf* m_pBuf; -}; - -//============================================================================== -// FUNCTION: Comparisons -// PURPOSE: Compares two strings. - -OPCUTILS_API inline bool operator==(LPCSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) == 0);} -OPCUTILS_API inline bool operator<=(LPCSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) <= 0);} -OPCUTILS_API inline bool operator <(LPCSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) < 0);} -OPCUTILS_API inline bool operator!=(LPCSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) != 0);} -OPCUTILS_API inline bool operator >(LPCSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) > 0);} -OPCUTILS_API inline bool operator>=(LPCSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) >= 0);} - -OPCUTILS_API inline bool operator==(LPCWSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) == 0);} -OPCUTILS_API inline bool operator<=(LPCWSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) <= 0);} -OPCUTILS_API inline bool operator <(LPCWSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) < 0);} -OPCUTILS_API inline bool operator!=(LPCWSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) != 0);} -OPCUTILS_API inline bool operator >(LPCWSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) > 0);} -OPCUTILS_API inline bool operator>=(LPCWSTR szStr1, const COpcString& cStr2) {return (cStr2.Compare(szStr1) >= 0);} - -#endif // _COpcString_H_ diff --git a/ComIOP/Wrapper/Common/COpcText.cpp b/ComIOP/Wrapper/Common/COpcText.cpp deleted file mode 100644 index 16ad0b5ed..000000000 --- a/ComIOP/Wrapper/Common/COpcText.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcText.h" - -//============================================================================== -// COpcText - -// Constructor -COpcText::COpcText() -{ - Reset(); -} - -// Reset -void COpcText::Reset() -{ - m_cData.Empty(); - - // Search Crtieria - m_eType = COpcText::NonWhitespace; - m_cHaltChars.Empty(); - m_uMaxChars = 0; - m_bNoExtract = false; - m_cText.Empty(); - m_bSkipLeading = false; - m_bSkipWhitespace = false; - m_bIgnoreCase = false; - m_bEofDelim = false; - m_bNewLineDelim = false; - m_cDelims.Empty(); - m_bLeaveDelim = true; - m_zStart = L'"'; - m_zEnd = L'"'; - m_bAllowEscape = true; - - // Search Results - m_uStart = 0; - m_uEnd = 0; - m_zHaltChar = 0; - m_uHaltPos = 0; - m_zDelimChar = 0; - m_bEof = false; - m_bNewLine = false; -} - -// CopyData -void COpcText::CopyData(LPCWSTR szData, UINT uLength) -{ - m_cData.Empty(); - - if (uLength > 0 && szData != NULL) - { - LPWSTR wszData = OpcArrayAlloc(WCHAR, uLength+1); - wcsncpy(wszData, szData, uLength); - wszData[uLength] = L'\0'; - - m_cData = wszData; - OpcFree(wszData); - } -} - -// SetType -void COpcText::SetType(COpcText::Type eType) -{ - Reset(); - - m_eType = eType; - - switch (eType) - { - case Literal: - { - m_cText.Empty(); - m_bSkipLeading = false; - m_bSkipWhitespace = true; - m_bIgnoreCase = false; - break; - } - - case Whitespace: - { - m_bSkipLeading = false; - m_bEofDelim = true; - break; - } - - case NonWhitespace: - { - m_bSkipWhitespace = true; - m_bEofDelim = true; - break; - } - - case Delimited: - { - m_cDelims.Empty(); - m_bSkipWhitespace = false; - m_bIgnoreCase = false; - m_bEofDelim = false; - m_bNewLineDelim = false; - m_bLeaveDelim = false; - break; - } - - default: - { - break; - } - } -} diff --git a/ComIOP/Wrapper/Common/COpcText.h b/ComIOP/Wrapper/Common/COpcText.h deleted file mode 100644 index 29021a3e6..000000000 --- a/ComIOP/Wrapper/Common/COpcText.h +++ /dev/null @@ -1,263 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcText_H -#define _COpcText_H - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcString.h" - -#define OPC_EOF -1 - -//============================================================================== -// CLASS: COpcText -// PURPOSE: Stores a text element extracted from a text buffer. - -class OPCUTILS_API COpcText -{ - OPC_CLASS_NEW_DELETE(); - -public: - - //========================================================================== - // Public Types - - enum Type - { - Literal, - NonWhitespace, - Whitespace, - Delimited - }; - -public: - - //========================================================================== - // Operators - - // Constructor - COpcText(); - - // Destructor - ~COpcText() {} - - // Assignment - COpcText& operator=(const COpcString& cStr) { m_cData = cStr; return *this; } - - // Cast - operator COpcString&() { return m_cData; } - operator const COpcString&() const { return m_cData; } - - //========================================================================== - // Public Methods - - // Reset - void Reset(); - - // CopyData - void CopyData(const WCHAR* pData, UINT uLength); - - //========================================================================== - // Search Criteria - - // General - // - // Type - the type of token to extract. - // MaxChars - maximum number of characters to read before halting. - // NoExtract - do not extract the text from the buffer. - // HaltChars - a set of characters indicate the search failed. An eof is a halt unless the EofDelim is set. - // - // Literals - A token that matches a string exactly. - // - // Text - the string to match.("") - // SkipLeading - skips all chars until found or halt.(F) - // SkipWhitespace - skips whitespace until found or halt.(T) - // IgnoreCase - ignores case when finding a match.(F) - // - // Whitespace - A token consisting of whitespace only - // - // SkipLeading - ignores leading non-whitespace chars.(F) - // EofDelim - treats an eof as a non-whitespace.(T) - // - // NonWhitespace - A token consisting of non-whitespace chars - // - // SkipWhitespace - ignores leading whitespace.(T) - // EofDelim - treats an eof as a whitespace.(T) - // - // Delimited - A token Delimited by a char or a string. - // - // Delims - a set of chars that are possible delimiters.("") - // SkipWhitespace - ignores leading whitespace.(F) - // IgnoreCase - ignores case when looking for a delimiter.(F) - // EofDelim - treats an eof as a delimiter.(F) - // NewLineDelim - treats "\r\n" OR "\n" as a delimiter.(F) - // LeaveDelim - does not extract the delimiter char.(F) - // - // Enclosed - A token enclosed by two chars. - // - // Bounds - the start and end chars. Start:(") End:(") - // SkipWhitespace - ignores leading whitespace.(F) - // SkipLeading - ignores all chars until start found or halt.(F) - // AllowEscape - ignores end char if preceded by a backslash '\'.(T) - - // Type - COpcText::Type GetType() const { return m_eType; } - void SetType(COpcText::Type eType); - - // HaltChars - LPCWSTR GetHaltChars() const { return (COpcString&)m_cHaltChars; } - void SetHaltChars(LPCWSTR szHaltChars) { m_cHaltChars = szHaltChars; } - - // MaxChars - UINT GetMaxChars() const { return m_uMaxChars; } - void SetMaxChars(UINT uMaxChars) { m_uMaxChars = uMaxChars; } - - // NoExtract - bool GetNoExtract() const { return m_bNoExtract; } - void SetNoExtract(bool bNoExtract = true) { m_bNoExtract = bNoExtract; } - - // Text - LPCWSTR GetText() const { return (COpcString&)m_cText; } - void SetText(LPCWSTR szText) { m_cText = szText; } - - // SkipLeading - bool GetSkipLeading() const { return m_bSkipLeading; } - void SetSkipLeading(bool bSkipLeading = true) { m_bSkipLeading = bSkipLeading; } - - // SkipWhitespace - bool GetSkipWhitespace() const { return m_bSkipWhitespace; } - void SetSkipWhitespace(bool bSkipWhitespace = true) { m_bSkipWhitespace = bSkipWhitespace; } - - // IgnoreCase - bool GetIgnoreCase() const { return m_bIgnoreCase; } - void SetIgnoreCase(bool bIgnoreCase = true) { m_bIgnoreCase = bIgnoreCase; } - - // EofDelim - bool GetEofDelim() const { return m_bEofDelim; } - void SetEofDelim(bool bEofDelim = true) { m_bEofDelim = bEofDelim; } - - // NewLineDelim - bool GetNewLineDelim() const { return m_bNewLineDelim; } - void SetNewLineDelim(bool bNewLineDelim = true) { m_bNewLineDelim = bNewLineDelim; } - - // Delims - LPCWSTR GetDelims() const { return (COpcString&)m_cDelims; } - void SetDelims(LPCWSTR szDelims) { m_cDelims = szDelims; } - - // LeaveDelim - bool GetLeaveDelim() const { return m_bLeaveDelim; } - void SetLeaveDelim(bool bLeaveDelim = true) { m_bLeaveDelim = bLeaveDelim; } - - // Bounds - void GetBounds(WCHAR& zStart, WCHAR& zEnd) const { zStart = m_zStart; zEnd = m_zEnd; } - void SetBounds(WCHAR zStart, WCHAR zEnd = 0) { m_zStart = zStart; m_zEnd = (zEnd==0)?zStart:zEnd; } - - // AllowEscape - bool GetAllowEscape() const { return m_bAllowEscape; } - void SetAllowEscape(bool bAllowEscape = true) { m_bAllowEscape = bAllowEscape; } - - //========================================================================== - // Search Results - - // Start - position in buffer of start of token. - // End - position in buffer of end of token. - // DelimChar - the delim char found. 0 = not found. - // Eof - indicates that an eof was encountered. - // HaltChar - the char that caused a halt. 0 = no halt. - // HaltPos - the position in buffer of halt character. - // NewLine - indicates that an "\r\n" OR "\n" was encountered. - - // Start - UINT GetStart() const { return m_uStart; } - void SetStart(UINT uStart) { m_uStart = uStart; } - - // End - UINT GetEnd() const { return m_uEnd; } - void SetEnd(UINT uEnd) { m_uEnd = uEnd; } - - // HaltChar - WCHAR GetHaltChar() const { return m_zHaltChar; } - void SetHaltChar(WCHAR zHaltChar) { m_zHaltChar = zHaltChar; } - - // HaltPos - UINT GetHaltPos() const { return m_uHaltPos; } - void SetHaltPos(UINT uHaltPos) { m_uHaltPos = uHaltPos; } - - // DelimChar - WCHAR GetDelimChar() const { return m_zDelimChar; } - void SetDelimChar(WCHAR zDelimChar) { m_zDelimChar = zDelimChar; } - - // Eof - bool GetEof() const { return m_bEof; } - void SetEof(bool bEof = true) { m_bEof = bEof; } - - // NewLine - bool GetNewLine() const { return m_bNewLine; } - void SetNewLine(bool bNewLine = true) { m_bNewLine = bNewLine; } - -private: - - //========================================================================== - // Private Members - - // Data - COpcString m_cData; - - // Search Criteria - COpcText::Type m_eType; - COpcString m_cHaltChars; - UINT m_uMaxChars; - bool m_bNoExtract; - COpcString m_cText; - bool m_bSkipLeading; - bool m_bSkipWhitespace; - bool m_bIgnoreCase; - bool m_bEofDelim; - bool m_bNewLineDelim; - COpcString m_cDelims; - bool m_bLeaveDelim; - WCHAR m_zStart; - WCHAR m_zEnd; - bool m_bAllowEscape; - - // Search Results - UINT m_uStart; - UINT m_uEnd; - WCHAR m_zHaltChar; - UINT m_uHaltPos; - WCHAR m_zDelimChar; - bool m_bEof; - bool m_bNewLine; -}; - -#endif //ndef _COpcText_H diff --git a/ComIOP/Wrapper/Common/COpcTextReader.cpp b/ComIOP/Wrapper/Common/COpcTextReader.cpp deleted file mode 100644 index 2118011eb..000000000 --- a/ComIOP/Wrapper/Common/COpcTextReader.cpp +++ /dev/null @@ -1,613 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcTextReader.h" - -//============================================================================== -// Local Functions - -// IsEqual -static bool IsEqual(COpcText& cToken, WCHAR zValue1, WCHAR zValue2) -{ - if (cToken.GetIgnoreCase()) - { - WCHAR z1 = (iswlower(zValue1))?towupper(zValue1):zValue1; - WCHAR z2 = (iswlower(zValue2))?towupper(zValue2):zValue2; - - return (z1 == z2); - } - - return (zValue1 == zValue2); -} - -// IsEqual -static bool IsEqual(COpcText& cToken, WCHAR zValue, LPCWSTR szValue) -{ - if (szValue == NULL) - { - return false; - } - - return IsEqual(cToken, zValue, *szValue); -} - -// IsEqual -static bool IsEqual(COpcText& cToken, LPCWSTR szValue1, LPCWSTR szValue2, UINT uSize = -1) -{ - if (szValue1 == NULL || szValue2 == NULL) - { - return (szValue1 == szValue2); - } - - else if (uSize == -1 && cToken.GetIgnoreCase()) - { - return (wcsicmp(szValue1, szValue2) == 0); - } - - else if (uSize == -1) - { - return (wcscmp(szValue1, szValue2) == 0); - } - - else if (cToken.GetIgnoreCase()) - { - return (wcsnicmp(szValue1, szValue2, uSize) == 0); - } - - return (wcsncmp(szValue1, szValue2, uSize) == 0); -} - -//============================================================================== -// COpcTextReader - -// Constructor -COpcTextReader::COpcTextReader(LPCSTR szBuf, UINT uLength) -: - m_szBuf(NULL), - m_uLength(0), - m_uEndOfData(0) -{ - if (szBuf != NULL) - { - m_uLength = (uLength == -1)?strlen(szBuf):uLength; - m_szBuf = (WCHAR*)OpcAlloc((m_uLength+1)*sizeof(WCHAR)); - - int iLength = MultiByteToWideChar( - CP_ACP, - 0, - szBuf, - m_uLength, - m_szBuf, - m_uLength+1 - ); - - if (iLength == 0) - { - OpcFree(m_szBuf); - m_uLength = 0; - m_szBuf = NULL; - } - - m_uEndOfData = m_uLength; - m_szBuf[m_uEndOfData] = L'\0'; - } -} - -COpcTextReader::COpcTextReader(const COpcString& cBuffer) -: - m_szBuf(NULL), - m_uLength(0), - m_uEndOfData(0) -{ - if (!cBuffer.IsEmpty()) - { - LPCWSTR szBuf = (COpcString&)cBuffer; - - m_uLength = (szBuf != NULL)?wcslen(szBuf):0; - m_szBuf = (WCHAR*)OpcAlloc((m_uLength+1)*sizeof(WCHAR)); - - wcsncpy(m_szBuf, szBuf, m_uLength); - - m_uEndOfData = m_uLength; - m_szBuf[m_uEndOfData] = L'\0'; - } -} - -// Constructor -COpcTextReader::COpcTextReader(LPCWSTR szBuf, UINT uLength) -: - m_szBuf(NULL), - m_uLength(0), - m_uEndOfData(0) -{ - if (szBuf != NULL) - { - m_uLength = (uLength == -1)?wcslen(szBuf):uLength; - m_szBuf = (WCHAR*)OpcAlloc((m_uLength+1)*sizeof(WCHAR)); - - wcsncpy(m_szBuf, szBuf, m_uLength); - - m_uEndOfData = m_uLength; - } -} - -// Destructor -COpcTextReader::~COpcTextReader() -{ - OpcFree(m_szBuf); -} - -// CheckForHalt -bool COpcTextReader::CheckForHalt(COpcText& cToken, UINT uPosition) -{ - // check if max chars exceeded. - if (cToken.GetMaxChars() > 0) - { - if (cToken.GetMaxChars() <= uPosition) - { - return false; - } - } - - // check for end of data - halts if EOF is not a delim. - if (uPosition >= m_uEndOfData) - { - cToken.SetEof(); - return !cToken.GetEofDelim(); - } - - // check for one of halt characters. - LPCWSTR szHaltChars = cToken.GetHaltChars(); - - if (szHaltChars == NULL) - { - return false; - } - - UINT uCount = wcslen(szHaltChars); - - for (UINT ii = 0; ii < uCount; ii++) - { - if (IsEqual(cToken, m_szBuf[uPosition], szHaltChars[ii])) - { - cToken.SetHaltChar(szHaltChars[ii]); - return true; - } - } - - return false; -} - -// CheckForDelim -bool COpcTextReader::CheckForDelim(COpcText& cToken, UINT uPosition) -{ - // check for new line delim. - if (cToken.GetNewLineDelim()) - { - if (m_szBuf[uPosition] == L'\n' || m_szBuf[uPosition] == L'\r') - { - cToken.SetNewLine(); - cToken.SetDelimChar(m_szBuf[uPosition]); - return true; - } - } - - // check for one of the delim chars. - LPCWSTR szDelims = cToken.GetDelims(); - UINT uCount = (szDelims != NULL)?wcslen(szDelims):0; - - for (UINT ii = 0; ii < uCount; ii++) - { - if (IsEqual(cToken, m_szBuf[uPosition], szDelims[ii])) - { - cToken.SetDelimChar(szDelims[ii]); - return true; - } - } - - return false; -} - -// SkipWhitespace -UINT COpcTextReader::SkipWhitespace(COpcText& cToken) -{ - if (!cToken.GetSkipWhitespace()) - { - return 0; - } - - for (UINT ii = 0; ii < m_uEndOfData; ii++) - { - if (CheckForHalt(cToken, ii) || !iswspace(m_szBuf[ii])) - { - return ii; - } - } - - return m_uEndOfData; -} - -// CopyData -void COpcTextReader::CopyData(COpcText& cToken, UINT uStart, UINT uEnd) -{ - cToken.CopyData(m_szBuf+uStart, uEnd-uStart); - cToken.SetStart(uStart); - cToken.SetEnd(uEnd-1); -} - -// FindLiteral -bool COpcTextReader::FindLiteral(COpcText& cToken) -{ - OPC_ASSERT(m_szBuf != NULL); - OPC_ASSERT(m_uLength != 0); - - LPCWSTR szText = cToken.GetText(); - UINT uLength = (szText != NULL)?wcslen(szText):0; - - // check for trivial case - if (uLength == 0) - { - return false; - } - - UINT uPosition = SkipWhitespace(cToken); - - // check if there is enough data. - if (uLength > (m_uEndOfData - uPosition)) - { - return false; - } - - for (UINT ii = uPosition; ii < m_uEndOfData-uLength+1; ii++) - { - // check if search halted. - if (CheckForHalt(cToken, ii)) - { - return false; - } - - // compare text at current position. - if (IsEqual(cToken, m_szBuf+ii, szText, uLength)) - { - CopyData(cToken, ii, ii+uLength); - return true; - } - - // stop search if leading unmatching characters are not ignored. - if (!cToken.GetSkipLeading()) - { - break; - } - } - - return false; -} - -// FindWhitespace -bool COpcTextReader::FindWhitespace(COpcText& cToken) -{ - OPC_ASSERT(m_szBuf != NULL); - OPC_ASSERT(m_uLength != 0); - - UINT uPosition = 0; - - // skip leading non-whitespace - if (cToken.GetSkipLeading()) - { - for (UINT ii = 0; ii < m_uEndOfData; ii++) - { - if (CheckForHalt(cToken, ii)) - { - return false; - } - - if (iswspace(m_szBuf[ii])) - { - uPosition = ii; - break; - } - } - } - - // check if there is still data left to read. - if (uPosition >= m_uEndOfData) - { - return false; - } - - // read until a non-whitespace. - for (UINT ii = uPosition; ii < m_uEndOfData; ii++) - { - if (CheckForHalt(cToken, ii)) - { - break; - } - - if (!iswspace(m_szBuf[ii])) - { - break; - } - } - - // check for empty token - if (ii == uPosition) - { - return false; - } - - // copy token. - CopyData(cToken, uPosition, ii); - return true; -} - -// FindNonWhitespace -bool COpcTextReader::FindNonWhitespace(COpcText& cToken) -{ - OPC_ASSERT(m_szBuf != NULL); - OPC_ASSERT(m_uLength != 0); - - // skip leading whitespace - UINT uPosition = SkipWhitespace(cToken); - - // check if there is still data left to read. - if (uPosition >= m_uEndOfData) - { - return false; - } - - // read until a whitespace. - for (UINT ii = uPosition; ii < m_uEndOfData; ii++) - { - if (CheckForHalt(cToken, ii)) - { - break; - } - - if (iswspace(m_szBuf[ii])) - { - break; - } - } - - // check for empty token - if (ii == uPosition) - { - return false; - } - - // copy token. - CopyData(cToken, uPosition, ii); - return true; -} - -// FindDelimited -bool COpcTextReader::FindDelimited(COpcText& cToken) -{ - OPC_ASSERT(m_szBuf != NULL); - OPC_ASSERT(m_uLength != 0); - - // skip leading whitespace - UINT uPosition = SkipWhitespace(cToken); - - // check if there is still data left to read. - if (uPosition >= m_uEndOfData) - { - return false; - } - - // read until a delimiter. - for (UINT ii = uPosition; ii < m_uEndOfData; ii++) - { - // check if search halted. - if (CheckForHalt(cToken, ii)) - { - return false; - } - - // check if delimiter found. - if (CheckForDelim(cToken, ii)) - { - // copy token - empty tokens are valid. - CopyData(cToken, uPosition, ii); - return true; - } - } - - // check for end of data - true if EOF is a delim. - if (ii >= m_uEndOfData) - { - cToken.SetEof(); - - if (cToken.GetEofDelim()) - { - CopyData(cToken, uPosition, ii); - return true; - } - } - - return false; -} - - -// FindEnclosed -bool COpcTextReader::FindEnclosed(COpcText& cToken) -{ - OPC_ASSERT(m_szBuf != NULL); - OPC_ASSERT(m_uLength != 0); - - WCHAR zStart = 0; - WCHAR zEnd = 0; - cToken.GetBounds(zStart, zEnd); - - // skip leading whitespace - UINT uPosition = SkipWhitespace(cToken); - - // check if there is still data left to read. - if (uPosition >= m_uEndOfData) - { - return false; - } - - // read until finding the start delimiter, - for (UINT ii = uPosition; ii < m_uEndOfData; ii++) - { - // check if search halted. - if (CheckForHalt(cToken, ii)) - { - return false; - } - - // check for start character. - if (IsEqual(cToken, m_szBuf[ii], zStart)) - { - uPosition = ii; - break; - } - } - - // check if there is still data left to read. - if (ii >= m_uEndOfData) - { - return false; - } - - // read until finding the end delimiter, - for (ii = uPosition+1; ii < m_uEndOfData; ii++) - { - // check if search halted. - if (CheckForHalt(cToken, ii)) - { - return false; - } - - // check for end character. - if (IsEqual(cToken, m_szBuf[ii], zStart)) - { - // ignore if character is escaped. - if (cToken.GetAllowEscape() && (uPosition < ii-1)) - { - if (m_szBuf[ii-1] == L'\\') - { - continue; - } - } - - // copy token - empty tokens are valid. - CopyData(cToken, uPosition+1, ii); - return true; - } - } - - return false; -} - -// FindToken -bool COpcTextReader::FindToken(COpcText& cToken) -{ - OPC_ASSERT(m_szBuf != NULL); - OPC_ASSERT(m_uLength != 0); - - switch (cToken.GetType()) - { - case COpcText::Literal: return FindLiteral(cToken); - case COpcText::NonWhitespace: return FindNonWhitespace(cToken); - case COpcText::Whitespace: return FindWhitespace(cToken); - case COpcText::Delimited: return FindDelimited(cToken); - } - - return false; -} - -// GetNext -bool COpcTextReader::GetNext(COpcText& cToken) -{ - // no more data to get - give up - if (m_uEndOfData == 0) - { - return false; - } - - // find the token - if (!FindToken(cToken)) - { - return false; - } - - // all done if token is not being extracted. - if (cToken.GetNoExtract()) - { - return true; - } - - UINT uEndOfToken = cToken.GetEnd() + 1; - UINT uDataLeft = m_uEndOfData - uEndOfToken; - - // extract the delimiter if extracting token. - - // new line delimiter found. - if (cToken.GetNewLine()) - { - if (cToken.GetDelimChar() == _T('\r')) - { - uEndOfToken += 2; - uDataLeft -= 2; - } - - else - { - uEndOfToken += 1; - uDataLeft -= 1; - } - } - - // specific delimiter found. - else if (cToken.GetDelimChar() > 0 && !cToken.GetEof()) - { - uEndOfToken++; - uDataLeft--; - } - - // move leftover data to the start of the buffer - for (UINT ii = 0; ii < uDataLeft; ii++) - { - m_szBuf[ii] = m_szBuf[uEndOfToken+ii]; - } - - m_szBuf[ii] = L'\0'; - m_uEndOfData = uDataLeft; - - // set EOF flag if no data left in buffer. - if (m_uEndOfData == 0) - { - cToken.SetEof(); - } - - return true; -} diff --git a/ComIOP/Wrapper/Common/COpcTextReader.h b/ComIOP/Wrapper/Common/COpcTextReader.h deleted file mode 100644 index bcd7748ad..000000000 --- a/ComIOP/Wrapper/Common/COpcTextReader.h +++ /dev/null @@ -1,116 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcTextReader_H -#define _COpcTextReader_H - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcText.h" - -//============================================================================== -// CLASS: COpcTextReader -// PURPOSE: Extracts tokens from a stream. - -class OPCUTILS_API COpcTextReader -{ - OPC_CLASS_NEW_DELETE(); - -public: - - //========================================================================== - // Operators - - // Constructor - COpcTextReader(const COpcString& cBuffer); - COpcTextReader(LPCSTR szBuffer, UINT uLength = -1); - COpcTextReader(LPCWSTR szBuffer, UINT uLength = -1); - - // Destructor - ~COpcTextReader(); - - //========================================================================== - // Public Methods - - // GetNext - bool GetNext(COpcText& cText); - - // GetBuf - LPCWSTR GetBuf() const { return m_szBuf; } - -private: - - //========================================================================== - // Private Methods - - // ReadData - bool ReadData(); - - // FindToken - bool FindToken(COpcText& cText); - - // FindLiteral - bool FindLiteral(COpcText& cText); - - // FindNonWhitespace - bool FindNonWhitespace(COpcText& cText); - - // FindWhitespace - bool FindWhitespace(COpcText& cText); - - // FindDelimited - bool FindDelimited(COpcText& cText); - - // FindEnclosed - bool FindEnclosed(COpcText& cText); - - // CheckForHalt - bool CheckForHalt(COpcText& cText, UINT uIndex); - - // CheckForDelim - bool CheckForDelim(COpcText& cText, UINT uIndex); - - // SkipWhitespace - UINT SkipWhitespace(COpcText& cText); - - // CopyData - void CopyData(COpcText& cText, UINT uStart, UINT uEnd); - - //========================================================================== - // Private Members - - LPWSTR m_szBuf; - UINT m_uLength; - UINT m_uEndOfData; -}; - -#endif //ndef _COpcTextReader_H diff --git a/ComIOP/Wrapper/Common/COpcThread.cpp b/ComIOP/Wrapper/Common/COpcThread.cpp deleted file mode 100644 index 14c60dab4..000000000 --- a/ComIOP/Wrapper/Common/COpcThread.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcThread.h" - -//============================================================================== -// Local Functions - -static DWORD WINAPI ThreadProc(LPVOID lpParameter) -{ - return ((COpcThread*)lpParameter)->Run(); -} - -//============================================================================== -// COpcThread - -// Constructor -COpcThread::COpcThread() -{ - m_dwID = NULL; - m_hThread = NULL; - m_hEvent = NULL; - m_pfnControl = NULL; - m_pData = NULL; - m_bWaitingForStop = false; -} - -// Destructor -COpcThread::~COpcThread() -{ - if (m_hThread != NULL) CloseHandle(m_hThread); - if (m_hEvent != NULL) CloseHandle(m_hEvent); -} - -//============================================================================== -// Public Methods - -// Start -bool COpcThread::Start( - PfnOpcThreadControl pfnControl, - void* pData, - DWORD dwTimeout, - int iPriority) -{ - m_pfnControl = pfnControl; - m_pData = pData; - - // no control procedure specified. - if (m_pfnControl == NULL) - { - return false; - } - - // thread already running. - if (m_hThread != NULL) - { - return false; - } - - // create thread started event. - m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - if (m_hEvent == NULL) - { - return false; - } - - // start thread. - m_hThread = CreateThread( - NULL, - NULL, - ThreadProc, - (void*)this, - NULL, - &m_dwID); - - if (m_hThread == NULL) - { - return false; - } - - // set thread priority. - SetThreadPriority(m_hThread, iPriority); - - // wait for thread start. - DWORD dwResult = WaitForSingleObject(m_hEvent, dwTimeout); - - if (dwResult != WAIT_OBJECT_0) - { - return false; - } - - // reset thread event. - ResetEvent(m_hEvent); - - return true; -} - -// Stop -void COpcThread::Stop(DWORD dwTimeout) -{ - // check if thread is not stopping itself and if thread is running. - if (m_dwID != GetCurrentThreadId() && m_hThread != NULL) - { - m_bWaitingForStop = true; - - // post quit message. - PostThreadMessage(m_dwID, WM_QUIT, 0, 0); - - // call thread procedure for user defined stop message. - m_pfnControl(NULL, true); - - // wait for thread stopped event. - WaitForSingleObject(m_hEvent, dwTimeout); - } - - // close handles. - if (m_hThread != NULL) CloseHandle(m_hThread); - if (m_hEvent != NULL) CloseHandle(m_hEvent); - - // intialize state. - m_dwID = NULL; - m_hThread = NULL; - m_hEvent = NULL; - m_pfnControl = NULL; - m_pData = NULL; - m_bWaitingForStop = false; -} - -// Run -DWORD COpcThread::Run() -{ - // initialize message queue. - MSG cMsg; memset(&cMsg, 0, sizeof(cMsg)); - PeekMessage(&cMsg, NULL, 0, 0, PM_NOREMOVE); - - // signal that the thread started. - SetEvent(m_hEvent); - - // call thread procedure. - m_pfnControl(m_pData, false); - - // signal that the thread stopped. - CloseHandle(m_hThread); - InterlockedExchange((LONG*)&m_hThread, NULL); - - SetEvent(m_hEvent); - - return 0; -} - -// PostMessage -bool COpcThread::PostMessage(UINT uMsgID, WPARAM wParam, LPARAM lParam) -{ - return (PostThreadMessage(m_dwID, uMsgID, wParam, lParam) != 0); -} diff --git a/ComIOP/Wrapper/Common/COpcThread.h b/ComIOP/Wrapper/Common/COpcThread.h deleted file mode 100644 index 739eedc2b..000000000 --- a/ComIOP/Wrapper/Common/COpcThread.h +++ /dev/null @@ -1,102 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcThread_H_ -#define _COpcThread_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcString.h" - -//============================================================================== -// TYPEDEF: PfnOpcThreadControl -// PURPOSE: Pointer to a function that controls a thread. - -typedef void (WINAPI *FnOpcThreadControl)(void* pData, bool bStopThread); -typedef FnOpcThreadControl PfnOpcThreadControl; - -//============================================================================== -// CLASS: COpcThread -// PURPOSE: Manages startup and shutdown of a thread. - -class OPCUTILS_API COpcThread -{ - OPC_CLASS_NEW_DELETE() - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcThread(); - - // Destructor - ~COpcThread(); - - //========================================================================== - // Public Methods - - // Start - bool Start( - PfnOpcThreadControl pfnStartProc, - void* pData, - DWORD dwTimeout = INFINITE, - int iPriority = THREAD_PRIORITY_NORMAL); - - // Stop - void Stop(DWORD dwTimeout = INFINITE); - - // WaitingForStop - bool WaitingForStop() { return m_bWaitingForStop; } - - // Run - DWORD Run(); - - // PostMessage - bool PostMessage(UINT uMsgID, WPARAM wParam, LPARAM lParam); - -private: - - //========================================================================== - // Private Members - - DWORD m_dwID; - HANDLE m_hThread; - HANDLE m_hEvent; - bool m_bWaitingForStop; - - PfnOpcThreadControl m_pfnControl; - void* m_pData; -}; - -#endif // _COpcThread_H_ diff --git a/ComIOP/Wrapper/Common/COpcThreadPool.cpp b/ComIOP/Wrapper/Common/COpcThreadPool.cpp deleted file mode 100644 index a0831bfbe..000000000 --- a/ComIOP/Wrapper/Common/COpcThreadPool.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcThreadPool.h" - -//============================================================================== -// Local Declarations - -static UINT g_uLastID = 0; - -//============================================================================== -// Local Functions - -static DWORD WINAPI ThreadProc(LPVOID lpParameter) -{ - ((COpcThreadPool*)lpParameter)->Run(); - return 0; -} - -//============================================================================== -// COpcMessage - -// Constructor -COpcMessage::COpcMessage(UINT uType, IOpcMessageCallback* ipCallback) -{ - m_uType = uType; - m_uID = (UINT)InterlockedIncrement((LONG*)&g_uLastID); - - m_ipCallback = NULL; - - if (ipCallback != NULL) - { - m_ipCallback = ipCallback; - m_ipCallback->AddRef(); - } -} - -// Copy Constructor -COpcMessage::COpcMessage(const COpcMessage& cMessage) -{ - m_uType = cMessage.m_uType; - m_uID = cMessage.m_uID; - m_ipCallback = cMessage.m_ipCallback; - - if (m_ipCallback != NULL) - { - m_ipCallback->AddRef(); - } -} - -// Destructor -COpcMessage::~COpcMessage() -{ - if (m_ipCallback != NULL) - { - m_ipCallback->Release(); - } -} - -//============================================================================== -// COpcThreadPool - -// Constructor -COpcThreadPool::COpcThreadPool() -{ - m_hEvent = NULL; - m_uTotalThreads = 0; - m_uWaitingThreads = 0; - m_uMinThreads = 1; - m_uMaxThreads = 4; -} - -// Destructor -COpcThreadPool::~COpcThreadPool() -{ - // check that stop was called prior to destruction. - OPC_ASSERT(m_cQueue.GetCount() == 0); -} - -// Start -bool COpcThreadPool::Start() -{ - COpcLock cLock(*this); - - if (m_hEvent != NULL) - { - Stop(); - } - - m_hEvent = CreateEvent( - NULL, - TRUE, - FALSE, - NULL - ); - - if (m_hEvent == NULL) - { - return false; - } - - return true; -} - -// Stop -void COpcThreadPool::Stop() -{ - COpcLock cLock(*this); - - // delete any remaining messages. - while (m_cQueue.GetCount() > 0) - { - COpcMessage* pMessage = m_cQueue.RemoveHead(); - delete pMessage; - } - - // close handle. - CloseHandle(m_hEvent); - m_hEvent = NULL; -} - -// QueueMessage -bool COpcThreadPool::QueueMessage(COpcMessage* pMsg) -{ - COpcLock cLock(*this); - - // check for active queue. - if (m_hEvent == NULL) - { - return false; - } - - // add to queue. - m_cQueue.AddTail(pMsg); - - // signal that the queue is not empty - SetEvent(m_hEvent); - - // start a new thread if required. - if (m_uWaitingThreads == 0 && m_uTotalThreads < m_uMaxThreads) - { - DWORD dwID = 0; - - HANDLE hThread = CreateThread( - NULL, - NULL, - ThreadProc, - (void*)this, - NULL, - &dwID); - - if (hThread == NULL) - { - return false; - } - - CloseHandle(hThread); - - // increment thread count. - m_uTotalThreads++; - } - - return true; -} - -// Run -void COpcThreadPool::Run() -{ - COpcLock cLock(*this); - - do - { - // increment waiting thread count. - m_uWaitingThreads++; - - cLock.Unlock(); - - // wait for message. - DWORD dwResult = WaitForSingleObject(m_hEvent, INFINITE); - - cLock.Lock(); - - // decrement waiting thread count. - m_uWaitingThreads--; - - // check for error or shutdown event. - if (m_hEvent == NULL || dwResult != WAIT_OBJECT_0) - { - break; - } - - // check if the queue has already been cleared. - if (m_cQueue.GetCount() == 0) - { - ResetEvent(m_hEvent); - - if (m_uWaitingThreads >= m_uMinThreads) - { - break; - } - - continue; - } - - // get next message. - COpcMessage* pMessage = m_cQueue.RemoveHead(); - - // release queue lock - process message could hang. - cLock.Unlock(); - - // process message. - pMessage->Process(); - delete pMessage; - - // re-acquire lock. - cLock.Lock(); - } - while (m_uWaitingThreads < m_uMinThreads); - - // decrement thread count. - m_uTotalThreads--; -} - -// SetSize -void COpcThreadPool::SetSize(UINT uMinThreads, UINT uMaxThreads) -{ - COpcLock cLock(*this); - - m_uMinThreads = uMinThreads; - m_uMaxThreads = uMaxThreads; -} diff --git a/ComIOP/Wrapper/Common/COpcThreadPool.h b/ComIOP/Wrapper/Common/COpcThreadPool.h deleted file mode 100644 index 1e6b9a146..000000000 --- a/ComIOP/Wrapper/Common/COpcThreadPool.h +++ /dev/null @@ -1,154 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcThreadPool_H_ -#define _COpcThreadPool_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcList.h" -#include "COpcCriticalSection.h" - -class COpcMessage; - -//============================================================================== -// INTERFACE: IOpcMessageCallback -// PURPOSE: A interface to an object that processes messages. - -interface IOpcMessageCallback : public IUnknown -{ - // ProcessMessage - virtual void ProcessMessage(COpcMessage& cMsg) = 0; -}; - -//============================================================================== -// CLASS: COpcMessage -// PURPOSE: A base class for a message. - -class OPCUTILS_API COpcMessage -{ - OPC_CLASS_NEW_DELETE(); - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcMessage(UINT uType, IOpcMessageCallback* ipCallback); - - // Copy Constructor - COpcMessage(const COpcMessage& cMessage); - - // Destructor - virtual ~COpcMessage(); - - //========================================================================== - // Public Methods - - // Process - virtual void Process() - { - if (m_ipCallback != NULL) - { - m_ipCallback->ProcessMessage(*this); - } - } - - // GetID - UINT GetID() { return m_uID; } - - // GetType - UINT GetType() { return m_uType; } - -protected: - - //========================================================================== - // Protected Operators - - UINT m_uID; - UINT m_uType; - IOpcMessageCallback* m_ipCallback; -}; - -//============================================================================== -// CLASS: COpcThreadPool -// PURPOSE: Manages a pool of threads that process queued messages. - -class OPCUTILS_API COpcThreadPool : public COpcSynchObject -{ - OPC_CLASS_NEW_DELETE(); - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcThreadPool(); - - // Destructor - ~COpcThreadPool(); - - //========================================================================== - // Public Methods - - // Start - bool Start(); - - // Stop - void Stop(); - - // Run - void Run(); - - // QueueMessage - bool QueueMessage(COpcMessage* pMsg); - - // SetSize - void SetSize(UINT uMinThreads, UINT uMaxThreads); - -private: - - //========================================================================== - // Private Members - - HANDLE m_hEvent; - COpcList m_cQueue; - - UINT m_uTotalThreads; - UINT m_uWaitingThreads; - UINT m_uMinThreads; - UINT m_uMaxThreads; -}; - -#endif // _COpcThreadPool_H_ diff --git a/ComIOP/Wrapper/Common/COpcVariant.cpp b/ComIOP/Wrapper/Common/COpcVariant.cpp deleted file mode 100644 index b15b6287b..000000000 --- a/ComIOP/Wrapper/Common/COpcVariant.cpp +++ /dev/null @@ -1,1407 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcVariant.h" - -#include "math.h" - -using namespace OpcXml; - -//============================================================================== -// Local Functions - -// MakeByRef -static void MakeByRef(VARTYPE vtType, void* pData, VARIANT& cValue) -{ - OpcVariantInit(&cValue); - - // return a reference to array memory. - cValue.vt = (vtType & VT_TYPEMASK) | VT_BYREF; - - switch (vtType & VT_TYPEMASK) - { - case VT_I1: { cValue.pcVal = (CHAR*)pData; break; } - case VT_UI1: { cValue.pbVal = (BYTE*)pData; break; } - case VT_I2: { cValue.piVal = (SHORT*)pData; break; } - case VT_UI2: { cValue.puiVal = (USHORT*)pData; break; } - case VT_I4: { cValue.plVal = (LONG*)pData; break; } - case VT_UI4: { cValue.pulVal = (ULONG*)pData; break; } - case VT_I8: { cValue.pllVal = (LONGLONG*)pData; break; } - case VT_UI8: { cValue.pullVal = (ULONGLONG*)pData; break; } - case VT_R4: { cValue.pfltVal = (FLOAT*)pData; break; } - case VT_R8: { cValue.pdblVal = (DOUBLE*)pData; break; } - case VT_CY: { cValue.pcyVal = (CY*)pData; break; } - case VT_DATE: { cValue.pdate = (DATE*)pData; break; } - case VT_BSTR: { cValue.pbstrVal = (BSTR*)pData; break; } - case VT_BOOL: { cValue.pboolVal = (VARIANT_BOOL*)pData; break; } - case VT_VARIANT: { cValue.pvarVal = (VARIANT*)pData; break; } - } -} - -// GetValuePtr -static void* GetValuePtr(VARIANT& cValue) -{ - switch (cValue.vt) - { - case VT_I1: { return &cValue.cVal; } - case VT_UI1: { return &cValue.bVal; } - case VT_I2: { return &cValue.iVal; } - case VT_UI2: { return &cValue.uiVal; } - case VT_I4: { return &cValue.lVal; } - case VT_UI4: { return &cValue.ulVal; } - case VT_I8: { return &cValue.llVal; } - case VT_UI8: { return &cValue.ullVal; } - case VT_R4: { return &cValue.fltVal; } - case VT_R8: { return &cValue.dblVal; } - case VT_CY: { return &cValue.cyVal; } - case VT_DATE: { return &cValue.date; } - case VT_BSTR: { return &cValue.bstrVal; } - case VT_BOOL: { return &cValue.boolVal; } - } - - return NULL; -} - -//============================================================================ -// GetUtcTime -// -// These functions were provided by the because they preserve the milliseconds -// in the conversion between FILETIME and DATE and they are more efficient. - -inline DATE FileTimeToDate(FILETIME *pft) -{ - return (double)((double)(*(__int64 *)pft) / 8.64e11) - (double)(363 + (1899 - 1601) * 365 + (24 + 24 + 24)); -} - -inline void FileTimeToDate(FILETIME *pft, DATE *pdate) -{ - *pdate = FileTimeToDate(pft); -} - -inline FILETIME DateToFileTime(DATE *pdate) -{ - __int64 temp = (__int64)((*pdate + (double)(363 + (1899 - 1601) * 365 + (24 + 24 + 24))) * 8.64e11); - return *(FILETIME *)&temp; -} - -inline void DateToFileTime(DATE *pdate, FILETIME *pft) -{ - *pft = DateToFileTime(pdate); -} - -//============================================================================== -// Free Functions - -// OpcVariantInit -void OpcVariantInit(VARIANT* pValue) -{ - if (pValue != NULL) - { - memset(pValue, 0, sizeof(pValue)); - } -} - -// OpcVariantClear -void OpcVariantClear(VARIANT* pValue) -{ - if (pValue == NULL) - { - return; - } - - VariantClear(pValue); - memset(pValue, 0, sizeof(VARIANT)); -} - -// OpcVariantCopy -void OpcVariantCopy(VARIANT* pDst, const VARIANT* pSrc) -{ - if (pDst == NULL) - { - return; - } - - OpcVariantClear(pDst); - - if (pSrc == NULL) - { - return; - } - - VariantCopy(pDst, (VARIANT*)pSrc); -} - -struct TOpcXmlVarType -{ - Type eType; - VARTYPE varType; -}; - -// XML data type to VARIANT type mapping table. -static const TOpcXmlVarType g_pVarTypes[] = -{ - { XML_SBYTE, VT_I1 }, - { XML_BYTE, VT_UI1 }, - { XML_SHORT, VT_I2 }, - { XML_USHORT, VT_UI2 }, - { XML_INT, VT_I4 }, - { XML_UINT, VT_UI4 }, - { XML_LONG, VT_I8 }, - { XML_ULONG, VT_UI8 }, - { XML_FLOAT, VT_R4 }, - { XML_DOUBLE, VT_R8 }, - { XML_DECIMAL, VT_CY }, - { XML_DATETIME, VT_DATE }, - { XML_BOOLEAN, VT_BOOL }, - { XML_STRING, VT_BSTR }, - { XML_ANY_TYPE, VT_VARIANT }, - { XML_EMPTY, VT_EMPTY } -}; - -// GetVarType -VARTYPE OpcXml::GetVarType(Type eType) -{ - for (int ii = 0; g_pVarTypes[ii].varType != VT_EMPTY; ii++) - { - if (eType == g_pVarTypes[ii].eType) - { - return g_pVarTypes[ii].varType; - } - } - - return VT_EMPTY; -} - -// GetXmlType -Type OpcXml::GetXmlType(VARTYPE varType) -{ - for (int ii = 0; g_pVarTypes[ii].varType != VT_EMPTY; ii++) - { - if (varType == g_pVarTypes[ii].varType) - { - return g_pVarTypes[ii].eType; - } - } - - return XML_EMPTY; -} - -// GetVarDate -DATE OpcXml::GetVarDate(const DateTime& cValue) -{ - DATE dblDate = FileTimeToDate((FILETIME*)&cValue); - - dblDate = floor(dblDate*1e9 + 0.5)/1e9; - - return dblDate; -} - -// GetXmlDateTime -DateTime OpcXml::GetXmlDateTime(const DATE& cDate) -{ - return DateToFileTime((DATE*)&cDate); -} - -//============================================================================== -// COpcVariant - -// Clear -void COpcVariant::Clear() -{ - OpcVariantClear(&m_cValue); -} - -// Assignment -COpcVariant& COpcVariant::operator=(bool cValue) -{ - Clear(); m_cValue.vt = VT_BOOL; m_cValue.boolVal = (cValue)?VARIANT_TRUE:VARIANT_FALSE; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(char cValue) -{ - Clear(); m_cValue.vt = VT_I1; m_cValue.cVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(unsigned char cValue) -{ - Clear(); m_cValue.vt = VT_UI1; m_cValue.bVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(short cValue) -{ - Clear(); m_cValue.vt = VT_I2; m_cValue.iVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(unsigned short cValue) -{ - Clear(); m_cValue.vt = VT_UI2; m_cValue.uiVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(int cValue) -{ - Clear(); m_cValue.vt = VT_I4; m_cValue.lVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(unsigned int cValue) -{ - Clear(); m_cValue.vt = VT_UI4; m_cValue.ulVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(long cValue) -{ - Clear(); m_cValue.vt = VT_I4; m_cValue.lVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(unsigned long cValue) -{ - Clear(); m_cValue.vt = VT_UI4; m_cValue.ulVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(__int64 cValue) -{ - Clear(); m_cValue.vt = VT_I8; m_cValue.llVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(unsigned __int64 cValue) -{ - Clear(); m_cValue.vt = VT_UI8; m_cValue.ullVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(float cValue) -{ - Clear(); m_cValue.vt = VT_R4; m_cValue.fltVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(double cValue) -{ - Clear(); m_cValue.vt = VT_R8; m_cValue.dblVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(CY cValue) -{ - Clear(); m_cValue.vt = VT_CY; m_cValue.cyVal = cValue; return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(FILETIME cValue) -{ - Clear(); m_cValue.vt = VT_DATE; m_cValue.date = GetVarDate((DateTime)cValue); return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(const COpcString& cValue) -{ - Clear(); m_cValue.vt = VT_BSTR; m_cValue.bstrVal = SysAllocString((LPCWSTR)cValue); return *this; -} - -// Assignment -COpcVariant& COpcVariant::operator=(const VARIANT& cValue) -{ - Clear(); - OpcVariantCopy(&m_cValue, &cValue); - - return *this; -} - -COpcVariant& COpcVariant::operator=(const COpcVariant& cValue) -{ - if (&cValue == this) - { - return *this; - } - - Clear(); - OpcVariantCopy(&m_cValue, &cValue.m_cValue); - - return *this; -} - -// Cast -COpcVariant::operator bool() const -{ - OPC_ASSERT(m_cValue.vt == VT_BOOL); return (m_cValue.boolVal)?true:false; -} - -// Cast -COpcVariant::operator char() const -{ - OPC_ASSERT(m_cValue.vt == VT_I1); return m_cValue.cVal; -} - -// Cast -COpcVariant::operator unsigned char() const -{ - OPC_ASSERT(m_cValue.vt == VT_UI1); return m_cValue.bVal; -} - -// Cast -COpcVariant::operator short() const -{ - OPC_ASSERT(m_cValue.vt == VT_I2); return m_cValue.iVal; -} - -// Cast -COpcVariant::operator unsigned short() const -{ - OPC_ASSERT(m_cValue.vt == VT_UI2); return m_cValue.uiVal; -} - -// Cast -COpcVariant::operator int() const -{ - OPC_ASSERT(m_cValue.vt == VT_I4); return m_cValue.lVal; -} - -// Cast -COpcVariant::operator unsigned int() const -{ - OPC_ASSERT(m_cValue.vt == VT_UI4); return m_cValue.ulVal; -} - -// Cast -COpcVariant::operator long() const -{ - OPC_ASSERT(m_cValue.vt == VT_I4); return m_cValue.lVal; -} - -// Cast -COpcVariant::operator unsigned long() const -{ - OPC_ASSERT(m_cValue.vt == VT_UI4); return m_cValue.ulVal; -} - -// Cast -COpcVariant::operator __int64() const -{ - OPC_ASSERT(m_cValue.vt == VT_I8); return m_cValue.llVal; -} - -// Cast -COpcVariant::operator unsigned __int64() const -{ - OPC_ASSERT(m_cValue.vt == VT_UI8); return m_cValue.ullVal; -} - -// Cast -COpcVariant::operator float() const -{ - OPC_ASSERT(m_cValue.vt == VT_R4); return m_cValue.fltVal; -} - -// Cast -COpcVariant::operator double() const -{ - OPC_ASSERT(m_cValue.vt == VT_R8); return m_cValue.dblVal; -} - -// Cast -COpcVariant::operator CY() const -{ - OPC_ASSERT(m_cValue.vt == VT_CY); return m_cValue.cyVal; -} - -// Cast -COpcVariant::operator FILETIME() const -{ - OPC_ASSERT(m_cValue.vt == VT_DATE); return (FILETIME)GetXmlDateTime(m_cValue.date); -} - -// Cast -COpcVariant::operator COpcString() const -{ - OPC_ASSERT(m_cValue.vt == VT_BSTR); return (LPCWSTR)m_cValue.bstrVal; -} - -// IsEqual -bool COpcVariant::IsEqual(const VARIANT& cValue1, const VARIANT& cValue2) -{ - if (cValue1.vt != cValue2.vt) return false; - - if (cValue1.vt & VT_ARRAY) - { - return COpcSafeArray::IsEqual(cValue1, cValue2); - } - - switch (cValue1.vt) - { - case VT_EMPTY: return (cValue1.vt == cValue2.vt); - case VT_I1: return (cValue1.cVal == cValue2.cVal); - case VT_UI1: return (cValue1.bVal == cValue2.bVal); - case VT_I2: return (cValue1.iVal == cValue2.iVal); - case VT_UI2: return (cValue1.uiVal == cValue2.uiVal); - case VT_I4: return (cValue1.lVal == cValue2.lVal); - case VT_UI4: return (cValue1.ulVal == cValue2.ulVal); - case VT_I8: return (cValue1.llVal == cValue2.llVal); - case VT_UI8: return (cValue1.ullVal == cValue2.ullVal); - case VT_R4: return (cValue1.fltVal == cValue2.fltVal); - case VT_R8: return (cValue1.dblVal == cValue2.dblVal); - case VT_CY: return (cValue1.cyVal.int64 == cValue2.cyVal.int64); - case VT_DATE: return (cValue1.date == cValue2.date); - case VT_BOOL: return (cValue1.boolVal == cValue2.boolVal); - - case VT_BSTR: - { - if (cValue1.bstrVal != NULL && cValue2.bstrVal != NULL) - { - return (wcscmp(cValue1.bstrVal, cValue2.bstrVal) == 0); - } - - return (cValue1.bstrVal == cValue2.bstrVal); - } - } - - return false; -} - -// ChangeType -HRESULT COpcVariant::ChangeType( - VARIANT& cDst, - const VARIANT& cSrc, - LCID lcid, - VARTYPE vtType -) -{ - if (vtType == VT_EMPTY || vtType == VT_VARIANT || cSrc.vt == vtType) - { - OpcVariantCopy(&cDst, &cSrc); - return S_OK; - } - - OpcVariantInit(&cDst); - - // check for conversion from an array. - if ((cSrc.vt & VT_ARRAY) != 0) - { - return COpcSafeArray::ChangeType(cDst, cSrc, lcid, vtType); - } - - // check for conversion from a byref variant containing an array. - if (cSrc.vt == (VT_BYREF | VT_VARIANT) && (cSrc.pvarVal->vt & VT_ARRAY) != 0) - { - return COpcSafeArray::ChangeType(cDst, *cSrc.pvarVal, lcid, vtType); - } - - // convert value. - HRESULT hResult = VariantChangeTypeEx(&cDst, (VARIANT*)&cSrc, lcid, VARIANT_NOVALUEPROP, vtType); - - if (FAILED(hResult)) - { - return hResult; - } - - // check for incorrect conversion from signed to unsigned types. - switch (vtType) - { - case VT_UI1: - case VT_UI2: - case VT_UI4: - case VT_UI8: - { - switch (cSrc.vt) - { - case VT_I1: { if (cSrc.cVal < 0) return DISP_E_OVERFLOW; break; } - case VT_I2: { if (cSrc.iVal < 0) return DISP_E_OVERFLOW; break; } - case VT_I4: { if (cSrc.lVal < 0) return DISP_E_OVERFLOW; break; } - case VT_I8: { if (cSrc.lVal < 0) return DISP_E_OVERFLOW; break; } - } - - break; - } - } - - // check for incorrect conversion from unsigned to signed types. - switch (cSrc.vt) - { - case VT_UI1: - case VT_UI2: - case VT_UI4: - case VT_UI8: - { - switch (cDst.vt) - { - case VT_I1: { if (cDst.cVal < 0) return DISP_E_OVERFLOW; break; } - case VT_I2: { if (cDst.iVal < 0) return DISP_E_OVERFLOW; break; } - case VT_I4: { if (cDst.lVal < 0) return DISP_E_OVERFLOW; break; } - case VT_I8: { if (cDst.lVal < 0) return DISP_E_OVERFLOW; break; } - } - - break; - } - } - - return S_OK; -} - -//============================================================================== -// COpcSafeArray - -// Constructor -COpcSafeArray::COpcSafeArray(VARIANT& cValue) : m_cValue(cValue), m_uLocks(0) -{ - OPC_ASSERT(m_cValue.vt == VT_EMPTY || m_cValue.vt & VT_ARRAY); -} - -// Destructor -COpcSafeArray::~COpcSafeArray() -{ - if (m_cValue.vt != VT_EMPTY) - { - // release all locks. - for (;m_uLocks > 0; m_uLocks--) - { - HRESULT hResult = SafeArrayUnlock(m_cValue.parray); - OPC_ASSERT(SUCCEEDED(hResult)); - } - } -} - -// Alloc -void COpcSafeArray::Alloc(VARTYPE vtType, UINT uLength) -{ - OpcVariantClear(&m_cValue); - - SAFEARRAYBOUND cBound; - - cBound.lLbound = 0; - cBound.cElements = uLength; - - m_cValue.vt = vtType | VT_ARRAY; - m_cValue.parray = SafeArrayCreate(vtType, 1, &cBound); - - OPC_ASSERT(m_cValue.parray != NULL); -} - -// Lock -void COpcSafeArray::Lock() -{ - if (m_cValue.vt != VT_EMPTY) - { - m_uLocks++; - HRESULT hResult = SafeArrayLock(m_cValue.parray); - OPC_ASSERT(SUCCEEDED(hResult)); - } -} - -// Unlock -void COpcSafeArray::Unlock() -{ - if (m_cValue.vt != VT_EMPTY) - { - m_uLocks--; - HRESULT hResult = SafeArrayUnlock(m_cValue.parray); - OPC_ASSERT(SUCCEEDED(hResult)); - } -} - -// GetLength -UINT COpcSafeArray::GetLength() const -{ - LONG lLength = 0; - - if (m_cValue.vt != VT_EMPTY) - { - HRESULT hResult = SafeArrayGetUBound(m_cValue.parray, 1, &lLength); - OPC_ASSERT(SUCCEEDED(hResult)); - - return (UINT)(lLength+1); - } - - return 0; -} - -// GetData -void* COpcSafeArray::GetData() const -{ - void* pData = NULL; - - if (m_cValue.vt != VT_EMPTY) - { - HRESULT hResult = SafeArrayAccessData(m_cValue.parray, &pData); - OPC_ASSERT(SUCCEEDED(hResult)); - - SafeArrayUnaccessData(m_cValue.parray); - } - - return pData; -} - -// GetElemType -VARTYPE COpcSafeArray::GetElemType() const -{ - VARTYPE vtType = VT_EMPTY; - - if (m_cValue.vt != VT_EMPTY) - { - HRESULT hResult = SafeArrayGetVartype(m_cValue.parray, &vtType); - OPC_ASSERT(SUCCEEDED(hResult)); - } - - return vtType; -} - -// GetElemSize -UINT COpcSafeArray::GetElemSize() const -{ - if (m_cValue.vt != VT_EMPTY) - { - return SafeArrayGetElemsize(m_cValue.parray); - } - - return 0; -} - -// GetElem -void* COpcSafeArray::GetElem(UINT uIndex) -{ - void* pData = NULL; - - if (m_cValue.vt != VT_EMPTY) - { - HRESULT hResult = SafeArrayPtrOfIndex(m_cValue.parray, (LONG*)&uIndex, (void**)&pData); - OPC_ASSERT(SUCCEEDED(hResult)); - } - - return pData; -} - -// SetElem -void COpcSafeArray::SetElem(UINT uIndex, void* pElem) -{ - if (pElem == NULL) return; - - void* pData = NULL; - - if (m_cValue.vt != VT_EMPTY) - { - ULONG uSize = SafeArrayGetElemsize(m_cValue.parray); - BYTE* pData = (BYTE*)GetData(); - - memcpy(pData + uSize*uIndex, pElem, uSize); - } -} - -// IsEqual -bool COpcSafeArray::IsEqual(const VARIANT& cValue1, const VARIANT& cValue2) -{ - if (cValue1.vt != cValue2.vt) return false; - - COpcSafeArray cArray1((VARIANT&)cValue1); - COpcSafeArray cArray2((VARIANT&)cValue2); - - // check if the length differs. - if (cArray1.GetLength() != cArray2.GetLength()) return false; - - // compare each element, - UINT uLength = cArray1.GetLength(); - - cArray1.Lock(); - cArray2.Lock(); - - bool bIsEqual = true; - - for (UINT ii = 0; ii < uLength; ii++) - { - void* pElem1 = cArray1.GetElem(ii); - void* pElem2 = cArray2.GetElem(ii); - - switch (cValue1.vt & VT_TYPEMASK) - { - default: { bIsEqual = false; } - - case VT_I1: { bIsEqual = (*((char*)pElem1) == *((char*)pElem2)); break; } - case VT_UI1: { bIsEqual = (*((unsigned char*)pElem1) == *((unsigned char*)pElem2)); break; } - case VT_I2: { bIsEqual = (*((short*)pElem1) == *((short*)pElem2)); break; } - case VT_UI2: { bIsEqual = (*((unsigned short*)pElem1) == *((unsigned short*)pElem2)); break; } - case VT_I4: { bIsEqual = (*((long*)pElem1) == *((long*)pElem2)); break; } - case VT_UI4: { bIsEqual = (*((unsigned long*)pElem1) == *((unsigned long*)pElem2)); break; } - case VT_I8: { bIsEqual = (*((__int64*)pElem1) == *((__int64*)pElem2)); break; } - case VT_UI8: { bIsEqual = (*((unsigned __int64*)pElem1) == *((unsigned __int64*)pElem2)); break; } - case VT_R4: { bIsEqual = (*((float*)pElem1) == *((float*)pElem2)); break; } - case VT_R8: { bIsEqual = (*((double*)pElem1) == *((double*)pElem2)); break; } - case VT_CY: { bIsEqual = (((CY*)pElem1)->int64 == ((CY*)pElem2)->int64); break; } - case VT_DATE: { bIsEqual = (*((DATE*)pElem1) == *((DATE*)pElem2)); break; } - case VT_BOOL: { bIsEqual = (*((VARIANT_BOOL*)pElem1) == *((VARIANT_BOOL*)pElem2)); break; } - - case VT_BSTR: { bIsEqual = (wcscmp(*((BSTR*)pElem1), *((BSTR*)pElem2)) == 0); break; } - - case VT_VARIANT: { bIsEqual = COpcVariant::IsEqual(*((VARIANT*)pElem1), *((VARIANT*)pElem2)); break; } - } - - if (!bIsEqual) - { - break; - } - } - - cArray1.Unlock(); - cArray2.Unlock(); - - return bIsEqual; -} - -// ChangeType -HRESULT COpcSafeArray::ChangeType(VARIANT& cDst, const VARIANT& cSrc, LCID lcid, VARTYPE vtType) -{ - if (((cSrc.vt & VT_ARRAY) == 0) || ((vtType & VT_ARRAY) == 0 && vtType != VT_BSTR)) - { - return DISP_E_TYPEMISMATCH; - } - - HRESULT hResult = S_OK; - - COpcSafeArray cSrcArr((VARIANT&)cSrc); - cSrcArr.Lock(); - - UINT uLength = cSrcArr.GetLength(); - - if (vtType != VT_BSTR) - { - COpcSafeArray cDstArr((VARIANT&)cDst); - - // allocate new array. - cDstArr.Alloc(vtType & VT_TYPEMASK, uLength); - - cDstArr.Lock(); - - for (UINT ii = 0; ii < uLength; ii++) - { - VARIANT cSrcElem; OpcVariantInit(&cSrcElem); - VARIANT cDstElem; OpcVariantInit(&cDstElem); - - MakeByRef(cSrc.vt & VT_TYPEMASK, cSrcArr.GetElem(ii), cSrcElem); - - hResult = COpcVariant::ChangeType(cDstElem, cSrcElem, lcid, vtType & VT_TYPEMASK); - - if (FAILED(hResult)) - { - hResult = DISP_E_OVERFLOW; - break; - } - - if ((vtType & VT_TYPEMASK) == VT_VARIANT) - { - cDstArr.SetElem(ii, &cDstElem); - } - else - { - cDstArr.SetElem(ii, GetValuePtr(cDstElem)); - } - } - - cDstArr.Unlock(); - } - else - { - COpcString cDstStr; - - cDstStr += _T("{"); - - for (UINT ii = 0; ii < uLength; ii++) - { - VARIANT cDstElem; OpcVariantInit(&cDstElem); - VARIANT cSrcElem; OpcVariantInit(&cSrcElem); - - MakeByRef(cSrc.vt & VT_TYPEMASK, cSrcArr.GetElem(ii), cSrcElem); - - hResult = COpcVariant::ChangeType(cDstElem, cSrcElem, lcid, VT_BSTR); - - if (FAILED(hResult)) - { - hResult = DISP_E_OVERFLOW; - break; - } - - cDstStr += (LPCWSTR)cDstElem.bstrVal; - - if (ii < uLength-1) - { - cDstStr += _T(" | "); - } - } - - cDstStr += _T("}"); - - cDst.vt = VT_BSTR; - cDst.bstrVal = SysAllocString((LPCWSTR)cDstStr); - } - - cSrcArr.Unlock(); - - if (FAILED(hResult)) - { - OpcVariantClear(&cDst); - } - - return hResult; -} - -// OpcReadVariant -HRESULT OpcReadVariant(bool& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_BOOL); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = (vDst.boolVal)?true:false; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(char& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_I1); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.cVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(unsigned char& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_UI1); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.bVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(short& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_I2); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.iVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(unsigned short& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_UI2); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.uiVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(int& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_I4); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.lVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(unsigned int& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_UI4); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.lVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(long& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_I4); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.lVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(unsigned long& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_UI4); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.lVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(__int64& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_I8); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.lVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(unsigned __int64& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_UI8); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.lVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(float& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_R4); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.fltVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(double& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_R8); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.dblVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(CY& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_CY); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.cyVal; - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(FILETIME& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_DATE); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = OpcXml::GetXmlDateTime(vDst.date); - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(COpcString& cDst, const VARIANT& cSrc) -{ - VARIANT vDst; VariantInit(&vDst); - - HRESULT hResult = VariantChangeType(&vDst, (VARIANT*)&cSrc, VARIANT_NOVALUEPROP, VT_BSTR); - - if (FAILED(hResult)) - { - return hResult; - } - - cDst = vDst.bstrVal; - VariantClear(&vDst); - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(COpcStringList& cDst, const VARIANT& cSrc) -{ - cDst.RemoveAll(); - - if (cSrc.vt != (VT_ARRAY | VT_BSTR)) - { - return DISP_E_TYPEMISMATCH; - } - - COpcSafeArray cArray((VARIANT&)cSrc); - - cArray.Lock(); - - UINT uLength = cArray.GetLength(); - BSTR* pData = (BSTR*)cArray.GetData(); - - for (UINT ii = 0; ii < uLength; ii++) - { - cDst.AddTail(pData[ii]); - } - - cArray.Unlock(); - - return S_OK; -} - -// OpcReadVariant -HRESULT OpcReadVariant(COpcStringArray& cDst, const VARIANT& cSrc) -{ - cDst.RemoveAll(); - - if (cSrc.vt != (VT_ARRAY | VT_BSTR)) - { - return DISP_E_TYPEMISMATCH; - } - - COpcSafeArray cArray((VARIANT&)cSrc); - - cArray.Lock(); - - UINT uLength = cArray.GetLength(); - BSTR* pData = (BSTR*)cArray.GetData(); - - cDst.SetSize(uLength); - - for (UINT ii = 0; ii < uLength; ii++) - { - cDst[ii] = pData[ii]; - } - - cArray.Unlock(); - - return S_OK; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, bool cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_BOOL; - cDst.boolVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, char cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_I1; - cDst.cVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, unsigned char cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_UI1; - cDst.bVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, short cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_I2; - cDst.iVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, unsigned short cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_UI2; - cDst.uiVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, int cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_I4; - cDst.lVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, unsigned int cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_UI4; - cDst.ulVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, long cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_I4; - cDst.lVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, unsigned long cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_UI4; - cDst.ulVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, __int64 cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_I8; - cDst.llVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, unsigned __int64 cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_UI8; - cDst.ullVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, float cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_R4; - cDst.fltVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, double cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_R8; - cDst.dblVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, CY cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_CY; - cDst.cyVal = cSrc; -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, FILETIME& cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_DATE; - cDst.date = OpcXml::GetVarDate(cSrc); -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, LPWSTR cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_BSTR; - cDst.bstrVal = SysAllocString(cSrc); -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, const COpcString& cSrc) -{ - VariantClear(&cDst); - cDst.vt = VT_BSTR; - cDst.bstrVal = SysAllocString((LPCWSTR)cSrc); -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, const COpcStringList& cSrc) -{ - VariantClear(&cDst); - - UINT uLength = cSrc.GetCount(); - - if (uLength > 0) - { - COpcSafeArray cArray(cDst); - - cArray.Alloc(VT_BSTR, uLength); - cArray.Lock(); - - BSTR* pData = (BSTR*)cArray.GetData(); - - OPC_POS pos = cSrc.GetHeadPosition(); - - for (UINT ii = 0; pos != NULL; ii++) - { - pData[ii] = SysAllocString((LPCWSTR)cSrc.GetNext(pos)); - } - - cArray.Unlock(); - } -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, const COpcStringArray& cSrc) -{ - VariantClear(&cDst); - - UINT uLength = cSrc.GetSize(); - - if (uLength > 0) - { - COpcSafeArray cArray(cDst); - - cArray.Alloc(VT_BSTR, uLength); - cArray.Lock(); - - BSTR* pData = (BSTR*)cArray.GetData(); - - for (UINT ii = 0; ii < uLength; ii++) - { - pData[ii] = SysAllocString((LPCWSTR)cSrc[ii]); - } - - cArray.Unlock(); - } -} - -// OpcWriteVariant -void OpcWriteVariant(VARIANT& cDst, const LPCWSTR* pszStrings) -{ - VariantClear(&cDst); - - if (pszStrings == NULL) - { - return; - } - - for (UINT uLength = 0; pszStrings[uLength] != NULL; uLength++); - - if (uLength > 0) - { - COpcSafeArray cArray(cDst); - - cArray.Alloc(VT_BSTR, uLength); - cArray.Lock(); - - BSTR* pData = (BSTR*)cArray.GetData(); - - for (UINT ii = 0; ii < uLength; ii++) - { - pData[ii] = SysAllocString(pszStrings[ii]); - } - - cArray.Unlock(); - } -} diff --git a/ComIOP/Wrapper/Common/COpcVariant.h b/ComIOP/Wrapper/Common/COpcVariant.h deleted file mode 100644 index 1bcb5a3cd..000000000 --- a/ComIOP/Wrapper/Common/COpcVariant.h +++ /dev/null @@ -1,343 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcVariant_H_ -#define _COpcVariant_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcXmlType.h" -#include "COpcXmlElement.h" -#include "COpcList.h" -#include "COpcArray.h" - -//============================================================================== -// FUNCTION: OpcVariantInit -// PURPOSE Initializes a VARIANT. - -OPCUTILS_API void OpcVariantInit(VARIANT* pValue); - -//============================================================================== -// FUNCTION: OpcVariantClear -// PURPOSE Clears a VARIANT. - -OPCUTILS_API void OpcVariantClear(VARIANT* pValue); - -//============================================================================== -// FUNCTION: OpcVariantCopy -// PURPOSE Copies a VARIANT. - -OPCUTILS_API void OpcVariantCopy(VARIANT* pDst, const VARIANT* pSrc); - -//============================================================================== -// CLASS: COpcVariant -// PURPOSE A wrapper for an VARIANT. - -class OPCUTILS_API COpcVariant -{ - OPC_CLASS_NEW_DELETE() - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcVariant() { Init(); } - - COpcVariant(bool cValue) { Init(); *this = cValue; } - COpcVariant(char cValue) { Init(); *this = cValue; } - COpcVariant(unsigned char cValue) { Init(); *this = cValue; } - COpcVariant(short cValue) { Init(); *this = cValue; } - COpcVariant(unsigned short cValue) { Init(); *this = cValue; } - COpcVariant(int cValue) { Init(); *this = cValue; } - COpcVariant(unsigned int cValue) { Init(); *this = cValue; } - COpcVariant(long cValue) { Init(); *this = cValue; } - COpcVariant(unsigned long cValue) { Init(); *this = cValue; } - COpcVariant(__int64 cValue) { Init(); *this = cValue; } - COpcVariant(unsigned __int64 cValue) { Init(); *this = cValue; } - COpcVariant(float cValue) { Init(); *this = cValue; } - COpcVariant(double cValue) { Init(); *this = cValue; } - COpcVariant(CY cValue) { Init(); *this = cValue; } - COpcVariant(FILETIME cValue) { Init(); *this = cValue; } - COpcVariant(const COpcString& cValue) { Init(); *this = cValue; } - COpcVariant(const VARIANT& cValue) { Init(); *this = cValue; } - - // Copy Constructor - COpcVariant(const COpcVariant& cValue) { Init(); *this = cValue; } - - // Destructor - ~COpcVariant() { Clear(); } - - // Assignment - COpcVariant& operator=(bool cValue); - COpcVariant& operator=(char cValue); - COpcVariant& operator=(unsigned char cValue); - COpcVariant& operator=(short cValue); - COpcVariant& operator=(unsigned short cValue); - COpcVariant& operator=(int cValue); - COpcVariant& operator=(unsigned int cValue); - COpcVariant& operator=(long cValue); - COpcVariant& operator=(unsigned long cValue); - COpcVariant& operator=(__int64 cValue); - COpcVariant& operator=(unsigned __int64 cValue); - COpcVariant& operator=(float cValue); - COpcVariant& operator=(double cValue); - COpcVariant& operator=(CY cValue); - COpcVariant& operator=(FILETIME cValue); - COpcVariant& operator=(const COpcString& cValue); - COpcVariant& operator=(const VARIANT& cValue); - COpcVariant& operator=(const COpcVariant& cValue); - - // Cast - operator bool() const; - operator char() const; - operator unsigned char() const; - operator short() const; - operator unsigned short() const; - operator int() const; - operator unsigned int() const; - operator long() const; - operator unsigned long() const; - operator __int64() const; - operator unsigned __int64() const; - operator float() const; - operator double() const; - operator CY() const; - operator FILETIME() const; - operator COpcString() const; - - operator const VARIANT&() const { return m_cValue; } - - //========================================================================== - // Public Methods - - // Init - void Init() { memset(&m_cValue, 0, sizeof(VARIANT)); } - - // Clear - void Clear(); - - // GetType - VARTYPE GetType() const { return m_cValue.vt; } - - // GetRef - VARIANT& GetRef() { return m_cValue; } - - // GetPtr - VARIANT* GetPtr() { return &m_cValue; } - - // Attach - void Attach(VARIANT& cValue) { Clear(); *this = cValue; OpcVariantInit(&cValue); } - - // Detach - void Detach(VARIANT& cValue) { cValue = *this; Init(); } - - // IsEqual - static bool IsEqual(const VARIANT& cValue1, const VARIANT& cValue2); - - // ChangeType - static HRESULT ChangeType( - VARIANT& cDst, - const VARIANT& cSrc, - LCID lcid, - VARTYPE vtType - ); - -private: - - VARIANT m_cValue; -}; - -//============================================================================== -// CLASS: COpcSafeArray -// PURPOSE A wrapper for an SAFEARRAY contained in a VARIANT. - -class OPCUTILS_API COpcSafeArray -{ - OPC_CLASS_NEW_DELETE() - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcSafeArray(VARIANT& cValue); - - // Destructor - ~COpcSafeArray(); - - //========================================================================== - // Public Methods - - // Alloc - void Alloc(VARTYPE vtType, UINT uLength); - - // Lock - void Lock(); - - // Unlock - void Unlock(); - - // GetLength - UINT GetLength() const; - - // GetData - void* GetData() const; - - // GetElemType - VARTYPE GetElemType() const; - - // GetElemSize - UINT GetElemSize() const; - - // GetElem - void* GetElem(UINT uIndex); - - // SetElem - void SetElem(UINT uIndex, void* pElem); - - // IsEqual - static bool IsEqual(const VARIANT& cValue1, const VARIANT& cValue2); - - // ChangeType - static HRESULT ChangeType( - VARIANT& cDst, - const VARIANT& cSrc, - LCID lcid, - VARTYPE vtType - ); - -private: - - VARIANT& m_cValue; - UINT m_uLocks; -}; - -//============================================================================== -// FUNCTION: OpcReadVariant -// PURPOSE Uses function overloading and VariantChangeType() to simplify variant access. - -OPCUTILS_API HRESULT OpcReadVariant(bool& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(char& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(unsigned char& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(short& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(unsigned short& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(int& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(unsigned int& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(long& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(unsigned long& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(__int64& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(unsigned __int64& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(float& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(double& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(CY& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(FILETIME& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(COpcString& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(COpcStringList& cDst, const VARIANT& cSrc); -OPCUTILS_API HRESULT OpcReadVariant(COpcStringArray& cDst, const VARIANT& cSrc); - -//============================================================================== -// FUNCTION: OpcWriteVariant -// PURPOSE Uses function overloading ad VariantClear() to simplify variant access. - -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, bool cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, char cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, unsigned char cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, short cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, unsigned short cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, int cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, unsigned int cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, long cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, unsigned long cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, __int64 cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, unsigned __int64 cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, float cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, double cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, CY cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, FILETIME& cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, LPWSTR cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, const COpcString& cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, const COpcStringList& cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, const COpcStringArray& cSrc); -OPCUTILS_API void OpcWriteVariant(VARIANT& cDst, const LPCWSTR* pszStrings); - -namespace OpcXml -{ - -//============================================================================== -// FUNCTION: GetVarType -// PURPOSE Converts an XML data type to a VARIANT type. - -OPCUTILS_API VARTYPE GetVarType(Type eType); - -//============================================================================== -// FUNCTION: GetXmlType -// PURPOSE Converts an VARIANT type to an XML data type. - -OPCUTILS_API Type GetXmlType(VARTYPE varType); - -//============================================================================== -// FUNCTION: GetVarDate -// PURPOSE Converts an XML DateTime type to an VARIANT DATE type. - -OPCUTILS_API DATE GetVarDate(const DateTime& cDateTime); - -//============================================================================== -// FUNCTION: GetXmlDateTime -// PURPOSE Converts an VARIANT DATE type to an type XML DateTime. - -OPCUTILS_API DateTime GetXmlDateTime(const DATE& cVarDate); - -/* -//============================================================================== -// FUNCTION: XXX -// PURPOSE Defines conversion functions for COpcVariants. - -template<> OPCUTILS_API void Init(VARIANT& cValue); -template<> OPCUTILS_API void Clear(VARIANT& cValue); -template<> OPCUTILS_API bool ReadXml(IXMLDOMNode* ipNode, VARIANT& cValue); -template<> OPCUTILS_API bool WriteXml(IXMLDOMNode* ipNode, const VARIANT& cValue); - -//============================================================================== -// FUNCTION: XXX -// PURPOSE Defines conversion functions for COpcVariants. - -template<> OPCUTILS_API void Init(COpcVariant& cValue); -template<> OPCUTILS_API void Clear(COpcVariant& cValue); -template<> OPCUTILS_API bool ReadXml(IXMLDOMNode* ipNode, COpcVariant& cValue); -template<> OPCUTILS_API bool WriteXml(IXMLDOMNode* ipNode, const COpcVariant& cValue); -*/ - -}; // OpcXml - -#endif // _COpcVariant_H_ diff --git a/ComIOP/Wrapper/Common/COpcXmlAnyType.cpp b/ComIOP/Wrapper/Common/COpcXmlAnyType.cpp deleted file mode 100644 index 969fe1381..000000000 --- a/ComIOP/Wrapper/Common/COpcXmlAnyType.cpp +++ /dev/null @@ -1,1739 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcXmlAnyType.h" -#include "COpcVariant.h" - -using namespace OpcXml; - -//============================================================================== -// Local Functions - -#define TAG_HEX_BINARY _T("hexBinary") - -struct TOpcXmlTypeMap -{ - LPCWSTR szName; - OpcXml::Type eType; -}; - -static const TOpcXmlTypeMap g_pTypes[] = -{ - { L"byte", OpcXml::XML_SBYTE }, - { L"unsignedByte", OpcXml::XML_BYTE }, - { L"short", OpcXml::XML_SHORT }, - { L"unsignedShort", OpcXml::XML_USHORT }, - { L"int", OpcXml::XML_INT }, - { L"unsignedInt", OpcXml::XML_UINT }, - { L"long", OpcXml::XML_LONG }, - { L"unsignedLong", OpcXml::XML_ULONG }, - { L"float", OpcXml::XML_FLOAT }, - { L"double", OpcXml::XML_DOUBLE }, - { L"decimal", OpcXml::XML_DECIMAL }, - { L"boolean", OpcXml::XML_BOOLEAN }, - { L"string", OpcXml::XML_STRING }, - { L"dateTime", OpcXml::XML_DATETIME }, - { L"anyType", OpcXml::XML_ANY_TYPE }, - { NULL, OpcXml::XML_EMPTY } -}; - -static OpcXml::Type GetType(const COpcString& cType) -{ - for (UINT ii = 0; g_pTypes[ii].szName != NULL; ii++) - { - if (cType == g_pTypes[ii].szName) - { - return g_pTypes[ii].eType; - } - } - - return OpcXml::XML_EMPTY; -} - -static LPCWSTR GetType(OpcXml::Type cType) -{ - for (UINT ii = 0; g_pTypes[ii].szName != NULL; ii++) - { - if (cType == g_pTypes[ii].eType) - { - return g_pTypes[ii].szName; - } - } - - return NULL; -} - -//============================================================================== -// Schema - -bool OpcXml::Schema::Read(COpcXmlElement& cElement) -{ - // save the fully qualified element name. - SetName(cElement.GetQualifiedName()); - - // fetch the element attributes. - COpcXmlAttributeList cAttributes; - - if (cElement.GetAttributes(cAttributes) == 0) - { - return true; - } - - // save the attributes in the schema. - OpcXml::QName cTypeAttribute(OPCXML_TYPE_ATTRIBUTE, OPCXML_NS_SCHEMA_INSTANCE); - - for (UINT ii = 0; ii < cAttributes.GetSize(); ii++) - { - COpcXmlAttribute cAttribute = cAttributes[ii]; - - // the type is specified with the 'xsi:type' attribute. - - if (cAttribute.GetQualifiedName() == cTypeAttribute) - { - // lookup any namespace prefix contained in the attribute value. - COpcString cType = cAttribute.GetValue(); - COpcString cNamespace = cElement.ResolvePrefix(_T("")); - - int iIndex = cType.Find(_T(":")); - - if (iIndex != -1) - { - cNamespace = cElement.ResolvePrefix(cType.SubStr(0, iIndex)); - cType = cType.SubStr(iIndex+1); - } - - // save the fully qualified type name. - OpcXml::QName cName(cType, cNamespace); - SetType(cName); - } - - // save other attributes (excluding namespace attributes). - else - { - if (cAttribute.GetPrefix() != OPCXML_NAMESPACE_ATTRIBUTE) - { - this->Set(cAttribute.GetQualifiedName(), cAttribute.GetValue()); - } - } - } - - return true; -} - -// Write -bool OpcXml::Schema::Write(COpcXmlElement& cElement) const -{ - // set the type. - cElement.SetType(GetType()); - - // write additional attributes. - OPC_POS pos = m_cAttributes.GetStartPosition(); - - while (pos != NULL) - { - OpcXml::QName cName; - COpcString cValue; - m_cAttributes.GetNextAssoc(pos, cName, cValue); - - // lookup attribute namespace prefix. - if (!cName.GetNamespace().IsEmpty()) - { - COpcString cFullName = cElement.ResolveNamespace(cName.GetNamespace()); - - if (!cFullName.IsEmpty()) - { - cFullName += _T(":"); - } - - cFullName += cName.GetName(); - - // add attribute qualified with namespace prefix. - cElement.SetAttribute(cFullName, cValue); - } - else - { - // add attribute. - cElement.SetAttribute(cName.GetName(), cValue); - } - } - - return true; -} - -//============================================================================== -// AnyType - -// Init -template<> void OpcXml::Init(AnyType& cValue) -{ - cValue.Clear(); -} - -// Clear -template<> void OpcXml::Clear(AnyType& cValue) -{ - cValue.Clear(); -} - -// ReadSimpleArray -static bool ReadSimpleArray(COpcXmlElementList& cElements, OpcXml::AnyType& cValue) -{ - switch (cValue.eType) - { - case OpcXml::XML_SBYTE: - { - cValue.psbyteValue = OpcArrayAlloc(OpcXml::SByte, cValue.iLength); - memset(cValue.psbyteValue, 0, sizeof(OpcXml::SByte)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.psbyteValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_BYTE: - { - cValue.pbyteValue = OpcArrayAlloc(OpcXml::Byte, cValue.iLength); - memset(cValue.pbyteValue, 0, sizeof(OpcXml::Byte)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pbyteValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_SHORT: - { - cValue.pshortValue = OpcArrayAlloc(OpcXml::Short, cValue.iLength); - memset(cValue.pshortValue, 0, sizeof(OpcXml::Short)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pshortValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_USHORT: - { - cValue.pushortValue = OpcArrayAlloc(OpcXml::UShort, cValue.iLength); - memset(cValue.pushortValue, 0, sizeof(OpcXml::UShort)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pushortValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_INT: - { - cValue.pintValue = OpcArrayAlloc(OpcXml::Int, cValue.iLength); - memset(cValue.pintValue, 0, sizeof(OpcXml::Int)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pintValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_UINT: - { - cValue.puintValue = OpcArrayAlloc(OpcXml::UInt, cValue.iLength); - memset(cValue.puintValue, 0, sizeof(OpcXml::UInt)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.puintValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_LONG: - { - cValue.plongValue = OpcArrayAlloc(OpcXml::Long, cValue.iLength); - memset(cValue.plongValue, 0, sizeof(OpcXml::Long)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.plongValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_ULONG: - { - cValue.pulongValue = OpcArrayAlloc(OpcXml::ULong, cValue.iLength); - memset(cValue.pulongValue, 0, sizeof(OpcXml::ULong)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pulongValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_FLOAT: - { - cValue.pfloatValue = OpcArrayAlloc(OpcXml::Float, cValue.iLength); - memset(cValue.pfloatValue, 0, sizeof(OpcXml::Float)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pfloatValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_DOUBLE: - { - cValue.pdoubleValue = OpcArrayAlloc(OpcXml::Double, cValue.iLength); - memset(cValue.pdoubleValue, 0, sizeof(OpcXml::Double)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pdoubleValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_DECIMAL: - { - cValue.pdecimalValue = OpcArrayAlloc(OpcXml::Decimal, cValue.iLength); - memset(cValue.pdecimalValue, 0, sizeof(OpcXml::Decimal)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pdecimalValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_BOOLEAN: - { - cValue.pboolValue = OpcArrayAlloc(OpcXml::Boolean, cValue.iLength); - memset(cValue.pboolValue, 0, sizeof(OpcXml::Boolean)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pboolValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_DATETIME: - { - cValue.pdateTimeValue = OpcArrayAlloc(OpcXml::DateTime, cValue.iLength); - memset(cValue.pdateTimeValue, 0, sizeof(OpcXml::DateTime)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pdateTimeValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - - case OpcXml::XML_STRING: - { - cValue.pstringValue = OpcArrayAlloc(OpcXml::String, cValue.iLength); - memset(cValue.pstringValue, 0, sizeof(OpcXml::String)*cValue.iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!OpcXml::ReadXml(cElements[ii], cValue.pstringValue[ii])) break; - } - - return (ii >= cValue.iLength); - } - } - - return false; -} - -// ReadHexBinary -static bool ReadHexBinary(LPCWSTR wszBuffer, BYTE* pBuffer, UINT uLength) -{ - memset(pBuffer, 0, uLength); - - UINT uStrLen = wcslen(wszBuffer); - - for (UINT ii = 0; ii < uLength && ii*2 < uStrLen; ii++) - { - pBuffer[ii] = 0; - - for (UINT jj = 0; jj < 2 && ii*2+jj < uStrLen; jj++) - { - WCHAR wzBuffer = wszBuffer[ii*2+jj]; - - if (!iswxdigit(wzBuffer)) - { - return false; - } - - if (iswlower(wzBuffer)) - { - wzBuffer = towupper(wzBuffer); - } - - pBuffer[ii] <<= 4; - - if (isdigit(wzBuffer)) - { - pBuffer[ii] += (BYTE)wzBuffer - 0x30; - } - else - { - pBuffer[ii] += (BYTE)wzBuffer - 0x41 + 0x0A; - } - } - } - - return true; -} - -// WriteHexBinary -static bool WriteHexBinary(COpcString& cBuffer, BYTE* pBuffer, UINT uLength) -{ - LPWSTR szBuffer = OpcArrayAlloc(WCHAR, (uLength+1)*2); - - for (UINT ii = 0; ii < uLength; ii++) - { - swprintf(szBuffer+ii*2, L"%02X", pBuffer[ii]); - } - - szBuffer[ii*2] = 0; - - cBuffer = szBuffer; - OpcFree(szBuffer); - - return true; -} - -// ReadXml -template<> bool OpcXml::ReadXml(IXMLDOMNode* ipNode, AnyType& cValue) -{ - cValue.Clear(); - - COpcXmlElement cElement(ipNode); - - // can only read AnyType values from XML elements. - if (cElement == NULL) - { - return false; - } - - // read schema. - if (!cValue.cSchema.Read(cElement)) - { - cValue.Clear(); - return false; - } - - COpcXmlElementList cChildren; - cElement.GetChildren(cChildren); - - // read simple value. - if (cChildren.GetSize() == 0) - { - // initialize type from schema. - COpcString cTypeName = cValue.cSchema.GetType().GetName(); - - cValue.eType = ::GetType(cTypeName); - cValue.iLength = -1; - - // get the element value. - COpcString cText = cElement.GetValue(); - - // check for empty element. - if (cText.IsEmpty()) - { - cValue.eType = XML_EMPTY; - cValue.iLength = -1; - return true; - } - - // handle hex binary as a special case. - if (cTypeName == TAG_HEX_BINARY) - { - cValue.Alloc(XML_BYTE, cText.GetLength()/2); - - if (!ReadHexBinary((LPCWSTR)cText, cValue.pbyteValue, cValue.iLength)) - { - return false; - } - - return true; - } - - // read simple value. - switch (cValue.eType) - { - case XML_SBYTE: { return Read(cText, cValue.sbyteValue); } - case XML_BYTE: { return Read(cText, cValue.byteValue); } - case XML_SHORT: { return Read(cText, cValue.shortValue); } - case XML_USHORT: { return Read(cText, cValue.ushortValue); } - case XML_INT: { return Read(cText, cValue.intValue); } - case XML_UINT: { return Read(cText, cValue.uintValue); } - case XML_LONG: { return Read(cText, cValue.longValue); } - case XML_ULONG: { return Read(cText, cValue.ulongValue); } - case XML_FLOAT: { return Read(cText, cValue.floatValue); } - case XML_DOUBLE: { return Read(cText, cValue.doubleValue); } - case XML_DECIMAL: { return Read(cText, cValue.decimalValue); } - case XML_BOOLEAN: { return Read(cText, cValue.boolValue); } - case XML_DATETIME: { return Read(cText, cValue.dateTimeValue); } - - default: - { - cValue.eType = XML_STRING; - } - } - - // store unrecognized types as strings. - if (!Read(cText, cValue.stringValue)) - { - cValue.Clear(); - return false; - } - - return true; - } - - // read complex value. - cValue.iLength = cChildren.GetSize(); - - // check for array of simple types. - COpcString cType = cValue.cSchema.GetType().GetName(); - - int iIndex = cType.Find(OPCXML_ARRAY_PREFIX); - - if (iIndex == 0) - { - cType = cType.SubStr(_tcslen(OPCXML_ARRAY_PREFIX)).ToLower(0); - - cValue.eType = ::GetType(cType); - - if (cValue.eType != XML_EMPTY && cValue.eType != XML_ANY_TYPE) - { - if (!ReadSimpleArray(cChildren, cValue)) - { - cValue.Clear(); - return false; - } - - return true; - } - } - - // read array of complex values. - cValue.eType = XML_ANY_TYPE; - cValue.panyTypeValue = new OpcXml::AnyType[cValue.iLength]; - - for (int ii = 0; ii < cValue.iLength; ii++) - { - if (!ReadXml(cChildren[ii], cValue.panyTypeValue[ii])) - { - cValue.Clear(); - return false; - } - } - - return true; -} - -// WriteSimpleArray -static bool WriteSimpleArray(COpcXmlElement& cElement, const OpcXml::AnyType& cValue) -{ - COpcString cElementName = ::GetType(cValue.eType); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - COpcString cText; - - switch (cValue.eType) - { - case OpcXml::XML_SBYTE: - { - if (!OpcXml::Write(cValue.psbyteValue[ii], cText)) false; - break; - } - - case OpcXml::XML_BYTE: - { - if (!OpcXml::Write(cValue.pbyteValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_SHORT: - { - if (!OpcXml::Write(cValue.pshortValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_USHORT: - { - if (!OpcXml::Write(cValue.pushortValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_INT: - { - if (!OpcXml::Write(cValue.pintValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_UINT: - { - if (!OpcXml::Write(cValue.puintValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_LONG: - { - if (!OpcXml::Write(cValue.plongValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_ULONG: - { - if (!OpcXml::Write(cValue.pulongValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_FLOAT: - { - if (!OpcXml::Write(cValue.pfloatValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_DOUBLE: - { - if (!OpcXml::Write(cValue.pdoubleValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_DECIMAL: - { - if (!OpcXml::Write(cValue.pdecimalValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_BOOLEAN: - { - if (!OpcXml::Write(cValue.pboolValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_DATETIME: - { - if (!OpcXml::Write(cValue.pdateTimeValue[ii], cText)) return false; - break; - } - - case OpcXml::XML_STRING: - { - if (!OpcXml::Write(cValue.pstringValue[ii], cText)) return false; - break; - } - } - - COpcXmlElement cChild = cElement.AppendChild(cElementName); - - if (cChild != NULL) - { - cChild.SetValue(cText); - } - } - - return true; -} - -// WriteXml -template<> bool OpcXml::WriteXml(IXMLDOMNode* ipNode, const AnyType& cValue) -{ - COpcXmlElement cElement(ipNode); - - // can only write AnyType values to XML elements. - if (cElement == NULL) - { - return false; - } - - // write schema. - if (!cValue.cSchema.Write(cElement)) - { - return false; - } - - if (cValue.iLength < 0) - { - // write simple value. - COpcString cText; - - switch (cValue.eType) - { - case XML_SBYTE: { if (!Write(cValue.sbyteValue, cText)) return false; break; } - case XML_BYTE: { if (!Write(cValue.byteValue, cText)) return false; break; } - case XML_SHORT: { if (!Write(cValue.shortValue, cText)) return false; break; } - case XML_USHORT: { if (!Write(cValue.ushortValue, cText)) return false; break; } - case XML_INT: { if (!Write(cValue.intValue, cText)) return false; break; } - case XML_UINT: { if (!Write(cValue.uintValue, cText)) return false; break; } - case XML_LONG: { if (!Write(cValue.longValue, cText)) return false; break; } - case XML_ULONG: { if (!Write(cValue.ulongValue, cText)) return false; break; } - case XML_FLOAT: { if (!Write(cValue.floatValue, cText)) return false; break; } - case XML_DOUBLE: { if (!Write(cValue.doubleValue, cText)) return false; break; } - case XML_DECIMAL: { if (!Write(cValue.decimalValue, cText)) return false; break; } - case XML_BOOLEAN: { if (!Write(cValue.boolValue, cText)) return false; break; } - case XML_DATETIME: { if (!Write(cValue.dateTimeValue, cText)) return false; break; } - case XML_STRING: { if (!Write(cValue.stringValue, cText)) return false; break; } - } - - cElement.SetValue(cText); - return true; - } - - // check for array of simple types. - if (cValue.eType != XML_ANY_TYPE) - { - if (cValue.eType == XML_BYTE) - { - COpcString cText; - - if (!WriteHexBinary(cText, cValue.pbyteValue, cValue.iLength)) - { - return false; - } - - cElement.SetValue(cText); - } - else - { - if (!WriteSimpleArray(cElement, cValue)) - { - return false; - } - } - - return true; - } - - // check for array of complex types. - COpcString cTypeName = cValue.cSchema.GetType().GetName(); - - int iIndex = cTypeName.Find(OPCXML_ARRAY_PREFIX); - - if (iIndex == 0) - { - cTypeName = cTypeName.SubStr(_tcslen(OPCXML_ARRAY_PREFIX)); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - COpcXmlElement cChild = cElement.AppendChild(cTypeName); - - // add the data type to the value schema if not already there. - QName cType = cValue.panyTypeValue[ii].cSchema.GetType(); - - if (cType.GetName().IsEmpty()) - { - COpcString cName = GetType(cValue.panyTypeValue[ii].eType); - - if (cValue.panyTypeValue[ii].iLength >= 0) - { - if (cValue.panyTypeValue[ii].eType == XML_BYTE) - { - cType.SetName(TAG_HEX_BINARY); - cType.SetNamespace(OPCXML_NS_SCHEMA); - } - else - { - COpcString cFullName; - - cFullName += OPCXML_ARRAY_PREFIX; - cFullName += cName.ToUpper(0); - - cType.SetName(cFullName); - cType.SetNamespace(cElement.ResolvePrefix((LPCWSTR)NULL)); - } - } - else - { - cType.SetName(cName); - cType.SetNamespace(OPCXML_NS_SCHEMA); - } - - cValue.panyTypeValue[ii].cSchema.SetType(cType); - } - - // write the value. - if (!WriteXml(cChild, cValue.panyTypeValue[ii])) - { - return false; - } - } - - return true; - } - - // write complex type. - for (int ii = 0; ii < cValue.iLength; ii++) - { - OpcXml::QName cName = cValue.panyTypeValue[ii].cSchema.GetName(); - - if (!WriteXml(cElement.AppendChild(cName), cValue.panyTypeValue[ii])) - { - return false; - } - } - - return true; -} - -// Assignment -AnyType& AnyType::operator=(const AnyType& cValue) -{ - Clear(); - - eType = cValue.eType; - cSchema = cValue.cSchema; - iLength = cValue.iLength; - - if (iLength < 0) - { - switch (eType) - { - case XML_BOOLEAN: { boolValue = cValue.boolValue; break; } - case XML_SBYTE: { psbyteValue = cValue.psbyteValue; break; } - case XML_BYTE: { byteValue = cValue.byteValue; break; } - case XML_SHORT: { shortValue = cValue.shortValue; break; } - case XML_USHORT: { ushortValue = cValue.ushortValue; break; } - case XML_INT: { intValue = cValue.intValue; break; } - case XML_UINT: { uintValue = cValue.uintValue; break; } - case XML_LONG: { longValue = cValue.longValue; break; } - case XML_ULONG: { ulongValue = cValue.ulongValue; break; } - case XML_FLOAT: { floatValue = cValue.floatValue; break; } - case XML_DOUBLE: { doubleValue = cValue.doubleValue; break; } - case XML_DECIMAL: { decimalValue = cValue.decimalValue; break; } - case XML_DATETIME: { dateTimeValue = cValue.dateTimeValue; break; } - case XML_STRING: { stringValue = OpcStrDup(cValue.stringValue); break; } - } - - return *this; - } - - Alloc(eType, iLength); - - for (int ii = 0; ii < cValue.iLength; ii++) - { - switch (eType) - { - case XML_BOOLEAN: { pboolValue[ii] = cValue.pboolValue[ii]; break; } - case XML_SBYTE: { psbyteValue[ii] = cValue.psbyteValue[ii]; break; } - case XML_BYTE: { pbyteValue[ii] = cValue.pbyteValue[ii]; break; } - case XML_SHORT: { pshortValue[ii] = cValue.pshortValue[ii]; break; } - case XML_USHORT: { pushortValue[ii] = cValue.pushortValue[ii]; break; } - case XML_INT: { pintValue[ii] = cValue.pintValue[ii]; break; } - case XML_UINT: { puintValue[ii] = cValue.puintValue[ii]; break; } - case XML_LONG: { plongValue[ii] = cValue.plongValue[ii]; break; } - case XML_ULONG: { pulongValue[ii] = cValue.pulongValue[ii]; break; } - case XML_FLOAT: { pfloatValue[ii] = cValue.pfloatValue[ii]; break; } - case XML_DOUBLE: { pdoubleValue[ii] = cValue.pdoubleValue[ii]; break; } - case XML_DECIMAL: { pdecimalValue[ii] = cValue.pdecimalValue[ii]; break; } - case XML_DATETIME: { pdateTimeValue[ii] = cValue.pdateTimeValue[ii]; break; } - case XML_STRING: { pstringValue[ii] = OpcStrDup(cValue.pstringValue[ii]); break; } - case XML_ANY_TYPE: { panyTypeValue[ii] = cValue.panyTypeValue[ii]; break; } - } - } - - return *this; -} - -// Compare -int AnyType::Compare(const AnyType& cValue) -{ - if (eType != cValue.eType) return (eType < cValue.eType)?-1:+1; - if (iLength != cValue.iLength) return (iLength < cValue.iLength)?-1:+1; - - if (iLength < 0) - { - switch (eType) - { - case XML_BOOLEAN: { if (boolValue != cValue.boolValue) return (boolValue < cValue.boolValue)?-1:+1; break; } - case XML_SBYTE: { if (sbyteValue != cValue.sbyteValue) return (sbyteValue < cValue.sbyteValue)?-1:+1; break; } - case XML_BYTE: { if (byteValue != cValue.byteValue) return (byteValue < cValue.byteValue)?-1:+1; break; } - case XML_SHORT: { if (shortValue != cValue.shortValue) return (shortValue < cValue.shortValue)?-1:+1; break; } - case XML_USHORT: { if (ushortValue != cValue.ushortValue) return (ushortValue < cValue.ushortValue)?-1:+1; break; } - case XML_INT: { if (intValue != cValue.intValue) return (intValue < cValue.intValue)?-1:+1; break; } - case XML_UINT: { if (uintValue != cValue.uintValue) return (uintValue < cValue.uintValue)?-1:+1; break; } - case XML_LONG: { if (longValue != cValue.longValue) return (longValue < cValue.longValue)?-1:+1; break; } - case XML_ULONG: { if (ulongValue != cValue.ulongValue) return (ulongValue < cValue.ulongValue)?-1:+1; break; } - case XML_FLOAT: { if (floatValue != cValue.floatValue) return (floatValue < cValue.floatValue)?-1:+1; break; } - case XML_DOUBLE: { if (doubleValue != cValue.doubleValue) return (doubleValue < cValue.doubleValue)?-1:+1; break; } - case XML_DECIMAL: { if (decimalValue != cValue.decimalValue) return (decimalValue < cValue.decimalValue)?-1:+1; break; } - case XML_DATETIME: { if (dateTimeValue != cValue.dateTimeValue) return (dateTimeValue < cValue.dateTimeValue)?-1:+1; break; } - - case XML_STRING: - { - int iResult = wcscmp(stringValue, cValue.stringValue); - - if (iResult != 0) - { - return iResult; - } - - break; - } - } - - return 0; - } - - for (int ii = 0; ii < iLength; ii++) - { - switch (eType) - { - case XML_BOOLEAN: { if (pboolValue[ii] != cValue.pboolValue[ii]) return (pboolValue[ii] < cValue.pboolValue[ii])?-1:+1; break; } - case XML_SBYTE: { if (psbyteValue[ii] != cValue.psbyteValue[ii]) return (psbyteValue[ii] < cValue.psbyteValue[ii])?-1:+1; break; } - case XML_BYTE: { if (pbyteValue[ii] != cValue.pbyteValue[ii]) return (pbyteValue[ii] < cValue.pbyteValue[ii])?-1:+1; break; } - case XML_SHORT: { if (pshortValue[ii] != cValue.pshortValue[ii]) return (pshortValue[ii] < cValue.pshortValue[ii])?-1:+1; break; } - case XML_USHORT: { if (pushortValue[ii] != cValue.pushortValue[ii]) return (pushortValue[ii] < cValue.pushortValue[ii])?-1:+1; break; } - case XML_INT: { if (pintValue[ii] != cValue.pintValue[ii]) return (pintValue[ii] < cValue.pintValue[ii])?-1:+1; break; } - case XML_UINT: { if (puintValue[ii] != cValue.puintValue[ii]) return (puintValue[ii] < cValue.puintValue[ii])?-1:+1; break; } - case XML_LONG: { if (plongValue[ii] != cValue.plongValue[ii]) return (plongValue[ii] < cValue.plongValue[ii])?-1:+1; break; } - case XML_ULONG: { if (pulongValue[ii] != cValue.pulongValue[ii]) return (pulongValue[ii] < cValue.pulongValue[ii])?-1:+1; break; } - case XML_FLOAT: { if (pfloatValue[ii] != cValue.pfloatValue[ii]) return (pfloatValue[ii] < cValue.pfloatValue[ii])?-1:+1; break; } - case XML_DOUBLE: { if (pdoubleValue[ii] != cValue.pdoubleValue[ii]) return (pdoubleValue[ii] < cValue.pdoubleValue[ii])?-1:+1; break; } - case XML_DECIMAL: { if (pdecimalValue[ii] != cValue.pdecimalValue[ii]) return (pdecimalValue[ii] < cValue.pdecimalValue[ii])?-1:+1; break; } - case XML_DATETIME: { if (pdateTimeValue[ii] != cValue.pdateTimeValue[ii]) return (pdateTimeValue[ii] < cValue.pdateTimeValue[ii])?-1:+1; break; } - - case XML_STRING: - { - int iResult = wcscmp(pstringValue[ii], cValue.pstringValue[ii]); - - if (iResult != 0) - { - return iResult; - } - - break; - } - } - } - - return 0; -} - -// Clear -void AnyType::Clear() -{ - if (iLength >= 0) - { - switch (eType) - { - case XML_BOOLEAN: { OpcFree(pboolValue); break; } - case XML_SBYTE: { OpcFree(psbyteValue); break; } - case XML_BYTE: { OpcFree(pbyteValue); break; } - case XML_SHORT: { OpcFree(pshortValue); break; } - case XML_USHORT: { OpcFree(pushortValue); break; } - case XML_INT: { OpcFree(pintValue); break; } - case XML_UINT: { OpcFree(puintValue); break; } - case XML_LONG: { OpcFree(plongValue); break; } - case XML_ULONG: { OpcFree(pulongValue); break; } - case XML_FLOAT: { OpcFree(pfloatValue); break; } - case XML_DOUBLE: { OpcFree(pdoubleValue); break; } - case XML_DECIMAL: { OpcFree(pdecimalValue); break; } - case XML_DATETIME: { OpcFree(pdateTimeValue); break; } - - case XML_STRING: - { - for (int ii = 0; ii < iLength; ii++) - { - OpcFree(pstringValue[ii]); - } - - OpcFree(pstringValue); - break; - } - - case XML_ANY_TYPE: - { - delete [] panyTypeValue; - break; - } - } - } - else - { - switch (eType) - { - case XML_STRING: { OpcFree(stringValue); break; } - } - } - - - eType = XML_EMPTY; - iLength = -1; - - memset(&dateTimeValue, 0, sizeof(dateTimeValue)); -} - -// Alloc -void AnyType::Alloc(Type eElement, UINT uLength) -{ - Clear(); - - eType = eElement; - iLength = uLength; - - switch (eType) - { - case XML_BOOLEAN: { pboolValue = OpcArrayAlloc(Boolean, iLength); break; } - case XML_SBYTE: { psbyteValue = OpcArrayAlloc(SByte, iLength); break; } - case XML_BYTE: { pbyteValue = OpcArrayAlloc(Byte, iLength); break; } - case XML_SHORT: { pshortValue = OpcArrayAlloc(Short, iLength); break; } - case XML_USHORT: { pushortValue = OpcArrayAlloc(UShort, iLength); break; } - case XML_INT: { pintValue = OpcArrayAlloc(Int, iLength); break; } - case XML_UINT: { puintValue = OpcArrayAlloc(UInt, iLength); break; } - case XML_LONG: { plongValue = OpcArrayAlloc(Long, iLength); break; } - case XML_ULONG: { pulongValue = OpcArrayAlloc(ULong, iLength); break; } - case XML_FLOAT: { pfloatValue = OpcArrayAlloc(Float, iLength); break; } - case XML_DOUBLE: { pdoubleValue = OpcArrayAlloc(Double, iLength); break; } - case XML_DECIMAL: { pdecimalValue = OpcArrayAlloc(Decimal, iLength); break; } - case XML_DATETIME: { pdateTimeValue = OpcArrayAlloc(DateTime, iLength); break; } - case XML_STRING: { pstringValue = OpcArrayAlloc(String, iLength); break; } - case XML_ANY_TYPE: { panyTypeValue = new AnyType[iLength]; break; } - } -} - -// MoveTo -void AnyType::MoveTo(AnyType& cTarget) -{ - cTarget.Clear(); - - cTarget.eType = eType; - cTarget.iLength = iLength; - cTarget.cSchema = cSchema; - - memcpy(&cTarget.dateTimeValue, &dateTimeValue, sizeof(dateTimeValue)); - - Init(); -} - -// CopyTo -bool AnyType::CopyTo(AnyType& cValue, Type eNewType) -{ - if (eType == eNewType) - { - cValue = *this; - return true; - } - - COpcVariant cSrc; - - if (!Get(cSrc.GetRef())) - { - return false; - } - - COpcVariant cDst; - - HRESULT hResult = COpcVariant::ChangeType(cDst.GetRef(), cSrc.GetRef(), NULL, GetVarType(eNewType)); - - if (FAILED(hResult)) - { - return false; - } - - cValue.Set(cDst.GetRef()); - - return true; -} - -// GetElement -bool AnyType::GetElement(int iIndex, AnyType& cElement) const -{ - if (iLength < 0 || iIndex < 0 || iIndex >= iLength) - { - return false; - } - - switch (eType) - { - default: { return false; } - case XML_BOOLEAN: { cElement.Set(pboolValue[iIndex]); break; } - case XML_SBYTE: { cElement.Set(psbyteValue[iIndex]); break; } - case XML_BYTE: { cElement.Set(pbyteValue[iIndex]); break; } - case XML_SHORT: { cElement.Set(pshortValue[iIndex]); break; } - case XML_USHORT: { cElement.Set(pushortValue[iIndex]); break; } - case XML_INT: { cElement.Set(pintValue[iIndex]); break; } - case XML_UINT: { cElement.Set(puintValue[iIndex]); break; } - case XML_LONG: { cElement.Set(plongValue[iIndex]); break; } - case XML_ULONG: { cElement.Set(pulongValue[iIndex]); break; } - case XML_FLOAT: { cElement.Set(pfloatValue[iIndex]); break; } - case XML_DOUBLE: { cElement.Set(pdoubleValue[iIndex]); break; } - case XML_DECIMAL: { cElement.Set(pdecimalValue[iIndex]); break; } - case XML_DATETIME: { cElement.Set(pdateTimeValue[iIndex]); break; } - case XML_STRING: { cElement.Set(pstringValue[iIndex]); break; } - case XML_ANY_TYPE: { cElement = panyTypeValue[iIndex]; break; } - } - - return true; -} - -// SetElement -bool AnyType::SetElement(int iIndex, const AnyType& cElement) -{ - if (iLength < 0 || iIndex < 0 || iIndex >= iLength) - { - return false; - } - - switch (eType) - { - default: { return false; } - case XML_BOOLEAN: { return cElement.Get(pboolValue[iIndex]); } - case XML_SBYTE: { return cElement.Get(psbyteValue[iIndex]); } - case XML_BYTE: { return cElement.Get(pbyteValue[iIndex]); } - case XML_SHORT: { return cElement.Get(pshortValue[iIndex]); } - case XML_USHORT: { return cElement.Get(pushortValue[iIndex]); } - case XML_INT: { return cElement.Get(pintValue[iIndex]); } - case XML_UINT: { return cElement.Get(puintValue[iIndex]); } - case XML_LONG: { return cElement.Get(plongValue[iIndex]); } - case XML_ULONG: { return cElement.Get(pulongValue[iIndex]); } - case XML_FLOAT: { return cElement.Get(pfloatValue[iIndex]); } - case XML_DOUBLE: { return cElement.Get(pdoubleValue[iIndex]); } - case XML_DECIMAL: { return cElement.Get(pdecimalValue[iIndex]); } - case XML_DATETIME: { return cElement.Get(pdateTimeValue[iIndex]); } - case XML_STRING: { return cElement.Get(pstringValue[iIndex]); } - case XML_ANY_TYPE: { panyTypeValue[iIndex] = cElement; return true; } - } - - return false; -} - -// Get -bool AnyType::Get(Boolean& value) const -{ - if (eType == XML_BOOLEAN && iLength < 0) - { - value = boolValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(SByte& value) const -{ - if (eType == XML_SBYTE && iLength < 0) - { - value = sbyteValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(Byte& value) const -{ - if (eType == XML_BYTE && iLength < 0) - { - value = byteValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(Short& value) const -{ - if (eType == XML_SHORT && iLength < 0) - { - value = shortValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(UShort& value) const -{ - if (eType == XML_USHORT && iLength < 0) - { - value = ushortValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(Int& value) const -{ - if (eType == XML_INT && iLength < 0) - { - value = intValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(UInt& value) const -{ - if (eType == XML_UINT && iLength < 0) - { - value = uintValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(long& value) const -{ - if (eType == XML_INT && iLength < 0) - { - value = intValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(unsigned long& value) const -{ - if (eType == XML_UINT && iLength < 0) - { - value = uintValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(Long& value) const -{ - if (eType == XML_LONG && iLength < 0) - { - value = longValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(ULong& value) const -{ - if (eType == XML_ULONG && iLength < 0) - { - value = ulongValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(Float& value) const -{ - if (eType == XML_FLOAT && iLength < 0) - { - value = floatValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(Double& value) const -{ - if (eType == XML_DOUBLE && iLength < 0) - { - value = doubleValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(Decimal& value) const -{ - if (eType == XML_DECIMAL && iLength < 0) - { - value = decimalValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(DateTime& value) const -{ - if (eType == XML_DATETIME && iLength < 0) - { - value = dateTimeValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(String& value) const -{ - if (eType == XML_STRING && iLength < 0) - { - value = OpcStrDup(stringValue); - return true; - } - - return false; -} - -// Get -bool AnyType::Get(LPSTR& value) const -{ - if (eType == XML_STRING && iLength < 0) - { - value = OpcStrDup((LPCSTR)(COpcString)stringValue); - return true; - } - - return false; -} - -// Get -bool AnyType::Get(COpcString& value) const -{ - if (eType == XML_STRING && iLength < 0) - { - value = stringValue; - return true; - } - - return false; -} - -// Get -bool AnyType::Get(COpcStringArray& value) const -{ - if (eType == XML_STRING && iLength >= 0) - { - value.SetSize(iLength); - - for (int ii = 0; ii < iLength; ii++) - { - value[ii] = pstringValue[ii]; - } - - return true; - } - - return false; -} - -// Get -bool AnyType::Get(VARIANT& cVariant) const -{ - OpcVariantClear(&cVariant); - - VARTYPE vtType = GetVarType(eType); - - if (iLength < 0) - { - cVariant.vt = vtType; - - switch (eType) - { - case XML_SBYTE: { cVariant.cVal = sbyteValue; break; } - case XML_BYTE: { cVariant.bVal = byteValue; break; } - case XML_SHORT: { cVariant.iVal = shortValue; break; } - case XML_USHORT: { cVariant.uiVal = ushortValue; break; } - case XML_INT: { cVariant.lVal = intValue; break; } - case XML_UINT: { cVariant.ulVal = uintValue; break; } - case XML_LONG: { cVariant.llVal = longValue; break; } - case XML_ULONG: { cVariant.ullVal = ulongValue; break; } - case XML_FLOAT: { cVariant.fltVal = floatValue; break; } - case XML_DOUBLE: { cVariant.dblVal = doubleValue; break; } - case XML_DECIMAL: { cVariant.cyVal = decimalValue; break; } - case XML_BOOLEAN: { cVariant.boolVal = (boolValue)?VARIANT_TRUE:VARIANT_FALSE; break; } - case XML_DATETIME: { cVariant.date = GetVarDate(dateTimeValue); break; } - case XML_STRING: { cVariant.bstrVal = SysAllocString(stringValue); break; } - } - - return true; - } - - COpcSafeArray cArray(cVariant); - - cArray.Alloc(vtType, iLength); - cArray.Lock(); - - void* pData = cArray.GetData(); - - for (int ii = 0; ii < iLength; ii++) - { - switch (eType) - { - case XML_SBYTE: { ((CHAR*)pData)[ii] = psbyteValue[ii]; break; } - case XML_BYTE: { ((BYTE*)pData)[ii] = pbyteValue[ii]; break; } - case XML_SHORT: { ((SHORT*)pData)[ii] = pshortValue[ii]; break; } - case XML_USHORT: { ((USHORT*)pData)[ii] = pushortValue[ii]; break; } - case XML_INT: { ((LONG*)pData)[ii] = pintValue[ii]; break; } - case XML_UINT: { ((ULONG*)pData)[ii] = puintValue[ii]; break; } - case XML_LONG: { ((LONGLONG*)pData)[ii] = plongValue[ii]; break; } - case XML_ULONG: { ((ULONGLONG*)pData)[ii] = pulongValue[ii]; break; } - case XML_FLOAT: { ((FLOAT*)pData)[ii] = pfloatValue[ii]; break; } - case XML_DOUBLE: { ((DOUBLE*)pData)[ii] = pdoubleValue[ii]; break; } - case XML_DECIMAL: { ((CY*)pData)[ii] = pdecimalValue[ii]; break; } - case XML_DATETIME: { ((DATE*)pData)[ii] = GetVarDate(pdateTimeValue[ii]); break; } - - case XML_STRING: - { - BSTR* pbstrData = (BSTR*)pData; - pbstrData[ii] = SysAllocString(pstringValue[ii]); - break; - } - - case XML_BOOLEAN: - { - ((VARIANT_BOOL*)pData)[ii] = (pboolValue[ii])?VARIANT_TRUE:VARIANT_FALSE; - break; - } - - case XML_ANY_TYPE: - { - panyTypeValue[ii].Get(((VARIANT*)pData)[ii]); - break; - } - } - } - - cArray.Unlock(); - return true; -} - -// Set -void AnyType::Set(Boolean value) -{ - Clear(); - - eType = XML_BOOLEAN; - iLength = -1; - boolValue = value; -} - -// Set -void AnyType::Set(SByte value) -{ - Clear(); - - eType = XML_SBYTE; - iLength = -1; - sbyteValue = value; -} - -// Set -void AnyType::Set(Byte value) -{ - Clear(); - - eType = XML_BYTE; - iLength = -1; - byteValue = value; -} - -// Set -void AnyType::Set(Short value) -{ - Clear(); - - eType = XML_SHORT; - iLength = -1; - shortValue = value; -} - -// Set -void AnyType::Set(UShort value) -{ - Clear(); - - eType = XML_USHORT; - iLength = -1; - ushortValue = value; -} - -// Set -void AnyType::Set(Int value) -{ - Clear(); - - eType = XML_INT; - iLength = -1; - intValue = value; -} - -// Set -void AnyType::Set(UInt value) -{ - Clear(); - - eType = XML_UINT; - iLength = -1; - uintValue = value; -} - -// Set -void AnyType::Set(long value) -{ - Clear(); - - eType = XML_INT; - iLength = -1; - intValue = (Int)value; -} - -// Set -void AnyType::Set(unsigned long value) -{ - Clear(); - - eType = XML_UINT; - iLength = -1; - uintValue = (UInt)value; -} - -// Set -void AnyType::Set(Long value) -{ - Clear(); - - eType = XML_LONG; - iLength = -1; - longValue = value; -} - -// Set -void AnyType::Set(ULong value) -{ - Clear(); - - eType = XML_ULONG; - iLength = -1; - ulongValue = value; -} - -// Set -void AnyType::Set(Float value) -{ - Clear(); - - eType = XML_FLOAT; - iLength = -1; - floatValue = value; -} - -// Set -void AnyType::Set(Double value) -{ - Clear(); - - eType = XML_DOUBLE; - iLength = -1; - doubleValue = value; -} - -// Set -void AnyType::Set(Decimal value) -{ - Clear(); - - eType = XML_DECIMAL; - iLength = -1; - decimalValue = value; -} - -// Set -void AnyType::Set(DateTime value) -{ - Clear(); - - eType = XML_DATETIME; - iLength = -1; - dateTimeValue = value; -} - -// Set -void AnyType::Set(const String value) -{ - Clear(); - - eType = XML_STRING; - iLength = -1; - stringValue = OpcStrDup(value); -} - -// Set -void AnyType::Set(LPCSTR value) -{ - Clear(); - - eType = XML_STRING; - iLength = -1; - stringValue = OpcStrDup((LPCWSTR)(COpcString)value); -} - -// Set -void AnyType::Set(const COpcString& value) -{ - Clear(); - - eType = XML_STRING; - iLength = -1; - stringValue = OpcStrDup((LPCWSTR)value); -} - -// Set -void AnyType::Set(const COpcStringArray& value) -{ - Clear(); - - eType = XML_STRING; - iLength = value.GetSize(); - - pstringValue = OpcArrayAlloc(String, iLength); - memset(pstringValue, 0, sizeof(String)*iLength); - - for (int ii = 0; ii < iLength; ii++) - { - pstringValue[ii] = OpcStrDup((LPCWSTR)value[ii]); - } -} - -// Set -void AnyType::Set(const VARIANT& cVariant) -{ - Clear(); - - eType = OpcXml::GetXmlType(cVariant.vt & VT_TYPEMASK); - - if ((cVariant.vt & VT_ARRAY) == 0) - { - switch (eType) - { - case XML_SBYTE: { sbyteValue = cVariant.cVal; break; } - case XML_BYTE: { byteValue = cVariant.bVal; break; } - case XML_SHORT: { shortValue = cVariant.iVal; break; } - case XML_USHORT: { ushortValue = cVariant.uiVal; break; } - case XML_INT: { intValue = cVariant.lVal; break; } - case XML_UINT: { uintValue = cVariant.ulVal; break; } - case XML_LONG: { longValue = cVariant.llVal; break; } - case XML_ULONG: { ulongValue = cVariant.ullVal; break; } - case XML_FLOAT: { floatValue = cVariant.fltVal; break; } - case XML_DOUBLE: { doubleValue = cVariant.dblVal; break; } - case XML_DECIMAL: { decimalValue = cVariant.cyVal; break; } - case XML_BOOLEAN: { boolValue = (cVariant.boolVal == VARIANT_TRUE); break; } - case XML_DATETIME: { dateTimeValue = GetXmlDateTime(cVariant.date); break; } - case XML_STRING: { stringValue = OpcStrDup(cVariant.bstrVal); break; } - } - - return; - } - - COpcSafeArray cArray((VARIANT&)cVariant); - - Alloc(eType, cArray.GetLength()); - - cArray.Lock(); - - void* pData = cArray.GetData(); - - for (int ii = 0; ii < iLength; ii++) - { - switch (eType) - { - case XML_SBYTE: { psbyteValue[ii] = ((CHAR*)pData)[ii]; break; } - case XML_BYTE: { pbyteValue[ii] = ((BYTE*)pData)[ii]; break; } - case XML_SHORT: { pshortValue[ii] = ((SHORT*)pData)[ii]; break; } - case XML_USHORT: { pushortValue[ii] = ((USHORT*)pData)[ii]; break; } - case XML_INT: { pintValue[ii] = ((LONG*)pData)[ii]; break; } - case XML_UINT: { puintValue[ii] = ((ULONG*)pData)[ii]; break; } - case XML_LONG: { plongValue[ii] = ((LONGLONG*)pData)[ii]; break; } - case XML_ULONG: { pulongValue[ii] = ((ULONGLONG*)pData)[ii]; break; } - case XML_FLOAT: { pfloatValue[ii] = ((FLOAT*)pData)[ii]; break; } - case XML_DOUBLE: { pdoubleValue[ii] = ((DOUBLE*)pData)[ii]; break; } - case XML_DECIMAL: { pdecimalValue[ii] = ((CY*)pData)[ii]; break; } - case XML_DATETIME: { pdateTimeValue[ii] = GetXmlDateTime(((DATE*)pData)[ii]); break; } - case XML_BOOLEAN: { pboolValue[ii] = (((VARIANT_BOOL*)pData)[ii] == VARIANT_TRUE); break; } - - case XML_STRING: - { - BSTR* pbstrData = (BSTR*)pData; - pstringValue[ii] = OpcStrDup(pbstrData[ii]); - break; - } - - case XML_ANY_TYPE: - { - panyTypeValue[ii].Set(((VARIANT*)pData)[ii]); - break; - } - } - } - - cArray.Unlock(); -} diff --git a/ComIOP/Wrapper/Common/COpcXmlAnyType.h b/ComIOP/Wrapper/Common/COpcXmlAnyType.h deleted file mode 100644 index ea6f731b1..000000000 --- a/ComIOP/Wrapper/Common/COpcXmlAnyType.h +++ /dev/null @@ -1,339 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcXmlAnyType_H_ -#define _COpcXmlAnyType_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "COpcString.h" -#include "COpcMap.h" -#include "COpcXmlElement.h" -#include "COpcVariant.h" - -namespace OpcXml -{ - -//============================================================================== -// CLASS: Schema -// PURPOSE: Describes the schema on XML element. - -class Schema -{ - OPC_CLASS_NEW_DELETE_ARRAY(); - -public: - - //========================================================================== - // Public Operators - - // Constructor - Schema() {} - Schema(const Schema& cSchema) { *this = cSchema; } - - // Destructor - ~Schema() {} - - // Assignment - Schema& operator=(const Schema& cSchema) - { - m_cName = cSchema.m_cName; - m_cType = cSchema.m_cType; - m_cAttributes = cSchema.m_cAttributes; - - return *this; - } - - //========================================================================== - // Public Properties - - // Name - const QName& GetName() const { return m_cName; } - void SetName(const QName& cName) { m_cName = cName; } - - // Type - const QName& GetType() const { return m_cType; } - void SetType(const QName& cType) { m_cType = cType; } - - // Get - template - bool Get(const QName& cName, TYPE& value) const - { - COpcString cValue; - - if (m_cAttributes.Lookup(cName, cValue)) - { - if (OpcXml::Read(cValue, value)) - { - return true; - } - } - - Init(value); - - return false; - } - - // Set - template - bool Set(const QName& cName, const TYPE& value) - { - COpcString cValue; - - if (OpcXml::Write(value, cValue)) - { - m_cAttributes.SetAt(cName, cValue); - return true; - } - - return false; - } - - //========================================================================== - // Public Methods - - // Read - bool Read(COpcXmlElement& cElement); - - // Write - bool Write(COpcXmlElement& cParent) const; - -private: - - //========================================================================== - // Private Members - - QName m_cName; - QName m_cType; - COpcMap m_cAttributes; -}; - -//============================================================================== -// CLASS: AnyType -// PURPOSE: Represents an arbitrary element of data. - -class AnyType -{ - OPC_CLASS_NEW_DELETE_ARRAY(); - -public: - - //========================================================================== - // Public Members - - Type eType; - Schema cSchema; - Int iLength; - - union - { - Boolean boolValue; - SByte sbyteValue; - Byte byteValue; - Short shortValue; - UShort ushortValue; - Int intValue; - UInt uintValue; - Long longValue; - ULong ulongValue; - Float floatValue; - Double doubleValue; - Decimal decimalValue; - DateTime dateTimeValue; - String stringValue; - Boolean* pboolValue; - SByte* psbyteValue; - Byte* pbyteValue; - Short* pshortValue; - UShort* pushortValue; - Int* pintValue; - UInt* puintValue; - Long* plongValue; - ULong* pulongValue; - Float* pfloatValue; - Double* pdoubleValue; - Decimal* pdecimalValue; - String* pstringValue; - DateTime* pdateTimeValue; - AnyType* panyTypeValue; - }; - - //========================================================================== - // Public Operators - - // Constructor - AnyType() { Init(); } - AnyType(Boolean value) { Init(); Set(value); } - AnyType(SByte value) { Init(); Set(value); } - AnyType(Byte value) { Init(); Set(value); } - AnyType(Short value) { Init(); Set(value); } - AnyType(UShort value) { Init(); Set(value); } - AnyType(Int value) { Init(); Set(value); } - AnyType(UInt value) { Init(); Set(value); }; - AnyType(long value) { Init(); Set(value); } - AnyType(unsigned long value) { Init(); Set(value); } - AnyType(Long value) { Init(); Set(value); } - AnyType(ULong value) { Init(); Set(value); } - AnyType(Float value) { Init(); Set(value); } - AnyType(Double value) { Init(); Set(value); } - AnyType(Decimal value) { Init(); Set(value); } - AnyType(DateTime value) { Init(); Set(value); } - AnyType(const String value) { Init(); Set(value); } - AnyType(LPCSTR value) { Init(); Set(value); } - AnyType(const COpcString& value) { Init(); Set(value); } - AnyType(const COpcStringArray& value) { Init(); Set(value); } - AnyType(const VARIANT& value) { Init(); Set(value); } - AnyType(const AnyType& cValue) { Init(); *this = cValue; } - - // Destructor - ~AnyType() - { - Clear(); - } - - // Assignment - AnyType& operator=(const AnyType& cValue); - AnyType& operator=(const VARIANT& cValue) { Set(cValue); } - AnyType& operator=(const COpcVariant& cValue) { Set(((COpcVariant&)cValue).GetRef()); } - - // Comparison - bool operator==(const AnyType& cValue) { return (Compare(cValue) == 0); } - bool operator<=(const AnyType& cValue) { return (Compare(cValue) <= 0); } - bool operator>=(const AnyType& cValue) { return (Compare(cValue) >= 0); } - bool operator< (const AnyType& cValue) { return (Compare(cValue) < 0); } - bool operator> (const AnyType& cValue) { return (Compare(cValue) < 0); } - bool operator!=(const AnyType& cValue) { return (Compare(cValue) != 0); } - - //========================================================================== - // Public Methods - - // Init - void Init() - { - eType = XML_EMPTY; - iLength = -1; - memset(&dateTimeValue, 0, sizeof(dateTimeValue)); - } - - // Clear - void Clear(); - - // Compare - int Compare(const AnyType& cValue); - - // Alloc - void Alloc(Type eElement, UINT uLength); - - // MoveTo - void MoveTo(AnyType& cTarget); - - // CopyTo - bool CopyTo(AnyType& cValue, Type eNewType); - - // GetElement - bool GetElement(int iIndex, AnyType& cElement) const; - - // SetElement - bool SetElement(int iIndex, const AnyType& cElement); - - // Get - bool Get(Boolean& value) const; - bool Get(SByte& value) const; - bool Get(Byte& value) const; - bool Get(Short& value) const; - bool Get(UShort& value) const; - bool Get(Int& value) const; - bool Get(UInt& value) const; - bool Get(long& value) const; - bool Get(unsigned long& value) const; - bool Get(Long& value) const; - bool Get(ULong& value) const; - bool Get(Float& value) const; - bool Get(Double& value) const; - bool Get(Decimal& value) const; - bool Get(DateTime& value) const; - bool Get(String& value) const; - bool Get(LPSTR& value) const; - bool Get(COpcString& value) const; - bool Get(COpcStringArray& value) const; - bool Get(VARIANT& cVariant) const; - - // Set - void Set(Boolean value); - void Set(SByte value); - void Set(Byte value); - void Set(Short value); - void Set(UShort value); - void Set(Int value); - void Set(UInt value); - void Set(long value); - void Set(unsigned long value); - void Set(Long value); - void Set(ULong value); - void Set(Float value); - void Set(Double value); - void Set(Decimal value); - void Set(DateTime value); - void Set(const String value); - void Set(LPCSTR value); - void Set(const COpcString& value); - void Set(const COpcStringArray& value); - void Set(const VARIANT& cVariant); -}; - -//============================================================================== -// FUNCTION: XXX -// PURPOSE Defines conversion functions for COpcVariants. - -template<> OPCUTILS_API void Init(AnyType& cValue); -template<> OPCUTILS_API void Clear(AnyType& cValue); -template<> OPCUTILS_API bool ReadXml(IXMLDOMNode* ipNode, AnyType& cValue); -template<> OPCUTILS_API bool WriteXml(IXMLDOMNode* ipNode, const AnyType& cValue); - -}; // OpcXml - -//============================================================================== -// FUNCTION: HashKey -// PURPOSE: QName hash key generator. - -template<> -inline UINT HashKey(const OpcXml::QName& cName) -{ - LPCTSTR key = cName.GetName(); - if (key == NULL) return -1; - - UINT nHash = 0; - while (*key) - nHash = (nHash<<5) + nHash + *key++; - return nHash; -} - -#endif // _COpcXmlAnyType_H_ diff --git a/ComIOP/Wrapper/Common/COpcXmlAttribute.cpp b/ComIOP/Wrapper/Common/COpcXmlAttribute.cpp deleted file mode 100644 index 62510c182..000000000 --- a/ComIOP/Wrapper/Common/COpcXmlAttribute.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcXmlAttribute.h" -#include "COpcVariant.h" - -//============================================================================== -// COpcXmlAttribute - -// Constructor -COpcXmlAttribute::COpcXmlAttribute(IUnknown* ipUnknown) -{ - m_ipAttribute = NULL; - *this = ipUnknown; -} - -// Copy Constructor -COpcXmlAttribute::COpcXmlAttribute(const COpcXmlAttribute& cAttribute) -{ - m_ipAttribute = NULL; - *this = cAttribute.m_ipAttribute; -} - -// Destructor -COpcXmlAttribute::~COpcXmlAttribute() -{ - if (m_ipAttribute != NULL) - { - m_ipAttribute->Release(); - m_ipAttribute = NULL; - } -} - -// Assignment -COpcXmlAttribute& COpcXmlAttribute::operator=(IUnknown* ipUnknown) -{ - if (m_ipAttribute != NULL) - { - m_ipAttribute->Release(); - m_ipAttribute = NULL; - } - - if (ipUnknown != NULL) - { - HRESULT hResult = ipUnknown->QueryInterface(__uuidof(IXMLDOMAttribute), (void**)&m_ipAttribute); - - if (FAILED(hResult)) - { - m_ipAttribute = NULL; - } - } - - return *this; -} - -// Assignment -COpcXmlAttribute& COpcXmlAttribute::operator=(const COpcXmlAttribute& cAttribute) -{ - if (this == &cAttribute) - { - return *this; - } - - *this = cAttribute.m_ipAttribute; - return *this; -} - -// GetName -COpcString COpcXmlAttribute::GetName() -{ - if (m_ipAttribute != NULL) - { - BSTR bstrName = NULL; - - HRESULT hResult = m_ipAttribute->get_name(&bstrName); - OPC_ASSERT(SUCCEEDED(hResult)); - - COpcString cName = bstrName; - SysFreeString(bstrName); - - return cName; - } - - return (LPCWSTR)NULL; -} - -// GetPrefix -COpcString COpcXmlAttribute::GetPrefix() -{ - if (m_ipAttribute != NULL) - { - BSTR bstrName = NULL; - - HRESULT hResult = m_ipAttribute->get_prefix(&bstrName); - OPC_ASSERT(SUCCEEDED(hResult)); - - COpcString cName = bstrName; - SysFreeString(bstrName); - - return cName; - } - - return (LPCWSTR)NULL; -} - -// GetQualifiedName -OpcXml::QName COpcXmlAttribute::GetQualifiedName() -{ - OpcXml::QName cQName; - - if (m_ipAttribute != NULL) - { - BSTR bstrName = NULL; - - HRESULT hResult = m_ipAttribute->get_baseName(&bstrName); - OPC_ASSERT(SUCCEEDED(hResult)); - - cQName.SetName(bstrName); - cQName.SetNamespace(GetNamespace()); - - SysFreeString(bstrName); - } - - return cQName; -} - -// GetNamespace -COpcString COpcXmlAttribute::GetNamespace() -{ - if (m_ipAttribute != NULL) - { - BSTR bstrName = NULL; - - HRESULT hResult = m_ipAttribute->get_namespaceURI(&bstrName); - OPC_ASSERT(SUCCEEDED(hResult)); - - COpcString cName = bstrName; - SysFreeString(bstrName); - - return cName; - } - - return (LPCWSTR)NULL; -} - -// GetValue -COpcString COpcXmlAttribute::GetValue() -{ - VARIANT cVariant; OpcVariantInit(&cVariant); - - if (FAILED(m_ipAttribute->get_value(&cVariant))) { OPC_ASSERT(false); } - - COpcString cValue = cVariant.bstrVal; - OpcVariantClear(&cVariant); - - return cValue; -} diff --git a/ComIOP/Wrapper/Common/COpcXmlAttribute.h b/ComIOP/Wrapper/Common/COpcXmlAttribute.h deleted file mode 100644 index 2ba65550c..000000000 --- a/ComIOP/Wrapper/Common/COpcXmlAttribute.h +++ /dev/null @@ -1,102 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcXmlAttribute_H_ -#define _COpcXmlAttribute_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "COpcString.h" -#include "COpcArray.h" -#include "OpcXmlType.h" - -//============================================================================== -// CLASS: COpcXmlAttribute -// PURPOSE Represents an XML attribute. - -class OPCUTILS_API COpcXmlAttribute -{ - OPC_CLASS_NEW_DELETE_ARRAY(); - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcXmlAttribute(IUnknown* ipUnknown = NULL); - - // Copy Constructor - COpcXmlAttribute(const COpcXmlAttribute& cAttribute); - - // Destructor - ~COpcXmlAttribute(); - - // Assignment - COpcXmlAttribute& operator=(IUnknown* ipUnknown); - COpcXmlAttribute& operator=(const COpcXmlAttribute& cAttribute); - - // Accessor - operator IXMLDOMAttribute*() const { return m_ipAttribute; } - - //========================================================================== - // Public Methods - - // GetName - COpcString GetName(); - - // Prefix - COpcString GetPrefix(); - - // Namespace - COpcString GetNamespace(); - - // GetQualifiedName - OpcXml::QName GetQualifiedName(); - - // GetValue - COpcString GetValue(); - -protected: - - //========================================================================== - // Private Members - - IXMLDOMAttribute* m_ipAttribute; -}; - -//============================================================================== -// TYPE: COpcXmlAttributeList -// PURPOSE: A list of elements. - -typedef COpcArray COpcXmlAttributeList; - -#endif // _COpcXmlAttribute_H_ diff --git a/ComIOP/Wrapper/Common/COpcXmlDocument.cpp b/ComIOP/Wrapper/Common/COpcXmlDocument.cpp deleted file mode 100644 index 69938f951..000000000 --- a/ComIOP/Wrapper/Common/COpcXmlDocument.cpp +++ /dev/null @@ -1,767 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcXmlDocument.h" -#include "COpcXmlElement.h" -#include "COpcXmlAttribute.h" -#include "COpcVariant.h" - -//============================================================================== -// Local Declarations - -#define TAG_DOCTYPE L"xml" -#define TAG_FORMAT L"version=\"1.0\" encoding=\"utf-16\"" -#define TAG_XSD L"xsd" -#define TAG_XSI L"xsi" - -//============================================================================== -// COpcXmlDocument - -// Constructor -COpcXmlDocument::COpcXmlDocument(IXMLDOMDocument* ipUnknown) -{ - m_ipDocument = NULL; - *this = ipUnknown; -} - -// Copy Constructor -COpcXmlDocument::COpcXmlDocument(const COpcXmlDocument& cDocument) -{ - m_ipDocument = NULL; - *this = cDocument.m_ipDocument; -} - -// Destructor -COpcXmlDocument::~COpcXmlDocument() -{ - if (m_ipDocument != NULL) - { - m_ipDocument->Release(); - m_ipDocument = NULL; - } -} - -// Assignment -COpcXmlDocument& COpcXmlDocument::operator=(IUnknown* ipUnknown) -{ - if (m_ipDocument != NULL) - { - m_ipDocument->Release(); - m_ipDocument = NULL; - } - - if (ipUnknown != NULL) - { - HRESULT hResult = ipUnknown->QueryInterface(__uuidof(IXMLDOMDocument), (void**)&m_ipDocument); - - if (FAILED(hResult)) - { - m_ipDocument = NULL; - } - } - - return *this; -} - -// Assignment -COpcXmlDocument& COpcXmlDocument::operator=(const COpcXmlDocument& cDocument) -{ - if (this == &cDocument) - { - return *this; - } - - *this = cDocument.m_ipDocument; - return *this; -} - -// GetRoot -COpcXmlElement COpcXmlDocument::GetRoot() const -{ - COpcXmlElement cElement; - - // check if document exists. - if (m_ipDocument == NULL) - { - return cElement; - } - - IXMLDOMElement* ipRoot = NULL; - - HRESULT hResult = m_ipDocument->get_documentElement(&ipRoot); - - if (FAILED(hResult)) - { - return cElement; - } - - cElement = ipRoot; - - if (ipRoot != NULL) - { - ipRoot->Release(); - } - - return cElement; -} - -// FindElement -COpcXmlElement COpcXmlDocument::FindElement(const COpcString& cXPath) -{ - COpcXmlElement cElement; - - // check if document exists. - if (m_ipDocument == NULL) - { - return cElement; - } - - // serach for single node. - IXMLDOMElement* ipElement = NULL; - BSTR bstrQuery = SysAllocString(cXPath); - HRESULT hResult = m_ipDocument->selectSingleNode(bstrQuery, (IXMLDOMNode**)&ipElement); - SysFreeString(bstrQuery); - - if (FAILED(hResult)) - { - return cElement; - } - - // return result. - cElement = ipElement; - - if (ipElement != NULL) - { - ipElement->Release(); - } - - return cElement; -} - -// FindElements -UINT COpcXmlDocument::FindElements(const COpcString& cXPath, COpcXmlElementList& cElements) -{ - cElements.RemoveAll(); - - // check if document exists. - if (m_ipDocument == NULL) - { - return 0; - } - - // search for matching nodes. - IXMLDOMNodeList* ipNodes = NULL; - - BSTR bstrQuery = SysAllocString(cXPath); - HRESULT hResult = m_ipDocument->selectNodes(bstrQuery, &ipNodes); - SysFreeString(bstrQuery); - - if (FAILED(hResult)) - { - return 0; - } - - // add found nodes to element list. - do - { - IXMLDOMNode* ipNode = NULL; - - hResult = ipNodes->nextNode(&ipNode); - - if (hResult != S_OK || ipNode == NULL) - { - break; - } - - COpcXmlElement cElement(ipNode); - ipNode->Release(); - - if (cElement != NULL) - { - cElements.Append(cElement); - } - } - while (SUCCEEDED(hResult)); - - if (ipNodes != NULL) - { - ipNodes->Release(); - } - - // return the number of elements found. - return cElements.GetSize(); -} - -// GetXml -bool COpcXmlDocument::GetXml(COpcString& cXml) const -{ - // check if document exists. - if (m_ipDocument == NULL) - { - return false; - } - - // get the xml. - BSTR bstrXml = NULL; - - HRESULT hResult = m_ipDocument->get_xml(&bstrXml); - - if (FAILED(hResult)) - { - return false; - } - - // copy the text. - cXml = bstrXml; - SysFreeString(bstrXml); - return true; -} - -// Init -bool COpcXmlDocument::Init() -{ - HRESULT hResult = S_OK; - - TRY - { - // clear existing document. - Clear(); - - // create new document. - hResult = CoCreateInstance( - __uuidof(DOMDocument), - NULL, - CLSCTX_INPROC_SERVER, - __uuidof(IXMLDOMDocument), - (void**)&m_ipDocument - ); - - if (FAILED(hResult)) - { - THROW(); - } - } - CATCH - { - Clear(); - } - - FINALLY - - return SUCCEEDED(hResult); -} - -// Clear -void COpcXmlDocument::Clear() -{ - // release the document. - if (m_ipDocument != NULL) - { - m_ipDocument->Release(); - m_ipDocument = NULL; - } -} - -// New -bool COpcXmlDocument::New() -{ - HRESULT hResult = S_OK; - - IXMLDOMProcessingInstruction* ipHeader = NULL; - IXMLDOMNode* ipResult = NULL; - - BSTR bstrDocType = SysAllocString(TAG_DOCTYPE); - BSTR bstrFormat = SysAllocString(TAG_FORMAT); - - TRY - { - // create new document instance. - if (!Init()) - { - THROW_(hResult, E_FAIL); - } - - // add document header. - hResult = m_ipDocument->createProcessingInstruction(bstrDocType, bstrFormat, &ipHeader); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = m_ipDocument->appendChild(ipHeader, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - } - - CATCH - { - Clear(); - } - - FINALLY - { - // release memory. - if (ipHeader != NULL) ipHeader->Release(); - if (ipResult != NULL) ipResult->Release(); - - SysFreeString(bstrDocType); - SysFreeString(bstrFormat); - } - - return SUCCEEDED(hResult); -} - -// New -bool COpcXmlDocument::New(IXMLDOMElement* ipElement) -{ - HRESULT hResult = S_OK; - - IXMLDOMElement* ipClone = NULL; - IXMLDOMNode* ipParent = NULL; - IXMLDOMNode* ipResult = NULL; - - TRY - { - // create new document instance. - if (!New()) - { - THROW_(hResult, E_FAIL); - } - - // clone the element. - hResult = ipElement->cloneNode(VARIANT_TRUE, (IXMLDOMNode**)&ipClone); - - if (FAILED(hResult)) - { - THROW(); - } - - // remove clone from parent. - hResult = ipClone->get_parentNode(&ipParent); - - if (FAILED(hResult)) - { - THROW(); - } - - if (ipParent != NULL) - { - hResult = ipParent->removeChild(ipClone, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - - if (ipResult != NULL) - { - ipResult->Release(); - ipResult = NULL; - } - } - - // add root element to document. - hResult = m_ipDocument->appendChild(ipClone, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - - if (ipResult != NULL) - { - ipResult->Release(); - ipResult = NULL; - } - - // declare element as the document element. - hResult = m_ipDocument->putref_documentElement(ipClone); - - if (FAILED(hResult)) - { - THROW(); - } - - // add predefined namespaces - AddNamespace(TAG_XSD, OPCXML_NS_SCHEMA); - AddNamespace(TAG_XSI, OPCXML_NS_SCHEMA_INSTANCE); - } - - CATCH - { - Clear(); - } - - FINALLY - { - // release memory. - if (ipClone != NULL) ipClone->Release(); - if (ipParent != NULL) ipParent->Release(); - if (ipResult != NULL) ipResult->Release(); - } - - return SUCCEEDED(hResult); -} - -// New -bool COpcXmlDocument::New(const COpcString& cRoot, const COpcString& cDefaultNamespace) -{ - HRESULT hResult = S_OK; - - IXMLDOMElement* ipRoot = NULL; - IXMLDOMNode* ipResult = NULL; - - BSTR bstrRoot = SysAllocString((LPCWSTR)cRoot); - - TRY - { - // create new document instance. - if (!New()) - { - THROW_(hResult, E_FAIL); - } - - // create root element. - VARIANT vNodeType; - vNodeType.vt = VT_I4; - vNodeType.lVal = NODE_ELEMENT; - - BSTR bstrNamespace = SysAllocString(cDefaultNamespace); - hResult = m_ipDocument->createNode(vNodeType, bstrRoot, bstrNamespace, (IXMLDOMNode**)&ipRoot); - SysFreeString(bstrNamespace); - - if (FAILED(hResult)) - { - THROW(); - } - - // add root element to document. - hResult = m_ipDocument->appendChild(ipRoot, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - - if (ipResult != NULL) - { - ipResult->Release(); - ipResult = NULL; - } - - // declare element as the document element. - hResult = m_ipDocument->putref_documentElement(ipRoot); - - if (FAILED(hResult)) - { - THROW(); - } - - // add predefined namespaces - AddNamespace(TAG_XSD, OPCXML_NS_SCHEMA); - AddNamespace(TAG_XSI, OPCXML_NS_SCHEMA_INSTANCE); - } - - CATCH - { - Clear(); - } - - FINALLY - { - // release memory. - if (ipRoot != NULL) ipRoot->Release(); - if (ipResult != NULL) ipResult->Release(); - - SysFreeString(bstrRoot); - } - - return SUCCEEDED(hResult); -} - -// Init -bool COpcXmlDocument::LoadXml(LPCWSTR szXml) -{ - HRESULT hResult = S_OK; - - BSTR bstrXml = SysAllocString(szXml); - - TRY - { - // create new document instance. - if (!Init()) - { - THROW_(hResult, E_FAIL); - } - - // parse the XML. - VARIANT_BOOL bResult = VARIANT_FALSE; - - hResult = m_ipDocument->loadXML(bstrXml, &bResult); - - if (FAILED(hResult)) - { - THROW(); - } - - if (!bResult) - { - THROW_(hResult, E_FAIL); - } - - // add predefined namespaces - AddNamespace(TAG_XSD, OPCXML_NS_SCHEMA); - AddNamespace(TAG_XSI, OPCXML_NS_SCHEMA_INSTANCE); - } - - CATCH - { - Clear(); - } - - FINALLY - { - SysFreeString(bstrXml); - } - - return SUCCEEDED(hResult); -} - - -// Load -bool COpcXmlDocument::Load(const COpcString& cFilePath) -{ - HRESULT hResult = S_OK; - - VARIANT varFile; - - varFile.vt = VT_BSTR; - varFile.bstrVal = SysAllocString((LPCWSTR)cFilePath); - - TRY - { - // create new document instance. - if (!Init()) - { - THROW_(hResult, E_FAIL); - } - - // load the file. - VARIANT_BOOL bResult = VARIANT_FALSE; - - hResult = m_ipDocument->load(varFile, &bResult); - - if (FAILED(hResult)) - { - THROW(); - } - - if (!bResult) - { - IXMLDOMParseError* ipError = NULL; - - hResult = m_ipDocument->get_parseError(&ipError); - - if (FAILED(hResult)) - { - THROW_(hResult, E_FAIL); - } - - BSTR bstrReason = NULL; - - hResult = ipError->get_reason(&bstrReason); - - if (SUCCEEDED(hResult)) - { - SysFreeString(bstrReason); - } - - ipError->Release(); - } - - // update default path. - if (!cFilePath.IsEmpty()) m_cFilePath = cFilePath; - } - - CATCH - { - Clear(); - } - - FINALLY - { - OpcVariantClear(&varFile); - } - - return SUCCEEDED(hResult); -} - -// Save -bool COpcXmlDocument::Save(const COpcString& cFilePath) -{ - HRESULT hResult = S_OK; - - VARIANT varFile; - - varFile.vt = VT_BSTR; - varFile.bstrVal = SysAllocString((LPCWSTR)((cFilePath.IsEmpty())?m_cFilePath:cFilePath)); - - TRY - { - // save the file. - hResult = m_ipDocument->save(varFile); - - if (FAILED(hResult)) - { - THROW(); - } - } - - CATCH_FINALLY - { - OpcVariantClear(&varFile); - } - - return SUCCEEDED(hResult); -} - -// GetDefaultNamespace -COpcString COpcXmlDocument::GetDefaultNamespace() -{ - // check for a valid root element. - COpcXmlElement cElement(GetRoot()); - - if (cElement == NULL) - { - return (LPCWSTR)NULL; - } - - return cElement.GetNamespace(); -} - -// GetNamespaces -void COpcXmlDocument::GetNamespaces(COpcStringMap& cNamespaces) -{ - // clear the current set. - cNamespaces.RemoveAll(); - - // check for a valid root element. - COpcXmlElement cElement(GetRoot()); - - if (cElement == NULL) - { - return; - } - - // add the namespace for the root element. - COpcString cPrefix = cElement.GetPrefix(); - - if (!cPrefix.IsEmpty()) - { - cNamespaces[cPrefix] = cElement.GetNamespace(); - } - - // fetch the attributes from the root element. - COpcXmlAttributeList cAttributes; - - if (cElement.GetAttributes(cAttributes) > 0) - { - for (UINT ii = 0; ii < cAttributes.GetSize(); ii++) - { - if (cAttributes[ii].GetPrefix() == OPCXML_NAMESPACE_ATTRIBUTE) - { - COpcString cName = cAttributes[ii].GetQualifiedName().GetName(); - - // don't add the default namespace. - if (!cName.IsEmpty()) - { - cNamespaces[cName] = cAttributes[ii].GetValue(); - } - } - } - } -} - -// GetNamespacePrefix -COpcString COpcXmlDocument::GetNamespacePrefix(const COpcString& cNamespace) -{ - COpcStringMap cNamespaces; - GetNamespaces(cNamespaces); - - OPC_POS pos = cNamespaces.GetStartPosition(); - - while (pos != NULL) - { - COpcString cPrefix; - COpcString cValue; - cNamespaces.GetNextAssoc(pos, cPrefix, cValue); - - if (cValue == cNamespace) - { - return cPrefix; - } - } - - return (LPCWSTR)NULL; -} - -// AddNamespace -bool COpcXmlDocument::AddNamespace(const COpcString& cPrefix, const COpcString& cNamespace) -{ - // check for a valid root element. - COpcXmlElement cElement(GetRoot()); - - if (cElement == NULL) - { - return false; - } - - // check for an invalid prefix - if (cPrefix.IsEmpty()) - { - return false; - } - - // construct the new namespace attribute name. - COpcString cAttributeName; - - cAttributeName += OPCXML_NAMESPACE_ATTRIBUTE; - cAttributeName += ":"; - cAttributeName += cPrefix; - - // add or update the namespace string. - cElement.SetAttribute(cAttributeName, cNamespace); - - return true; -} diff --git a/ComIOP/Wrapper/Common/COpcXmlDocument.h b/ComIOP/Wrapper/Common/COpcXmlDocument.h deleted file mode 100644 index db126ce9e..000000000 --- a/ComIOP/Wrapper/Common/COpcXmlDocument.h +++ /dev/null @@ -1,141 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcXmlDocument_H_ -#define _COpcXmlDocument_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "COpcMap.h" -#include "OpcXmlType.h" -#include "COpcXmlElement.h" - -//============================================================================== -// CLASS: COpcXmlDocument -// PURPOSE Facilitiates manipulation of XML documents, - -class OPCUTILS_API COpcXmlDocument -{ - OPC_CLASS_NEW_DELETE() - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcXmlDocument(IXMLDOMDocument* ipUnknown = NULL); - - // Copy Constructor - COpcXmlDocument(const COpcXmlDocument& cDocument); - - // Destructor - ~COpcXmlDocument(); - - // Assignment - COpcXmlDocument& operator=(IUnknown* ipUnknown); - COpcXmlDocument& operator=(const COpcXmlDocument& cDocument); - - // Accessor - operator IXMLDOMDocument*() const { return m_ipDocument; } - - //========================================================================== - // Public Methods - - // Init - virtual bool Init(); - - // Clear - virtual void Clear(); - - // New - virtual bool New(); - - // New - virtual bool New(const COpcString& cRoot, const COpcString& cDefaultNamespace); - - // New - virtual bool New(IXMLDOMElement* ipElement); - - // Init - virtual bool LoadXml(LPCWSTR szXml); - - // Load - virtual bool Load(const COpcString& cFilePath = OPC_EMPTY_STRING); - - // Save - virtual bool Save(const COpcString& cFilePath = OPC_EMPTY_STRING); - - // GetRoot - COpcXmlElement GetRoot() const; - - // GetXml - bool GetXml(COpcString& cXml) const; - - // GetDefaultNamespace - COpcString GetDefaultNamespace(); - - // AddNamespace - bool AddNamespace(const COpcString& cPrefix, const COpcString& cNamespace); - - // GetNamespaces - void GetNamespaces(COpcStringMap& cNamespaces); - - // GetNamespacePrefix - COpcString GetNamespacePrefix(const COpcString& cNamespace); - - // FindElement - COpcXmlElement FindElement(const COpcString& cXPath); - - // FindElements - UINT FindElements(const COpcString& cXPath, COpcXmlElementList& cElements); - -protected: - - //========================================================================== - // Protected Methods - - // GetFilePath - const COpcString& GetFilePath() const { return m_cFilePath; } - - // SetFilePath - void SetFilePath(const COpcString& cFilePath) { m_cFilePath = cFilePath; } - -private: - - //========================================================================== - // Private Members - - COpcString m_cFilePath; - IXMLDOMDocument* m_ipDocument; -}; - -#endif // _COpcXmlDocument_H_ diff --git a/ComIOP/Wrapper/Common/COpcXmlElement.cpp b/ComIOP/Wrapper/Common/COpcXmlElement.cpp deleted file mode 100644 index fc97cd2fd..000000000 --- a/ComIOP/Wrapper/Common/COpcXmlElement.cpp +++ /dev/null @@ -1,1349 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "COpcXmlElement.h" -#include "COpcVariant.h" - -//============================================================================== -// Local Declarations - -#define TAG_TYPE _T("xsi:type") -#define TAG_ARRAY_TYPE _T("ArrayOf") - -//============================================================================== -// COpcXmlElement - -// Constructor -COpcXmlElement::COpcXmlElement(IUnknown* ipUnknown) -{ - m_ipElement = NULL; - *this = ipUnknown; -} - -// Copy Constructor -COpcXmlElement::COpcXmlElement(const COpcXmlElement& cElement) -{ - m_ipElement = NULL; - *this = cElement.m_ipElement; -} - -// Destructor -COpcXmlElement::~COpcXmlElement() -{ - if (m_ipElement != NULL) - { - m_ipElement->Release(); - m_ipElement = NULL; - } -} - -// Assignment -COpcXmlElement& COpcXmlElement::operator=(IUnknown* ipUnknown) -{ - if (m_ipElement != NULL) - { - m_ipElement->Release(); - m_ipElement = NULL; - } - - if (ipUnknown != NULL) - { - HRESULT hResult = ipUnknown->QueryInterface(__uuidof(IXMLDOMElement), (void**)&m_ipElement); - - if (FAILED(hResult)) - { - m_ipElement = NULL; - } - } - - return *this; -} - -// Assignment -COpcXmlElement& COpcXmlElement::operator=(const COpcXmlElement& cElement) -{ - if (this == &cElement) - { - return *this; - } - - *this = cElement.m_ipElement; - return *this; -} - -// GetName -COpcString COpcXmlElement::GetName() -{ - if (m_ipElement != NULL) - { - BSTR bstrName = NULL; - - HRESULT hResult = m_ipElement->get_nodeName(&bstrName); - OPC_ASSERT(SUCCEEDED(hResult)); - - COpcString cName = bstrName; - SysFreeString(bstrName); - - return cName; - } - - return (LPCWSTR)NULL; -} - -// GetPrefix -COpcString COpcXmlElement::GetPrefix() -{ - if (m_ipElement != NULL) - { - BSTR bstrName = NULL; - - HRESULT hResult = m_ipElement->get_prefix(&bstrName); - OPC_ASSERT(SUCCEEDED(hResult)); - - COpcString cName = bstrName; - SysFreeString(bstrName); - - return cName; - } - - return (LPCWSTR)NULL; -} - -// GetQualifiedName -OpcXml::QName COpcXmlElement::GetQualifiedName() -{ - OpcXml::QName cQName; - - if (m_ipElement != NULL) - { - BSTR bstrName = NULL; - - HRESULT hResult = m_ipElement->get_baseName(&bstrName); - OPC_ASSERT(SUCCEEDED(hResult)); - - cQName.SetName(bstrName); - cQName.SetNamespace(GetNamespace()); - - SysFreeString(bstrName); - } - - return cQName; -} - -// GetValue -COpcString COpcXmlElement::GetValue() -{ - BSTR bstrValue = NULL; - - HRESULT hResult = m_ipElement->get_text(&bstrValue); - OPC_ASSERT(SUCCEEDED(hResult)); - - COpcString cValue = bstrValue; - SysFreeString(bstrValue); - - return cValue; -} - -// SetValue -void COpcXmlElement::SetValue(const COpcString& cValue) -{ - BSTR bstrValue = SysAllocString((LPCWSTR)cValue); - - HRESULT hResult = m_ipElement->put_text(bstrValue); - OPC_ASSERT(SUCCEEDED(hResult)); - - SysFreeString(bstrValue); -} - -// GetAttribute -COpcXmlAttribute COpcXmlElement::GetAttribute(const COpcString& cName, const COpcString& cNamespace) -{ - COpcString cFullName = ResolveNamespace(cNamespace, m_ipElement); - - if (!cFullName.IsEmpty()) - { - cFullName += _T(":"); - } - - cFullName += cName; - - return GetAttribute(cFullName); -} - -// GetAttribute -COpcXmlAttribute COpcXmlElement::GetAttribute(const COpcString& cName) -{ - COpcXmlAttribute cAttribute; - - HRESULT hResult = S_OK; - - IXMLDOMNamedNodeMap* ipMap = NULL; - IXMLDOMNode* ipNode = NULL; - - BSTR bstrName = SysAllocString((LPCWSTR)cName); - - TRY - { - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_attributes(&ipMap); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = ipMap->getNamedItem(bstrName, &ipNode); - - if (FAILED(hResult)) - { - THROW(); - } - - if (hResult == S_OK) - { - cAttribute = ipNode; - } - } - CATCH_FINALLY - { - if (ipMap != NULL) ipMap->Release(); - if (ipNode != NULL) ipNode->Release(); - - SysFreeString(bstrName); - } - - return cAttribute; -} - -// GetAttributes -UINT COpcXmlElement::GetAttributes(COpcStringMap& cAttributes) -{ - HRESULT hResult = S_OK; - - IXMLDOMNamedNodeMap* ipMap = NULL; - - TRY - { - cAttributes.RemoveAll(); - - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_attributes(&ipMap); - - if (FAILED(hResult)) - { - THROW(); - } - - LONG lLength = 0; - hResult = ipMap->get_length(&lLength); - - for (LONG ii = 0; ii < lLength; ii++) - { - IXMLDOMNode* ipEntry = NULL; - ipMap->get_item(ii, &ipEntry); - - if (ipEntry != NULL) - { - IXMLDOMAttribute* ipAttribute = NULL; - ipEntry->QueryInterface(__uuidof(IXMLDOMAttribute), (void**)&ipAttribute); - - if (ipAttribute != NULL) - { - // get the name. - BSTR bsName = NULL; - ipAttribute->get_name(&bsName); - - // get the value. - VARIANT cVariant; OpcVariantInit(&cVariant); - if (FAILED(ipAttribute->get_value(&cVariant))) { OPC_ASSERT(false); } - - // add to table. - cAttributes[(COpcString)bsName] = (COpcString)cVariant.bstrVal; - - // free memory. - OpcVariantClear(&cVariant); - SysFreeString(bsName); - - // release object. - ipAttribute->Release(); - } - } - } - } - CATCH_FINALLY - { - if (ipMap != NULL) ipMap->Release(); - } - - return cAttributes.GetCount(); -} - -// GetAttributes -UINT COpcXmlElement::GetAttributes(COpcXmlAttributeList& cAttributes) -{ - HRESULT hResult = S_OK; - - IXMLDOMNamedNodeMap* ipMap = NULL; - - TRY - { - cAttributes.RemoveAll(); - - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_attributes(&ipMap); - - if (FAILED(hResult)) - { - THROW(); - } - - LONG lLength = 0; - hResult = ipMap->get_length(&lLength); - - for (LONG ii = 0; ii < lLength; ii++) - { - IXMLDOMNode* ipEntry = NULL; - ipMap->get_item(ii, &ipEntry); - - if (ipEntry != NULL) - { - IXMLDOMAttribute* ipAttribute = NULL; - ipEntry->QueryInterface(__uuidof(IXMLDOMAttribute), (void**)&ipAttribute); - - if (ipAttribute != NULL) - { - cAttributes.Append((COpcXmlAttribute)(ipAttribute)); - ipAttribute->Release(); - } - } - } - } - CATCH_FINALLY - { - if (ipMap != NULL) ipMap->Release(); - } - - return cAttributes.GetSize(); -} - -// SetAttribute -COpcXmlAttribute COpcXmlElement::SetAttribute(const COpcString& cName, const COpcString& cValue) -{ - COpcXmlAttribute cAttribute; - - HRESULT hResult = S_OK; - - IXMLDOMDocument* ipDocument = NULL; - IXMLDOMNamedNodeMap* ipMap = NULL; - IXMLDOMAttribute* ipAttribute = NULL; - IXMLDOMNode* ipNode = NULL; - - BSTR bstrName = SysAllocString((LPCWSTR)cName); - - TRY - { - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_attributes(&ipMap); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = m_ipElement->get_ownerDocument(&ipDocument); - - if (FAILED(hResult)) - { - THROW(); - } - - /* - VARIANT vNodeType; - vNodeType.vt = VT_I4; - vNodeType.lVal = NODE_ATTRIBUTE; - - hResult = ipDocument->createNode(vNodeType, bstrName, bstrNamespace, (IXMLDOMNode**)&ipAttribute); - */ - - hResult = ipDocument->createAttribute(bstrName, &ipAttribute); - - if (FAILED(hResult)) - { - THROW(); - } - - COpcVariant cVariant(cValue); - - hResult = ipAttribute->put_value(cVariant); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = ipMap->setNamedItem(ipAttribute, &ipNode); - - if (FAILED(hResult)) - { - THROW(); - } - - cAttribute = ipAttribute; - } - CATCH_FINALLY - { - if (ipDocument != NULL) ipDocument->Release(); - if (ipMap != NULL) ipMap->Release(); - if (ipAttribute != NULL) ipAttribute->Release(); - if (ipNode != NULL) ipNode->Release(); - - SysFreeString(bstrName); - } - - return cAttribute; -} - -// GetChildren -UINT COpcXmlElement::GetChildren(COpcXmlElementList& cChildren) -{ - HRESULT hResult = S_OK; - - IXMLDOMNodeList* ipList = NULL; - IXMLDOMNode* ipNode = NULL; - - TRY - { - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_childNodes(&ipList); - - if (FAILED(hResult)) - { - THROW(); - } - - long lLength = 0; - - hResult = ipList->get_length(&lLength); - - if (FAILED(hResult)) - { - THROW(); - } - - for (long ii = 0; ii < lLength; ii++) - { - hResult = ipList->get_item(ii, &ipNode); - - if (FAILED(hResult)) - { - THROW(); - } - - if (ipNode != NULL) - { - COpcXmlElement cChild(ipNode); - - ipNode->Release(); - ipNode = NULL; - - if (cChild != NULL) - { - cChildren.Append(cChild); - } - } - } - } - CATCH - { - cChildren.SetSize(0); - } - FINALLY - { - if (ipList != NULL) ipList->Release(); - } - - return cChildren.GetSize(); -} - -// GetChild -COpcXmlElement COpcXmlElement::GetChild(const COpcString& cName) -{ - COpcXmlElement cElement; - - HRESULT hResult = S_OK; - - IXMLDOMNodeList* ipList = NULL; - IXMLDOMNode* ipNode = NULL; - - TRY - { - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_childNodes(&ipList); - - if (FAILED(hResult)) - { - THROW(); - } - - long lLength = 0; - - hResult = ipList->get_length(&lLength); - - if (FAILED(hResult)) - { - THROW(); - } - - for (long ii = 0; ii < lLength; ii++) - { - hResult = ipList->get_item(ii, &ipNode); - - if (FAILED(hResult)) - { - THROW(); - } - - if (ipNode != NULL) - { - cElement = ipNode; - - ipNode->Release(); - ipNode = NULL; - - if (cElement.GetName() == cName) - { - break; - } - } - - cElement = NULL; - } - } - CATCH_FINALLY - { - if (ipList != NULL) ipList->Release(); - if (ipNode != NULL) ipNode->Release(); - } - - return cElement; -} - -// GetChild -COpcXmlElement COpcXmlElement::GetChild(UINT uIndex) -{ - COpcXmlElement cElement; - - HRESULT hResult = S_OK; - - IXMLDOMNodeList* ipList = NULL; - IXMLDOMNode* ipNode = NULL; - - TRY - { - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_childNodes(&ipList); - - if (FAILED(hResult)) - { - THROW(); - } - - long lLength = 0; - - hResult = ipList->get_length(&lLength); - - if (FAILED(hResult)) - { - THROW(); - } - - if (lLength <= (long)uIndex) - { - THROW_(hResult, E_FAIL); - } - - hResult = ipList->get_item((long)uIndex, &ipNode); - - if (FAILED(hResult)) - { - THROW(); - } - - cElement = ipNode; - } - CATCH_FINALLY - { - if (ipList != NULL) ipList->Release(); - if (ipNode != NULL) ipNode->Release(); - } - - return cElement; -} - -// GetNamespace -COpcString COpcXmlElement::GetNamespace(IXMLDOMElement* ipElement) -{ - COpcXmlElement cElement; - - BSTR bstrNamespace = NULL; - IXMLDOMElement* ipParent = NULL; - - COpcString cNamespace; - - TRY - { - if (ipElement == NULL) - { - THROW(); - } - - HRESULT hResult = ipElement->get_namespaceURI(&bstrNamespace); - - if (FAILED(hResult)) - { - THROW(); - } - - cNamespace = bstrNamespace; - - if (cNamespace.IsEmpty()) - { - hResult = ipElement->get_parentNode((IXMLDOMNode**)&ipParent); - - if (FAILED(hResult)) - { - THROW(); - } - - cNamespace = GetNamespace(ipParent); - } - } - CATCH_FINALLY - { - SysFreeString(bstrNamespace); - if (ipParent != NULL) ipParent->Release(); - } - - return cNamespace; -} - -// GetNamespace -COpcString COpcXmlElement::GetNamespace() -{ - return GetNamespace(m_ipElement); -} - -// AddChild -COpcXmlElement COpcXmlElement::AddChild(const COpcString& cName) -{ - OpcXml::QName cQName(cName, ResolvePrefix("")); - return AddChild(cQName); -} - -// AddChild -COpcXmlElement COpcXmlElement::AddChild(const OpcXml::QName& cName) -{ - COpcXmlElement cElement; - - HRESULT hResult = S_OK; - - IXMLDOMDocument* ipDocument = NULL; - IXMLDOMNode* ipOldChild = NULL; - IXMLDOMElement* ipNewChild = NULL; - IXMLDOMNode* ipResult = NULL; - - COpcString cFullName = ResolveNamespace(cName.GetNamespace()); - - if (!cFullName.IsEmpty()) - { - cFullName += _T(":"); - } - - cFullName += cName.GetName(); - - BSTR bstrName = SysAllocString((LPCWSTR)cFullName); - BSTR bstrNamespace = SysAllocString((LPCWSTR)cName.GetNamespace()); - - TRY - { - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_ownerDocument(&ipDocument); - - if (FAILED(hResult)) - { - THROW(); - } - - VARIANT vNodeType; - vNodeType.vt = VT_I4; - vNodeType.lVal = NODE_ELEMENT; - - hResult = ipDocument->createNode(vNodeType, bstrName, bstrNamespace, (IXMLDOMNode**)&ipNewChild); - - if (FAILED(hResult)) - { - THROW(); - } - - COpcXmlElement cOldChild = GetChild(cFullName); - - if (cOldChild == NULL) - { - hResult = m_ipElement->appendChild(ipNewChild, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - } - - else - { - hResult = ((IXMLDOMElement*)cOldChild)->QueryInterface(__uuidof(IXMLDOMNode), (void**)&ipOldChild); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = m_ipElement->replaceChild(ipNewChild, ipOldChild, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - } - - cElement = ipNewChild; - } - CATCH_FINALLY - { - if (ipDocument != NULL) ipDocument->Release(); - if (ipOldChild != NULL) ipOldChild->Release(); - if (ipNewChild != NULL) ipNewChild->Release(); - if (ipResult != NULL) ipResult->Release(); - - SysFreeString(bstrName); - SysFreeString(bstrNamespace); - } - - return cElement; -} - -// AppendChild -COpcXmlElement COpcXmlElement::AppendChild(const COpcString& cName) -{ - OpcXml::QName cQName(cName, ResolvePrefix("")); - return AppendChild(cQName); -} - -// AppendChild -COpcXmlElement COpcXmlElement::AppendChild(const OpcXml::QName& cName) -{ - COpcXmlElement cElement; - - HRESULT hResult = S_OK; - - IXMLDOMDocument* ipDocument = NULL; - IXMLDOMElement* ipNewChild = NULL; - IXMLDOMNode* ipResult = NULL; - - COpcString cFullName = ResolveNamespace(cName.GetNamespace()); - - if (!cFullName.IsEmpty()) - { - cFullName += _T(":"); - } - - cFullName += cName.GetName(); - - BSTR bstrName = SysAllocString((LPCWSTR)cFullName); - BSTR bstrNamespace = SysAllocString((LPCWSTR)cName.GetNamespace()); - - TRY - { - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_ownerDocument(&ipDocument); - - if (FAILED(hResult)) - { - THROW(); - } - - VARIANT vNodeType; - vNodeType.vt = VT_I4; - vNodeType.lVal = NODE_ELEMENT; - - hResult = ipDocument->createNode(vNodeType, bstrName, bstrNamespace, (IXMLDOMNode**)&ipNewChild); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = m_ipElement->appendChild(ipNewChild, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - - cElement = ipNewChild; - } - CATCH_FINALLY - { - if (ipDocument != NULL) ipDocument->Release(); - if (ipNewChild != NULL) ipNewChild->Release(); - if (ipResult != NULL) ipResult->Release(); - - SysFreeString(bstrName); - SysFreeString(bstrNamespace); - } - - return cElement; -} - -// AppendChild -bool COpcXmlElement::AppendChild(IXMLDOMElement* ipElement) -{ - HRESULT hResult = S_OK; - - IXMLDOMElement* ipClone = NULL; - IXMLDOMNode* ipParent = NULL; - IXMLDOMNode* ipResult = NULL; - - TRY - { - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - // clone the element. - hResult = ipElement->cloneNode(VARIANT_TRUE, (IXMLDOMNode**)&ipClone); - - if (FAILED(hResult)) - { - THROW(); - } - - // remove clone from parent. - hResult = ipClone->get_parentNode(&ipParent); - - if (FAILED(hResult)) - { - THROW(); - } - - if (ipParent != NULL) - { - hResult = ipParent->removeChild(ipClone, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - - if (ipResult != NULL) - { - ipResult->Release(); - ipResult = NULL; - } - } - - // add root element to document. - hResult = m_ipElement->appendChild(ipClone, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - - if (ipResult != NULL) - { - ipResult->Release(); - ipResult = NULL; - } - } - CATCH_FINALLY - { - // release memory. - if (ipClone != NULL) ipClone->Release(); - if (ipParent != NULL) ipParent->Release(); - if (ipResult != NULL) ipResult->Release(); - } - - return SUCCEEDED(hResult); -} - - -// AppendText -void COpcXmlElement::AppendText(const COpcString& cText) -{ - HRESULT hResult = S_OK; - - IXMLDOMDocument* ipDocument = NULL; - IXMLDOMText* ipNewChild = NULL; - IXMLDOMNode* ipResult = NULL; - - BSTR bstrText = SysAllocString((LPCWSTR)cText); - - TRY - { - if (m_ipElement == NULL) - { - THROW_(hResult, E_POINTER); - } - - hResult = m_ipElement->get_ownerDocument(&ipDocument); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = ipDocument->createTextNode(bstrText, &ipNewChild); - - if (FAILED(hResult)) - { - THROW(); - } - - hResult = m_ipElement->appendChild(ipNewChild, &ipResult); - - if (FAILED(hResult)) - { - THROW(); - } - } - CATCH_FINALLY - { - if (ipDocument != NULL) ipDocument->Release(); - if (ipNewChild != NULL) ipNewChild->Release(); - if (ipResult != NULL) ipResult->Release(); - - SysFreeString(bstrText); - } -} - -/* -// GetType -bool COpcXmlElement::GetType(OpcXml::Type& eType) -{ - eType = OpcXml::XML_EMPTY; - - if (m_ipElement == NULL) - { - return false; - } - - COpcXmlAttribute cAttribute = GetAttribute(TAG_TYPE); - - if (cAttribute == NULL) - { - return false; - } - - return OpcXml::Read(cAttribute.GetValue(), eType); -} - -// SetType -bool COpcXmlElement::SetType(OpcXml::Type eType) -{ - if (m_ipElement == NULL || eType == OpcXml::XML_EMPTY) - { - return false; - } - - COpcString cText; - - if (!OpcXml::Write(eType, cText)) - { - return false; - } - - COpcXmlAttribute cAttribute = SetAttribute(TAG_TYPE, cText); - - if (cAttribute == NULL) - { - return false; - } - - return true; -} - -// GetArrayType -bool COpcXmlElement::GetArrayType(OpcXml::Type& eType) -{ - eType = OpcXml::XML_EMPTY; - - if (m_ipElement == NULL) - { - return false; - } - - COpcXmlAttribute cAttribute = GetAttribute(TAG_TYPE); - - if (cAttribute == NULL) - { - return false; - } - - COpcString cText = cAttribute.GetValue(); - - UINT uIndex = cText.Find(TAG_ARRAY_TYPE); - - if (uIndex != 0) - { - return false; - } - - // remove prefix and set first letter to lower case. - cText = cText.SubStr(_tcslen(TAG_ARRAY_TYPE)).ToLower(0); - - return OpcXml::Read(cText, eType); -} - -// SetArrayType -bool COpcXmlElement::SetArrayType(OpcXml::Type eType) -{ - if (m_ipElement == NULL || eType == OpcXml::XML_EMPTY) - { - return false; - } - - COpcString cText; - - if (!OpcXml::Write(eType, cText)) - { - return false; - } - - // remove the xsd prefix. - int iIndex = cText.Find(_T("xsd:")); - - if (iIndex == 0) - { - cText = cText.SubStr(4); - } - - // set first letter to upper case and prepend prefix. - cText = cText.ToUpper(0); - cText = TAG_ARRAY_TYPE + cText; - - COpcXmlAttribute cAttribute = SetAttribute(TAG_TYPE, cText); - - if (cAttribute == NULL) - { - return false; - } - - return true; -} -*/ - -// ResolvePrefix -COpcString COpcXmlElement::ResolvePrefix(const COpcString& cPrefix) -{ - return ResolvePrefix(cPrefix, m_ipElement); -} - -// ResolvePrefix -COpcString COpcXmlElement::ResolvePrefix(const COpcString& cPrefix, IXMLDOMNode* ipNode) -{ - if (ipNode == NULL) - { - return (LPCWSTR)NULL; - } - - COpcXmlElement cElement(ipNode); - - // compare the search prefix to the prefix for the current element. - if (cElement.GetPrefix() == cPrefix) - { - return cElement.GetNamespace(); - } - - COpcXmlAttributeList cAttributes; - - if (cElement.GetAttributes(cAttributes) > 0) - { - for (UINT ii = 0; ii < cAttributes.GetSize(); ii++) - { - if (cAttributes[ii].GetPrefix() == OPCXML_NAMESPACE_ATTRIBUTE) - { - if (cAttributes[ii].GetQualifiedName().GetName() == cPrefix) - { - return cAttributes[ii].GetValue(); - } - } - } - } - - IXMLDOMNode* ipParent = NULL; - - HRESULT hResult = ipNode->get_parentNode(&ipParent); - - if (FAILED(hResult)) - { - return (LPCWSTR)NULL; - } - - DOMNodeType nodeType = NODE_ELEMENT; - - if (ipParent != NULL) - { - hResult = ipParent->get_nodeType(&nodeType); - - if (FAILED(hResult)) - { - return (LPCWSTR)NULL; - } - } - - // search in parent element for namespace. - if (ipParent != NULL && nodeType == NODE_ELEMENT) - { - COpcString cNamespace = ResolvePrefix(cPrefix, ipParent); - ipParent->Release(); - return cNamespace; - } - - return (LPCWSTR)NULL; -} - -// ResolveNamespace -COpcString COpcXmlElement::ResolveNamespace(const COpcString& cNamespace) -{ - return ResolveNamespace(cNamespace, m_ipElement); -} - -// ResolveNamespace -COpcString COpcXmlElement::ResolveNamespace(const COpcString& cNamespace, IXMLDOMNode* ipNode) -{ - if (ipNode == NULL) - { - return (LPCWSTR)NULL; - } - - COpcXmlElement cElement(ipNode); - - // check element namespace. - if (cElement.GetNamespace() == cNamespace) - { - return cElement.GetPrefix(); - } - - // check for additional namespace declarations on the element. - COpcXmlAttributeList cAttributes; - - if (cElement.GetAttributes(cAttributes) > 0) - { - for (UINT ii = 0; ii < cAttributes.GetSize(); ii++) - { - if (cAttributes[ii].GetPrefix() == OPCXML_NAMESPACE_ATTRIBUTE) - { - if (cAttributes[ii].GetValue() == cNamespace) - { - return cAttributes[ii].GetQualifiedName().GetName(); - } - } - } - } - - IXMLDOMNode* ipParent = NULL; - - HRESULT hResult = ipNode->get_parentNode(&ipParent); - - if (FAILED(hResult)) - { - return (LPCWSTR)NULL; - } - - DOMNodeType nodeType = NODE_ELEMENT; - - if (ipParent != NULL) - { - hResult = ipParent->get_nodeType(&nodeType); - - if (FAILED(hResult)) - { - return (LPCWSTR)NULL; - } - } - - // search in parent element for namespace. - if (ipParent != NULL && nodeType == NODE_ELEMENT) - { - COpcString cPrefix = ResolveNamespace(cNamespace, ipParent); - ipParent->Release(); - return cPrefix; - } - - // find unused prefix. - COpcString cPrefix; - - for (int ii = 0; cPrefix.IsEmpty(); ii++) - { - TCHAR tsBuf[16]; - _stprintf(tsBuf, _T("s%d"), ii); - cPrefix = tsBuf; - - if (!ResolvePrefix(cPrefix, ipNode).IsEmpty()) - { - cPrefix.Empty(); - } - } - - // add namespace to current element. - COpcString cAttributeName; - - cAttributeName += OPCXML_NAMESPACE_ATTRIBUTE; - cAttributeName += _T(":"); - cAttributeName += cPrefix; - - cElement.SetAttribute(cAttributeName, cNamespace); - - return cPrefix; -} - -// GetType -bool COpcXmlElement::GetType(OpcXml::QName& cType) -{ - // construct the name of the XML schema type attribute. - COpcString cFullName = ResolveNamespace(OPCXML_NS_SCHEMA_INSTANCE); - - if (!cFullName.IsEmpty()) - { - cFullName += _T(":"); - } - - cFullName += OPCXML_TYPE_ATTRIBUTE; - - // get the type attribute. - COpcXmlAttribute cAttribute = GetAttribute(cFullName); - - if (cAttribute == NULL) - { - return false; - } - - // parse attribute value to find the namespace of the type. - COpcString cPrefix; - COpcString cTypeName = cAttribute.GetValue(); - - if (cTypeName.IsEmpty()) - { - return false; - } - - int iIndex = cTypeName.Find(_T(":")); - - if (iIndex != -1) - { - cPrefix = cTypeName.SubStr(0, iIndex); - cTypeName = cTypeName.SubStr(iIndex+1); - } - - // set the type name and namespace. - cType.SetName(cTypeName); - cType.SetNamespace(ResolvePrefix(cPrefix)); - - return true; -} - -// SetType -void COpcXmlElement::SetType(OpcXml::QName cType) -{ - // check for trivial case. - if (cType.GetName().IsEmpty()) - { - return; - } - - // construct the name of the XML schema type attribute. - COpcString cFullName = ResolveNamespace(OPCXML_NS_SCHEMA_INSTANCE); - - if (!cFullName.IsEmpty()) - { - cFullName += _T(":"); - } - - cFullName += OPCXML_TYPE_ATTRIBUTE; - - // construct the name of the type. - COpcString cTypeName = ResolveNamespace(cType.GetNamespace()); - - if (!cTypeName.IsEmpty()) - { - cTypeName += _T(":"); - } - - cTypeName += cType.GetName(); - - // update the type attribute. - SetAttribute(cFullName, cTypeName); -} diff --git a/ComIOP/Wrapper/Common/COpcXmlElement.h b/ComIOP/Wrapper/Common/COpcXmlElement.h deleted file mode 100644 index cdad99e9a..000000000 --- a/ComIOP/Wrapper/Common/COpcXmlElement.h +++ /dev/null @@ -1,222 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _COpcXmlElement_H_ -#define _COpcXmlElement_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "COpcString.h" -#include "COpcMap.h" -#include "COpcArray.h" -#include "OpcXmlType.h" -#include "COpcXmlAttribute.h" - -class COpcXmlElement; - -//============================================================================== -// TYPE: COpcXmlElementList -// PURPOSE: A list of elements. - -typedef COpcArray COpcXmlElementList; - -//============================================================================== -// CLASS: COpcXmlElement -// PURPOSE Facilitiates manipulation of XML Elements, - -class OPCUTILS_API COpcXmlElement -{ - OPC_CLASS_NEW_DELETE_ARRAY(); - -public: - - //========================================================================== - // Public Operators - - // Constructor - COpcXmlElement(IUnknown* ipUnknown = NULL); - - // Copy Constructor - COpcXmlElement(const COpcXmlElement& cElement); - - // Destructor - ~COpcXmlElement(); - - // Assignment - COpcXmlElement& operator=(IUnknown* ipUnknown); - COpcXmlElement& operator=(const COpcXmlElement& cElement); - - // Accessor - operator IXMLDOMElement*() const { return m_ipElement; } - - //========================================================================== - // Public Methods - - // GetName - COpcString GetName(); - - // GetPrefix - COpcString GetPrefix(); - - // GetNamespace - COpcString GetNamespace(); - - // GetQualifiedName - OpcXml::QName GetQualifiedName(); - - // Value - COpcString GetValue(); - void SetValue(const COpcString& cValue); - - // Type - bool GetType(OpcXml::QName& cType); - void SetType(OpcXml::QName cType); - - // GetAttribute - COpcXmlAttribute GetAttribute(const COpcString& cName); - - // GetAttribute - COpcXmlAttribute GetAttribute(const COpcString& cName, const COpcString& cNamespace); - - // GetAttributes - UINT GetAttributes(COpcStringMap& cAttributes); - - // GetAttributes - UINT GetAttributes(COpcXmlAttributeList& cAttributes); - - // SetAttribute - COpcXmlAttribute SetAttribute(const COpcString& cName, const COpcString& cValue); - - // GetChild - COpcXmlElement GetChild(const COpcString& cName); - - // GetChild - COpcXmlElement GetChild(UINT uIndex); - - // GetChildren - UINT GetChildren(COpcXmlElementList& cElements); - - // AddChild - COpcXmlElement AddChild(const COpcString& cName); - COpcXmlElement AddChild(const OpcXml::QName& cName); - - // AppendChild - COpcXmlElement AppendChild(const COpcString& cName); - COpcXmlElement AppendChild(const OpcXml::QName& cName); - - // AppendChild - bool AppendChild(IXMLDOMElement* ipElement); - - // AppendText - void AppendText(const COpcString& cText); - - // ResolvePrefix - COpcString ResolvePrefix(const COpcString& cPrefix); - - // ResolveNamespace - COpcString ResolveNamespace(const COpcString& cNamespace); - -private: - - //========================================================================== - // Private Methods - - // GetNamespace - COpcString GetNamespace(IXMLDOMElement* ipElement); - - // ResolvePrefix - COpcString ResolvePrefix(const COpcString& cPrefix, IXMLDOMNode* ipNode); - - // ResolveNamespace - COpcString ResolveNamespace(const COpcString& cNamespace, IXMLDOMNode* ipNode); - - //========================================================================== - // Private Members - - IXMLDOMElement* m_ipElement; -}; - -//============================================================================== -// INTERFACE: IOpcXmlSerialize -// PURPOSE Defines standard XML serialization methods for an object. - -interface IOpcXmlSerialize -{ -public: - - // Init - virtual void Init() = 0; - - // Clear - virtual void Clear() = 0; - - // Read - virtual bool Read(COpcXmlElement& cElement) = 0; - - // Write - virtual bool Write(COpcXmlElement& cElement) = 0; -}; - -//============================================================================== -// MACRO: READ_XXX/WRITE_XXX -// PURPOSE Facilitiate implementation of XML serialization code, - -#define READ_ATTRIBUTE(xName, xValue) OpcXml::ReadXml(cElement.GetAttribute(xName), xValue); - -#define READ_DEFAULT_ATTRIBUTE(xName, xValue, xDefault) \ -if (!OpcXml::ReadXml(cElement.GetAttribute(xName), xValue)) \ -{ \ - xValue = xDefault; \ -} - -#define READ_OPTIONAL_ATTRIBUTE(xName, xValue) \ -if (!OpcXml::ReadXml(cElement.GetAttribute(xName), xValue)) \ -{ \ - OpcXml::Init(xValue); \ - xValue##Specified = false; \ -} \ -else \ -{ \ - xValue##Specified = true; \ -} - -#define WRITE_ATTRIBUTE(xName, xValue) {COpcString cText; if (OpcXml::Write(xValue, cText)) {cElement.SetAttribute(xName, cText);}} - -#define READ_ELEMENT(xName, xValue) OpcXml::ReadXml(cElement.GetChild(xName), xValue); -#define WRITE_ELEMENT(xName, xValue) OpcXml::WriteXml(cElement.AddChild(xName), xValue); - -#define READ_ATTRIBUTE_EX(xName, xValue, xAction) if (!OpcXml::ReadXml(cElement.GetAttribute(xName), xValue)) { xAction; } -#define WRITE_ATTRIBUTE_EX(xName, xValue, xAction) { COpcString cText; if (!OpcXml::Write(xValue, cText)) {xAction;} if (cElement.SetAttribute(xName, cText) == NULL) {xAction;}} - -#define READ_ELEMENT_EX(xName, xValue, xAction) if (!OpcXml::ReadXml(cElement.GetChild(xName), xValue)) {xAction;} -#define WRITE_ELEMENT_EX(xName, xValue, xAction) if (!OpcXml::WriteXml(cElement.AddChild(xName), xValue)) {xAction;} - -#endif // _COpcXmlElement_H_ diff --git a/ComIOP/Wrapper/Common/OPC Sample Utility Classes.vcxproj b/ComIOP/Wrapper/Common/OPC Sample Utility Classes.vcxproj deleted file mode 100644 index 31f5712dd..000000000 --- a/ComIOP/Wrapper/Common/OPC Sample Utility Classes.vcxproj +++ /dev/null @@ -1,328 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - UA COM Server Class Library - {268AE545-D614-4B66-AEF3-C5B85919AD9D} - OPC Sample Utility Classes - 10.0 - - - - StaticLibrary - v143 - false - Unicode - - - StaticLibrary - v143 - false - Unicode - - - - - - - - - - - - - <_ProjectFileVersion>12.0.30501.0 - - - ..\..\bin\Release\ - $(OutDir)intermediate\$(ProjectName)\ - OpcComServer - - - ..\..\bin\Debug\ - $(OutDir)intermediate\$(ProjectName)\ - OpcComServer - - - - - - - OnlyExplicitInline - ..\Include;..\..\..\Include;$(CommonProgramFiles)\OPC Foundation\Include;%(AdditionalIncludeDirectories) - NDEBUG;WIN32;_LIB;_WIN32_DCOM;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions) - true - true - false - Use - StdAfx.h - Level3 - true - Default - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)OpcComServer.lib - true - - - - - - - - Disabled - ..\Include;..\..\..\Include;$(OutDir);%(AdditionalIncludeDirectories) - _DEBUG;WIN32;_LIB;_WIN32_DCOM;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - false - Use - StdAfx.h - Level3 - true - ProgramDatabase - Default - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)OpcComServer.lib - true - - - $(OutDir)docs\$(TargetName).xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ComIOP/Wrapper/Common/OpcCategory.cpp b/ComIOP/Wrapper/Common/OpcCategory.cpp deleted file mode 100644 index 9f66abc30..000000000 --- a/ComIOP/Wrapper/Common/OpcCategory.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "OpcCategory.h" -#include "OpcRegistry.h" - -//============================================================================== -// Define category ids that require special handling. - -#define LOCAL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} - -LOCAL_DEFINE_GUID(CLSID, CATID_OPCDAServer10, 0x63D5F430, 0xCFE4, 0x11d1, 0xB2,0xC8,0x00,0x60,0x08,0x3B,0xA1,0xFB); -LOCAL_DEFINE_GUID(CLSID, CATID_OPCDAServer20, 0x63D5F432, 0xCFE4, 0x11d1, 0xB2,0xC8,0x00,0x60,0x08,0x3B,0xA1,0xFB); - -// OpcEnumServersInCategory -HRESULT OpcEnumServersInCategory( - LPCTSTR tsHostName, - const CATID& tCategory, - COpcList* pServers -) -{ - HRESULT hResult = S_OK; - - IOPCServerList* ipInfo = NULL; - IEnumGUID* ipEnumClsid = NULL; - - COSERVERINFO tInfo; - memset(&tInfo, 0, sizeof(tInfo)); - - MULTI_QI tInterfaces; - memset(&tInterfaces, 0, sizeof(tInterfaces)); - - TRY - { - // invalid arguments - generate error. - if (pServers == NULL) - { - hResult = E_INVALIDARG; - THROW(); - } - - // lookup clsid for OpcEnum server. - CLSID cClsid = GUID_NULL; - - hResult = CLSIDFromProgID(L"OPC.ServerList.1", &cClsid); - - if (FAILED(hResult)) - { - THROW(); - } - - tInfo.pwszName = OpcStrDup((LPCWSTR)(COpcString)tsHostName); - tInterfaces.pIID = &__uuidof(IOPCServerList); - - // create the remote component category manager. - hResult = CoCreateInstanceEx( - cClsid, - NULL, - CLSCTX_SERVER, - &tInfo, - 1, - &tInterfaces - ); - - if (FAILED(hResult) || FAILED(tInterfaces.hr)) - { - THROW(); - } - - ipInfo = (IOPCServerList*)tInterfaces.pItf; - - // enumerate - hResult = ipInfo->EnumClassesOfCategories( - 1, - (CATID*)&tCategory, - 0, - NULL, - &ipEnumClsid - ); - - if (FAILED(hResult)) - { - THROW(); - } - - // copy clsids into return parameter. - pServers->RemoveAll(); - - do - { - ULONG ulFetched = 0; - CLSID tClsid = GUID_NULL; - - hResult = ipEnumClsid->Next(1, &tClsid, &ulFetched); - - if (ulFetched == 1) - { - pServers->AddTail(tClsid); - } - } - while (hResult == S_OK); - - // error while enumerating clsids. - if (FAILED(hResult)) - { - THROW(); - } - } - CATCH - { - if (pServers != NULL) pServers->RemoveAll(); - } - FINALLY - { - if (ipEnumClsid != NULL) ipEnumClsid->Release(); - if (ipInfo != NULL) ipInfo->Release(); - } - - return hResult; -} - -// RegisterClsidInCategory -HRESULT RegisterClsidInCategory(REFCLSID clsid, CATID catid, LPCWSTR szDescription) -{ - HRESULT hResult = S_OK; - - ICatRegister* ipRegister = NULL; - ICatInformation* ipInfo = NULL; - - CoInitialize(NULL); - - TRY - { - // invalid arguments - generate error. - if (catid == GUID_NULL) - { - hResult = E_INVALIDARG; - THROW(); - } - - // create component category manager. - hResult = CoCreateInstance( - CLSID_StdComponentCategoriesMgr, - NULL, - CLSCTX_INPROC_SERVER, - IID_ICatRegister, - (void**)&ipRegister - ); - - if (FAILED(hResult)) - { - THROW(); - } - - // create category - CATEGORYINFO pInfo[1]; - - pInfo[0].catid = catid; - pInfo[0].lcid = LOCALE_USER_DEFAULT; - pInfo[0].szDescription[0] = L'\0'; - - if (szDescription != NULL) - { - _tcsncpy(pInfo[0].szDescription, szDescription, 127); - } - - hResult = ipRegister->RegisterCategories(1, pInfo); - - if (FAILED(hResult)) - { - THROW(); - } - - // create register class in category. - hResult = ipRegister->RegisterClassImplCategories(clsid, 1, &catid); - - if (FAILED(hResult)) - { - THROW(); - } - - // create OPC subkey for DA1.0 and DA2.0 servers. - if (catid == CATID_OPCDAServer10 || catid == CATID_OPCDAServer20) - { - LPWSTR szProgID = NULL; - - if (SUCCEEDED(ProgIDFromCLSID(clsid, &szProgID))) - { - COpcString cSubKey; - cSubKey += szProgID; - cSubKey += _T("\\OPC"); - - OpcRegSetValue(HKEY_CLASSES_ROOT, cSubKey, _T(""), _T("")); - OpcFree(szProgID); - } - } - } - CATCH - { - } - FINALLY - { - if (ipRegister != NULL) ipRegister->Release(); - } - - CoUninitialize(); - - return hResult; -} - -// UnregisterClsidInCategory -HRESULT UnregisterClsidInCategory(REFCLSID clsid, CATID catid) -{ - HRESULT hResult = S_OK; - - ICatRegister* ipRegister = NULL; - - CoInitialize(NULL); - - TRY - { - // invalid arguments - generate error. - if (catid == GUID_NULL) - { - hResult = E_INVALIDARG; - THROW(); - } - - // remove OPC subkey for DA1.0 and DA2.0 servers. - if (catid == CATID_OPCDAServer10 || catid == CATID_OPCDAServer20) - { - LPWSTR szProgID = NULL; - - if (SUCCEEDED(ProgIDFromCLSID(clsid, &szProgID))) - { - COpcString cSubKey; - cSubKey += szProgID; - cSubKey += _T("\\OPC"); - - OpcRegDeleteKey(HKEY_CLASSES_ROOT, cSubKey); - OpcFree(szProgID); - } - } - - // create component category manager. - hResult = CoCreateInstance( - CLSID_StdComponentCategoriesMgr, - NULL, - CLSCTX_INPROC_SERVER, - IID_ICatRegister, - (void**)&ipRegister - ); - - if (FAILED(hResult)) - { - THROW(); - } - - // create category. - hResult = ipRegister->UnRegisterClassImplCategories(clsid, 1, &catid); - - if (FAILED(hResult)) - { - THROW(); - } - } - CATCH - { - } - FINALLY - { - if (ipRegister != NULL) ipRegister->Release(); - } - - CoUninitialize(); - - return hResult; -} diff --git a/ComIOP/Wrapper/Common/OpcCategory.h b/ComIOP/Wrapper/Common/OpcCategory.h deleted file mode 100644 index f76b5630e..000000000 --- a/ComIOP/Wrapper/Common/OpcCategory.h +++ /dev/null @@ -1,92 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _OpcCategory_H_ -#define _OpcCategory_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcComObject.h" -#include "COpcList.h" - -//============================================================================== -// FUNCTION: OpcEnumServers -// PURPOSE: Enumerates servers in the specified category on the host. - -// OpcEnumServers -OPCUTILS_API HRESULT OpcEnumServersInCategory( - LPCTSTR tsHostName, - const CATID& tCategory, - COpcList* pServers -); - -//============================================================================== -// FUNCTION: RegisterClsidInCategory -// PURPOSE: Registers a CLSID as belonging to a component category. - -HRESULT RegisterClsidInCategory(REFCLSID clsid, CATID catid, LPCWSTR szDescription) ; - -//============================================================================== -// FUNCTION: UnregisterClsidInCategory -// PURPOSE: Unregisters a CLSID as belonging to a component category. -HRESULT UnregisterClsidInCategory(REFCLSID clsid, CATID catid); - -//============================================================================== -// STRUCT: TClassCategories -// PURPOSE: Associates a clsid with a component category. - -struct TClassCategories -{ - const CLSID* pClsid; - const CATID* pCategory; - const TCHAR* szDescription; -}; - -//============================================================================== -// MACRO: OPC_BEGIN_CATEGORY_TABLE -// PURPOSE: Begins the module class category table. - -#define OPC_BEGIN_CATEGORY_TABLE() static const TClassCategories g_pCategoryTable[] = { - -//============================================================================== -// MACRO: OPC_CATEGORY_TABLE_ENTRY -// PURPOSE: An entry in the module class category table. - -#define OPC_CATEGORY_TABLE_ENTRY(xClsid, xCatid, xDescription) {&(__uuidof(xClsid)), &(xCatid), (xDescription)}, - -//============================================================================== -// MACRO: OPC_END_CATEGORY_TABLE -// PURPOSE: Ends the module class category table. - -#define OPC_END_CATEGORY_TABLE() {NULL, NULL, NULL}}; - -#endif // _OpcCategory_H_ diff --git a/ComIOP/Wrapper/Common/OpcDefs.h b/ComIOP/Wrapper/Common/OpcDefs.h deleted file mode 100644 index 75ddf2c47..000000000 --- a/ComIOP/Wrapper/Common/OpcDefs.h +++ /dev/null @@ -1,255 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _OpcDefs_H_ -#define _OpcDefs_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include -#include - -//============================================================================== -// MACRO: OPC_ASSERT -// PURPOSE: Halts program execution if condition is not met. - -#ifdef _DEBUG -#define OPC_ASSERT(x) _ASSERTE(x) -#else -#define OPC_ASSERT(x) -#endif - -//============================================================================== -// MACRO: TRY, LEAVE. FINALLY -// PURPOSE: Macros to facilitate cleanup after error conditions. - -#pragma warning(disable: 4102) - -#ifndef OPC_NO_EXCEPTIONS - -#define TRY try -#define CATCH catch (DWORD) -#define CATCH_FINALLY catch (DWORD) {} finally: -#define FINALLY finally: -#define THROW() throw (DWORD)0; -#define THROW_(xResult, xValue) { (xResult) = (xValue); throw (DWORD)0; } -#define GOTOFINALLY() goto finally; - -#else - -#define TRY { -#define CATCH } goto finally; onerror: -#define CATCH_FINALLY onerror: finally: -#define FINALLY finally: -#define THROW() goto onerror; -#define THROW_(xResult, xValue) { (xResult) = (xValue); goto onerror; } -#define GOTOFINALLY() goto finally; - -#endif - -//============================================================================== -// FUNCTION: OpcAlloc -// PURPOSE: Allocates a block of memory. - -OPCUTILS_API void* OpcAlloc(size_t tSize); - -//============================================================================== -// FUNCTION: OpcFree -// PURPOSE: Frees a block of memory. - -OPCUTILS_API void OpcFree(void* pBlock); - -//============================================================================== -// MACRO: OpcArrayAlloc -// PURPOSE: Allocates an array of simple data (i.e. not classes). - -#define OpcArrayAlloc(xType,xLength) (xType*)OpcAlloc((xLength)*sizeof(xType)) - -//============================================================================== -// FUNCTION: OpcStrDup -// PURPOSE: Duplicates a string. - -OPCUTILS_API CHAR* OpcStrDup(LPCSTR szValue); -OPCUTILS_API WCHAR* OpcStrDup(LPCWSTR szValue); - -//============================================================================== -// FUNCTION: OpcArrayDup -// PURPOSE: Duplicates an array of types (bitwise copy must be valid). - -#define OpcArrayDup(xCopy, xType, xLength, xValue) \ -{ \ - UINT uLength = (xLength)*sizeof(xType); \ - xCopy = (xType*)OpcAlloc(uLength); \ - \ - if (xValue != NULL) memcpy(xCopy, xValue, uLength); \ - else memset(xCopy, 0, uLength); \ -} - -//============================================================================== -// MACRO: OPC_CLASS_NEW_DELETE -// PURPOSE: Implements a class new and delete operators. - -#define OPC_CLASS_NEW_DELETE() \ -public: void* operator new(size_t nSize) {return OpcAlloc(nSize);} \ -public: void operator delete(void* p) {OpcFree(p);} - -#define OPC_CLASS_NEW_DELETE_EX(xCallType) \ -xCallType void* operator new(size_t nSize) {return OpcAlloc(nSize);} \ -xCallType void operator delete(void* p) {OpcFree(p);} - -//============================================================================== -// MACRO: OPC_CLASS_NEW_DELETE_ARRAY -// PURPOSE: Implements a class new and delete instance and array operators. - -#define OPC_CLASS_NEW_DELETE_ARRAY() \ -OPC_CLASS_NEW_DELETE() \ -public: void* operator new[](size_t nSize) {return OpcAlloc(nSize);} \ -public: void operator delete[](void* p) {OpcFree(p);} - -#define OPC_CLASS_NEW_DELETE_ARRAY_EX(xCallType) \ -OPC_CLASS_NEW_DELETE_EX(xCallType) \ -xCallType void* operator new[](size_t nSize) {return OpcAlloc(nSize);} \ -xCallType void operator delete[](void* p) {OpcFree(p);} - -//============================================================================== -// FUNCTION: OpcUtcNow -// PURPOSE: Returns the current UTC time - -OPCUTILS_API FILETIME OpcUtcNow(); - -//============================================================================== -// FUNCTION: OpcMinDate -// PURPOSE: Returns the minimum value for a file time. - -OPCUTILS_API FILETIME OpcMinDate(); - -//============================================================================== -// FUNCTION: OpcToInt64 -// PURPOSE: Converts a FILETIME to a 64-bit integer. - -OPCUTILS_API LONGLONG OpcToInt64(FILETIME ftTime); - -//============================================================================== -// FUNCTION: OpcToFILETIME -// PURPOSE: Converts a 64-bit integer to a FILETIME. - -OPCUTILS_API FILETIME OpcToFILETIME(LONGLONG llTime); - -//============================================================================ -// FUNCTION: OpcLocalTimeToUtcTime -// PURPOSE: Converts a local time to a UTC time. - -OPCUTILS_API bool OpcLocalTimeToUtcTime(FILETIME& ftLocalTime, FILETIME& ftUtcTime); -OPCUTILS_API bool OpcLocalTimeToUtcTime(SYSTEMTIME& stLocalTime, FILETIME& ftUtcTime); - -//============================================================================ -// FUNCTION: OpcGetDaysInMonth -// PURPOSE: Returns the number of days in a month. - -OPCUTILS_API UINT OpcGetDaysInMonth(UINT uYear, UINT uMonth); - -//============================================================================== -// FUNCTION: operator -// PURPOSE: Implements various operators for FILETIME structures. - -inline bool operator==(const FILETIME& a, const FILETIME& b) -{ - return (memcmp(&a, &b, sizeof(FILETIME)) == 0); -} - -inline bool operator!=(const FILETIME& a, const FILETIME& b) -{ - return (memcmp(&a, &b, sizeof(FILETIME)) != 0); -} - -inline bool operator<(const FILETIME& a, const FILETIME& b) -{ - return (a.dwHighDateTime != b.dwHighDateTime)?(a.dwHighDateTime < b.dwHighDateTime):(a.dwLowDateTime < b.dwLowDateTime); -} - -inline bool operator<=(const FILETIME& a, const FILETIME& b) -{ - return (a.dwHighDateTime != b.dwHighDateTime)?(a.dwHighDateTime <= b.dwHighDateTime):(a.dwLowDateTime <= b.dwLowDateTime); -} - -inline bool operator>(const FILETIME& a, const FILETIME& b) -{ - return (a.dwHighDateTime != b.dwHighDateTime)?(a.dwHighDateTime > b.dwHighDateTime):(a.dwLowDateTime > b.dwLowDateTime); -} - -inline bool operator>=(const FILETIME& a, const FILETIME& b) -{ - return (a.dwHighDateTime != b.dwHighDateTime)?(a.dwHighDateTime >= b.dwHighDateTime):(a.dwLowDateTime >= b.dwLowDateTime); -} - -//============================================================================== -// FUNCTION: operator -// PURPOSE: Implements various operators for CY structures. - -inline bool operator==(const CY& a, const CY& b) -{ - return (a.int64 == b.int64); -} - -inline bool operator!=(const CY& a, const CY& b) -{ - return (a.int64 != b.int64); -} - -inline bool operator<(const CY& a, const CY& b) -{ - return (a.int64 < b.int64); -} - -inline bool operator<=(const CY& a, const CY& b) -{ - return (a.int64 <= b.int64); -} - -inline bool operator>(const CY& a, const CY& b) -{ - return (a.int64 > b.int64); -} - -inline bool operator>=(const CY& a, const CY& b) -{ - return (a.int64 >= b.int64); -} - -//============================================================================== -// MACRO: OPC_MASK_XXX -// PURPOSE: Facilitate manipulation of bit masks. - -#define OPC_MASK_ISSET(xValue, xMask) (((xValue) & (xMask)) == (xMask)) -#define OPC_MASK_SET(xValue, xMask) xValue |= (xMask) -#define OPC_MASK_UNSET(xValue, xMask) xValue &= ~(xMask) - -#endif // _OpcDefs_H_ diff --git a/ComIOP/Wrapper/Common/OpcMatch.cpp b/ComIOP/Wrapper/Common/OpcMatch.cpp deleted file mode 100644 index 4dbc4c42f..000000000 --- a/ComIOP/Wrapper/Common/OpcMatch.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "OpcMatch.h" - -//============================================================================== -// Local Functions - -// ConvertCase -static inline int ConvertCase(int c, bool bCaseSensitive) -{ - return (bCaseSensitive)?c:toupper(c); -} - -//============================================================================== -// OpcMatchPattern - -bool OpcMatchPattern( - LPCTSTR szString, - LPCTSTR szPattern, - bool bCaseSensitive -) -{ - // an empty pattern always matches. - if (szPattern == NULL) - { - return true; - } - - // an empty string never matches. - if (szString == NULL) - { - return false; - } - - TCHAR c, p, l; - - for (;;) - { - switch (p = ConvertCase(*szPattern++, bCaseSensitive)) - { - // end of pattern. - case 0: - { - return (*szString)?false:true; // if end of string true - } - - // match zero or more char. - case _T('*'): - { - while (*szString) - { - if (OpcMatchPattern(szString++, szPattern, bCaseSensitive)) - { - return true; - } - } - - return OpcMatchPattern(szString, szPattern, bCaseSensitive); - } - - // match any one char. - case _T('?'): - { - if (*szString++ == 0) - { - return false; // not end of string - } - - break; - } - - // match char set - case _T('['): - { - if ((c = ConvertCase(*szString++, bCaseSensitive)) == 0) - { - return false; // syntax - } - - l = 0; - - // match a char if NOT in set [] - if (*szPattern == _T('!')) - { - ++szPattern; - - while ((p = ConvertCase(*szPattern++, bCaseSensitive)) != _T('\0')) - { - if (p == _T(']')) // if end of char set, then - { - break; // no match found - } - - if (p == _T('-')) - { - // check a range of chars? - p = ConvertCase( *szPattern, bCaseSensitive ); - - // get high limit of range - if (p == 0 || p == _T(']')) - { - return false; // syntax - } - - if (c >= l && c <= p) - { - return false; // if in range, return false - } - } - - l = p; - - if (c == p) // if char matches this element - { - return false; // return false - } - } - } - - // match if char is in set [] - else - { - while ((p = ConvertCase(*szPattern++, bCaseSensitive)) != _T('\0')) - { - if (p == _T(']')) // if end of char set, then no match found - { - return false; - } - - if (p == _T('-')) - { - // check a range of chars? - p = ConvertCase( *szPattern, bCaseSensitive ); - - // get high limit of range - if (p == 0 || p == _T(']')) - { - return false; // syntax - } - - if (c >= l && c <= p) - { - break; // if in range, move on - } - } - - l = p; - - if (c == p) // if char matches this element move on - { - break; - } - } - - while (p && p != _T(']')) // got a match in char set skip to end of set - { - p = *szPattern++; - } - } - - break; - } - - // match digit. - case _T('#'): - { - c = *szString++; - - if (!_istdigit(c)) - { - return false; // not a digit - } - - break; - } - - // match exact char. - default: - { - c = ConvertCase(*szString++, bCaseSensitive); - - if (c != p) // check for exact char - { - return false; // not a match - } - - break; - } - } - } - - return false; -} diff --git a/ComIOP/Wrapper/Common/OpcMatch.h b/ComIOP/Wrapper/Common/OpcMatch.h deleted file mode 100644 index a66e4067c..000000000 --- a/ComIOP/Wrapper/Common/OpcMatch.h +++ /dev/null @@ -1,109 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _OpcMatch_H_ -#define _OpcMatch_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" -#include "COpcString.h" - -//============================================================================== -// FUNCTION: OpcMatchPattern -// PURPOSE: Provides the same functionality as the LIKE operator in Visual Basic. -// -// Return Value: -// -// If string matches pattern, return is TRUE; if there is no match, return is FALSE. -// If the pattern is empty, the return is always TRUE; -// If the string is empty and the pattern is not empty, the return is FALSE; -// -// Parameters: -// -// szString String to be compared with pattern. -// szPattern Any string conforming to the pattern-matching conventions described in Remarks. -// bCaseSensitive TRUE if comparison should be case sensitive. -// -// Remarks: -// -// A versatile tool used to compare two strings. The pattern-matching features -// allow you to use wildcard characters, character lists, or character ranges, in -// any combination, to match strings. The following table shows the characters -// allowed in pattern and what they match: -// -// Characters in pattern Matches in string -// ? Any single character. -// * Zero or more characters. -// # Any single digit (0-9). -// [charlist] Any single character in charlist. -// [!charlist] Any single character not in charlist. -// -// A group of one or more characters (charlist) enclosed in brackets ([]) -// can be used to match any single character in string and can include almost -// any charcter code, including digits. -// -// 0Note To match the special characters left bracket ([), question mark (?), -// number sign (#), and asterisk (*), enclose them in brackets. -// -// The right bracket (]) can't be used within a group to match itself, but it -// can be used outside a group as an individual character. -// -// By using a hyphen (-) to separate the upper and lower bounds of the range, -// charlist can specify a range of characters. For example, [A-Z] results in -// a match if the corresponding character position in string contains any -// uppercase letters in the range A-Z. Multiple ranges are included within -// the brackets without delimiters. -// -// Other important rules for pattern matching include the following: -// -// - An exclamation point (!) at the beginning of charlist means that -// a match is made if any character except the characters in charlist -// is found in string. When used outside brackets, the exclamation -// point matches itself. -// -// - A hyphen (-) can appear either at the beginning (after an exclamation -// point if one is used) or at the end of charlist to match itself. In -// any other location, the hyphen is used to identify a range of characters. -// -// - When a range of characters is specified, they must appear in ascending -// sort order (from lowest to highest). [A-Z] is a valid pattern, -// but [Z-A] is not. -// -// - The character sequence [] is considered a zero-length string (""). - -OPCUTILS_API bool OpcMatchPattern( - LPCTSTR szString, - LPCTSTR szPattern, - bool bCaseSensitive = false -); - -#endif // _OpcMatch_H_ diff --git a/ComIOP/Wrapper/Common/OpcRegistry.cpp b/ComIOP/Wrapper/Common/OpcRegistry.cpp deleted file mode 100644 index 5fc8891e8..000000000 --- a/ComIOP/Wrapper/Common/OpcRegistry.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "OpcRegistry.h" -#include "COpcString.h" - -//============================================================================== -// OpcRegGetValue - -bool OpcRegGetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - LPTSTR* ptsValue -) -{ - bool bResult = true; - - if (ptsValue == NULL) - { - return false; - } - - *ptsValue = NULL; - - HKEY hKey = NULL; - BYTE* pData = NULL; - - TRY - { - // open registry key. - LONG lResult = RegOpenKeyEx( - hBaseKey, - tsSubKey, - NULL, - KEY_READ, - &hKey - ); - - if (lResult != ERROR_SUCCESS) - { - THROW_(bResult, false); - } - - // determine the string value length. - DWORD dwType = 0; - DWORD dwLength = 0; - - lResult = ::RegQueryValueEx( - hKey, - tsValueName, - NULL, - &dwType, - NULL, - &dwLength - ); - - if (lResult != ERROR_SUCCESS) - { - THROW_(bResult, false); - } - - // check for correct value type. - if ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ)) - { - THROW_(bResult, false); - } - - // allocate space and read the value. - pData = (BYTE*)OpcAlloc(dwLength); - memset(pData, 0, dwLength); - - lResult = ::RegQueryValueEx( - hKey, - tsValueName, - NULL, - NULL, - pData, - &dwLength - ); - - if (lResult != ERROR_SUCCESS) - { - THROW_(bResult, false); - } - - *ptsValue = OpcArrayAlloc(TCHAR, dwLength/sizeof(TCHAR)); - _tcscpy(*ptsValue, (LPCTSTR)pData); - (*ptsValue)[dwLength/sizeof(TCHAR)-1] = _T('\0'); - } - CATCH - { - } - FINALLY - { - if (hKey != NULL) RegCloseKey(hKey); - OpcFree(pData); - } - - return bResult; -} - -//============================================================================== -// OpcRegGetValue - -bool OpcRegGetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - DWORD* pdwValue -) -{ - return false; -} - -//============================================================================== -// OpcRegSetValue - -bool OpcRegSetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - DWORD dwType, - BYTE* pValue, - DWORD dwLength -) -{ - bool bResult = true; - - HKEY hKey = NULL; - - TRY - { - DWORD dwDisposition = NULL; - - LONG lResult = RegCreateKeyEx( - hBaseKey, - tsSubKey, - NULL, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_WRITE, - NULL, - &hKey, - &dwDisposition - ); - - if (lResult != ERROR_SUCCESS) - { - THROW_(bResult, false); - } - - lResult = RegSetValueEx( - hKey, - tsValueName, - NULL, - dwType, - pValue, - dwLength - ); - - if (lResult != ERROR_SUCCESS) - { - THROW_(bResult, false); - } - } - CATCH - { - } - FINALLY - { - if (hKey != NULL) RegCloseKey(hKey); - } - - return bResult; -} - -//============================================================================== -// OpcRegSetValue - -bool OpcRegSetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - LPCTSTR tsValue -) -{ - return OpcRegSetValue( - hBaseKey, - tsSubKey, - tsValueName, - REG_SZ, - (BYTE*)tsValue, - (_tcslen(tsValue)+1)*sizeof(TCHAR) - ); -} - -//============================================================================== -// OpcRegSetValue - -bool OpcRegSetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - DWORD dwValue -) -{ - return OpcRegSetValue( - hBaseKey, - tsSubKey, - tsValueName, - REG_DWORD, - (BYTE*)&dwValue, - sizeof(DWORD) - ); -} - -//============================================================================== -// OpcRegSetValue - -bool OpcRegSetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - BYTE* pValue, - DWORD dwLength -) -{ - return OpcRegSetValue( - hBaseKey, - tsSubKey, - tsValueName, - REG_BINARY, - pValue, - dwLength - ); -} - -//============================================================================== -// OpcRegDeleteKey - -bool OpcRegDeleteKey( - HKEY hBaseKey, - LPCTSTR tsSubKey -) -{ - bool bResult = true; - - HKEY hKey = NULL; - - TRY - { - // parse the sub key path. - COpcString cKey(tsSubKey); - COpcString cParent; - - int iIndex = cKey.ReverseFind(_T("\\")); - - if (iIndex != -1) - { - cParent = cKey.SubStr(0, iIndex); - cKey = cKey.SubStr(iIndex+1); - } - - // safety check - don't delete root keys - if (cKey.IsEmpty()) - { - THROW_(bResult, false); - } - - // open the key for modifications. - LONG lResult = RegOpenKeyEx( - hBaseKey, - tsSubKey, - NULL, - KEY_ALL_ACCESS, - &hKey - ); - - if (lResult != ERROR_SUCCESS) - { - THROW_(bResult, false); - } - - // determine the number of sub keys. - DWORD dwCount = 0; - DWORD dwMaxLength = 0; - - lResult = RegQueryInfoKey( - hKey, // handle to key - NULL, // class buffer - NULL, // size of class buffer - NULL, // reserved - &dwCount, // number of subkeys - &dwMaxLength, // longest subkey name - NULL, // longest class string - NULL, // number of value entries - NULL, // longest value name - NULL, // longest value data - NULL, // descriptor length - NULL // last write time - ); - - if (lResult != ERROR_SUCCESS) - { - THROW_(bResult, false); - } - - // recursively delete sub keys. - LPTSTR tsName = new TCHAR[dwMaxLength+1]; - - while (dwCount > 0 && (lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA)) - { - DWORD dwLength = dwMaxLength+1; - - lResult = RegEnumKeyEx( - hKey, - 0, - tsName, - &dwLength, - NULL, - NULL, - NULL, - NULL); - - if (lResult == ERROR_MORE_DATA || lResult == ERROR_SUCCESS) - { - COpcString cSubKey(tsSubKey); - - cSubKey += _T("\\"); - cSubKey += tsName; - - OpcRegDeleteKey(hBaseKey, cSubKey); - } - } - - delete [] tsName; - - // close the key before delete. - RegCloseKey(hKey); - - // open the parent key for delete. - lResult = RegOpenKeyEx( - hBaseKey, - cParent, - NULL, - KEY_ALL_ACCESS, - &hKey - ); - - if (lResult != ERROR_SUCCESS) - { - THROW_(bResult, false); - } - - // delete key - lResult = RegDeleteKey(hKey, cKey); - - if (lResult != ERROR_SUCCESS) - { - THROW_(bResult, false); - } - } - CATCH - { - } - FINALLY - { - if (hKey != NULL) RegCloseKey(hKey); - } - - return bResult; -} diff --git a/ComIOP/Wrapper/Common/OpcRegistry.h b/ComIOP/Wrapper/Common/OpcRegistry.h deleted file mode 100644 index cf0d7dfee..000000000 --- a/ComIOP/Wrapper/Common/OpcRegistry.h +++ /dev/null @@ -1,117 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _OpcRegistry_H_ -#define _OpcRegistry_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "OpcDefs.h" - -//============================================================================== -// FUNCTION: OpcRegGetValue -// PURPOSE: Gets a string value from the registry. - -bool OPCUTILS_API OpcRegGetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - LPTSTR* ptsValue -); - -//============================================================================== -// FUNCTION: OpcRegGetValue -// PURPOSE: Gets a DWORD value from the registry. - -bool OPCUTILS_API OpcRegGetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - DWORD* pdwValue -); - -//============================================================================== -// FUNCTION: OpcRegGetValue -// PURPOSE: Gets a DWORD value from the registry. - -bool OPCUTILS_API OpcRegGetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - BYTE** ppValue, - DWORD* pdwLength -); - -//============================================================================== -// FUNCTION: OpcRegSetValue -// PURPOSE: Sets a string value in the registry. - -bool OPCUTILS_API OpcRegSetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - LPCTSTR tsValue -); - -//============================================================================== -// FUNCTION: OpcRegSetValue -// PURPOSE: Gets a DWORD value from the registry. - -bool OPCUTILS_API OpcRegSetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - DWORD dwValue -); - -//============================================================================== -// FUNCTION: OpcRegSetValue -// PURPOSE: Sets a string value in the registry. - -bool OPCUTILS_API OpcRegSetValue( - HKEY hBaseKey, - LPCTSTR tsSubKey, - LPCTSTR tsValueName, - BYTE* pValue, - DWORD dwLength -); - -//============================================================================== -// FUNCTION: OpcRegDeleteKey -// PURPOSE: Recursively deletes a key and all sub keys. -// NOTES: - -bool OPCUTILS_API OpcRegDeleteKey( - HKEY hBaseKey, - LPCTSTR tsSubKey -); - -#endif //ndef _OpcRegistry_H_ diff --git a/ComIOP/Wrapper/Common/OpcUtils.cpp b/ComIOP/Wrapper/Common/OpcUtils.cpp deleted file mode 100644 index d0e479e2c..000000000 --- a/ComIOP/Wrapper/Common/OpcUtils.cpp +++ /dev/null @@ -1,380 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" -#include "OpcDefs.h" -#include "COpcArray.h" -#include "COpcList.h" -#include "COpcMap.h" - -#include - -//============================================================================== -// OpcAlloc - -void* OpcAlloc(size_t tSize) -{ - return CoTaskMemAlloc(tSize); -} - -//============================================================================== -// OpcFree - -void OpcFree(void* pBlock) -{ - if (pBlock != NULL) - { - CoTaskMemFree(pBlock); - } -} - -//============================================================================== -// OpcStrDup - -CHAR* OpcStrDup(LPCSTR szValue) -{ - CHAR* pCopy = NULL; - - if (szValue != NULL) - { - pCopy = OpcArrayAlloc(CHAR, strlen(szValue)+1); - - if (pCopy == NULL) - { - return NULL; - } - - strcpy(pCopy, szValue); - } - - return pCopy; -} - -//============================================================================== -// OpcStrDup - -WCHAR* OpcStrDup(LPCWSTR szValue) -{ - WCHAR* pCopy = NULL; - - if (szValue != NULL) - { - pCopy = OpcArrayAlloc(WCHAR, wcslen(szValue)+1); - - if (pCopy == NULL) - { - return NULL; - } - - wcscpy(pCopy, szValue); - } - - return pCopy; -} - -//============================================================================== -// OpcUtcNow - -FILETIME OpcUtcNow() -{ - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - return ft; -} - -//============================================================================== -// OpcMinDate - -FILETIME OpcMinDate() -{ - FILETIME ft; - memset(&ft, 0, sizeof(ft)); - return ft; -} - -//============================================================================== -// OpcToInt64 - -LONGLONG OpcToInt64(FILETIME ftTime) -{ - LONGLONG llBuffer = (LONGLONG)ftTime.dwHighDateTime; - - if (llBuffer < 0) - { - llBuffer += (((LONGLONG)_UI32_MAX)+1); - } - - LONGLONG llTime = (llBuffer<<32); - - llBuffer = (LONGLONG)ftTime.dwLowDateTime; - - if (llBuffer < 0) - { - llBuffer += (((LONGLONG)_UI32_MAX)+1); - } - - llTime += llBuffer; - - return llTime; -} - -//============================================================================== -// OpcToFILETIME - -FILETIME OpcToFILETIME(LONGLONG llTime) -{ - FILETIME ftTime; - - ftTime.dwLowDateTime = (DWORD)(0x00000000FFFFFFFF & llTime); - ftTime.dwHighDateTime = (DWORD)((0xFFFFFFFF00000000 & llTime) >> 32); - - return ftTime; -} - - -//============================================================================ -// OpcGetDaysInMonth - -UINT OpcGetDaysInMonth(UINT uYear, UINT uMonth) -{ - // array of days in month. - static const int pDaysInMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - - // adjust for number of months greater than 12. - uYear += (uMonth-1)/12; - uMonth = (uMonth-1)%12; - - // lookup number of days in static array. - UINT uDays = pDaysInMonth[uMonth]; - - // adjust for leap year. - if (uMonth == 1) - { - if (uYear%4 != 0 || uYear%400 == 0) - { - uDays--; - } - } - - // return number of days. - return uDays; -} - -//============================================================================ -// OpcIsDaylightSaving - -static bool OpcIsDaylightTime(TIME_ZONE_INFORMATION& cTimeZone, SYSTEMTIME& stLocalTime) -{ - - // check if daylight time not used. - if (cTimeZone.DaylightDate.wMonth == cTimeZone.StandardDate.wMonth) - { - return false; - } - - bool bNorthern = (cTimeZone.DaylightDate.wMonth < cTimeZone.StandardDate.wMonth); - - if (bNorthern) - { - // check if month definitely falls within daylight time. - if (stLocalTime.wMonth > cTimeZone.DaylightDate.wMonth && stLocalTime.wMonth < cTimeZone.StandardDate.wMonth) - { - return true; - } - - // check if month definitely falls in standard time. - if (stLocalTime.wMonth < cTimeZone.DaylightDate.wMonth || stLocalTime.wMonth > cTimeZone.StandardDate.wMonth) - { - return false; - } - } - else - { - // check if month definitely falls within standard time. - if (stLocalTime.wMonth > cTimeZone.StandardDate.wMonth && stLocalTime.wMonth < cTimeZone.DaylightDate.wMonth) - { - return false; - } - - // check if month definitely falls in daylight time. - if (stLocalTime.wMonth < cTimeZone.StandardDate.wMonth || stLocalTime.wMonth > cTimeZone.DaylightDate.wMonth) - { - return true; - } - } - - bool bGoingToDaylight = (stLocalTime.wMonth == cTimeZone.DaylightDate.wMonth); - - // get the transition information. - SYSTEMTIME& stTransition = (bGoingToDaylight)?cTimeZone.DaylightDate:cTimeZone.StandardDate; - - // get start of month. - SYSTEMTIME stStart; - memset(&stStart, 0, sizeof(SYSTEMTIME)); - - stStart.wYear = stLocalTime.wYear; - stStart.wMonth = stLocalTime.wMonth; - stStart.wDay = 1; - - // convert to FILETIME and back again to get day of week. - FILETIME ftStart; - SystemTimeToFileTime(&stStart, &ftStart); - FileTimeToSystemTime(&ftStart, &stStart); - - // get start of next month. - SYSTEMTIME stEnd; - memset(&stEnd, 0, sizeof(SYSTEMTIME)); - - stEnd.wYear = stLocalTime.wYear; - stEnd.wMonth = stLocalTime.wMonth; - stEnd.wDay = OpcGetDaysInMonth(stLocalTime.wYear, stLocalTime.wMonth); - - // convert to FILETIME and back again to get day of week. - FILETIME ftEnd; - SystemTimeToFileTime(&stEnd, &ftEnd); - FileTimeToSystemTime(&ftEnd, &stEnd); - - WORD wDay = 1; - WORD wWeek = 0; - WORD wDayOfWeek = stTransition.wDayOfWeek; - - // find the nth day of the month that falls on the change over day. - if (wWeek < 5) - { - while (wDay <= stEnd.wDay) - { - if (wDayOfWeek == stTransition.wDayOfWeek) - { - wWeek++; - - if (wWeek == stTransition.wDay) - { - break; - } - } - - wDay++; - wDayOfWeek = (wDayOfWeek+1)%7; - } - } - - // find the last day of the month that falls on the change over day. - else - { - wDay = stEnd.wDay; - - while (wDay > 0) - { - if (wDayOfWeek == stTransition.wDayOfWeek) - { - break; - } - - wDay--; - wDayOfWeek = (wDayOfWeek > 0)?wDayOfWeek-1:6; - } - } - - // check if it definately before the transition day. - if (stLocalTime.wDay < wDay) - { - return !bGoingToDaylight; - } - - // check if it definately fater the transition day. - if (stLocalTime.wDay > wDay) - { - return bGoingToDaylight; - } - - // check if it definately before the transition hour. - if (stLocalTime.wHour < stTransition.wHour) - { - return !bGoingToDaylight; - } - - // must be after the transition hour. - return bGoingToDaylight; -} - - -//============================================================================ -// OpcLocalTimeToUtcTime - -bool OpcLocalTimeToUtcTime(FILETIME& ftLocalTime, FILETIME& ftUtcTime) -{ - SYSTEMTIME stLocalTime; - - if (!FileTimeToSystemTime(&ftLocalTime, &stLocalTime)) - { - return false; - } - - return OpcLocalTimeToUtcTime(stLocalTime, ftUtcTime); -} - -bool OpcLocalTimeToUtcTime(SYSTEMTIME& stLocalTime, FILETIME& ftUtcTime) -{ - // get the timezone information for the machine. - TIME_ZONE_INFORMATION cTimeZone; - - DWORD dwResult = GetTimeZoneInformation(&cTimeZone); - - // convert to file time. - FILETIME ftLocalTime; - - if (!SystemTimeToFileTime(&stLocalTime, &ftLocalTime)) - { - return false; - } - - LONGLONG llLocalTime = OpcToInt64(ftLocalTime); - - // calculate offset from UTC. - LONGLONG llBias = cTimeZone.Bias; - - if (dwResult != TIME_ZONE_ID_UNKNOWN) - { - if (OpcIsDaylightTime(cTimeZone, stLocalTime)) - { - llBias += cTimeZone.DaylightBias; - } - else - { - llBias += cTimeZone.StandardBias; - } - } - - // apply offset from UTC. - llLocalTime += llBias*60*10000000; - - // convert back FILETIME. - ftUtcTime = OpcToFILETIME(llLocalTime); - return true; -} diff --git a/ComIOP/Wrapper/Common/OpcUtils.h b/ComIOP/Wrapper/Common/OpcUtils.h deleted file mode 100644 index 1dfe6fdac..000000000 --- a/ComIOP/Wrapper/Common/OpcUtils.h +++ /dev/null @@ -1,73 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _OpcUtils_H_ -#define _OpcUtils_H_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "opccomn.h" - -#define OPCUTILS_API - -#include "OpcDefs.h" -#include "COpcString.h" -#include "COpcFile.h" -#include "OpcMatch.h" -#include "COpcCriticalSection.h" -#include "COpcArray.h" -#include "COpcList.h" -#include "COpcMap.h" -#include "COpcSortedArray.h" -#include "COpcText.h" -#include "COpcTextReader.h" -#include "COpcThread.h" -#include "OpcCategory.h" -#include "OpcRegistry.h" -#include "OpcXmlType.h" -#include "COpcXmlAnyType.h" -#include "COpcXmlElement.h" -#include "COpcXmlDocument.h" -#include "COpcVariant.h" -#include "COpcComObject.h" -#include "COpcClassFactory.h" -#include "COpcComModule.h" -#include "COpcCommon.h" -#include "COpcConnectionPoint.h" -#include "COpcCPContainer.h" -#include "COpcEnumCPs.h" -#include "COpcEnumString.h" -#include "COpcEnumUnknown.h" -#include "COpcSecurity.h" -#include "COpcThreadPool.h" -#include "COpcBrowseElement.h" - -#endif // _OpcUtils_H_ diff --git a/ComIOP/Wrapper/Common/OpcXmlType.cpp b/ComIOP/Wrapper/Common/OpcXmlType.cpp deleted file mode 100644 index 04ee232f0..000000000 --- a/ComIOP/Wrapper/Common/OpcXmlType.cpp +++ /dev/null @@ -1,1064 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#include "StdAfx.h" - -#include -#include - -#include "OpcXmlType.h" -#include "COpcTextReader.h" - -using namespace OpcXml; - -//============================================================================== -// Local Delcarations - -#define MAX_VALUE_BUF_SIZE 1024 - -// numeric upper/lower bounds. -#define MIN_SBYTE _I8_MIN -#define MAX_SBYTE _I8_MAX -#define MAX_BYTE _UI8_MAX -#define MIN_SHORT _I16_MIN -#define MAX_SHORT _I16_MAX -#define MAX_USHORT _UI16_MAX -#define MIN_INT _I32_MIN -#define MAX_INT _I32_MAX -#define MAX_UINT _UI32_MAX -#define MIN_LONG _I64_MIN -#define MAX_LONG _I64_MAX -#define MAX_ULONG _UI64_MAX -#define MIN_FLOAT FLT_MIN -#define MAX_FLOAT FLT_MAX -#define MIN_DOUBLE DBL_MIN -#define MAX_DOUBLE DBL_MAX -#define MIN_DECIMAL (_I64_MIN/10000) -#define MAX_DECIMAL (_I64_MAX/10000) -#define MAX_DEC_FRACTION 9999 -#define MIN_YEAR 1601 -#define MAX_YEAR 9999 -#define MIN_MONTH 1 -#define MAX_MONTH 12 -#define MIN_DAY 1 -#define MAX_DAY 31 -#define MIN_HOUR 0 -#define MAX_HOUR 23 -#define MIN_MINUTE 0 -#define MAX_MINUTE 59 -#define MIN_SECOND 0 -#define MAX_SECOND 59 -#define MIN_SEC_FRACTION 0 -#define MAX_SEC_FRACTION 999 - -//============================================================================== -// Local Functions - -// CharToValue -static UINT CharToValue(TCHAR tzChar, UINT uBase) -{ - static const LPCTSTR g_tsDigits = _T("0123456789ABCDEF"); - - TCHAR tzDigit = (_istlower(tzChar))?_toupper(tzChar):tzChar; - - for (UINT ii = 0; ii < uBase; ii++) - { - if (tzDigit == g_tsDigits[ii]) - { - return ii; - } - } - - return -1; -} - -// ToUnsigned -static bool ToUnsigned( - const COpcString& cString, - ULong& nValue, - ULong nMax, - ULong nMin, - UINT uBase -) -{ - bool bResult = true; - - TRY - { - COpcText cText; - COpcTextReader cReader(cString); - - // extract non-whitespace. - cText.SetType(COpcText::NonWhitespace); - cText.SetEofDelim(); - - if (!cReader.GetNext(cText)) - { - THROW_(bResult, false); - } - - COpcString cValue = cText; - - nValue = 0; - - for (UINT ii = 0; ii < cValue.GetLength(); ii++) - { - UINT uDigit = CharToValue(cValue[ii], uBase); - - // invalid digit found. - if (uDigit == -1) - { - bResult = false; - break; - } - - // detect overflow - if (nValue > nMax/uBase) THROW_(bResult, false); - - // shift result up by base. - nValue *= uBase; - - // detect overflow - if (nValue > nMax - uDigit) THROW_(bResult, false); - - // add digit. - nValue += uDigit; - } - - // detect underflow - if (nMin > nValue) THROW_(bResult, false); - } - CATCH - { - nValue = 0; - } - - return bResult; -} - -// ToUnsigned -static bool ToUnsigned( - const COpcString& cString, - ULong& nValue, - ULong nMax, - ULong nMin -) -{ - // extract base - COpcText cText; - COpcTextReader cReader(cString); - - UINT uBase = 10; - - cText.SetType(COpcText::Literal); - cText.SetText(L"0x"); - cText.SetIgnoreCase(); - - if (cReader.GetNext(cText)) - { - uBase = 16; - } - - // read unsigned value. - return ToUnsigned(cReader.GetBuf(), nValue, nMax, nMin, uBase); -} - -// ToSigned -static bool ToSigned( - const COpcString& cString, - Long& nValue, - Long nMax, - Long nMin -) -{ - nValue = 0; - - // extract plus sign - bool bSign = true; - - COpcText cText; - COpcTextReader cReader(cString); - - cText.SetType(COpcText::Literal); - cText.SetText(L"+"); - - if (!cReader.GetNext(cText)) - { - // extract minus sign - cText.SetType(COpcText::Literal); - cText.SetText(L"-"); - - bSign = !cReader.GetNext(cText); - } - - // read unsigned value. - ULong uValue = 0; - - if (!ToUnsigned(cReader.GetBuf(), uValue, (bSign)?nMax:-nMin, 0, 10)) - { - return false; - } - - nValue = (Long)uValue; - - // apply sign. - if (!bSign) - { - nValue = -nValue; - } - - return true; -} - -// ToReal -static bool ToReal( - const COpcString& cString, - Double& nValue, - Double nMax, - Double nMin -) -{ - bool bResult = true; - - TRY - { - // extract non-whitespace token. - COpcText cText; - COpcTextReader cReader(cString); - - cText.SetType(COpcText::NonWhitespace); - cText.SetSkipLeading(); - - if (!cReader.GetNext(cText)) - { - THROW_(bResult, false); - } - - // parse double with C runtime function. - WCHAR* pzEnd = NULL; - nValue = (Double)wcstod((LPCWSTR)(COpcString&)cText, &pzEnd); - - // check for error - all text must have been parsed. - if (pzEnd == NULL || wcslen(pzEnd) != 0) - { - THROW_(bResult, false); - } - - // check limits. - if (nValue > nMax && nValue < nMin) THROW_(bResult, false); - } - CATCH - { - nValue = 0; - } - - return bResult; -} - -// ToDate -static bool ToDate( - const COpcString& cString, - WORD& wYear, - WORD& wMonth, - WORD& wDay -) -{ - bool bResult = true; - - TRY - { - COpcText cText; - COpcTextReader cReader(cString); - - ULong uValue = 0; - - // parse year field. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L"-"); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - if (!ToUnsigned(cText, uValue, MAX_YEAR, MIN_YEAR, 10)) THROW_(bResult, false); - wYear = (WORD)uValue; - - // parse month field. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L"-"); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - if (!ToUnsigned(cText, uValue, MAX_MONTH, MIN_MONTH, 10)) THROW_(bResult, false); - wMonth = (WORD)uValue; - - // parse day field. - cText.SetType(COpcText::Delimited); - cText.SetEofDelim(); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - if (!ToUnsigned(cText, uValue, MAX_DAY, MIN_DAY, 10)) THROW_(bResult, false); - wDay = (WORD)uValue; - } - CATCH - { - wYear = 0; - wMonth = 0; - wDay = 0; - } - - return bResult; -} - -// ToTime -static bool ToTime( - const COpcString& cString, - WORD& wHour, - WORD& wMinute, - WORD& wSeconds, - WORD& wFraction -) -{ - bool bResult = true; - - TRY - { - COpcText cText; - COpcTextReader cReader(cString); - - ULong uValue = 0; - - // parse hour field. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L":"); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - if (!ToUnsigned(cText, uValue, MAX_HOUR, MIN_HOUR, 10)) THROW_(bResult, false); - wHour = (WORD)uValue; - - // parse month field. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L":"); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - if (!ToUnsigned(cText, uValue, MAX_MINUTE, MIN_MINUTE, 10)) THROW_(bResult, false); - wMinute = (WORD)uValue; - - // parse seconds field. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L"."); - cText.SetEofDelim(); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - if (!ToUnsigned(cText, uValue, MAX_SECOND, MIN_SECOND, 10)) THROW_(bResult, false); - wSeconds = (WORD)uValue; - - // parse seconds fraction field. - wFraction = 0; - - if (cText.GetDelimChar() == L'.') - { - cText.SetType(COpcText::Delimited); - cText.SetEofDelim(); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - - // preprocess text. - COpcString cFraction = cText; - - // add trailing zeros. - while (cFraction.GetLength() < 3) cFraction += _T("0"); - - // truncate extra digits. - if (cFraction.GetLength() > 3) cFraction = cFraction.SubStr(0,3); - - if (!ToUnsigned(cFraction, uValue, MAX_ULONG, 0, 10)) - { - THROW_(bResult, false); - } - - // result is in milliseconds. - wFraction = (WORD)uValue; - } - } - CATCH - { - wHour = 0; - wMinute = 0; - wSeconds = 0; - wFraction = 0; - } - - return bResult; -} - -// ToOffset -static bool ToOffset( - const COpcString& cString, - bool bNegative, - SHORT& sMinutes -) -{ - bool bResult = true; - - TRY - { - COpcText cText; - COpcTextReader cReader(cString); - - ULong uValue = 0; - - // parse hour field. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L":"); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - if (!ToUnsigned(cText, uValue, MAX_HOUR, MIN_HOUR, 10)) THROW_(bResult, false); - - sMinutes = (SHORT)uValue*60; - - // parse minute field. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L"."); - cText.SetEofDelim(); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - if (!ToUnsigned(cText, uValue, MAX_MINUTE, MIN_MINUTE, 10)) THROW_(bResult, false); - - sMinutes += (SHORT)uValue; - - // add sign. - if (bNegative) - { - sMinutes = -sMinutes; - } - } - CATCH - { - sMinutes = 0; - } - - return bResult; -} - -//============================================================================== -// FUNCTION: Read -// PURPOSE Explicit template implementations for common data types. - -// Read -template<> bool OpcXml::Read(const COpcString& cText, SByte& cValue) -{ - Long lValue = 0; - - if (!ToSigned(cText, lValue, MAX_SBYTE, MIN_SBYTE)) - { - cValue = 0; - return false; - } - - cValue = (SByte)lValue; - return true; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, Byte& cValue) -{ - ULong ulValue = 0; - - if (!ToUnsigned(cString, ulValue, MAX_BYTE, 0)) - { - cValue = 0; - return false; - } - - cValue = (Byte)ulValue; - return true; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, Short& cValue) -{ - Long lValue = 0; - - if (!ToSigned(cString, lValue, MAX_SHORT, MIN_SHORT)) - { - cValue = 0; - return false; - } - - cValue = (Short)lValue; - return true; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, UShort& cValue) -{ - ULong ulValue = 0; - - if (!ToUnsigned(cString, ulValue, MAX_USHORT, 0)) - { - cValue = 0; - return false; - } - - cValue = (UShort)ulValue; - return true; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, Int& cValue) -{ - Long lValue = 0; - - if (!ToSigned(cString, lValue, MAX_INT, MIN_INT)) - { - cValue = 0; - return false; - } - - cValue = (Int)lValue; - return true; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, UInt& cValue) -{ - ULong ulValue = 0; - - if (!ToUnsigned(cString, ulValue, MAX_UINT, 0)) - { - cValue = 0; - return false; - } - - cValue = (UInt)ulValue; - return true; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, long& cValue) -{ - Long lValue = 0; - - if (!ToSigned(cString, lValue, MAX_INT, MIN_INT)) - { - cValue = 0; - return false; - } - - cValue = (Int)lValue; - return true; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, unsigned long& cValue) -{ - ULong ulValue = 0; - - if (!ToUnsigned(cString, ulValue, MAX_UINT, 0)) - { - cValue = 0; - return false; - } - - cValue = (UInt)ulValue; - return true; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, Long& cValue) -{ - return ToSigned(cString, cValue, MAX_LONG, MIN_LONG); -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, ULong& cValue) -{ - return ToUnsigned(cString, cValue, MAX_ULONG, 0); -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, Float& cValue) -{ - Double dblValue = 0; - - if (!ToReal(cString, dblValue, MAX_FLOAT, MIN_FLOAT)) - { - cValue = 0; - return false; - } - - cValue = (Float)dblValue; - return true; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, Double& cValue) -{ - return ToReal(cString, cValue, MAX_DOUBLE, MIN_DOUBLE); -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, Decimal& cValue) -{ - bool bResult = true; - - TRY - { - COpcText cText; - COpcTextReader cReader(cString); - - // parse whole integer portion. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L"."); - cText.SetEofDelim(); - - if (!cReader.GetNext(cText)) - { - THROW_(bResult, false); - } - - // convert to signed integer. - Long nValue = 0; - - if (!ToSigned(cText, nValue, MAX_DECIMAL, MIN_DECIMAL)) - { - THROW_(bResult, false); - } - - cValue.int64 = nValue*10000; - - if (cText.GetDelimChar() == L'.') - { - // parse decimal portion. - cText.SetType(COpcText::Delimited); - cText.SetEofDelim(); - - if (!cReader.GetNext(cText)) - { - THROW_(bResult, false); - } - - // convert to unsigned integer. - ULong uValue = 0; - - if (!ToUnsigned(cText, uValue, MAX_DEC_FRACTION, 0, 10)) - { - THROW_(bResult, false); - } - - cValue.int64 += (Long)uValue; - } - } - CATCH - { - cValue.int64 = 0; - } - - return bResult; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, DateTime& cValue) -{ - bool bResult = true; - - FILETIME cFileTime; - - // check for invalid date. - if (cString.IsEmpty()) - { - cValue = OpcMinDate(); - return true; - } - - TRY - { - SYSTEMTIME cSystemTime; ZeroMemory(&cSystemTime, sizeof(cSystemTime)); - - COpcText cText; - COpcTextReader cReader(cString); - - // parse date fields. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L"T"); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - - if (!ToDate(cText, cSystemTime.wYear, cSystemTime.wMonth, cSystemTime.wDay)) - { - THROW_(bResult, false); - } - - // parse time fields. - cText.SetType(COpcText::Delimited); - cText.SetDelims(L"Z-+"); - cText.SetEofDelim(); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - - bResult = ToTime( - cText, - cSystemTime.wHour, - cSystemTime.wMinute, - cSystemTime.wSecond, - cSystemTime.wMilliseconds); - - if (!bResult) - { - THROW_(bResult, false); - } - - // convert to a UTC file time. - if (!SystemTimeToFileTime(&cSystemTime, &cFileTime)) - { - THROW_(bResult, false); - } - - if (cText.GetDelimChar() != _T('Z')) - { - // convert local system time to UTC file time. - if (cText.GetEof()) - { - FILETIME ftUtcTime; - - if (!OpcLocalTimeToUtcTime(cFileTime, ftUtcTime)) - { - THROW_(bResult, false); - } - - cFileTime = ftUtcTime; - } - - // apply offset specified in the datetime string. - else - { - bool bNegative = (cText.GetDelimChar() == _T('-')); - - // parse time fields. - cText.SetType(COpcText::Delimited); - cText.SetEofDelim(); - - if (!cReader.GetNext(cText)) THROW_(bResult, false); - - SHORT sMinutes = 0; - - bResult = ToOffset( - cText, - bNegative, - sMinutes); - - if (!bResult) - { - THROW_(bResult, false); - } - - // apply timezone offset. - LONGLONG llTime = OpcToInt64(cFileTime); - - llTime -= ((LONGLONG)sMinutes)*60*10000000; - - cFileTime = OpcToFILETIME(llTime); - } - } - - cValue = cFileTime; - } - CATCH - { - ZeroMemory(&cFileTime, sizeof(cFileTime)); - cValue = cFileTime; - } - - return bResult; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, Boolean& cValue) -{ - // check for an integer representation (any non-zero value is true). - Long nValue = 0; - - if (Read(cString, nValue)) - { - cValue = (nValue != 0); - return true; - } - - // check for alphabetic representation. - COpcString cBoolean(cString); - cBoolean = cBoolean.ToLower(); - - // test for true value. - if (cBoolean == _T("true")) - { - cValue = true; - return true; - } - - // test for false value. - if (cBoolean == _T("false")) - { - cValue = false; - return true; - } - - return false; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cString, String& cValue) -{ - cValue = OpcStrDup((LPCWSTR)cString); - return true; -} - -//============================================================================== -// FUNCTION: Write -// PURPOSE Explicit template implementations for common data types. - -// Write -template<> bool OpcXml::Write(const SByte& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%d", (Int)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const Byte& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%u", (UInt)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const Short& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%d", (Int)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const UShort& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%u", (UInt)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const Int& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%d", (Int)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const UInt& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%u", (UInt)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const long& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%d", (Int)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const unsigned long& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%u", (UInt)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const Long& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%I64d", cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const ULong& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%I64u", cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const Float& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%0.8g", (Double)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const Double& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%0.16g", (Double)cValue); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const Decimal& cValue, COpcString& cString) -{ - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - swprintf(szBuf, L"%0I64d.%0I64u", (cValue.int64/10000), (cValue.int64%10000)); - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const DateTime& cValue, COpcString& cString) -{ - // check for invalid date. - if (cValue == OpcMinDate()) - { - cString.Empty(); - return true; - } - - // convert to xml dateTime representation. - SYSTEMTIME cSystemTime; - - if (!FileTimeToSystemTime(&((FILETIME)cValue), &cSystemTime)) - { - return false; - } - - WCHAR szBuf[MAX_VALUE_BUF_SIZE]; - - swprintf( - szBuf, - L"%04hu-%02hu-%02huT%02hu:%02hu:%02hu.%03hu", - cSystemTime.wYear, - cSystemTime.wMonth, - cSystemTime.wDay, - cSystemTime.wHour, - cSystemTime.wMinute, - cSystemTime.wSecond, - cSystemTime.wMilliseconds); - - cString = szBuf; - return true; -} - -// Write -template<> bool OpcXml::Write(const Boolean& cValue, COpcString& cString) -{ - cString = (cValue)?_T("True"):_T("False"); - return true; -} - -// Write -template<> bool OpcXml::Write(const String& cValue, COpcString& cString) -{ - // TBD - add any escape sequences. - cString = cValue; - return true; -} - -//============================================================================== -// XXX - -// Init -template<> void OpcXml::Init(COpcString& cValue) -{ - cValue.Empty(); -} - -// Clear -template<> void OpcXml::Clear(COpcString& cValue) -{ - cValue.Empty(); -} - -// Read -template<> bool OpcXml::Read(const COpcString& cText, COpcString& cValue) -{ - cValue = cText; - return true; -} - -// Write -template<> bool OpcXml::Write(const COpcString& cValue, COpcString& cText) -{ - cText = cValue; - return true; -} - -//============================================================================== -// XXX - -// Init -template<> void OpcXml::Init(GUID& cValue) -{ - cValue = GUID_NULL; -} - -// Clear -template<> void OpcXml::Clear(GUID& cValue) -{ - cValue = GUID_NULL; -} - -// Read -template<> bool OpcXml::Read(const COpcString& cText, GUID& cValue) -{ - return cText.ToGuid(cValue); -} - -// Write -template<> bool OpcXml::Write(const GUID& cValue, COpcString& cText) -{ - cText.FromGuid(cValue); - return true; -} diff --git a/ComIOP/Wrapper/Common/OpcXmlType.h b/ComIOP/Wrapper/Common/OpcXmlType.h deleted file mode 100644 index f012010a4..000000000 --- a/ComIOP/Wrapper/Common/OpcXmlType.h +++ /dev/null @@ -1,325 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -#ifndef _OpcXmlType_H_ -#define _OpcXmlType_H_ - -#include "OpcDefs.h" -#include "COpcString.h" - -#include "MsXml2.h" - -//============================================================================== -// MACRO: OPCXML_NS_XXX -// PURPOSE: Common XML namespace URIs. - -#define OPCXML_NS_SCHEMA _T("http://www.w3.org/2001/XMLSchema") -#define OPCXML_NS_SCHEMA_INSTANCE _T("http://www.w3.org/2001/XMLSchema-instance") -#define OPCXML_NS_OPC _T("http://schemas.opcfoundation.org/OPC/") -#define OPCXML_NS_OPC_SAMPLE _T("http://schemas.opcfoundation.org/OPCSample/") -#define OPCXML_NS_OPC_DATA_ACCESS _T("http://opcfoundation.org/webservices/XMLDA/10/") -#define OPCXML_NS_OPC_DATA_EXCHANGE _T("http://opcfoundation.org/webservices/DX/10/") -#define OPCXML_NS_OPCBINARY _T("http://opcfoundation.org/OPCBinary/1.0/") - -#define OPCXML_DEFAULT_ELEMENT _T("Element") -#define OPCXML_ARRAY_PREFIX _T("ArrayOf") -#define OPCXML_TYPE_ATTRIBUTE _T("type") -#define OPCXML_NAMESPACE_ATTRIBUTE _T("xmlns") - -namespace OpcXml -{ - -//============================================================================== -// TYPES: XXX -// PURPOSE: Define C++ types for each XML data type. - -typedef CHAR SByte; -typedef BYTE Byte; -typedef SHORT Short; -typedef USHORT UShort; -typedef INT Int; -typedef UINT UInt; -typedef LONGLONG Long; -typedef ULONGLONG ULong; -typedef FLOAT Float; -typedef DOUBLE Double; -typedef CY Decimal; -typedef bool Boolean; -typedef LPWSTR String; -typedef FILETIME DateTime; - -//============================================================================== -// ENUM: Type -// PURPOSE: Defines the set of possible XML data types. - -enum Type -{ - XML_EMPTY = 0x0000, - XML_BOOLEAN = 0x0001, - XML_SBYTE = 0x0002, - XML_BYTE = 0x0003, - XML_SHORT = 0x0004, - XML_USHORT = 0x0005, - XML_INT = 0x0006, - XML_UINT = 0x0007, - XML_LONG = 0x0008, - XML_ULONG = 0x0009, - XML_FLOAT = 0x000A, - XML_DOUBLE = 0x000B, - XML_DECIMAL = 0x000C, - XML_STRING = 0x000D, - XML_DATETIME = 0x000E, - XML_ANY_TYPE = 0x000F -}; - -//============================================================================== -// CLASS: QName -// PURPOSE: A fully qualified name in XML. - -class QName -{ - OPC_CLASS_NEW_DELETE_ARRAY(); - -public: - - //========================================================================== - // Public Operators - - // Constructors - QName() {} - QName(const QName& cQName) { *this = cQName; } - QName(const COpcString& cName) : m_cName(cName), m_cNamespace("") {} - QName(const COpcString& cName, const COpcString& cNamespace) : m_cName(cName), m_cNamespace(cNamespace) {} - - // Destructor - ~QName() {} - - // Assignment - QName& operator=(const QName& cQName) { m_cName = cQName.m_cName; m_cNamespace = cQName.m_cNamespace; return *this; } - - // Equality - bool operator==(const QName& cQName) { return ((m_cName == cQName.m_cName) && (m_cNamespace == cQName.m_cNamespace)); } - bool operator!=(const QName& cQName) { return !(*this == cQName); } - - //========================================================================== - // Public Properties - - // Name - const COpcString& GetName() const { return m_cName; } - void SetName(const COpcString& cName) { m_cName = cName; } - - // Namespace - const COpcString& GetNamespace() const { return m_cNamespace; } - void SetNamespace(const COpcString& cNamespace) { m_cNamespace = cNamespace; } - -private: - - //========================================================================== - // Private Members - - COpcString m_cName; - COpcString m_cNamespace; -}; - -//============================================================================== -// FUNCTION: Init -// PURPOSE Initializes an object with default values. - -template -void Init(TYPE& cValue) -{ - memset(&cValue, 0, sizeof(TYPE)); -} - -//============================================================================== -// FUNCTION: Clear -// PURPOSE Frees memory owned by an object and initializes it. - -template -void Clear(TYPE& cValue) -{ - Init(cValue); -} - -//============================================================================== -// FUNCTION: Copy -// PURPOSE Creates a deep copy of an object, - -template -void Copy(TYPE& cDst, TYPE& cSrc) -{ - cDst = cSrc; -} - -//============================================================================== -// FUNCTION: Read -// PURPOSE Reads an object from an string. - -template -bool Read(const COpcString& cText, TYPE& cValue) -{ - return false; -} - -//============================================================================== -// FUNCTION: Read -// PURPOSE Reads an object from an XML element or attribute. - -template -bool ReadXml(IXMLDOMNode* ipNode, TYPE& cValue) -{ - Clear(cValue); - - if (ipNode == NULL) return false; - - // get node text property. - BSTR bstrText = NULL; - - if (FAILED(ipNode->get_text(&bstrText))) - { - return false; - } - - // convert from string. - bool bResult = Read((LPCWSTR)bstrText, cValue); - SysFreeString(bstrText); - - return bResult; -} - -//============================================================================== -// FUNCTION: Write -// PURPOSE Writes an object with to a string. - -template -bool Write(const TYPE& cValue, COpcString& cText) -{ - return false; -} - -//============================================================================== -// FUNCTION: Write -// PURPOSE Writes an object to an XML element or attribute. - -template -bool WriteXml(IXMLDOMNode* ipNode, const TYPE& cValue) -{ - if (ipNode == NULL) return false; - - // convert to string. - COpcString cText; - - if (!Write(cValue, cText)) - { - return false; - } - - // set node text property. - BSTR bstrText = SysAllocString((LPCWSTR)cText); - HRESULT hResult = ipNode->put_text(bstrText); - SysFreeString(bstrText); - - return SUCCEEDED(hResult); -} - -//============================================================================== -// FUNCTION: Read -// PURPOSE Explicit template implementations for common data types. - -template<> OPCUTILS_API bool Read(const COpcString& cText, SByte& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, Byte& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, Short& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, UShort& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, Int& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, UInt& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, long& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, unsigned long& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, Long& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, ULong& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, Float& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, Double& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, Decimal& cValue); -template<> OPCUTILS_API bool Read(const COpcString& cText, DateTime& cValue); -//template<> OPCUTILS_API bool Read(const COpcString& cText, Date& cValue); -//template<> OPCUTILS_API bool Read