From aed9eda166a5f02bb5de6782225191c582489064 Mon Sep 17 00:00:00 2001 From: Alexander Wollbrink Date: Thu, 26 Sep 2024 08:28:35 +0200 Subject: [PATCH] removing OPCUA --- src/AasSecurity/AasSecurity.csproj | 8 +- .../Properties/launchSettings.json | 2 +- src/AasxServerStandardBib/AasEntityBuilder.cs | 823 ----- src/AasxServerStandardBib/AasNodeManager.cs | 426 --- src/AasxServerStandardBib/AasUaEntities.cs | 1984 ----------- .../AasUaEntities.cs.bak | 1668 --------- .../AasUaEntityFileType.cs | 391 --- src/AasxServerStandardBib/AasUaNodeHelper.cs | 146 - src/AasxServerStandardBib/AasUaUtils.cs | 186 - .../AasxServerStandardBib.csproj | 24 +- .../AasxUaServerOptions.cs | 117 - .../DataChangeMonitoredItem.cs | 826 ----- .../MonitoredItemQueue.cs | 386 --- src/AasxServerStandardBib/MonitoredNode.cs | 382 --- .../NodeStateCollection.cs | 627 ---- .../Opc.Ua.SampleClient.Config.xml | 99 - .../Opc.Ua.SampleServer.Config.xml | 221 -- src/AasxServerStandardBib/Program.cs | 29 +- .../SampleNodeManager.cs | 3013 ----------------- .../SampleServer.SampleModel.cs | 36 - .../SampleServer.UserAuthentication.cs | 179 - src/AasxServerStandardBib/SampleServer.cs | 209 -- .../Services/MetamodelVerificationService.cs | 4 +- src/AasxServerStandardBib/TimeSeries.cs | 37 +- src/AasxServerStandardBib/UASampleClient.cs | 230 -- 25 files changed, 50 insertions(+), 12003 deletions(-) delete mode 100644 src/AasxServerStandardBib/AasEntityBuilder.cs delete mode 100644 src/AasxServerStandardBib/AasNodeManager.cs delete mode 100644 src/AasxServerStandardBib/AasUaEntities.cs delete mode 100644 src/AasxServerStandardBib/AasUaEntities.cs.bak delete mode 100644 src/AasxServerStandardBib/AasUaEntityFileType.cs delete mode 100644 src/AasxServerStandardBib/AasUaNodeHelper.cs delete mode 100644 src/AasxServerStandardBib/AasUaUtils.cs delete mode 100644 src/AasxServerStandardBib/AasxUaServerOptions.cs delete mode 100644 src/AasxServerStandardBib/DataChangeMonitoredItem.cs delete mode 100644 src/AasxServerStandardBib/MonitoredItemQueue.cs delete mode 100644 src/AasxServerStandardBib/MonitoredNode.cs delete mode 100644 src/AasxServerStandardBib/NodeStateCollection.cs delete mode 100644 src/AasxServerStandardBib/Opc.Ua.SampleClient.Config.xml delete mode 100644 src/AasxServerStandardBib/Opc.Ua.SampleServer.Config.xml delete mode 100644 src/AasxServerStandardBib/SampleNodeManager.cs delete mode 100644 src/AasxServerStandardBib/SampleServer.SampleModel.cs delete mode 100644 src/AasxServerStandardBib/SampleServer.UserAuthentication.cs delete mode 100644 src/AasxServerStandardBib/SampleServer.cs delete mode 100644 src/AasxServerStandardBib/UASampleClient.cs diff --git a/src/AasSecurity/AasSecurity.csproj b/src/AasSecurity/AasSecurity.csproj index dd30a721e..ca0f7b9f8 100644 --- a/src/AasSecurity/AasSecurity.csproj +++ b/src/AasSecurity/AasSecurity.csproj @@ -8,12 +8,16 @@ false + + + + - + - + diff --git a/src/AasxServerBlazor/Properties/launchSettings.json b/src/AasxServerBlazor/Properties/launchSettings.json index 62ad90bcc..8647541c0 100644 --- a/src/AasxServerBlazor/Properties/launchSettings.json +++ b/src/AasxServerBlazor/Properties/launchSettings.json @@ -10,7 +10,7 @@ }, "AasxServerBlazor": { "commandName": "Project", - "commandLineArgs": "--with-db --start-index 100000 --save-temp 30 --no-security --secret-string-api 1234 --aasx-in-memory 1000 --data-path \"C:\\Development\\DB\" --edit --external-blazor http://localhost:5001", + "commandLineArgs": "--start-index 100000 --save-temp 30 --no-security --secret-string-api 1234 --aasx-in-memory 1000 --data-path \"C:\\Development\\DB\" --edit --external-blazor http://localhost:5001", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", diff --git a/src/AasxServerStandardBib/AasEntityBuilder.cs b/src/AasxServerStandardBib/AasEntityBuilder.cs deleted file mode 100644 index 1e17f725e..000000000 --- a/src/AasxServerStandardBib/AasEntityBuilder.cs +++ /dev/null @@ -1,823 +0,0 @@ -/* -Copyright (c) 2018-2019 Festo AG & Co. KG -Author: Michael Hoffmeister - -This source code is licensed under the Apache License 2.0 (see LICENSE.txt). - -This source code may use other Open Source software components (see LICENSE.txt). -*/ - - -using AdminShellNS; -using Extensions; -using Opc.Ua; -using System.Collections.Generic; - -namespace AasOpcUaServer -{ - public class AasEntityBuilder - { - //// Static singleton for AAS entity builders - // ugly, but simple: the singleton variables gives access to information - // - public static AasModeManager nodeMgr = null; - - public AdminShellPackageEnv[] packages = null; - - public AasxUaServerOptions theServerOptions = null; - - public IDictionary> nodeMgrExternalReferences = null; - - /// - /// Root of AASes - /// - public NodeState RootAAS = null; - - /// - /// Root for CDs - /// - public NodeState RootConceptDescriptions = null; - - /// - /// Root for DataSpecifications - /// - public NodeState RootDataSpecifications = null; - - /// - /// Provide a root node, if semantic ids shall create missing dictionary entry (targets), - /// which can not be found in the AAS environment. - /// - public NodeState RootMissingDictionaryEntries = null; - - public AasEntityBuilder(AasModeManager nodeMgr, AdminShellPackageEnv[] package, - IDictionary> externalReferences, AasxUaServerOptions options) - { - AasEntityBuilder.nodeMgr = nodeMgr; - this.packages = package; - this.nodeMgrExternalReferences = externalReferences; - this.aasTypes = new AasTypeEntities(); - this.theServerOptions = options; - this.aasTypes.BuildEntites(this); - } - - public class NodeRecord - { - public NodeState uanode = null; - public IReferable referable = null; - public string identification = null; - - public NodeRecord() { } - public NodeRecord(NodeState uanode, IReferable referable) - { - this.uanode = uanode; - this.referable = referable; - } - public NodeRecord(NodeState uanode, string identification) - { - this.uanode = uanode; - this.identification = identification; - } - } - - private Dictionary NodeRecordFromReferable - = new Dictionary(); - private Dictionary NodeRecordFromIdentificationHash - = new Dictionary(); - - /// - /// Use this function always to remeber new node records. - /// - /// - public void AddNodeRecord(NodeRecord nr) - { - if (nr.referable != null && !NodeRecordFromReferable.ContainsKey(nr.referable)) - NodeRecordFromReferable.Add(nr.referable, nr); - - if (nr.identification != null && nr.identification != "") - { - var hash = "" + nr.identification.Trim().ToUpper(); - if (!NodeRecordFromIdentificationHash.ContainsKey(hash)) - NodeRecordFromIdentificationHash.Add(hash, nr); - } - } - - /// - /// Use this always to lookup node records from Referable - /// - /// - /// - public NodeRecord LookupNodeRecordFromReferable(IReferable referable) - { - if (NodeRecordFromReferable == null || !NodeRecordFromReferable.ContainsKey(referable)) - return null; - return NodeRecordFromReferable[referable]; - } - - /// - /// Use this always to lookup node records from Indentifiable - /// - /// - /// - public NodeRecord LookupNodeRecordFromIdentification(string identification) - { - var hash = "" + identification.Trim().ToUpper(); - if (NodeRecordFromReferable == null || !NodeRecordFromIdentificationHash.ContainsKey(hash)) - return null; - return NodeRecordFromIdentificationHash[hash]; - } - - /// - /// Base class for actions, which shall be done on the 2nd pass of the information model building - /// - public class NodeLateAction - { - public NodeState uanode = null; - } - - /// - /// Make a late reference to another node identified by a AAS reference information - /// - public class NodeLateActionLinkToReference : NodeLateAction - { - public enum ActionType { None, SetAasReference, SetDictionaryEntry } - - public Reference targetReference = null; - public ActionType actionType = ActionType.None; - - public NodeLateActionLinkToReference(NodeState uanode, Reference targetReference, - ActionType actionType) - { - this.uanode = uanode; - this.targetReference = targetReference; - this.actionType = actionType; - } - } - - private List noteLateActions = new List(); - - /// - /// Add a late action, which will be processed as 2nd phase of info model preparation - /// - /// - public void AddNodeLateAction(NodeLateAction la) - { - this.noteLateActions.Add(la); - } - - private IReferable FindAllReferableByReference(AdminShellPackageEnv[] packages, - Reference rf) - { - // access - if (packages == null || rf == null) - return null; - - // find - foreach (var pck in packages) - { - var x = pck?.AasEnv?.FindReferableByReference(rf); - if (x != null) - return x; - } - - // oh, no - return null; - } - - /// - /// Top level creation functions. Uses the definitions of RootAAS, RootConceptDescriptions, - /// RootDataSpecifications to synthesize information model - /// - public void CreateAddInstanceObjects(AasCore.Aas3_0.Environment env) - { - if (RootAAS == null) - return; - - // CDs (build 1st to be "remembered" as targets for "HasDictionaryEntry") - if (env.ConceptDescriptions != null && this.RootConceptDescriptions != null) - foreach (var cd in env.ConceptDescriptions) - { - this.AasTypes.ConceptDescription.CreateAddElements(this.RootConceptDescriptions, - AasUaBaseEntity.CreateMode.Instance, cd); - } - - // AAS - if (env.AssetAdministrationShells != null) - foreach (var aas in env.AssetAdministrationShells) - this.AasTypes.AAS.CreateAddInstanceObject(RootAAS, env, aas); - - // go through late actions - foreach (var la in this.noteLateActions) - { - // make a Reference ?? - var lax = la as NodeLateActionLinkToReference; - - // more simple case: AasReference between known entities - if (lax != null && lax.actionType == NodeLateActionLinkToReference.ActionType.SetAasReference - && lax.uanode != null - && this.packages != null) - { - // 1st, take reference and turn it into Referable - var targetReferable = FindAllReferableByReference(this.packages, lax.targetReference); - if (targetReferable == null) - continue; - - // 2nd, try to lookup the Referable and turn it into a uanode - var targetNodeRec = this.LookupNodeRecordFromReferable(targetReferable); - if (targetNodeRec == null || targetNodeRec.uanode == null) - continue; - - // now, we have everything to formulate a reference - if (!lax.uanode.ReferenceExists(this.AasTypes.HasAasReference.GetTypeNodeId(), false, - targetNodeRec.uanode.NodeId)) - { - lax.uanode.AddReference(this.AasTypes.HasAasReference.GetTypeNodeId(), false, - targetNodeRec.uanode.NodeId); - } - } - - // a bit more complicated: could include a "empty reference" to outside concept - if (lax != null && lax.actionType == NodeLateActionLinkToReference.ActionType.SetDictionaryEntry - && lax.uanode != null - && this.packages != null) - { - // tracking - var foundAtAll = false; - - // 1st, take reference and turn it into Referable - var targetReferable = FindAllReferableByReference(this.packages, lax.targetReference); - if (targetReferable != null) - { - // 2nd, try to lookup the Referable and turn it into a uanode - var targetNodeRec = this.LookupNodeRecordFromReferable(targetReferable); - if (targetNodeRec != null && targetNodeRec.uanode != null) - { - // simple case: have a target node, just make a link - if (lax.uanode.ReferenceExists(this.AasTypes.HasDictionaryEntry.GetTypeNodeId(), false, - targetNodeRec.uanode.NodeId)) - { - lax.uanode.AddReference(this.AasTypes.HasDictionaryEntry.GetTypeNodeId(), false, - targetNodeRec.uanode.NodeId); - } - foundAtAll = true; - } - } - - // make "empty reference"?? - // by definition, this makes only sense if the targetReference has exactly 1 key, as we could - // only have one key in a dictionary entry - if (!foundAtAll && lax.targetReference.Keys.Count == 1) - { - // can turn the targetReference to a simple identification - //var targetId = new AdminShellConverters().Identifier(lax.targetReference.Keys[0].Value); - var targetId = lax.targetReference.Keys[0].Value; - - // we might have such an (empty) target already available as uanode - var nr = this.LookupNodeRecordFromIdentification(targetId); - if (nr != null) - { - // just create the missing link - if (!lax.uanode.ReferenceExists(this.AasTypes.HasDictionaryEntry.GetTypeNodeId(), false, - nr.uanode?.NodeId)) - { - lax.uanode.AddReference(this.AasTypes.HasDictionaryEntry.GetTypeNodeId(), false, - nr.uanode?.NodeId); - } - } - else - { - // create NEW empty reference? - if (this.RootMissingDictionaryEntries != null) - { - // create missing object - var miss = this.CreateAddObject( - this.RootMissingDictionaryEntries, - AasUaBaseEntity.CreateMode.Instance, - targetId, - ReferenceTypeIds.HasComponent, - this.AasTypes.ConceptDescription.GetTypeObjectFor(targetId)?.NodeId); - - // add the reference - if (lax.uanode.ReferenceExists(this.AasTypes.HasDictionaryEntry.GetTypeNodeId(), false, - miss?.NodeId)) - { - lax.uanode.AddReference(this.AasTypes.HasDictionaryEntry.GetTypeNodeId(), false, - miss?.NodeId); - } - - // put it into the NodeRecords, that it can be re-used?? no!! - this.AddNodeRecord(new AasEntityBuilder.NodeRecord(miss, targetId)); - } - else - { - // just create the missing link - // TODO (MIHO, 2020-08-06): check, which namespace shall be used - var missingTarget = new ExpandedNodeId("" + targetId, 99); - lax.uanode.AddReference(this.AasTypes.HasDictionaryEntry.GetTypeNodeId(), false, - missingTarget); - } - } - } - } - - } - } - - //// references - // - - // ReSharper disable once UnusedType.Global - public class AasReference : Opc.Ua.IReference - { - // private members - private NodeId referenceTypeId = null; - private bool isInverse = false; - private ExpandedNodeId targetId = null; - - // public getters for IReference - public NodeId ReferenceTypeId { get { return referenceTypeId; } } - public bool IsInverse { get { return isInverse; } } - public ExpandedNodeId TargetId { get { return targetId; } } - - public AasReference() - { - } - - public AasReference(NodeId referenceTypeId, bool isInverse, ExpandedNodeId targetId) - { - this.referenceTypeId = referenceTypeId; - this.isInverse = isInverse; - this.targetId = targetId; - } - } - - //// Reference types - // - - public ReferenceTypeState CreateAddReferenceType( - string browseDisplayName, string inverseName, - uint preferredNumId = 0, bool useZeroNS = false, NodeId sourceId = null) - { - // create node itself - var x = new ReferenceTypeState(); - x.BrowseName = browseDisplayName; - x.DisplayName = browseDisplayName; - x.InverseName = inverseName; - x.Symmetric = false; - x.IsAbstract = false; - x.NodeId = nodeMgr.NewType(nodeMgr.SystemContext, AasUaBaseEntity.CreateMode.Type, x, preferredNumId); - nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, x); - - // set Subtype reference - if (sourceId == null) - sourceId = new NodeId(32, 0); - nodeMgr.AddExternalReferencePublic(sourceId, ReferenceTypeIds.HasSubtype, false, - x.NodeId, nodeMgrExternalReferences); - - // done - return x; - } - - //// Folders - // - - public FolderState CreateAddFolder(AasUaBaseEntity.CreateMode mode, - NodeState parent, string browseDisplayName) - { - var x = new FolderState(parent); - x.BrowseName = browseDisplayName; - x.DisplayName = browseDisplayName; - x.NodeId = nodeMgr.NewFromParent(nodeMgr.SystemContext, mode, x, parent); - x.TypeDefinitionId = ObjectTypeIds.FolderType; - nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, x); - if (parent != null) - parent.AddChild(x); - return x; - } - - //// DataTypes - // - - public DataTypeState CreateAddDataType( - string browseDisplayName, NodeId superTypeId, uint preferredNumId = 0) - { - var x = new DataTypeState(); - x.BrowseName = "" + browseDisplayName; - x.DisplayName = "" + browseDisplayName; - x.Description = new LocalizedText("en", browseDisplayName); - x.SuperTypeId = superTypeId; - x.NodeId = nodeMgr.NewType(nodeMgr.SystemContext, AasUaBaseEntity.CreateMode.Type, x, preferredNumId); - nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, x); - return x; - } - - //// Object types - // - - /// - /// Helper to create an ObjectType-Node and it to the information model. - /// - /// Name displayed in the node tree - /// Base class or similar - /// Numerical id of the node in the default name space to be set fixed - /// Lookup a Description on AAS literal/ refSemantics - /// Modeling Rule, if not None - public BaseObjectTypeState CreateAddObjectType( - string browseDisplayName, - NodeId superTypeId, - uint preferredNumId = 0, - string descriptionKey = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - var x = AasUaNodeHelper.CreateObjectType(browseDisplayName, superTypeId, descriptionKey: descriptionKey); - x.NodeId = nodeMgr.NewType(nodeMgr.SystemContext, AasUaBaseEntity.CreateMode.Type, - x, preferredNumId); - nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, x); - return x; - } - - //// Variable types - // - - public class AasVariableTypeState : BaseVariableTypeState - { - // ReSharper disable once EmptyConstructor - public AasVariableTypeState() - : base() - { } - } - - public AasVariableTypeState CreateAddVariableType(string browseDisplayName, NodeId superTypeId, - uint preferredNumId = 0) - { - var x = new AasVariableTypeState(); - x.BrowseName = "" + browseDisplayName; - x.DisplayName = "" + browseDisplayName; - x.Description = new LocalizedText("en", browseDisplayName); - x.SuperTypeId = superTypeId; - x.NodeId = nodeMgr.NewType(nodeMgr.SystemContext, AasUaBaseEntity.CreateMode.Type, - x, preferredNumId); - - nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, x); - return x; - } - - //// Objects - // - - /// - /// Helper to create an Object-Node. Note: __NO__ NodeId is created by the default! Must be done by outer - /// functionality!! - /// - /// Parent node - /// Type or instance - /// Name displayed in the node tree - /// - /// Type of the Object - /// Modeling Rule, if not None - /// - /// The node - public BaseObjectState CreateAddObject( - NodeState parent, AasUaBaseEntity.CreateMode mode, - string browseDisplayName, - NodeId referenceTypeFromParentId = null, - NodeId typeDefinitionId = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None, - string extraName = null) - { - var x = AasUaNodeHelper.CreateObject(parent, browseDisplayName, typeDefinitionId: typeDefinitionId, - modellingRule: modellingRule, extraName: extraName); - x.NodeId = nodeMgr.NewFromParent(nodeMgr.SystemContext, mode, x, parent); - nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, x); - if (parent != null) - parent.AddChild(x); - - if (referenceTypeFromParentId != null) - { - if (parent != null) - { - if (!parent.ReferenceExists(referenceTypeFromParentId, false, x.NodeId)) - parent.AddReference(referenceTypeFromParentId, false, x.NodeId); - if (referenceTypeFromParentId == ReferenceTypeIds.HasComponent) - x.AddReference(referenceTypeFromParentId, true, parent.NodeId); - if (referenceTypeFromParentId == ReferenceTypeIds.HasProperty) - x.AddReference(referenceTypeFromParentId, true, parent.NodeId); - } - - //// nodeMgr.AddReference(parentNodeId, new AasReference(referenceTypeId, false, x.NodeId)); - } - - //// if (typeDefinitionId != null) - //// { - //// x.TypeDefinitionId = typeDefinitionId; - //// x.AddReference(ReferenceTypeIds.HasTypeDefinition, false, typeDefinitionId); - //// // nodeMgr.AddReference(x.NodeId, new AasReference(ReferenceTypeIds.HasTypeDefinition, false, - //// // typeDefinitionId)); - //// } - - return x; - } - - //// Properties - // - - /// - /// Helper to create an PropertyState-Node for a certain type and add it to the information model. - /// Note: __NO__ NodeId is created by the default! Must be done by outer functionality!! - /// - /// C# type of the proprty - /// Parent node - /// Type or instance - /// Name displayed in the node tree - /// Data type, such as String.. Given by DataTypeIds... - /// Value of the type T or Null - /// - /// Type definition; independent from DataType! - /// -1 or e.g. 1 for array - /// Apply default settings for a normal Property - /// Modeling Rule, if not None - /// NodeState - public PropertyState CreateAddPropertyState( - NodeState parent, AasUaBaseEntity.CreateMode mode, - string browseDisplayName, - NodeId dataTypeId, T value, - NodeId referenceTypeFromParentId = null, - NodeId typeDefinitionId = null, - int valueRank = -2, - bool defaultSettings = false, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - // apply cumulative settings - if (defaultSettings) - { - referenceTypeFromParentId = ReferenceTypeIds.HasProperty; - typeDefinitionId = VariableTypeIds.PropertyType; - if (valueRank == -2) - valueRank = -1; - } - - // make Property - var x = new PropertyState(parent); - x.BrowseName = "" + browseDisplayName; - x.DisplayName = "" + browseDisplayName; - x.Description = new LocalizedText("en", browseDisplayName); - x.DataType = dataTypeId; - if (valueRank > -2) - x.ValueRank = valueRank; - // ReSharper disable once RedundantCast - x.Value = (T)value; - AasUaNodeHelper.CheckSetModellingRule(modellingRule, x); - x.NodeId = nodeMgr.NewFromParent(nodeMgr.SystemContext, mode, x, parent); - - // add Node - nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, x); - if (parent != null) - parent.AddChild(x); - - // set relations - if (referenceTypeFromParentId != null) - { - if (parent != null) - { - if (!parent.ReferenceExists(referenceTypeFromParentId, false, x.NodeId)) - { - parent.AddReference(referenceTypeFromParentId, false, x.NodeId); - } - if (referenceTypeFromParentId == ReferenceTypeIds.HasComponent) - x.AddReference(referenceTypeFromParentId, true, parent.NodeId); - if (referenceTypeFromParentId == ReferenceTypeIds.HasProperty) - x.AddReference(referenceTypeFromParentId, true, parent.NodeId); - } - } - if (typeDefinitionId != null) - { - x.TypeDefinitionId = typeDefinitionId; - } - - x.AccessLevel = AccessLevels.CurrentReadOrWrite; - x.UserAccessLevel = AccessLevels.CurrentReadOrWrite; - - return x; - } - - public MethodState CreateAddMethodState( - NodeState parent, AasUaBaseEntity.CreateMode mode, - string browseDisplayName, - Argument[] inputArgs = null, Argument[] outputArgs = null, NodeId referenceTypeFromParentId = null, - NodeId methodDeclarationId = null, GenericMethodCalledEventHandler onCalled = null) - { - // method node - var m = new MethodState(parent); - m.BrowseName = "" + browseDisplayName; - m.DisplayName = "" + browseDisplayName; - m.Description = new LocalizedText("en", browseDisplayName); - m.NodeId = nodeMgr.NewFromParent(nodeMgr.SystemContext, mode, m, parent); - if (methodDeclarationId != null) - m.MethodDeclarationId = methodDeclarationId; - - m.Executable = true; - m.UserExecutable = true; - - nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, m); - if (parent != null) - parent.AddChild(m); - - if (referenceTypeFromParentId != null) - { - if (parent != null) - { - parent.AddReference(referenceTypeFromParentId, false, m.NodeId); - if (referenceTypeFromParentId == ReferenceTypeIds.HasComponent) - m.AddReference(referenceTypeFromParentId, true, parent.NodeId); - if (referenceTypeFromParentId == ReferenceTypeIds.HasProperty) - m.AddReference(referenceTypeFromParentId, true, parent.NodeId); - } - } - - // can have inputs, outputs - for (int i = 0; i < 2; i++) - { - // pretty argument list - var arguments = (i == 0) ? inputArgs : outputArgs; - if (arguments == null || arguments.Length < 1) - continue; - - // make a property for this - var prop = CreateAddPropertyState( - m, mode, - (i == 0) ? "InputArguments" : "OutputArguments", - DataTypeIds.Argument, - arguments, - ReferenceTypeIds.HasProperty, - typeDefinitionId: VariableTypeIds.PropertyType, - valueRank: 1); - - // explicitely add arguments ass well? - if (i == 0) - m.InputArguments = prop; - - if (i == 1) - m.OutputArguments = prop; - - } - - // event handler - if (onCalled != null) - m.OnCallMethod = onCalled; - - - return m; - } - - - //// Entities - // - - public class AasTypeEntities - { - public AasUaEntityPathType PathType; - public AasUaEntityMimeType MimeType; - - public AasUaEntityIdentification Identification; - public AasUaEntityAdministration Administration; - public AasUaEntityQualifier Qualifier; - public AasUaEntityAssetKind AssetKind; - public AasUaEntityModelingKind ModelingKind; - public AasUaEntityReferable Referable; - public AasUaEntityReferenceBase ReferenceBase; - public AasUaEntityReference Reference; - public AasUaEntitySemanticId SemanticId; - public AasUaEntitySubmodel Submodel; - public AasUaEntityProperty Property; - public AasUaEntityCollection Collection; - public AasUaEntitySubmodelElement SubmodelElement; - public AasUaEntitySubmodelWrapper SubmodelWrapper; - public AasUaEntityFile File; - public AasUaEntityFileType FileType; - public AasUaEntityBlob Blob; - public AasUaEntityReferenceElement ReferenceElement; - public AasUaEntityRelationshipElement RelationshipElement; - public AasUaEntityOperationVariable OperationVariable; - public AasUaEntityOperation Operation; - public AasUaEntityConceptDescription ConceptDescription; - public AasUaEntityAsset Asset; - public AasUaEntityAAS AAS; - - public AasUaEntityDataSpecification DataSpecification; - public AasUaEntityDataSpecificationIEC61360 DataSpecificationIEC61360; - - public AasUaInterfaceAASIdentifiableType IAASIdentifiableType; - public AasUaInterfaceAASReferableType IAASReferableType; - - public AasUaNamespaceZeroEntity BaseInterfaceType; - - public AasUaNamespaceZeroReference HasDictionaryEntry; - public AasUaReferenceHasAasReference HasAasReference; - public AasUaNamespaceZeroReference HasInterface; - public AasUaNamespaceZeroReference HasAddIn; - public AasUaNamespaceZeroEntity DictionaryEntryType; - public AasUaNamespaceZeroEntity UriDictionaryEntryType; - public AasUaNamespaceZeroEntity IrdiDictionaryEntryType; - public AasUaNamespaceZeroEntity DictionaryFolderType; - - public void BuildEntites(AasEntityBuilder builder) - { - // build up entities, which are in the UA specs, but not in this Stack - BaseInterfaceType = new AasUaNamespaceZeroEntity(builder, 17602); - HasDictionaryEntry = new AasUaNamespaceZeroReference(builder, 17597); - HasInterface = new AasUaNamespaceZeroReference(builder, 17603); - HasAddIn = new AasUaNamespaceZeroReference(builder, 17604); - DictionaryEntryType = new AasUaNamespaceZeroEntity(builder, 17589); - UriDictionaryEntryType = new AasUaNamespaceZeroEntity(builder, 17600); - IrdiDictionaryEntryType = new AasUaNamespaceZeroEntity(builder, 17598); - DictionaryFolderType = new AasUaNamespaceZeroEntity(builder, 17591); - - // AAS DataTypes - PathType = new AasUaEntityPathType(builder); - MimeType = new AasUaEntityMimeType(builder); - - // first entities - Referable = new AasUaEntityReferable(builder, 1004); - Identification = new AasUaEntityIdentification(builder, 1000); - Administration = new AasUaEntityAdministration(builder, 1001); - - // interfaces - IAASReferableType = new AasUaInterfaceAASReferableType( - builder, 2001); // dependencies: Referable - IAASIdentifiableType = new AasUaInterfaceAASIdentifiableType( - builder, 2000); // dependencies: IAASReferable - - // AAS References - ReferenceBase = new AasUaEntityReferenceBase(builder, 0); - Reference = new AasUaEntityReference(builder, 1005); - SemanticId = new AasUaEntitySemanticId(builder, 1006); // dependecies: Reference - HasAasReference = new AasUaReferenceHasAasReference(builder, 4000); // dependencies: Referable - - // Data Specifications - DataSpecification = new AasUaEntityDataSpecification(builder, 3000); - DataSpecificationIEC61360 = new AasUaEntityDataSpecificationIEC61360( - builder, 3001); // dependencies: Reference, Identification, Administration - - // rest - Qualifier = new AasUaEntityQualifier(builder, 1002); // dependencies: SemanticId, Reference - AssetKind = new AasUaEntityAssetKind(builder, 1025); - ModelingKind = new AasUaEntityModelingKind(builder, 1003); - SubmodelElement = new AasUaEntitySubmodelElement(builder, 1008); - SubmodelWrapper = new AasUaEntitySubmodelWrapper(builder, 1012); // dependencies: SubmodelElement - Submodel = new AasUaEntitySubmodel(builder, 1007); // dependencies: SubmodelWrapper - Property = new AasUaEntityProperty(builder, 1009); - Collection = new AasUaEntityCollection(builder, 1010); // needs 2 ids! - FileType = new AasUaEntityFileType(builder, 1014); - File = new AasUaEntityFile(builder, 1013); // dependencies: FileType - Blob = new AasUaEntityBlob(builder, 1015); - ReferenceElement = new AasUaEntityReferenceElement(builder, 1016); - RelationshipElement = new AasUaEntityRelationshipElement(builder, 1017); - OperationVariable = new AasUaEntityOperationVariable(builder, 1018); - Operation = new AasUaEntityOperation(builder, 1019); - //TODO:Remove - //ConceptDictionary = new AasUaEntityConceptDictionary(builder, 1020); - ConceptDescription = new AasUaEntityConceptDescription(builder, 1021); - //TODO:Remove - //View = new AasUaEntityView(builder, 1022); - Asset = new AasUaEntityAsset(builder, 1023); - AAS = new AasUaEntityAAS(builder, 1024); - } - } - - private AasTypeEntities aasTypes = null; - public AasTypeEntities AasTypes { get { return aasTypes; } } - - //// Annotations - // - - private Dictionary> nodeStateAnnotations = new Dictionary>(); - - public void AddNodeStateAnnotation(NodeState nodeState, object businessObject) - { - if (!nodeStateAnnotations.ContainsKey(nodeState)) - nodeStateAnnotations[nodeState] = new List(); - nodeStateAnnotations[nodeState].Add(businessObject); - } - - public void RemoveNodeStateAnnotation(NodeState nodeState, object businessObject) - { - if (!nodeStateAnnotations.ContainsKey(nodeState)) - return; - if (nodeStateAnnotations[nodeState].Contains(businessObject)) - nodeStateAnnotations[nodeState].Remove(businessObject); - } - - public T FindNoteStateAnnotation(NodeState nodeState) where T : class - { - if (nodeState == null) - return null; - if (!nodeStateAnnotations.ContainsKey(nodeState)) - return null; - foreach (var bo in nodeStateAnnotations[nodeState]) - if (bo is T) - return bo as T; - return null; - } - - } - -} diff --git a/src/AasxServerStandardBib/AasNodeManager.cs b/src/AasxServerStandardBib/AasNodeManager.cs deleted file mode 100644 index c1772f09d..000000000 --- a/src/AasxServerStandardBib/AasNodeManager.cs +++ /dev/null @@ -1,426 +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 AdminShellNS; -using Opc.Ua; -using Opc.Ua.Sample; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; - -namespace AasOpcUaServer -{ - /// - /// A node manager the diagnostic information exposed by the server. - /// - public class AasModeManager : SampleNodeManager - { - private AdminShellPackageEnv[] thePackageEnv = null; - private AasxUaServerOptions theServerOptions = null; - - #region Constructors - /// - /// Initializes the node manager. - /// - public AasModeManager( - Opc.Ua.Server.IServerInternal server, - ApplicationConfiguration configuration, - AdminShellPackageEnv[] env, - AasxUaServerOptions serverOptions = null) - : - base(server) - { - thePackageEnv = env; - theServerOptions = serverOptions; - - List namespaceUris = new List(); - namespaceUris.Add("http://opcfoundation.org/UA/i4aas/"); - namespaceUris.Add("http://admin-shell.io/samples/i4aas/instance/"); - // ReSharper disable once VirtualMemberCallInConstructor - NamespaceUris = namespaceUris; - - m_typeNamespaceIndex = Server.NamespaceUris.GetIndexOrAppend(namespaceUris[0]); - m_namespaceIndex = Server.NamespaceUris.GetIndexOrAppend(namespaceUris[1]); - - m_lastUsedId = 0; - } - #endregion - - #region INodeIdFactory Members - /// - /// Creates the NodeId for the specified node. - /// - /// The context. - /// Type or instance - /// The node. - /// The new NodeId. - public NodeId New(ISystemContext context, AasUaBaseEntity.CreateMode mode, NodeState node) - { - if (mode == AasUaBaseEntity.CreateMode.Type) - { - uint id = Utils.IncrementIdentifier(ref m_lastUsedId); - return new NodeId(id, m_typeNamespaceIndex); - } - else - { - uint id = Utils.IncrementIdentifier(ref m_lastUsedId); - return new NodeId(id, m_namespaceIndex); - } - } - #endregion - - public NodeId NewFromParent(ISystemContext context, AasUaBaseEntity.CreateMode mode, NodeState node, NodeState parent) - { - // create known node ids from the full path in the AAS - // causes an exception if anything has more than one qualifier! - if (parent == null) - { - return new NodeId(node.BrowseName.Name, m_namespaceIndex); - } - if (node.BrowseName.Name == "Qualifier") - { - return New(context, mode, node); - } - else - { - return new NodeId(parent.NodeId.Identifier.ToString() + "." + node.BrowseName.Name, m_namespaceIndex); - } - } - - public NodeId NewType(ISystemContext context, AasUaBaseEntity.CreateMode mode, - NodeState node, uint preferredNumId = 0) - { - uint id = preferredNumId; - if (id == 0) - id = Utils.IncrementIdentifier(ref m_lastUsedTypeId); - // this is thought to be a BUG in the OPCF code - //// return new NodeId(preferredNumId, m_typeNamespaceIndex); - if (mode == AasUaBaseEntity.CreateMode.Type) - return new NodeId(id, m_typeNamespaceIndex); - else - return new NodeId(id, m_namespaceIndex); - } - - public void SaveNodestateCollectionAsNodeSet2(ISystemContext context, NodeStateCollection nsc, Stream stream, - bool filterSingleNodeIds) - { - Opc.Ua.Export.UANodeSet nodeSet = new Opc.Ua.Export.UANodeSet(); - nodeSet.LastModified = DateTime.UtcNow; - nodeSet.LastModifiedSpecified = true; - - foreach (var n in nsc) - nodeSet.Export(context, n); - - if (filterSingleNodeIds) - { - // MIHO: There might be DOUBLE nodeIds in the the set!!!!!!!!!! WTF!!!!!!!!!!!!! - // Brutally eliminate them - var nodup = new List(); - foreach (var it in nodeSet.Items) - { - var found = false; - foreach (var it2 in nodup) - if (it.NodeId == it2.NodeId) - found = true; - if (found) - continue; - nodup.Add(it); - } - nodeSet.Items = nodup.ToArray(); - } - - nodeSet.Write(stream); - } - - #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) - { - base.CreateAddressSpace(externalReferences); - - // Note: might be helpful for debugging - //// var env = new AdminShell.PackageEnv("Festo-USB-stick-sample-admin-shell.aasx"); - - if (true) - { - var builder = new AasEntityBuilder(this, thePackageEnv, null, this.theServerOptions); - - // Root of whole structure is special, needs to link to external reference - builder.RootAAS = builder.CreateAddFolder(AasUaBaseEntity.CreateMode.Instance, null, "AASROOT"); - // Note: this is TOTALLY WEIRD, but it establishes an inverse reference .. somehow - this.AddExternalReferencePublic(new NodeId(85, 0), ReferenceTypeIds.Organizes, false, - builder.RootAAS.NodeId, externalReferences); - this.AddExternalReferencePublic(builder.RootAAS.NodeId, ReferenceTypeIds.Organizes, true, - new NodeId(85, 0), externalReferences); - - - // Folders for DataSpecs - // DO NOT USE THIS FEATURE -> Data Spec are "under" the CDs - //// builder.RootDataSpecifications = builder.CreateAddFolder( - //// builder.RootAAS, "DataSpecifications"); - //// builder.RootDataSpecifications = builder.CreateAddObject( - //// builder.RootAAS, "DataSpecifications"); - - if (false) - // ReSharper disable once HeuristicUnreachableCode -#pragma warning disable 162 - { - // Folders for Concept Descriptions - // ReSharper disable once HeuristicUnreachableCode - builder.RootConceptDescriptions = builder.CreateAddFolder( - AasUaBaseEntity.CreateMode.Instance, - builder.RootAAS, "ConceptDescriptions"); - - // create missing dictionary entries - builder.RootMissingDictionaryEntries = builder.CreateAddFolder( - AasUaBaseEntity.CreateMode.Instance, - builder.RootAAS, "DictionaryEntries"); - } -#pragma warning restore 162 - else - { - // create folder(s) under root - var topOfDict = builder.CreateAddObject(null, - AasOpcUaServer.AasUaBaseEntity.CreateMode.Instance, "Dictionaries", - referenceTypeFromParentId: null, - typeDefinitionId: builder.AasTypes.DictionaryFolderType.GetTypeNodeId()); - // Note: this is TOTALLY WEIRD, but it establishes an inverse reference .. somehow - // 2253 = Objects? - this.AddExternalReferencePublic(new NodeId(2253, 0), - ReferenceTypeIds.HasComponent, false, topOfDict.NodeId, externalReferences); - this.AddExternalReferencePublic(topOfDict.NodeId, - ReferenceTypeIds.HasComponent, true, new NodeId(2253, 0), externalReferences); - - // now, create a dictionary under .. - // Folders for Concept Descriptions - builder.RootConceptDescriptions = builder.CreateAddObject(topOfDict, - AasOpcUaServer.AasUaBaseEntity.CreateMode.Instance, "ConceptDescriptions", - referenceTypeFromParentId: ReferenceTypeIds.HasComponent, - typeDefinitionId: builder.AasTypes.DictionaryFolderType.GetTypeNodeId()); - - // create missing dictionary entries - builder.RootMissingDictionaryEntries = builder.CreateAddObject(topOfDict, - AasOpcUaServer.AasUaBaseEntity.CreateMode.Instance, "DictionaryEntries", - referenceTypeFromParentId: ReferenceTypeIds.HasComponent, - typeDefinitionId: builder.AasTypes.DictionaryFolderType.GetTypeNodeId()); - } - - // start process - foreach (var ee in thePackageEnv) - { - if (ee != null) - builder.CreateAddInstanceObjects(ee.AasEnv); - } - } - - // Try: ensure the reverse refernces exist. - //// AddReverseReferences(externalReferences); - - if (theServerOptions != null - && theServerOptions.SpecialJob == AasxUaServerOptions.JobType.ExportNodesetXml) - { - try - { - // empty list - var nodesToExport = new NodeStateCollection(); - - // apply filter criteria - foreach (var y in this.PredefinedNodes) - { - var node = y.Value; - if (theServerOptions.ExportFilterNamespaceIndex != null - && !theServerOptions.ExportFilterNamespaceIndex.Contains(node.NodeId.NamespaceIndex)) - continue; - nodesToExport.Add(node); - } - - // export - Utils.Trace("Writing export file: " + theServerOptions.ExportFilename); - var stream = new StreamWriter(theServerOptions.ExportFilename); - - //// nodesToExport.SaveAsNodeSet2(this.SystemContext, stream.BaseStream, null, - //// theServerOptions != null && theServerOptions.FilterForSingleNodeIds); - - //// nodesToExport.SaveAsNodeSet2(this.SystemContext, stream.BaseStream); - SaveNodestateCollectionAsNodeSet2(this.SystemContext, nodesToExport, stream.BaseStream, - theServerOptions != null && theServerOptions.FilterForSingleNodeIds); - - try - { - stream.Close(); - } - catch (Exception ex) - { - AdminShellNS.LogInternally.That.SilentlyIgnoredError(ex); - } - - // stop afterwards - if (theServerOptions.FinalizeAction != null) - { - Utils.Trace("Requesting to shut down application.."); - theServerOptions.FinalizeAction(); - } - - } - catch (Exception ex) - { - Utils.Trace(ex, "When exporting to {0}", "" + theServerOptions.ExportFilename); - } - - // shutdown .. - - } - - Debug.WriteLine("Done creating custom address space!"); - Utils.Trace("Done creating custom address space!"); - } - } - - public NodeStateCollection GenerateInjectNodeStates() - { - // new list - var res = new NodeStateCollection(); - - // Missing Object Types - res.Add(AasUaNodeHelper.CreateObjectType("BaseInterfaceType", - ObjectTypeIds.BaseObjectType, new NodeId(17602, 0))); - res.Add(AasUaNodeHelper.CreateObjectType("DictionaryFolderType", - ObjectTypeIds.FolderType, new NodeId(17591, 0))); - res.Add(AasUaNodeHelper.CreateObjectType("DictionaryEntryType", - ObjectTypeIds.BaseObjectType, new NodeId(17589, 0))); - res.Add(AasUaNodeHelper.CreateObjectType("UriDictionaryEntryType", - new NodeId(17589, 0), new NodeId(17600, 0))); - res.Add(AasUaNodeHelper.CreateObjectType("IrdiDictionaryEntryType", - new NodeId(17589, 0), new NodeId(17598, 0))); - - // Missing Reference Types - res.Add(AasUaNodeHelper.CreateReferenceType("HasDictionaryEntry", "DictionaryEntryOf", - ReferenceTypeIds.NonHierarchicalReferences, new NodeId(17597, 0))); - res.Add(AasUaNodeHelper.CreateReferenceType("HasInterface", "InterfaceOf", - ReferenceTypeIds.NonHierarchicalReferences, new NodeId(17603, 0))); - res.Add(AasUaNodeHelper.CreateReferenceType("HasAddIn", "AddInOf", - ReferenceTypeIds.HasComponent, new NodeId(17604, 0))); - - // deliver list - return res; - } - - public void AddReference(NodeId node, Opc.Ua.IReference reference) - { - var dict = new Dictionary>(); - // ReSharper disable once RedundantExplicitArrayCreation - dict.Add(node, new List(new Opc.Ua.IReference[] { reference })); - this.AddReferences(dict); - } - - /// - /// 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(); - return predefinedNodes; - } - - /// - /// Replaces the generic node with a node specific to the model. - /// - protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context, NodeState predefinedNode) - { - return predefinedNode; - } - - /// - /// Does any processing after a monitored item is created. - /// - protected override void OnCreateMonitoredItem( - ISystemContext systemContext, - MonitoredItemCreateRequest itemToCreate, - MonitoredNode monitoredNode, - DataChangeMonitoredItem monitoredItem) - { - // TBD - } - - /// - /// Does any processing after a monitored item is created. - /// - protected override void OnModifyMonitoredItem( - ISystemContext systemContext, - MonitoredItemModifyRequest itemToModify, - MonitoredNode monitoredNode, - DataChangeMonitoredItem monitoredItem, - double previousSamplingInterval) - { - // TBD - } - - /// - /// Does any processing after a monitored item is deleted. - /// - protected override void OnDeleteMonitoredItem( - ISystemContext systemContext, - MonitoredNode monitoredNode, - DataChangeMonitoredItem monitoredItem) - { - // TBD - } - - /// - /// Does any processing after a monitored item is created. - /// - protected override void OnSetMonitoringMode( - ISystemContext systemContext, - MonitoredNode monitoredNode, - DataChangeMonitoredItem monitoredItem, - MonitoringMode previousMode, - MonitoringMode currentMode) - { - // TBD - } - #endregion - - #region Private Fields - private ushort m_namespaceIndex; - private ushort m_typeNamespaceIndex; - private long m_lastUsedId; - private long m_lastUsedTypeId; - #endregion - } -} diff --git a/src/AasxServerStandardBib/AasUaEntities.cs b/src/AasxServerStandardBib/AasUaEntities.cs deleted file mode 100644 index 53d91ea15..000000000 --- a/src/AasxServerStandardBib/AasUaEntities.cs +++ /dev/null @@ -1,1984 +0,0 @@ -/* -Copyright (c) 2018-2019 Festo AG & Co. KG -Author: Michael Hoffmeister - -This source code is licensed under the Apache License 2.0 (see LICENSE.txt). - -This source code may use other Open Source software components (see LICENSE.txt). -*/ - - -using Extensions; -using Opc.Ua; -using System; -using System.Collections.Generic; -using System.Globalization; -using AAS = AasCore.Aas3_0; - -// TODO (MIHO, 2020-08-29): The UA mapping needs to be overworked in order to comply the joint aligment with I4AAS -// TODO (MIHO, 2020-08-29): The UA mapping needs to be checked for the "new" HasDataSpecification strcuture of V2.0.1 - -namespace AasOpcUaServer -{ - public class AasUaBaseEntity - { - public enum CreateMode { Type, Instance }; - - /// - /// Reference back to the entity builder - /// - protected AasEntityBuilder entityBuilder = null; - - public AasUaBaseEntity(AasEntityBuilder entityBuilder) - { - this.entityBuilder = entityBuilder; - } - - /// - /// Typically the node of the entity in the AAS type object space - /// - protected NodeState typeObject = null; - - /// - /// If the entitiy does not have a direct type object, the object id instead (for pre-defined objects) - /// - protected NodeId typeObjectId = null; - - /// - /// Getter of the type object - /// - public NodeState GetTypeObject() - { - return typeObject; - } - - /// - /// Getter of the type object id, either directly or via the type object (if avilable) - /// - /// - public NodeId GetTypeNodeId() - { - if (typeObjectId != null) - return typeObjectId; - if (typeObject == null) - return null; - return typeObject.NodeId; - } - } - - public class AasUaEntityPathType : AasUaBaseEntity - { - public AasUaEntityPathType(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type elements - this.typeObject = this.entityBuilder.CreateAddDataType("AASPathType", DataTypeIds.String); - } - } - - public class AasUaEntityMimeType : AasUaBaseEntity - { - public AasUaEntityMimeType(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type elements - this.typeObject = this.entityBuilder.CreateAddDataType("AASMimeType", DataTypeIds.String); - } - } - - public class AasUaEntityIdentification : AasUaBaseEntity - { - public AasUaEntityIdentification(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASIdentifierType", - ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:Identifier"); - // add some elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "IdType", - DataTypeIds.String, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "Id", - DataTypeIds.String, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, - string identification = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - var o = this.entityBuilder.CreateAddObject(parent, mode, "Identification", - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - - if (mode == CreateMode.Instance) - { - if (identification != null) - { - //this.entityBuilder.CreateAddPropertyState(o, mode, "IdType", - // DataTypeIds.String, "" + "" + identification.IdType, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, mode, "Id", - DataTypeIds.String, "" + "" + identification, defaultSettings: true); - } - } - - return o; - } - } - - public class AasUaEntityAdministration : AasUaBaseEntity - { - public AasUaEntityAdministration(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASAdministrativeInformationType", - ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:AdministrativeInformation"); - // add some elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "Version", - DataTypeIds.String, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "Revision", - DataTypeIds.String, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, - IAdministrativeInformation administration = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - // Create whole object only if required - if (mode == CreateMode.Instance && administration == null) - return null; - - var o = this.entityBuilder.CreateAddObject(parent, mode, "Administration", - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - - if (mode == CreateMode.Instance) - { - if (administration == null) - return null; - this.entityBuilder.CreateAddPropertyState(o, mode, "Version", - DataTypeIds.String, "" + "" + administration.Version, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, mode, "Revision", - DataTypeIds.String, "" + "" + administration.Revision, defaultSettings: true); - } - - return o; - } - } - - public class AasUaEntityQualifier : AasUaBaseEntity - { - public AasUaEntityQualifier(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASQualifierType", - ObjectTypeIds.BaseObjectType, preferredTypeNumId, "AAS:Qualifier"); - - // add some elements - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(this.typeObject, - CreateMode.Type, null, "SemanticId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "Type", - DataTypeIds.String, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "Value", - DataTypeIds.String, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, - null, "ValueId", AasUaNodeHelper.ModellingRule.Optional); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, IQualifier qualifier = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - // Create whole object only if required - if (mode == CreateMode.Instance && qualifier == null) - return null; - - if (mode == CreateMode.Type) - { - // plain - var o = this.entityBuilder.CreateAddObject(parent, mode, "Qualifier", ReferenceTypeIds.HasComponent, - GetTypeObject().NodeId, modellingRule: modellingRule); - return o; - } - else - { - // need data - if (qualifier == null) - return null; - - // do a little extra? - string extraName = null; - if (qualifier.Type != null && qualifier.Type.Length > 0) - { - extraName = "Qualifier:" + qualifier.Type; - if (qualifier.Value != null && qualifier.Value.Length > 0) - extraName += "=" + qualifier.Value; - } - - var o = this.entityBuilder.CreateAddObject(parent, mode, "Qualifier", - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule, - extraName: extraName); - - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(o, - CreateMode.Instance, qualifier.SemanticId, "SemanticId"); - this.entityBuilder.CreateAddPropertyState(o, mode, "Type", - DataTypeIds.String, "" + qualifier.Type, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.String, "" + qualifier.Value, defaultSettings: true); - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, - CreateMode.Instance, qualifier.ValueId, "ValueId"); - - return o; - } - - } - } - - public class AasUaEntityAssetKind : AasUaBaseEntity - { - public AasUaEntityAssetKind(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - // no special type here (is a string) - } - - //public NodeState CreateAddElements(NodeState parent, CreateMode mode, AssetKind kind = null, - // TODO (jtikekar, 2023-09-04): What should be the default of AssetKind - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AssetKind kind = AssetKind.Type, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (mode == CreateMode.Instance) - return null; - - var o = this.entityBuilder.CreateAddPropertyState(parent, mode, "Kind", - DataTypeIds.String, (mode == CreateMode.Type) ? null : "" + kind, defaultSettings: true, - modellingRule: modellingRule); - - return o; - } - } - - public class AasUaEntityModelingKind : AasUaBaseEntity - { - public AasUaEntityModelingKind(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - // no special type here (is a string) - } - - //public NodeState CreateAddElements(NodeState parent, CreateMode mode, ModelingKind kind = null, - // TODO (jtikekar, 2023-09-04): default value of ModellingKind - public NodeState CreateAddElements(NodeState parent, CreateMode mode, ModellingKind kind = ModellingKind.Template, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (mode == CreateMode.Instance) - return null; - - var o = this.entityBuilder.CreateAddPropertyState(parent, mode, "Kind", - DataTypeIds.String, (mode == CreateMode.Type) ? null : "" + kind, defaultSettings: true, - modellingRule: modellingRule); - - return o; - } - } - - public class AasUaEntityReferable : AasUaBaseEntity - { - public AasUaEntityReferable(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // NO type object required - // see IAASReferable interface - } - - /// - /// This adds all Referable attributes to the parent and re-defines the descriptons - /// - public NodeState CreateAddElements(NodeState parent, CreateMode mode, IReferable refdata = null) - { - if (parent == null) - return null; - if (mode == CreateMode.Instance && refdata == null) - return null; - - if (mode == CreateMode.Type || refdata?.Category != null) - this.entityBuilder.CreateAddPropertyState(parent, mode, "Category", - DataTypeIds.String, (mode == CreateMode.Type) ? null : "" + refdata?.Category, - defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - // No idShort as typically in the DisplayName of the node - - if (mode == CreateMode.Instance) - { - // now, re-set the description on the parent - // ISSUE: only ONE language supported! - parent.Description = AasUaUtils.GetBestUaDescriptionFromAasDescription(refdata?.Description); - } - - return null; - } - } - - public class AasUaEntityReferenceBase : AasUaBaseEntity - { - public AasUaEntityReferenceBase(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // nothing, only used to share code - } - - /// - /// Sets the "Keys" value information of an AAS Reference. This is especially important for referencing - /// outwards of the AAS (environment). - /// - public void CreateAddKeyElements(NodeState parent, CreateMode mode, List keys = null) - { - if (parent == null) - return; - - // MIHO: open62541 does not to process Values as string[], therefore change it temporarily - - if (this.entityBuilder != null && this.entityBuilder.theServerOptions != null - && this.entityBuilder.theServerOptions.ReferenceKeysAsSingleString) - { - // fix for open62541 - var keyo = this.entityBuilder.CreateAddPropertyState(parent, mode, "Values", - DataTypeIds.String, null, defaultSettings: true); - - if (mode == CreateMode.Instance && keyo != null) - { - Reference newRef = new Reference(AasCore.Aas3_0.ReferenceTypes.ExternalReference, keys); - keyo.Value = AasUaUtils.ToOpcUaReference(newRef); - } - } - else - { - // default behaviour - var keyo = this.entityBuilder?.CreateAddPropertyState(parent, mode, "Values", - DataTypeIds.Structure, null, defaultSettings: true); - - if (mode == CreateMode.Instance && keyo != null) - { - Reference newRef = new Reference(AasCore.Aas3_0.ReferenceTypes.ModelReference, keys); - keyo.Value = AasUaUtils.ToOpcUaReferenceList(newRef)?.ToArray(); - } - } - } - - /// - /// Sets the "Keys" value information of an AAS Reference. This is especially important for referencing - /// outwards of the AAS (environment). - /// - public void CreateAddKeyElements(NodeState parent, CreateMode mode, List ids = null) - { - List keys = new List(); - if (parent == null) - return; - - // MIHO: open62541 does not to process Values as string[], therefore change it temporarily - - if (ids != null) - { - foreach (var id in ids) - { - var key = new Key(KeyTypes.GlobalReference, id.Id); - keys.Add(key); - } - } - - if (this.entityBuilder != null && this.entityBuilder.theServerOptions != null - && this.entityBuilder.theServerOptions.ReferenceKeysAsSingleString) - { - // fix for open62541 - var keyo = this.entityBuilder.CreateAddPropertyState(parent, mode, "Values", - DataTypeIds.String, null, defaultSettings: true); - - if (mode == CreateMode.Instance && keyo != null) - { - Reference newRef = new Reference(AasCore.Aas3_0.ReferenceTypes.ExternalReference, keys); - keyo.Value = AasUaUtils.ToOpcUaReference(newRef); - } - } - else - { - // default behaviour - var keyo = this.entityBuilder?.CreateAddPropertyState(parent, mode, "Values", - DataTypeIds.Structure, null, defaultSettings: true); - - if (mode == CreateMode.Instance && keyo != null) - { - Reference newRef = new Reference(AasCore.Aas3_0.ReferenceTypes.ExternalReference, keys); - keyo.Value = AasUaUtils.ToOpcUaReferenceList(newRef)?.ToArray(); - } - } - } - - /// - /// Sets the UA relation of an AAS Reference. This is especially important for reference within an AAS node - /// structure, to be - /// in the style of OPC UA - /// - public void CreateAddReferenceElements(NodeState parent, CreateMode mode, List keys = null) - { - if (parent == null) - return; - - if (mode == CreateMode.Type) - { - // makes no sense - } - else - { - // would make sense, but is replaced by the code in "CreateAddInstanceObjects" directly. - } - } - } - - public class AasUaEntityReference : AasUaEntityReferenceBase - { - public AasUaEntityReference(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASReferenceType", - ObjectTypeIds.BaseObjectType, preferredTypeNumId); - // with some elements - this.CreateAddKeyElements(this.typeObject, CreateMode.Type, keys: null); - this.CreateAddReferenceElements(this.typeObject, CreateMode.Type); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, - AAS.IReference reference, string browseDisplayName = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - if (mode == CreateMode.Type) - { - var o = this.entityBuilder.CreateAddObject(parent, mode, browseDisplayName ?? "Reference", - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - return o; - } - else - { - if (reference == null) - return null; - - var o = this.entityBuilder.CreateAddObject(parent, mode, browseDisplayName ?? "Reference", - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // explicit strings? - if (reference is Reference modrf) - { - this.CreateAddKeyElements(o, mode, modrf.Keys); - - // find a matching concept description or other referable? - // as we do not have all other nodes realized, store a late action - this.entityBuilder.AddNodeLateAction( - new AasEntityBuilder.NodeLateActionLinkToReference( - o, - modrf, - AasEntityBuilder.NodeLateActionLinkToReference.ActionType.SetAasReference - )); - } - - if (reference is Reference glbrf) - { - this.CreateAddKeyElements(o, mode, glbrf.Keys); - - // find a matching concept description or other referable? - // as we do not have all other nodes realized, store a late action - this.entityBuilder.AddNodeLateAction( - new AasEntityBuilder.NodeLateActionLinkToReference( - o, - new Reference(AasCore.Aas3_0.ReferenceTypes.ExternalReference, glbrf.Keys), - AasEntityBuilder.NodeLateActionLinkToReference.ActionType.SetAasReference - )); - } - - // OK - return o; - } - } - } - - public class AasUaEntitySemanticId : AasUaEntityReferenceBase - { - public AasUaEntitySemanticId(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // re-use AASReferenceType for this - this.typeObject = this.entityBuilder.AasTypes.Reference.GetTypeObject(); - // with some elements - this.CreateAddReferenceElements(this.typeObject, CreateMode.Type); - } - - public NodeState CreateAddInstanceObject(NodeState parent, CreateMode mode, - AAS.IReference semid = null, string browseDisplayName = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - if (mode == CreateMode.Type) - { - var o = this.entityBuilder.CreateAddObject(parent, mode, browseDisplayName ?? "SemanticId", - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - return o; - } - else - { - if (semid == null) - return null; - - var o = this.entityBuilder.CreateAddObject(parent, mode, browseDisplayName ?? "SemanticId", - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // explicit strings? - this.CreateAddKeyElements(o, mode, semid.Keys); - - // find a matching concept description or other referable? - // as we do not have all other nodes realized, store a late action - this.entityBuilder.AddNodeLateAction( - new AasEntityBuilder.NodeLateActionLinkToReference( - parent, - //Reference.CreateNew(Key.ConceptDescription, semid?.Keys), - new Reference(AasCore.Aas3_0.ReferenceTypes.ModelReference, semid?.Keys), - AasEntityBuilder.NodeLateActionLinkToReference.ActionType.SetDictionaryEntry - )); - - // OK - return o; - } - } - } - - public class AasUaEntityAsset : AasUaBaseEntity - { - public AasUaEntityAsset(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASAssetType", - ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:Asset"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, - this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - // add necessary type information - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasKind - this.entityBuilder.AasTypes.AssetKind.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.AssetKind.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, - null, "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, - null, "AssetIdentificationModel", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, IAssetInformation asset = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - // Create whole object only if required - if (mode == CreateMode.Instance && asset == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, mode, "Asset", ReferenceTypeIds.HasComponent, - GetTypeObject().NodeId, modellingRule: modellingRule); - - if (mode == CreateMode.Instance) - { - // access - if (asset == null) - return null; - - // register node record - - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, asset?.GlobalAssetId)); - - // Referable - //this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Instance, asset); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements( - o, CreateMode.Instance, asset?.GlobalAssetId); - //this.entityBuilder.AasTypes.Administration.CreateAddElements( - // o, CreateMode.Instance, asset.administration); - // HasKind - this.entityBuilder.AasTypes.AssetKind.CreateAddElements(o, CreateMode.Instance, asset.AssetKind); - // HasDataSpecification - //if (asset.hasDataSpecification != null && asset.hasDataSpecification != null) - // foreach (var ds in asset.hasDataSpecification) - // this.entityBuilder.AasTypes.Reference.CreateAddElements( - // o, CreateMode.Instance, ds?.dataSpecification, "DataSpecification"); - //// own attributes - //this.entityBuilder.AasTypes.Reference.CreateAddElements( - // o, CreateMode.Instance, asset.assetIdentificationModelRef, "AssetIdentificationModel"); - } - - return o; - } - } - - public class AasUaEntityAAS : AasUaBaseEntity - { - public AasUaEntityAAS(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASAssetAdministrationShellType", - ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:AssetAdministrationShell"); - - // interface - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, - this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - // add necessary type information - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, - "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, - "DerivedFrom", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // assets - this.entityBuilder.AasTypes.Asset.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - // associated views - //this.entityBuilder.AasTypes.View.CreateAddElements(this.typeObject, CreateMode.Type, - // modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // associated submodels - this.entityBuilder.AasTypes.Submodel.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // concept dictionary - //this.entityBuilder.AasTypes.ConceptDictionary.CreateAddElements(this.typeObject, CreateMode.Type, - // modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - } - - public NodeState CreateAddInstanceObject(NodeState parent, - AasCore.Aas3_0.Environment env, IAssetAdministrationShell aas) - { - // access - if (env == null || aas == null) - return null; - - // containing element - string extraName = null; - string browseName = "AssetAdministrationShell"; - if (aas.IdShort != null && aas.IdShort.Trim().Length > 0) - { - extraName = "AssetAdministrationShell:" + aas.IdShort; - browseName = aas.IdShort; - } - var o = this.entityBuilder.CreateAddObject(parent, CreateMode.Instance, - browseName, ReferenceTypeIds.HasComponent, - GetTypeObject().NodeId, extraName: extraName); - - // register node record - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, aas)); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Instance, aas); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements( - o, CreateMode.Instance, aas.Id); - this.entityBuilder.AasTypes.Administration.CreateAddElements( - o, CreateMode.Instance, aas.Administration); - // HasDataSpecification - if (aas.EmbeddedDataSpecifications != null && aas.EmbeddedDataSpecifications != null) - foreach (var ds in aas.EmbeddedDataSpecifications) - this.entityBuilder.AasTypes.Reference.CreateAddElements( - o, CreateMode.Instance, ds.DataSpecification, "DataSpecification"); - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements( - o, CreateMode.Instance, aas.DerivedFrom, "DerivedFrom"); - - // associated asset - if (aas.AssetInformation != null) - { - this.entityBuilder.AasTypes.Asset.CreateAddElements(o, CreateMode.Instance, aas.AssetInformation); - } - - //// associated views - //if (aas.views != null) - // foreach (var vw in aas.views.views) - // this.entityBuilder.AasTypes.View.CreateAddElements( - // o, CreateMode.Instance, vw); - - // associated submodels - if (aas.Submodels != null && aas.Submodels.Count > 0) - foreach (var smr in aas.Submodels) - { - var sm = env.FindSubmodel(smr); - if (sm != null) - this.entityBuilder.AasTypes.Submodel.CreateAddElements( - o, CreateMode.Instance, sm); - } - - // make up CD dictionaries - //if (aas.conceptDictionaries != null && aas.conceptDictionaries.Count > 0) - //{ - // // ReSharper disable once UnusedVariable - // foreach (var cdd in aas.conceptDictionaries) - // { - // // TODO (MIHO, 2020-08-06): check (again) if reference to CDs is done are shall be done - // // here. They are stored separately. - // } - //} - - // results - return o; - } - } - - public class AasUaEntitySubmodel : AasUaBaseEntity - { - public AasUaEntitySubmodel(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASSubmodelType", - ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:Submodel"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, - this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - // add some elements - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(this.typeObject, CreateMode.Type, null, - "SemanticId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasKind - this.entityBuilder.AasTypes.ModelingKind.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, - "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // Qualifiable - this.entityBuilder.AasTypes.Qualifier.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // SubmodelElements - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, ISubmodel sm = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - if (mode == CreateMode.Type) - { - // create only containing element with generic name - var o = this.entityBuilder.CreateAddObject(parent, mode, "Submodel", ReferenceTypeIds.HasComponent, - this.GetTypeNodeId(), modellingRule: modellingRule); - return o; - } - else - { - // access - if (sm == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, mode, - "" + sm.IdShort, ReferenceTypeIds.HasComponent, - GetTypeObject().NodeId, extraName: "Submodel:" + sm.IdShort); - - // register node record - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, sm)); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements( - o, CreateMode.Instance, sm); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements( - o, CreateMode.Instance, sm.Id); - this.entityBuilder.AasTypes.Administration.CreateAddElements( - o, CreateMode.Instance, sm.Administration); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject( - o, CreateMode.Instance, sm.SemanticId, "SemanticId"); - // HasKind - this.entityBuilder.AasTypes.ModelingKind.CreateAddElements( - o, CreateMode.Instance, (ModellingKind)sm.Kind); - // HasDataSpecification - if (sm.EmbeddedDataSpecifications != null && sm.EmbeddedDataSpecifications != null) - foreach (var ds in sm.EmbeddedDataSpecifications) - this.entityBuilder.AasTypes.Reference.CreateAddElements( - o, CreateMode.Instance, ds.DataSpecification, "DataSpecification"); - // Qualifiable - if (sm.Qualifiers != null) - foreach (var q in sm.Qualifiers) - this.entityBuilder.AasTypes.Qualifier.CreateAddElements( - o, CreateMode.Instance, q); - - // SubmodelElements - if (sm.SubmodelElements != null) - foreach (var smw in sm.SubmodelElements) - if (smw != null) - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements( - o, CreateMode.Instance, smw); - - // result - return o; - } - } - } - - /// - /// This class is for the representation if SME in UA namespace - /// - public class AasUaEntitySubmodelElement : AasUaBaseEntity - { - public AasUaEntitySubmodelElement(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASSubmodelElementType", - ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:SubmodelElement"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, - this.entityBuilder.AasTypes.IAASReferableType.GetTypeNodeId()); - - // add some elements to the type - // Note: in this special case, the instance elements are populated by AasUaEntitySubmodelElementBase, - // while the elements - // for the type are populated here - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(this.typeObject, CreateMode.Type, null, - "SemanticId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasKind - this.entityBuilder.AasTypes.ModelingKind.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, - "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // Qualifiable - this.entityBuilder.AasTypes.Qualifier.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - } - } - - /// - /// This class is the base class of derived properties - /// - public class AasUaEntitySubmodelElementBase : AasUaBaseEntity - { - public AasUaEntitySubmodelElementBase(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // do NOT create type object, as this is done by sub-class - } - - public NodeState PopulateInstanceObject(NodeState o, ISubmodelElement sme) - { - // access - if (o == null || sme == null) - return null; - - // take this as perfect opportunity to register node record - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, sme)); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements( - o, CreateMode.Instance, sme); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject( - o, CreateMode.Instance, sme.SemanticId, "SemanticId"); - // HasDataSpecification - if (sme.EmbeddedDataSpecifications != null && sme.EmbeddedDataSpecifications != null) - foreach (var ds in sme.EmbeddedDataSpecifications) - this.entityBuilder.AasTypes.Reference.CreateAddElements( - o, CreateMode.Instance, ds.DataSpecification, "DataSpecification"); - // Qualifiable - if (sme.Qualifiers != null) - foreach (var q in sme.Qualifiers) - this.entityBuilder.AasTypes.Qualifier.CreateAddElements( - o, CreateMode.Instance, q); - - // result - return o; - } - } - - /// - /// This class will automatically instantiate the correct SubmodelElement entity. - /// - public class AasUaEntitySubmodelWrapper : AasUaBaseEntity - { - public AasUaEntitySubmodelWrapper(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // do NOT create type object, as this is done by sub-class - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, - ISubmodelElement smw = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - // access - if (parent == null) - return null; - - if (mode == CreateMode.Type) - { - // create only containing element (base type) with generic name - var o = this.entityBuilder.CreateAddObject(parent, mode, - "SubmodelElement", ReferenceTypeIds.HasComponent, - this.entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), modellingRule: modellingRule); - return o; - } - else - { - if (smw == null) - return null; - - if (smw is SubmodelElementCollection) - { - var coll = smw as SubmodelElementCollection; - return this.entityBuilder.AasTypes.Collection.CreateAddInstanceObject(parent, coll); - } - else if (smw is Property) - return this.entityBuilder.AasTypes.Property.CreateAddInstanceObject( - parent, smw as Property); - else if (smw is File) - return this.entityBuilder.AasTypes.File.CreateAddInstanceObject( - parent, smw as File); - else if (smw is Blob) - return this.entityBuilder.AasTypes.Blob.CreateAddInstanceObject( - parent, smw as Blob); - else if (smw is ReferenceElement) - return this.entityBuilder.AasTypes.ReferenceElement.CreateAddInstanceObject( - parent, smw as ReferenceElement); - else if (smw is RelationshipElement) - return this.entityBuilder.AasTypes.RelationshipElement.CreateAddInstanceObject( - parent, smw as RelationshipElement); - else if (smw is Operation) - return this.entityBuilder.AasTypes.Operation.CreateAddInstanceObject( - parent, smw as Operation); - - // nope - return null; - } - } - } - - public class AasUaEntityProperty : AasUaEntitySubmodelElementBase - { - public AasUaEntityProperty(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType( - "AASPropertyType", entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, - descriptionKey: "AAS:Property"); - - // elements not in the base type - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Instance, null, - "ValueId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "ValueType", - DataTypeIds.String, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "Value", - DataTypeIds.BaseDataType, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddInstanceObject(NodeState parent, Property prop) - { - // access - if (prop == null) - return null; - - // for all - var mode = CreateMode.Instance; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, mode, "" + prop.IdShort, ReferenceTypeIds.HasComponent, - GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, prop); - - // TODO (MIHO, 2020-08-06): not sure if to add these - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, prop.ValueId, "ValueId"); - this.entityBuilder.CreateAddPropertyState(o, mode, "ValueType", - DataTypeIds.String, "" + prop.ValueType, defaultSettings: true); - - // aim is to support many types natively - var vt = prop.ValueType; - if (prop.ValueType == DataTypeDefXsd.Boolean) - { - var x = (prop.Value ?? "").ToLower().Trim(); - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.Boolean, x == "true", defaultSettings: true); - } - else if (vt == DataTypeDefXsd.DateTime || vt == DataTypeDefXsd.Date || vt == DataTypeDefXsd.Time) - { - if (DateTime.TryParse(prop.Value, CultureInfo.InvariantCulture, - DateTimeStyles.AssumeUniversal, out var dt)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.DateTime, dt.ToFileTimeUtc(), defaultSettings: true); - } - else if (vt == DataTypeDefXsd.Decimal || vt == DataTypeDefXsd.Integer || vt == DataTypeDefXsd.Long - || vt == DataTypeDefXsd.NonPositiveInteger || vt == DataTypeDefXsd.NegativeInteger) - { - if (Int64.TryParse(prop.Value, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.Int64, v, defaultSettings: true); - } - else if (vt == DataTypeDefXsd.Int) - { - if (Int32.TryParse(prop.Value, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.Int32, v, defaultSettings: true); - } - else if (vt == DataTypeDefXsd.Short) - { - if (Int16.TryParse(prop.Value, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.Int16, v, defaultSettings: true); - } - else if (vt == DataTypeDefXsd.Byte) - { - if (SByte.TryParse(prop.Value, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.Byte, v, defaultSettings: true); - } - else if (vt == DataTypeDefXsd.NonNegativeInteger || vt == DataTypeDefXsd.PositiveInteger || vt == DataTypeDefXsd.UnsignedLong) - { - if (UInt64.TryParse(prop.Value, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.UInt64, v, defaultSettings: true); - } - else if (vt == DataTypeDefXsd.UnsignedInt) - { - if (UInt32.TryParse(prop.Value, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.UInt32, v, defaultSettings: true); - } - else if (vt == DataTypeDefXsd.UnsignedShort) - { - if (UInt16.TryParse(prop.Value, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.UInt16, v, defaultSettings: true); - } - else if (vt == DataTypeDefXsd.UnsignedByte) - { - if (Byte.TryParse(prop.Value, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.Byte, v, defaultSettings: true); - } - else if (vt == DataTypeDefXsd.Double) - { - if (double.TryParse(prop.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.Double, v, defaultSettings: true); - } - else if (vt == DataTypeDefXsd.Float) - { - if (float.TryParse(prop.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var v)) - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.Float, v, defaultSettings: true); - } - else - { - // leave in string - this.entityBuilder.CreateAddPropertyState(o, mode, "Value", - DataTypeIds.String, prop.Value, defaultSettings: true); - } - - // result - return o; - } - } - - public class AasUaEntityCollection : AasUaEntitySubmodelElementBase - { - public NodeState typeObjectOrdered = null; - - public AasUaEntityCollection(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - // TODO (MIHO, 2020-08-06): use the collection element of UA? - this.typeObject = this.entityBuilder.CreateAddObjectType("AASSubmodelElementCollectionType", - entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, - descriptionKey: "AAS:SubmodelElementCollection"); - this.typeObjectOrdered = this.entityBuilder.CreateAddObjectType("AASSubmodelElementOrderedCollectionType", - this.GetTypeNodeId(), preferredTypeNumId + 1, - descriptionKey: "AAS:SubmodelElementCollection"); - - // some elements - // ReSharper disable once RedundantExplicitArrayCreation - foreach (var o in new NodeState[] { this.typeObject /* , this.typeObjectOrdered */ }) - { - this.entityBuilder.CreateAddPropertyState(o, CreateMode.Type, "AllowDuplicates", - DataTypeIds.Boolean, false, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - } - } - - public NodeState CreateAddInstanceObject(NodeState parent, SubmodelElementCollection coll) - { - // access - if (coll == null) - return null; - - // containing element - var to = GetTypeObject().NodeId; - var o = this.entityBuilder.CreateAddObject(parent, CreateMode.Instance, - "" + coll.IdShort, ReferenceTypeIds.HasComponent, to); - - // populate common attributes - base.PopulateInstanceObject(o, coll); - - // values - if (coll.Value != null) - foreach (var smw in coll.Value) - if (smw != null) - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements( - o, CreateMode.Instance, smw); - - // result - return o; - } - } - - public class AasUaEntityFile : AasUaEntitySubmodelElementBase - { - public AasUaEntityFile(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASFileType", - entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), - preferredTypeNumId, descriptionKey: "AAS:File"); - - // some elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "MimeType", - this.entityBuilder.AasTypes.MimeType.GetTypeNodeId(), null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "Value", - this.entityBuilder.AasTypes.PathType.GetTypeNodeId(), null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.FileType.CreateAddElements(this.typeObject, CreateMode.Type); - } - - public NodeState CreateAddInstanceObject(NodeState parent, File file) - { - // access - if (file == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, CreateMode.Instance, "" + file.IdShort, - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, file); - - // own attributes - this.entityBuilder.CreateAddPropertyState(o, CreateMode.Instance, "MimeType", - this.entityBuilder.AasTypes.MimeType.GetTypeNodeId(), file.ContentType, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, CreateMode.Instance, "Value", - this.entityBuilder.AasTypes.PathType.GetTypeNodeId(), file.Value, defaultSettings: true); - - // wonderful working - // TODO (MIHO, 2021-01-01): re-enable with adoptions - /* - if (this.entityBuilder.AasTypes.FileType.CheckSuitablity(this.entityBuilder.package, file)) - this.entityBuilder.AasTypes.FileType.CreateAddElements( - o, CreateMode.Instance, this.entityBuilder.package, file); - */ - // result - return o; - } - } - - public class AasUaEntityBlob : AasUaEntitySubmodelElementBase - { - public AasUaEntityBlob(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASBlobType", - entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, - descriptionKey: "AAS:Blob"); - - // some elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "ContentType", - DataTypeIds.String, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, "Value", - DataTypeIds.String, null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddInstanceObject(NodeState parent, Blob blob) - { - // access - if (blob == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, CreateMode.Instance, "" + blob.IdShort, - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, blob); - - // own attributes - this.entityBuilder.CreateAddPropertyState(o, CreateMode.Instance, "ContentType", - DataTypeIds.String, blob.ContentType, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, CreateMode.Instance, "Value", - DataTypeIds.String, blob.Value.ToString(), defaultSettings: true); - - // result - return o; - } - } - - public class AasUaEntityReferenceElement : AasUaEntitySubmodelElementBase - { - public AasUaEntityReferenceElement(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASReferenceElementType", - entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, - descriptionKey: "AAS:ReferenceElement"); - - // some elements - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "Value", - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddInstanceObject(NodeState parent, ReferenceElement refElem) - { - // access - if (refElem == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, CreateMode.Instance, "" + refElem.IdShort, - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, refElem); - - // own attributes - if (refElem is ReferenceElement referenceElement) - { - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, referenceElement.Value, "Value"); - } - - // result - return o; - } - } - - public class AasUaEntityRelationshipElement : AasUaEntitySubmodelElementBase - { - public AasUaEntityRelationshipElement(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASRelationshipElementType", - entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, - descriptionKey: "AAS:RelationshipElement"); - - // some elements - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, - "First", modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, - "Second", modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddInstanceObject(NodeState parent, RelationshipElement relElem) - { - // access - if (relElem == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, CreateMode.Instance, "" + relElem.IdShort, - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, relElem); - - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, relElem.First, "First"); - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, relElem.Second, "Second"); - - // result - return o; - } - } - - public class AasUaEntityOperationVariable : AasUaEntitySubmodelElementBase - { - public AasUaEntityOperationVariable(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("OperationVariableType", - entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, - descriptionKey: "AAS:OperationVariable"); - } - - public NodeState CreateAddInstanceObject(NodeState parent, OperationVariable opvar) - { - // access - if (opvar == null || opvar.Value == null || opvar.Value == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, CreateMode.Instance, - "" + opvar.Value.IdShort, - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, opvar.Value); - - // own attributes - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements(o, CreateMode.Instance, opvar.Value); - - // result - return o; - } - } - - public class AasUaEntityOperation : AasUaEntitySubmodelElementBase - { - public AasUaEntityOperation(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASOperationType", - entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, - descriptionKey: "AAS:Operation"); - - // indicate the Operation - this.entityBuilder.CreateAddMethodState(this.typeObject, CreateMode.Type, "Operation", - inputArgs: null, - outputArgs: null, - referenceTypeFromParentId: ReferenceTypeIds.HasComponent); - - // some elements - for (int i = 0; i < 2; i++) - { - var o2 = this.entityBuilder.CreateAddObject(this.typeObject, CreateMode.Type, (i == 0) ? "in" : "out", - ReferenceTypeIds.HasComponent, - this.entityBuilder.AasTypes.OperationVariable.GetTypeObject().NodeId); - this.entityBuilder.AasTypes.OperationVariable.CreateAddInstanceObject(o2, null); - } - } - - public NodeState CreateAddInstanceObject(NodeState parent, Operation op) - { - // access - if (op == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, CreateMode.Instance, - "" + op.IdShort, - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, op); - - // own AAS attributes (in/out op vars) - //for (int i = 0; i < 2; i++) - //{ - // var opvarList = op[i]; - // if (opvarList != null && opvarList.Count > 0) - // { - // var o2 = this.entityBuilder.CreateAddObject(o, - // CreateMode.Instance, - // (i == 0) ? "OperationInputVariables" : "OperationOutputVariables", - // ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - // foreach (var opvar in opvarList) - // if (opvar != null && opvar.Value != null) - // this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements( - // o2, CreateMode.Instance, opvar.Value); - // } - //} - - var opInputVarList = op.InputVariables; - if (opInputVarList != null && opInputVarList.Count > 0) - { - var o2 = this.entityBuilder.CreateAddObject(o, - CreateMode.Instance, - "OperationInputVariables", - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - foreach (var opvar in opInputVarList) - if (opvar != null && opvar.Value != null) - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements( - o2, CreateMode.Instance, opvar.Value); - } - - var opOutputVarList = op.OutputVariables; - if (opOutputVarList != null && opOutputVarList.Count > 0) - { - var o2 = this.entityBuilder.CreateAddObject(o, - CreateMode.Instance, - "OperationOutputVariables", - ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - foreach (var opvar in opOutputVarList) - if (opvar != null && opvar.Value != null) - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements( - o2, CreateMode.Instance, opvar.Value); - } - - // create a method? - if (true) - { - // ReSharper disable once RedundantExplicitArrayCreation - var args = new List[] { new List(), new List() }; - for (int i = 0; i < 2; i++) - { - if (i == 0) - { - CreateOperationArguments(i, ref args, op.InputVariables); - } - else if (i == 1) - { - CreateOperationArguments(i, ref args, op.OutputVariables); - } - } - - var unused = this.entityBuilder.CreateAddMethodState(o, CreateMode.Instance, "Operation", - inputArgs: args[0].ToArray(), - outputArgs: args[1].ToArray(), - referenceTypeFromParentId: ReferenceTypeIds.HasComponent); - } - - // result - return o; - } - - private void CreateOperationArguments(int i, ref List[] args, List opVariables) - { - if (opVariables != null) - { - foreach (var opvar in opVariables) - { - // TODO (MIHO, 2020-08-06): decide to from where the name comes - var name = "noname"; - - // TODO (MIHO, 2020-08-06): description: get "en" Version which is appropriate? - LocalizedText desc = new LocalizedText(""); - - // TODO (MIHO, 2020-08-06): parse UA data type out .. OK? - NodeId dataType = null; - if (opvar.Value != null && opvar.Value != null) - { - // better name .. but not best (see below) - if (opvar.Value.IdShort != null - && opvar.Value.IdShort.Trim() != "") - name = "" + opvar.Value.IdShort; - - // TODO (MIHO, 2020-08-06): description: get "en" Version is appropriate? - desc = AasUaUtils.GetBestUaDescriptionFromAasDescription( - opvar.Value.Description); - - // currenty, only accept properties as in/out arguments. - // Only these have an XSD value type!! - var prop = opvar.Value as Property; - if (prop != null) - { - // TODO (MIHO, 2020-08-06): this any better? - if (prop.IdShort != null && prop.IdShort.Trim() != "") - name = "" + prop.IdShort; - - // TODO (MIHO, 2020-08-06): description: get "en" Version is appropriate? - if (desc.Text == null || desc.Text == "") - desc = AasUaUtils.GetBestUaDescriptionFromAasDescription( - opvar.Value.Description); - - // try convert type - if (!AasUaUtils.AasValueTypeToUaDataType( - prop.ValueType.ToString(), out var dummy, out dataType)) - dataType = null; - } - } - if (dataType == null) - continue; - - var a = new Argument(name, dataType, -1, desc.Text ?? ""); - args[i].Add(a); - } - - } - } - } - - - public class AasUaEntityDataSpecification : AasUaBaseEntity - { - public AasUaEntityDataSpecification(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASDataSpecificationType", - ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:DataSpecification"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, - this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - } - - } - - public class AasUaEntityDataSpecificationIEC61360 : AasUaBaseEntity - { - public AasUaEntityDataSpecificationIEC61360(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASDataSpecificationIEC61360Type", - this.entityBuilder.AasTypes.DataSpecification.GetTypeNodeId(), preferredTypeNumId, - descriptionKey: "AAS:DataSpecificationIEC61360"); - - // very special rule here for the Identifiable - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, - this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Instance, - //new IIdentifiable("http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360"), - "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Instance, - new AdministrativeInformation(version: "1", revision: "0"), - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - // add some more elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, - "PreferredName", - DataTypeIds.LocalizedText, - value: null, defaultSettings: true, valueRank: 1, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, - "ShortName", - DataTypeIds.String, value: null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, - "Unit", - DataTypeIds.String, value: null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, - "UnitId", - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, - "SourceOfDefinition", - DataTypeIds.LocalizedText, - value: null, defaultSettings: true, valueRank: 1, - modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, - "Symbol", DataTypeIds.String, - value: null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, - "DataType", DataTypeIds.String, - value: null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, - "Definition", - DataTypeIds.LocalizedText, value: null, defaultSettings: true, valueRank: 1, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, CreateMode.Type, - "ValueFormat", - DataTypeIds.String, value: null, defaultSettings: true, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - // TODO (jtikekar, 2023-09-04): jtikekar Temporarily commented - //public NodeState CreateAddElements(NodeState parent, CreateMode mode, - // AdminShell.DataSpecificationIEC61360 ds = null, - // AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - //{ - // if (parent == null) - // return null; - - // // for the sake of clarity, we're directly splitting cases - // if (mode == CreateMode.Type) - // { - // // containing element (only) - // var o = this.entityBuilder.CreateAddObject(parent, mode, "DataSpecificationIEC61360", - // this.entityBuilder.AasTypes.HasAddIn.GetTypeNodeId(), GetTypeObject().NodeId, - // modellingRule: modellingRule); - // return o; - // } - // else - // { - // // access - // if (ds == null) - // return null; - - // // we can only provide minimal unique naming - // var name = "DataSpecificationIEC61360"; - // if (ds.shortName != null && this.entityBuilder.RootDataSpecifications != null) - // name += "_" + ds.shortName; - - // // containing element (depending on root folder) - // NodeState o = null; - // if (this.entityBuilder.RootDataSpecifications != null) - // { - // // under common folder - // o = this.entityBuilder.CreateAddObject(this.entityBuilder.RootDataSpecifications, mode, name, - // ReferenceTypeIds.Organizes, GetTypeObject().NodeId); - // // link to this object - // parent.AddReference(this.entityBuilder.AasTypes.HasAddIn.GetTypeNodeId(), false, o.NodeId); - // } - // else - // { - // // under parent - // o = this.entityBuilder.CreateAddObject(parent, mode, name, - // this.entityBuilder.AasTypes.HasAddIn.GetTypeNodeId(), GetTypeObject().NodeId); - // } - - // // add some elements - // if (ds.preferredName != null && ds.preferredName.Count > 0) - // this.entityBuilder.CreateAddPropertyState(o, mode, "PreferredName", - // DataTypeIds.LocalizedText, - // value: AasUaUtils.GetUaLocalizedTexts(ds.preferredName), - // defaultSettings: true, valueRank: 1); - - // if (ds.shortName != null && ds.shortName.Count > 0) - // this.entityBuilder.CreateAddPropertyState(o, mode, "ShortName", - // DataTypeIds.LocalizedText, - // value: AasUaUtils.GetUaLocalizedTexts(ds.shortName), - // defaultSettings: true, valueRank: 1); - - // if (ds.unit != null) - // this.entityBuilder.CreateAddPropertyState(o, mode, "Unit", - // DataTypeIds.String, value: ds.unit, defaultSettings: true); - - // if (ds.unitId != null) - // this.entityBuilder.AasTypes.Reference.CreateAddElements(o, mode, - // Reference.CreateNew(ds.unitId?.Value), "UnitId"); - - // if (ds.sourceOfDefinition != null) - // this.entityBuilder.CreateAddPropertyState(o, mode, "SourceOfDefinition", - // DataTypeIds.String, value: ds.sourceOfDefinition, defaultSettings: true); - - // if (ds.symbol != null) - // this.entityBuilder.CreateAddPropertyState(o, mode, "Symbol", - // DataTypeIds.String, value: ds.symbol, defaultSettings: true); - - // if (ds.dataType != null) - // this.entityBuilder.CreateAddPropertyState(o, mode, "DataType", - // DataTypeIds.String, value: ds.dataType, defaultSettings: true); - - // if (ds.definition != null && ds.definition.Count > 0) - // this.entityBuilder.CreateAddPropertyState(o, mode, "Definition", - // DataTypeIds.LocalizedText, value: AasUaUtils.GetUaLocalizedTexts(ds.definition), - // defaultSettings: true, valueRank: 1); - - // if (ds.ValueFormat != null) - // this.entityBuilder.CreateAddPropertyState(o, mode, "ValueFormat", - // DataTypeIds.String, value: ds.ValueFormat, defaultSettings: true); - - // // return - // return o; - // } - //} - } - - public class AasUaEntityConceptDescription : AasUaBaseEntity - { - public NodeState typeObjectIrdi; - public NodeState typeObjectUri; - public NodeState typeObjectCustom; - - - public AasUaEntityConceptDescription(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - // TODO (MIHO, 2020-08-06): check, if to make super classes for UriDictionaryEntryType? - this.typeObjectIrdi = this.entityBuilder.CreateAddObjectType("AASIrdiConceptDescriptionType", - this.entityBuilder.AasTypes.IrdiDictionaryEntryType.GetTypeNodeId(), 0, - descriptionKey: "AAS:ConceptDescription"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObjectIrdi, false, - this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - this.typeObjectUri = this.entityBuilder.CreateAddObjectType("AASUriConceptDescriptionType", - this.entityBuilder.AasTypes.UriDictionaryEntryType.GetTypeNodeId(), 0, - descriptionKey: "AAS:ConceptDescription"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObjectUri, false, - this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - this.typeObjectCustom = this.entityBuilder.CreateAddObjectType("AASCustomConceptDescriptionType", - this.entityBuilder.AasTypes.DictionaryEntryType.GetTypeNodeId(), 0, - descriptionKey: "AAS:ConceptDescription"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObjectCustom, false, - this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - // for each of them, add some elements - // ReSharper disable once RedundantExplicitArrayCreation - foreach (var o in new NodeState[] { this.typeObjectIrdi, this.typeObjectUri, this.typeObjectCustom }) - { - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Type); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(o, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(o, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // IsCaseOf - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Type, null, "IsCaseOf", - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Type, null, "DataSpecification", - modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - - // data specification is a child - // TODO (jtikekar, 2023-09-04): Temporarily commented - //this.entityBuilder.AasTypes.DataSpecificationIEC61360.CreateAddElements(o, CreateMode.Type, - // modellingRule: AasUaNodeHelper.ModellingRule.MandatoryPlaceholder); - } - } - - public NodeState GetTypeObjectFor(string identification) - { - var to = this.typeObject; // shall be NULL - - //commented as per new V3.0RC02 - //if (true == identification?.IsIRI()) - // to = this.typeObjectUri; - //else - //if (true == identification?.IsIRDI()) - // to = this.typeObjectIrdi; - - // TODO (MIHO, 2021-12-30): before V3.0, there was a compare to "custom" here. - - return to; - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, IConceptDescription cd = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - // split directly because of complexity - if (mode == CreateMode.Type) - { - // not sure, if this will required, ever - return null; - } - else - { - // access - if (cd == null) - return null; - - // makeup name - var name = "ConceptDescription_" + Guid.NewGuid().ToString(); - - if (false) -#pragma warning disable 162 - // ReSharper disable HeuristicUnreachableCode - { - // Conventional approach: build up a speaking name - // but: shall be target of "HasDictionaryEntry", therefore the __PURE__ identifications - // need to be the name! - // TODO (jtikekar, 2023-09-04): Temporarily commented - //if (cd.GetIEC61360() != null) - //{ - // var ds = cd.GetIEC61360(); - // if (ds.shortName != null) - // name = ds.shortName.GetDefaultStr(); - // if (cd.Id != null) - // name += "_" + cd.Id.ToString(); - //} - name = AasUaUtils.ToOpcUaName(name); - } - // ReSharper enable HeuristicUnreachableCode -#pragma warning restore 162 - else - { - // only identification (the type object will distinct between the id type) - if (cd.Id != null) - name = cd.Id; - } - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, mode, name, - ReferenceTypeIds.HasComponent, this.GetTypeObjectFor(cd.Id)?.NodeId, - modellingRule: modellingRule); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements( - o, CreateMode.Instance, cd); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements( - o, CreateMode.Instance, cd.Id); - this.entityBuilder.AasTypes.Administration.CreateAddElements( - o, CreateMode.Instance, cd.Administration); - // IsCaseOf - if (cd.IsCaseOf != null) - foreach (var ico in cd.IsCaseOf) - this.entityBuilder.AasTypes.Reference.CreateAddElements( - o, CreateMode.Instance, ico, "IsCaseOf"); - - // HasDataSpecification solely under the viewpoint of IEC61360 - // TODO (jtikekar, 2023-09-04): Temporarily commented - //var eds = cd.embeddedDataSpecification?.IEC61360; - //if (eds != null) - // this.entityBuilder.AasTypes.Reference.CreateAddElements( - // o, CreateMode.Instance, eds.dataSpecification, "DataSpecification"); - - // data specification is a child - /// TODO (jtikekar, 2023-09-04): Temporarily commented - //var ds61360 = cd.embeddedDataSpecification?.IEC61360Content; - //if (ds61360 != null) - //{ - // var unused = this.entityBuilder.AasTypes.DataSpecificationIEC61360.CreateAddElements( - // o, CreateMode.Instance, - // ds61360); - //} - - // remember CD as NodeRecord - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, cd.Id)); - - return o; - } - } - } - - // - // Elements from the UA spc - // - - public class AasUaNamespaceZeroEntity : AasUaBaseEntity - { - public AasUaNamespaceZeroEntity(AasEntityBuilder entityBuilder, uint presetNumId = 0) - : base(entityBuilder) - { - // just set node id based on existing knowledge - this.typeObjectId = new NodeId(presetNumId, 0); - } - } - - public class AasUaNamespaceZeroReference : AasUaBaseEntity - { - public AasUaNamespaceZeroReference(AasEntityBuilder entityBuilder, uint presetNumId = 0) - : base(entityBuilder) - { - // just set node id based on existing knowledge - this.typeObjectId = new NodeId(presetNumId, 0); - } - - public void CreateAddInstanceReference(NodeState source, bool isInverse, ExpandedNodeId target) - { - if (source != null && target != null && this.GetTypeNodeId() != null) - source.AddReference(this.GetTypeNodeId(), isInverse, target); - } - } - - // - // References - // - - public class AasUaReferenceHasAasReference : AasUaBaseEntity - { - public AasUaReferenceHasAasReference(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddReferenceType("AASReference", "AASReferencedBy", - preferredTypeNumId, useZeroNS: false); - } - - public NodeState CreateAddInstanceReference(NodeState parent) - { - return null; - } - } - - - // - // Interfaces - // - - public class AasUaInterfaceAASIdentifiableType : AasUaBaseEntity - { - public AasUaInterfaceAASIdentifiableType(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("IAASIdentifiableType", - this.entityBuilder.AasTypes.IAASReferableType.GetTypeNodeId() /* ObjectTypeIds.BaseObjectType */, - preferredTypeNumId, descriptionKey: "AAS:Identifiable"); - - // add some elements - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Type, - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - } - } - - public class AasUaInterfaceAASReferableType : AasUaBaseEntity - { - public AasUaInterfaceAASReferableType(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("IAASReferableType", - this.entityBuilder.AasTypes.BaseInterfaceType.GetTypeNodeId() /* ObjectTypeIds.BaseObjectType */, - preferredTypeNumId, descriptionKey: "AAS:Referable"); - - // some elements - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - } - } -} diff --git a/src/AasxServerStandardBib/AasUaEntities.cs.bak b/src/AasxServerStandardBib/AasUaEntities.cs.bak deleted file mode 100644 index 20aadaafb..000000000 --- a/src/AasxServerStandardBib/AasUaEntities.cs.bak +++ /dev/null @@ -1,1668 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using AdminShellNS; -using Opc.Ua; - -namespace AasOpcUaServer -{ - public class AasUaBaseEntity - { - public enum CreateMode { Type, Instance }; - - /// - /// Reference back to the entity builder - /// - protected AasEntityBuilder entityBuilder = null; - - public AasUaBaseEntity(AasEntityBuilder entityBuilder) - { - this.entityBuilder = entityBuilder; - } - - /// - /// Typically the node of the entity in the AAS type object space - /// - protected NodeState typeObject = null; - - /// - /// If the entitiy does not have a direct type object, the object id instead (for pre-defined objects) - /// - protected NodeId typeObjectId = null; - - /// - /// Getter of the type object - /// - public NodeState GetTypeObject() - { - return typeObject; - } - - /// - /// Getter of the type object id, either directly or via the type object (if avilable) - /// - /// - public NodeId GetTypeNodeId() - { - if (typeObjectId != null) - return typeObjectId; - if (typeObject == null) - return null; - return typeObject.NodeId; - } - } - - public class AasUaEntityPathType : AasUaBaseEntity - { - public AasUaEntityPathType(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type elements - this.typeObject = this.entityBuilder.CreateAddDataType("AASPathType", DataTypeIds.String); - } - } - - public class AasUaEntityMimeType : AasUaBaseEntity - { - public AasUaEntityMimeType(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type elements - this.typeObject = this.entityBuilder.CreateAddDataType("AASMimeType", DataTypeIds.String); - } - } - - public class AasUaEntityIdentification : AasUaBaseEntity - { - public AasUaEntityIdentification(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASIdentifierType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:Identifier"); - // add some elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, "IdType", DataTypeIds.String, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Id", DataTypeIds.String, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AdminShell.Identification identification = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - var o = this.entityBuilder.CreateAddObject(parent, "Identification", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - - if (mode == CreateMode.Instance) - { - this.entityBuilder.CreateAddPropertyState(o, "IdType", DataTypeIds.String, "" + "" + identification.idType, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, "Id", DataTypeIds.String, "" + "" + identification.id, defaultSettings: true); - } - - return o; - } - } - - public class AasUaEntityAdministration : AasUaBaseEntity - { - public AasUaEntityAdministration(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASAdministrativeInformationType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:AdministrativeInformation"); - // add some elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Version", DataTypeIds.String, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Revision", DataTypeIds.String, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AdminShell.Administration administration = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - // Create whole object only if required - if (mode == CreateMode.Instance && administration == null) - return null; - - var o = this.entityBuilder.CreateAddObject(parent, "Administration", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - - if (mode == CreateMode.Instance) - { - if (administration == null) - return null; - this.entityBuilder.CreateAddPropertyState(o, "Version", DataTypeIds.String, "" + "" + administration.version, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, "Revision", DataTypeIds.String, "" + "" + administration.revision, defaultSettings: true); - } - - return o; - } - } - - public class AasUaEntityQualifier : AasUaBaseEntity - { - public AasUaEntityQualifier(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASQualifierType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, "AAS:Qualifier"); - - // add some elements - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(this.typeObject, CreateMode.Type, null, "SemanticId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Type", DataTypeIds.String, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Value", DataTypeIds.String, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "ValueId", AasUaNodeHelper.ModellingRule.Optional); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, Qualifier qualifier = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - // Create whole object only if required - if (mode == CreateMode.Instance && qualifier == null) - return null; - - if (mode == CreateMode.Type) - { - // plain - var o = this.entityBuilder.CreateAddObject(parent, "Qualifier", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - return o; - } - else - { - // need data - if (qualifier == null) - return null; - - // do a little extra? - string extraName = null; - if (qualifier.type != null && qualifier.type.Length > 0) - { - extraName = "Qualifier:" + qualifier.type; - if (qualifier.Value != null && qualifier.Value.Length > 0) - extraName += "=" + qualifier.Value; - } - - var o = this.entityBuilder.CreateAddObject(parent, "Qualifier", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule, extraName: extraName); - - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(o, CreateMode.Instance, qualifier.semanticId, "SemanticId"); - this.entityBuilder.CreateAddPropertyState(o, "Type", DataTypeIds.String, "" + qualifier.type, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.String, "" + qualifier.Value, defaultSettings: true); - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, qualifier.ValueId, "ValueId"); - - return o; - } - - } - } - - public class AasUaEntityAssetKind : AasUaBaseEntity - { - public AasUaEntityAssetKind(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - // no special type here (is a string) - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AdminShell.AssetKind kind = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (mode == CreateMode.Instance && kind == null) - return null; - - var o = this.entityBuilder.CreateAddPropertyState(parent, "Kind", DataTypeIds.String, (mode == CreateMode.Type) ? null : "" + kind.kind, defaultSettings: true, modellingRule: modellingRule); - - return o; - } - } - - public class AasUaEntityModelingKind : AasUaBaseEntity - { - public AasUaEntityModelingKind(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - // no special type here (is a string) - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AdminShell.ModelingKind kind = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (mode == CreateMode.Instance && kind == null) - return null; - - var o = this.entityBuilder.CreateAddPropertyState(parent, "Kind", DataTypeIds.String, (mode == CreateMode.Type) ? null : "" + kind.kind, defaultSettings: true, modellingRule: modellingRule); - - return o; - } - } - - public class AasUaEntityReferable : AasUaBaseEntity - { - public AasUaEntityReferable(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // NO type object required - // see IAASReferable interface - } - - /// - /// This adds all Referable attributes to the parent and re-defines the descriptons - /// - public NodeState CreateAddElements(NodeState parent, CreateMode mode, IReferable refdata = null) - { - if (parent == null) - return null; - if (mode == CreateMode.Instance && refdata == null) - return null; - - if (mode == CreateMode.Type || refdata?.category != null) - this.entityBuilder.CreateAddPropertyState(parent, "Category", DataTypeIds.String, (mode == CreateMode.Type) ? null : "" + refdata.category, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - - - if (mode == CreateMode.Instance) - { - // now, re-set the description on the parent - // ISSUE: only ONE language supported! - parent.Description = AasUaUtils.GetBestUaDescriptionFromAasDescription(refdata.description); - } - - return null; - } - } - - public class AasUaEntityReferenceBase : AasUaBaseEntity - { - public AasUaEntityReferenceBase(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // nothing, only used to share code - } - - /// - /// Sets the "Keys" value information of an AAS Reference. This is especially important for referencing outwards of the AAS (environment). - /// - public void CreateAddKeyElements(NodeState parent, CreateMode mode, List keys = null) - { - if (parent == null) - return; - - // MIHO: open62541 does not to process Values as string[], therefore change it temporarily - - if (this.entityBuilder != null && this.entityBuilder.theServerOptions != null && this.entityBuilder.theServerOptions.ReferenceKeysAsSingleString) - { - // fix for open62541 - var keyo = this.entityBuilder.CreateAddPropertyState(parent, "Keys", DataTypeIds.String, null, defaultSettings: true); - - if (mode == CreateMode.Instance && keyo != null) - { - keyo.Value = AasUaUtils.ToOpcUaReference(AdminShell.Reference.CreateNew(keys)); - } - } - else - { - // default behaviour - var keyo = this.entityBuilder.CreateAddPropertyState(parent, "Keys", DataTypeIds.Structure, null, defaultSettings: true); - - if (mode == CreateMode.Instance && keyo != null) - { - keyo.Value = AasUaUtils.ToOpcUaReferenceList(AdminShell.Reference.CreateNew(keys))?.ToArray(); - } - } - } - - /// - /// Sets the UA relation of an AAS Reference. This is especially important for reference within an AAS node structure, to be - /// in the style of OPC UA - /// - public void CreateAddReferenceElements(NodeState parent, CreateMode mode, List keys = null) - { - if (parent == null) - return; - - if (mode == CreateMode.Type) - { - // makes no sense - } - else - { - // would make sense, but is replaced by the code in "CreateAddInstanceObjects" directly. - } - } - } - - public class AasUaEntityReference : AasUaEntityReferenceBase - { - public AasUaEntityReference(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASReferenceType", ObjectTypeIds.BaseObjectType, preferredTypeNumId); - // with some elements - this.CreateAddKeyElements(this.typeObject, CreateMode.Type); - this.CreateAddReferenceElements(this.typeObject, CreateMode.Type); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AdminShell.Reference reference, string browseDisplayName = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - if (mode == CreateMode.Type) - { - var o = this.entityBuilder.CreateAddObject(parent, browseDisplayName ?? "Reference", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - return o; - } - else - { - if (reference == null) - return null; - - var o = this.entityBuilder.CreateAddObject(parent, browseDisplayName ?? "Reference", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // explicit strings? - this.CreateAddKeyElements(o, mode, reference.Keys); - - // find a matching concept description or other referable? - // as we do not have all other nodes realized, store a late action - this.entityBuilder.AddNodeLateAction( - new AasEntityBuilder.NodeLateActionLinkToReference( - o, - reference, - AasEntityBuilder.NodeLateActionLinkToReference.ActionType.SetAasReference - )); - - // OK - return o; - } - } - } - - public class AasUaEntitySemanticId : AasUaEntityReferenceBase - { - public AasUaEntitySemanticId(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // re-use AASReferenceType for this - this.typeObject = this.entityBuilder.AasTypes.Reference.GetTypeObject(); - // with some elements - this.CreateAddReferenceElements(this.typeObject, CreateMode.Type); - } - - public NodeState CreateAddInstanceObject(NodeState parent, CreateMode mode, AdminShell.SemanticId semid = null, string browseDisplayName = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - if (mode == CreateMode.Type) - { - var o = this.entityBuilder.CreateAddObject(parent, browseDisplayName ?? "SemanticId", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - return o; - } - else - { - if (semid == null) - return null; - - var o = this.entityBuilder.CreateAddObject(parent, browseDisplayName ?? "SemanticId", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // explicit strings? - this.CreateAddKeyElements(o, mode, semid.Keys); - - // find a matching concept description or other referable? - // as we do not have all other nodes realized, store a late action - this.entityBuilder.AddNodeLateAction( - new AasEntityBuilder.NodeLateActionLinkToReference( - parent, - new AdminShell.Reference(semid), - AasEntityBuilder.NodeLateActionLinkToReference.ActionType.SetDictionaryEntry - )); - - // OK - return o; - } - } - } - - public class AasUaEntityAsset : AasUaBaseEntity - { - public AasUaEntityAsset(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASAssetType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:Asset"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - // add necessary type information - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasKind - this.entityBuilder.AasTypes.AssetKind.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "AssetIdentificationModel", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AdminShell.Asset asset = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - // Create whole object only if required - if (mode == CreateMode.Instance && asset == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "Asset", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - - if (mode == CreateMode.Instance) - { - // access - if (asset == null) - return null; - - // register node record - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, asset)); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Instance, asset); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(o, CreateMode.Instance, asset.identification); - this.entityBuilder.AasTypes.Administration.CreateAddElements(o, CreateMode.Instance, asset.administration); - // HasKind - this.entityBuilder.AasTypes.AssetKind.CreateAddElements(o, CreateMode.Instance, asset.kind); - // HasDataSpecification - if (asset.hasDataSpecification != null && asset.hasDataSpecification.reference != null) - foreach (var ds in asset.hasDataSpecification.reference) - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, ds, "DataSpecification"); - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, asset.assetIdentificationModelRef, "AssetIdentificationModel"); - } - - return o; - } - } - - public class AasUaEntityAAS : AasUaBaseEntity - { - public AasUaEntityAAS(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASAssetAdministrationShellType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:AssetAdministrationShell"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - // add necessary type information - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "DerivedFrom", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // assets - this.entityBuilder.AasTypes.Asset.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - // associated views - this.entityBuilder.AasTypes.View.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // associated submodels - this.entityBuilder.AasTypes.Submodel.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // concept dictionary - this.entityBuilder.AasTypes.ConceptDictionary.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - } - - public NodeState CreateAddInstanceObject(NodeState parent, AasCore.Aas3_0_RC02.Environment env, AssetAdministrationShell aas) - { - // access - if (env == null || aas == null) - return null; - - // containing element - string extraName = null; - string browseName = "AssetAdministrationShell"; - if (aas.IdShort != null && aas.IdShort.Trim().Length > 0) - { - extraName = "AssetAdministrationShell:" + aas.IdShort; - browseName = aas.IdShort; - } - var o = this.entityBuilder.CreateAddObject(parent, browseName, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, - extraName: extraName); - - // register node record - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, aas)); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Instance, aas); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(o, CreateMode.Instance, aas.identification); - this.entityBuilder.AasTypes.Administration.CreateAddElements(o, CreateMode.Instance, aas.administration); - // HasDataSpecification - if (aas.hasDataSpecification != null && aas.hasDataSpecification.reference != null) - foreach (var ds in aas.hasDataSpecification.reference) - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, ds, "DataSpecification"); - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, aas.derivedFrom, "DerivedFrom"); - - // associated asset - if (aas.assetRef != null) - { - var asset = env.FindAsset(aas.assetRef); - if (asset != null) - this.entityBuilder.AasTypes.Asset.CreateAddElements(o, CreateMode.Instance, asset); - } - - // associated views - if (aas.views != null) - foreach (var vw in aas.views.views) - this.entityBuilder.AasTypes.View.CreateAddElements(o, CreateMode.Instance, vw); - - // associated submodels - if (aas.Submodels != null && aas.Submodels.Count > 0) - foreach (var smr in aas.Submodels) - { - var sm = env.FindSubmodel(smr); - if (sm != null) - this.entityBuilder.AasTypes.Submodel.CreateAddElements(o, CreateMode.Instance, sm); - } - - // make up CD dictionaries - if (aas.conceptDictionaries != null && aas.conceptDictionaries.Count > 0) - { - foreach (var cdd in aas.conceptDictionaries) - { - // TODO: reference to CDs. They are stored sepaately - } - } - - // results - return o; - } - } - - public class AasUaEntitySubmodel : AasUaBaseEntity - { - public AasUaEntitySubmodel(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASSubmodelType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:Submodel"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - // add some elements - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(this.typeObject, CreateMode.Type, null, "SemanticId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasKind - this.entityBuilder.AasTypes.ModelingKind.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // Qualifiable - this.entityBuilder.AasTypes.Qualifier.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // SubmodelElements - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, Submodel sm = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - if (mode == CreateMode.Type) - { - // create only containing element with generic name - var o = this.entityBuilder.CreateAddObject(parent, "Submodel", ReferenceTypeIds.HasComponent, this.GetTypeNodeId(), modellingRule: modellingRule); - return o; - } - else - { - // access - if (sm == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "" + sm.IdShort, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, extraName: "Submodel:" + sm.IdShort); - - // register node record - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, sm)); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Instance, sm); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(o, CreateMode.Instance, sm.identification); - this.entityBuilder.AasTypes.Administration.CreateAddElements(o, CreateMode.Instance, sm.administration); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(o, CreateMode.Instance, sm.semanticId, "SemanticId"); - // HasKind - this.entityBuilder.AasTypes.ModelingKind.CreateAddElements(o, CreateMode.Instance, sm.kind); - // HasDataSpecification - if (sm.hasDataSpecification != null && sm.hasDataSpecification.reference != null) - foreach (var ds in sm.hasDataSpecification.reference) - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, ds, "DataSpecification"); - // Qualifiable - if (sm.qualifiers != null) - foreach (var q in sm.qualifiers) - this.entityBuilder.AasTypes.Qualifier.CreateAddElements(o, CreateMode.Instance, q); - - // SubmodelElements - if (sm.submodelElements != null) - foreach (var smw in sm.submodelElements) - if (smw.submodelElement != null) - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements(o, CreateMode.Instance, smw); - - // result - return o; - } - } - } - - /// - /// This class is for the representation if SME in UA namespace - /// - public class AasUaEntitySubmodelElement : AasUaBaseEntity - { - public AasUaEntitySubmodelElement(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASSubmodelElementType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:SubmodelElement"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, this.entityBuilder.AasTypes.IAASReferableType.GetTypeNodeId()); - - // add some elements to the type - // Note: in this special case, the instance elements are populated by AasUaEntitySubmodelElementBase, while the elements - // for the type are populated here - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(this.typeObject, CreateMode.Type, null, "SemanticId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasKind - this.entityBuilder.AasTypes.ModelingKind.CreateAddElements(this.typeObject, CreateMode.Type, null, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // Qualifiable - this.entityBuilder.AasTypes.Qualifier.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - } - } - - /// - /// This class is the base class of derived properties - /// - public class AasUaEntitySubmodelElementBase : AasUaBaseEntity - { - public AasUaEntitySubmodelElementBase(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // do NOT create type object, as this is done by sub-class - } - - public NodeState PopulateInstanceObject(NodeState o, SubmodelElement sme) - { - // access - if (o == null || sme == null) - return null; - - // take this as perfect opportunity to register node record - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, sme)); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Instance, sme); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(o, CreateMode.Instance, sme.semanticId, "SemanticId"); - // HasKind - this.entityBuilder.AasTypes.ModelingKind.CreateAddElements(o, CreateMode.Instance, sme.kind); - // HasDataSpecification - if (sme.hasDataSpecification != null && sme.hasDataSpecification.reference != null) - foreach (var ds in sme.hasDataSpecification.reference) - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, ds, "DataSpecification"); - // Qualifiable - if (sme.qualifiers != null) - foreach (var q in sme.qualifiers) - this.entityBuilder.AasTypes.Qualifier.CreateAddElements(o, CreateMode.Instance, q); - - // result - return o; - } - } - - /// - /// This class will automatically instantiate the correct SubmodelElement entity. - /// - public class AasUaEntitySubmodelWrapper : AasUaBaseEntity - { - public AasUaEntitySubmodelWrapper(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // do NOT create type object, as this is done by sub-class - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, SubmodelElementWrapper smw = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - // access - if (parent == null) - return null; - - if (mode == CreateMode.Type) - { - - - // create only containing element (base type) with generic name - var o = this.entityBuilder.CreateAddObject(parent, "SubmodelElement", ReferenceTypeIds.HasComponent, this.entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), modellingRule: modellingRule); - return o; - } - else - { - if (smw == null || smw.submodelElement == null) - return null; - - if (smw.submodelElement is SubmodelElementCollection) - { - var coll = smw.submodelElement as SubmodelElementCollection; - return this.entityBuilder.AasTypes.Collection.CreateAddInstanceObject(parent, coll); - } - else if (smw.submodelElement is Property) - return this.entityBuilder.AasTypes.Property.CreateAddInstanceObject(parent, smw.submodelElement as Property); - else if (smw.submodelElement is File) - return this.entityBuilder.AasTypes.File.CreateAddInstanceObject(parent, smw.submodelElement as File); - else if (smw.submodelElement is Blob) - return this.entityBuilder.AasTypes.Blob.CreateAddInstanceObject(parent, smw.submodelElement as Blob); - else if (smw.submodelElement is ReferenceElement) - return this.entityBuilder.AasTypes.ReferenceElement.CreateAddInstanceObject(parent, smw.submodelElement as ReferenceElement); - else if (smw.submodelElement is RelationshipElement) - return this.entityBuilder.AasTypes.RelationshipElement.CreateAddInstanceObject(parent, smw.submodelElement as RelationshipElement); - else if (smw.submodelElement is Operation) - return this.entityBuilder.AasTypes.Operation.CreateAddInstanceObject(parent, smw.submodelElement as Operation); - - // nope - return null; - } - } - } - - public class AasUaEntityProperty : AasUaEntitySubmodelElementBase - { - public AasUaEntityProperty(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASPropertyType", entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, descriptionKey: "AAS:Property"); - - // elements not in the base type - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Instance, null, "ValueId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - this.entityBuilder.CreateAddPropertyState(this.typeObject, "ValueType", DataTypeIds.String, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Value", DataTypeIds.BaseDataType, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddInstanceObject(NodeState parent, Property prop) - { - // access - if (prop == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "" + prop.IdShort, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, prop); - - // TODO: not sure if to add these - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, prop.ValueId, "ValueId"); - this.entityBuilder.CreateAddPropertyState(o, "ValueType", DataTypeIds.String, "" + prop.ValueType, defaultSettings: true); - - // TODO: aim is to support many types natively - var vt = (prop.ValueType ?? "").ToLower().Trim(); - if (vt == "boolean") - { - var x = (prop.Value ?? "").ToLower().Trim(); - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.Boolean, x == "true", defaultSettings: true); - } - else if (vt == "datetime" || vt == "datetimestamp" || vt == "time") - { - DateTime dt; - if (DateTime.TryParse(prop.Value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dt)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.DateTime, dt.ToFileTimeUtc(), defaultSettings: true); - } - else if (vt == "decimal" || vt == "integer" || vt == "long" || vt == "nonpositiveinteger" || vt == "negativeinteger") - { - Int64 v; - if (Int64.TryParse(prop.Value, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.Int64, v, defaultSettings: true); - } - else if (vt == "int") - { - Int32 v; - if (Int32.TryParse(prop.Value, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.Int32, v, defaultSettings: true); - } - else if (vt == "short") - { - Int16 v; - if (Int16.TryParse(prop.Value, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.Int16, v, defaultSettings: true); - } - else if (vt == "byte") - { - SByte v; - if (SByte.TryParse(prop.Value, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.Byte, v, defaultSettings: true); - } - else if (vt == "nonnegativeinteger" || vt == "positiveinteger" || vt == "unsignedlong") - { - UInt64 v; - if (UInt64.TryParse(prop.Value, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.UInt64, v, defaultSettings: true); - } - else if (vt == "unsignedint") - { - UInt32 v; - if (UInt32.TryParse(prop.Value, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.UInt32, v, defaultSettings: true); - } - else if (vt == "unsignedshort") - { - UInt16 v; - if (UInt16.TryParse(prop.Value, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.UInt16, v, defaultSettings: true); - } - else if (vt == "unsignedbyte") - { - Byte v; - if (Byte.TryParse(prop.Value, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.Byte, v, defaultSettings: true); - } - else if (vt == "double") - { - double v; - if (double.TryParse(prop.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.Double, v, defaultSettings: true); - } - else if (vt == "float") - { - float v; - if (float.TryParse(prop.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out v)) - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.Float, v, defaultSettings: true); - } - else - { - // leave in string - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.String, prop.Value, defaultSettings: true); - } - - // result - return o; - } - } - - public class AasUaEntityCollection : AasUaEntitySubmodelElementBase - { - public NodeState typeObjectOrdered = null; - - public AasUaEntityCollection(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - // TODO: use the collection element of UA - this.typeObject = this.entityBuilder.CreateAddObjectType("AASSubmodelElementCollectionType", entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, descriptionKey: "AAS:SubmodelElementCollection"); - this.typeObjectOrdered = this.entityBuilder.CreateAddObjectType("AASSubmodelElementOrderedCollectionType", this.GetTypeNodeId(), preferredTypeNumId + 1, descriptionKey: "AAS:SubmodelElementCollection"); - - // some elements - foreach (var o in new NodeState[] { this.typeObject /* , this.typeObjectOrdered */ }) - { - this.entityBuilder.CreateAddPropertyState(o, "AllowDuplicates", DataTypeIds.Boolean, false, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - } - } - - public NodeState CreateAddInstanceObject(NodeState parent, SubmodelElementCollection coll) - { - // access - if (coll == null) - return null; - - // containing element - var to = GetTypeObject().NodeId; - if (coll.ordered && this.typeObjectOrdered != null) - to = this.typeObjectOrdered.NodeId; - var o = this.entityBuilder.CreateAddObject(parent, "" + coll.IdShort, ReferenceTypeIds.HasComponent, to); - - // populate common attributes - base.PopulateInstanceObject(o, coll); - - // own attributes - this.entityBuilder.CreateAddPropertyState(o, "AllowDuplicates", DataTypeIds.Boolean, coll.allowDuplicates, defaultSettings: true); - - // values - if (coll.Value != null) - foreach (var smw in coll.Value) - if (smw.submodelElement != null) - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements(o, CreateMode.Instance, smw); - - // result - return o; - } - } - - public class AasUaEntityFile : AasUaEntitySubmodelElementBase - { - public AasUaEntityFile(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASFileType", entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, descriptionKey: "AAS:File"); - - // some elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, "MimeType", this.entityBuilder.AasTypes.MimeType.GetTypeNodeId(), null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Value", this.entityBuilder.AasTypes.PathType.GetTypeNodeId(), null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.FileType.CreateAddElements(this.typeObject, CreateMode.Type); - } - - public NodeState CreateAddInstanceObject(NodeState parent, File file) - { - // access - if (file == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "" + file.IdShort, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, file); - - // own attributes - this.entityBuilder.CreateAddPropertyState(o, "MimeType", this.entityBuilder.AasTypes.MimeType.GetTypeNodeId(), file.mimeType, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, "Value", this.entityBuilder.AasTypes.PathType.GetTypeNodeId(), file.Value, defaultSettings: true); - - // wonderful working - if (this.entityBuilder.AasTypes.FileType.CheckSuitablity(this.entityBuilder.package, file)) - this.entityBuilder.AasTypes.FileType.CreateAddElements(o, CreateMode.Instance, this.entityBuilder.package, file); - - // result - return o; - } - } - - public class AasUaEntityBlob : AasUaEntitySubmodelElementBase - { - public AasUaEntityBlob(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASBlobType", entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, descriptionKey: "AAS:Blob"); - - // some elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, "MimeType", DataTypeIds.String, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Value", DataTypeIds.String, null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddInstanceObject(NodeState parent, Blob blob) - { - // access - if (blob == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "" + blob.IdShort, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, blob); - - // own attributes - this.entityBuilder.CreateAddPropertyState(o, "MimeType", DataTypeIds.String, blob.mimeType, defaultSettings: true); - this.entityBuilder.CreateAddPropertyState(o, "Value", DataTypeIds.String, blob.Value, defaultSettings: true); - - // result - return o; - } - } - - public class AasUaEntityReferenceElement : AasUaEntitySubmodelElementBase - { - public AasUaEntityReferenceElement(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASReferenceElementType", entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, descriptionKey: "AAS:ReferenceElement"); - - // some elements - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "Value", modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddInstanceObject(NodeState parent, ReferenceElement refElem) - { - // access - if (refElem == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "" + refElem.IdShort, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, refElem); - - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, refElem.Value, "Value"); - - // result - return o; - } - } - - public class AasUaEntityRelationshipElement : AasUaEntitySubmodelElementBase - { - public AasUaEntityRelationshipElement(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASRelationshipElementType", entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, descriptionKey: "AAS:RelationshipElement"); - - // some elements - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "First", modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "Second", modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddInstanceObject(NodeState parent, RelationshipElement relElem) - { - // access - if (relElem == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "" + relElem.IdShort, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, relElem); - - // own attributes - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, relElem.first, "First"); - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, relElem.second, "Second"); - - // result - return o; - } - } - - public class AasUaEntityOperationVariable : AasUaEntitySubmodelElementBase - { - public AasUaEntityOperationVariable(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("OperationVariableType", entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, descriptionKey: "AAS:OperationVariable"); - } - - public NodeState CreateAddInstanceObject(NodeState parent, OperationVariable opvar) - { - // access - if (opvar == null || opvar.Value == null || opvar.Value.submodelElement == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "" + opvar.Value.submodelElement.IdShort, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, opvar.Value.submodelElement); - - // own attributes - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements(o, CreateMode.Instance, opvar.Value); - - // result - return o; - } - } - - public class AasUaEntityOperation : AasUaEntitySubmodelElementBase - { - public AasUaEntityOperation(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASOperationType", entityBuilder.AasTypes.SubmodelElement.GetTypeNodeId(), preferredTypeNumId, descriptionKey: "AAS:Operation"); - - // indicate the Operation - this.entityBuilder.CreateAddMethodState(this.typeObject, "Operation", - inputArgs: null, - outputArgs: null, - referenceTypeFromParentId: ReferenceTypeIds.HasComponent); - - // some elements - for (int i = 0; i < 2; i++) - { - var o2 = this.entityBuilder.CreateAddObject(this.typeObject, (i == 0) ? "in" : "out", ReferenceTypeIds.HasComponent, this.entityBuilder.AasTypes.OperationVariable.GetTypeObject().NodeId); - this.entityBuilder.AasTypes.OperationVariable.CreateAddInstanceObject(o2, null); - } - } - - public NodeState CreateAddInstanceObject(NodeState parent, Operation op) - { - // access - if (op == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "" + op.IdShort, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId); - - // populate common attributes - base.PopulateInstanceObject(o, op); - - // own AAS attributes (in/out op vars) - for (int i = 0; i < 2; i++) - { - var opvarList = op[i]; - if (opvarList != null && opvarList.Count > 0) - { - var o2 = this.entityBuilder.CreateAddObject(o, (i == 0) ? "OperationInputVariables" : "OperationOutputVariables", - ReferenceTypeIds.HasComponent, /* TODO */ GetTypeObject().NodeId); - foreach (var opvar in opvarList) - if (opvar != null && opvar.Value != null) - this.entityBuilder.AasTypes.SubmodelWrapper.CreateAddElements(o2, CreateMode.Instance, opvar.Value); - } - } - - // create a method? - if (true) - { - var args = new List[] { new List(), new List() }; - for (int i = 0; i < 2; i++) - if (op[i] != null) - foreach (var opvar in op[i]) - { - // TODO: decide to from where the name comes - var name = "noname"; - - // TODO: description: get "en" version is appropriate? - LocalizedText desc = new LocalizedText(""); - - // TODO: parse UA data type out .. OK? - NodeId dataType = null; - if (opvar.Value != null && opvar.Value.submodelElement != null) - { - // better name .. but not best (see below) - if (opvar.Value.submodelElement.IdShort != null && opvar.Value.submodelElement.IdShort.Trim() != "") - name = "" + opvar.Value.submodelElement.IdShort; - - // TODO: description: get "en" version is appropriate? - desc = AasUaUtils.GetBestUaDescriptionFromAasDescription(opvar.Value.submodelElement.description); - - // currenty, only accept properties as in/out arguments. Only these have an XSD value type!! - var prop = opvar.Value.submodelElement as Property; - if (prop != null && prop.ValueType != null) - { - // TODO: this any better? - if (prop.IdShort != null && prop.IdShort.Trim() != "") - name = "" + prop.IdShort; - - // TODO: description: get "en" version is appropriate? - if (desc.Text == null || desc.Text == "") - desc = AasUaUtils.GetBestUaDescriptionFromAasDescription(opvar.Value.submodelElement.description); - - // try convert type - Type sharpType; - if (!AasUaUtils.AasValueTypeToUaDataType(prop.ValueType, out sharpType, out dataType)) - dataType = null; - } - } - if (dataType == null) - continue; - - var a = new Argument(name, dataType, -1, desc.Text ?? ""); - args[i].Add(a); - } - - var opmeth = this.entityBuilder.CreateAddMethodState(o, "Operation", - inputArgs: args[0].ToArray(), - outputArgs: args[1].ToArray(), - referenceTypeFromParentId: ReferenceTypeIds.HasComponent); - } - - // result - return o; - } - } - - public class AasUaEntityView : AasUaBaseEntity - { - public AasUaEntityView(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASViewType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:View"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, this.entityBuilder.AasTypes.IAASReferableType.GetTypeNodeId()); - - // add some elements - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(this.typeObject, CreateMode.Type, null, "SemanticId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - // contained elements - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "ContainedElement", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AdminShell.View view = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - if (mode == CreateMode.Type) - { - - // create only containing element with generic name - var o = this.entityBuilder.CreateAddObject(parent, "View", ReferenceTypeIds.HasComponent, this.GetTypeNodeId(), modellingRule: modellingRule); - return o; - - } - else - { - // access - if (view == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "" + view.IdShort, ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, extraName: "View:" + view.IdShort); - - // register node record - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, view)); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Instance, view); - // HasSemantics - this.entityBuilder.AasTypes.SemanticId.CreateAddInstanceObject(o, CreateMode.Instance, view.semanticId, "SemanticId"); - // HasDataSpecification - if (view.hasDataSpecification != null && view.hasDataSpecification.reference != null) - foreach (var ds in view.hasDataSpecification.reference) - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, ds, "DataSpecification"); - - // contained elements - for (int i = 0; i < view.Count; i++) - { - var cer = view[i]; - if (cer != null) - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, cer, "ContainedElement"); - } - - // OK - return o; - } - } - } - - public class AasUaEntityConceptDictionary : AasUaBaseEntity - { - public AasUaEntityConceptDictionary(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASConceptDictionaryType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:ConceptDictionary"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, this.entityBuilder.AasTypes.IAASReferableType.GetTypeNodeId()); - - // add necessary type information - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - // Dictionary Entries - this.entityBuilder.CreateAddObject(this.typeObject, "DictionaryEntry", ReferenceTypeIds.HasComponent, this.entityBuilder.AasTypes.DictionaryEntryType.GetTypeNodeId(), modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AdminShell.ConceptDictionary cdd = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - // Create whole object only if required - if (mode == CreateMode.Instance && cdd == null) - return null; - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, "ConceptDictionary", ReferenceTypeIds.HasComponent, GetTypeObject().NodeId, modellingRule: modellingRule); - - if (mode == CreateMode.Instance) - { - // access - if (cdd == null) - return null; - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Instance, cdd); - } - - return o; - } - } - - public class AasUaEntityDataSpecification : AasUaBaseEntity - { - public AasUaEntityDataSpecification(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASDataSpecificationType", ObjectTypeIds.BaseObjectType, preferredTypeNumId, descriptionKey: "AAS:DataSpecification"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - } - - } - - public class AasUaEntityDataSpecificationIEC61360 : AasUaBaseEntity - { - public AasUaEntityDataSpecificationIEC61360(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("AASDataSpecificationIEC61360Type", this.entityBuilder.AasTypes.DataSpecification.GetTypeNodeId(), preferredTypeNumId, descriptionKey: "AAS:DataSpecificationIEC61360"); - - // very special rule here for the Identifiable - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObject, false, this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Instance, - new AdminShell.Identification("URI", "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360"), - modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Instance, - new AdminShell.Administration("1", "0"), - modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - // add some more elements - this.entityBuilder.CreateAddPropertyState(this.typeObject, "PreferredName", DataTypeIds.LocalizedText, - value: null, defaultSettings: true, valueRank: 1, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, "ShortName", DataTypeIds.String, value: null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Unit", DataTypeIds.String, value: null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - this.entityBuilder.AasTypes.Reference.CreateAddElements(this.typeObject, CreateMode.Type, null, "UnitId", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, "SourceOfDefinition", DataTypeIds.LocalizedText, - value: null, defaultSettings: true, valueRank: 1, modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Symbol", DataTypeIds.String, value: null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, "DataType", DataTypeIds.String, value: null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, "Definition", DataTypeIds.LocalizedText, - value: null, defaultSettings: true, valueRank: 1, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - - this.entityBuilder.CreateAddPropertyState(this.typeObject, "ValueFormat", DataTypeIds.String, value: null, defaultSettings: true, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, AdminShell.DataSpecificationIEC61360 ds = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - // for the sake of clarity, we're directly splitting cases - if (mode == CreateMode.Type) - { - // containing element (only) - var o = this.entityBuilder.CreateAddObject(parent, "DataSpecificationIEC61360", this.entityBuilder.AasTypes.HasAddIn.GetTypeNodeId(), GetTypeObject().NodeId, modellingRule: modellingRule); - return o; - } - else - { - // access - if (ds == null) - return null; - - // we can only provide minimal unique naming - var name = "DataSpecificationIEC61360"; - if (ds.shortName != null && this.entityBuilder.RootDataSpecifications != null) - name += "_" + ds.shortName; - - // containing element (depending on root folder) - NodeState o = null; - if (this.entityBuilder.RootDataSpecifications != null) - { - // under common folder - o = this.entityBuilder.CreateAddObject(this.entityBuilder.RootDataSpecifications, name, ReferenceTypeIds.Organizes, GetTypeObject().NodeId); - // link to this object - parent.AddReference(this.entityBuilder.AasTypes.HasAddIn.GetTypeNodeId(), false, o.NodeId); - } - else - { - // under parent - o = this.entityBuilder.CreateAddObject(parent, name, this.entityBuilder.AasTypes.HasAddIn.GetTypeNodeId(), GetTypeObject().NodeId); - } - - // add some elements - if (ds.preferredName != null && ds.preferredName.Count > 0) - this.entityBuilder.CreateAddPropertyState(o, "PreferredName", DataTypeIds.LocalizedText, - value: AasUaUtils.GetUaLocalizedTexts(ds.preferredName?.langString), defaultSettings: true, valueRank: 1); - - if (ds.shortName != null && ds.shortName.Count > 0) - this.entityBuilder.CreateAddPropertyState(o, "ShortName", DataTypeIds.LocalizedText, - value: AasUaUtils.GetUaLocalizedTexts(ds.shortName?.langString), defaultSettings: true, valueRank: 1); - - if (ds.unit != null) - this.entityBuilder.CreateAddPropertyState(o, "Unit", DataTypeIds.String, value: ds.unit, defaultSettings: true); - - if (ds.unitId != null) - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, AdminShell.Reference.CreateNew(ds.unitId?.Keys), "UnitId"); - - if (ds.sourceOfDefinition != null) - this.entityBuilder.CreateAddPropertyState(o, "SourceOfDefinition", DataTypeIds.String, value: ds.sourceOfDefinition, defaultSettings: true); - - if (ds.symbol != null) - this.entityBuilder.CreateAddPropertyState(o, "Symbol", DataTypeIds.String, value: ds.symbol, defaultSettings: true); - - if (ds.dataType != null) - this.entityBuilder.CreateAddPropertyState(o, "DataType", DataTypeIds.String, value: ds.dataType, defaultSettings: true); - - if (ds.definition != null && ds.definition.Count > 0) - this.entityBuilder.CreateAddPropertyState(o, "Definition", DataTypeIds.LocalizedText, - value: AasUaUtils.GetUaLocalizedTexts(ds.definition?.langString), defaultSettings: true, valueRank: 1); - - if (ds.ValueFormat != null) - this.entityBuilder.CreateAddPropertyState(o, "ValueFormat", DataTypeIds.String, value: ds.ValueFormat, defaultSettings: true); - - // return - return o; - } - } - } - - public class AasUaEntityConceptDescription : AasUaBaseEntity - { - public NodeState typeObjectIrdi; - public NodeState typeObjectUri; - public NodeState typeObjectCustom; - - - public AasUaEntityConceptDescription(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - // TODO: make super classes for UriDictionaryEntryType.. - this.typeObjectIrdi = this.entityBuilder.CreateAddObjectType("AASIrdiConceptDescriptionType", this.entityBuilder.AasTypes.IrdiDictionaryEntryType.GetTypeNodeId(), 0, descriptionKey: "AAS:ConceptDescription"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObjectIrdi, false, this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - this.typeObjectUri = this.entityBuilder.CreateAddObjectType("AASUriConceptDescriptionType", this.entityBuilder.AasTypes.UriDictionaryEntryType.GetTypeNodeId(), 0, descriptionKey: "AAS:ConceptDescription"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObjectUri, false, this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - this.typeObjectCustom = this.entityBuilder.CreateAddObjectType("AASCustomConceptDescriptionType", this.entityBuilder.AasTypes.DictionaryEntryType.GetTypeNodeId(), 0, descriptionKey: "AAS:ConceptDescription"); - this.entityBuilder.AasTypes.HasInterface.CreateAddInstanceReference(this.typeObjectCustom, false, this.entityBuilder.AasTypes.IAASIdentifiableType.GetTypeNodeId()); - - // for each of them, add some elements - foreach (var o in new NodeState[] { this.typeObjectIrdi, this.typeObjectUri, this.typeObjectCustom }) - { - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Type); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(o, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(o, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // IsCaseOf - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Type, null, "IsCaseOf", modellingRule: AasUaNodeHelper.ModellingRule.Optional); - // HasDataSpecification - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Type, null, "DataSpecification", modellingRule: AasUaNodeHelper.ModellingRule.OptionalPlaceholder); - - // data specification is a child - this.entityBuilder.AasTypes.DataSpecificationIEC61360.CreateAddElements(o, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.MandatoryPlaceholder); - } - } - - public NodeState GetTypeObjectFor(AdminShell.Identification identification) - { - var to = this.typeObject; // shall be NULL - if (identification != null && identification.idType != null && identification.idType.Trim().ToUpper() == "URI") - to = this.typeObjectUri; - if (identification != null && identification.idType != null && identification.idType.Trim().ToUpper() == "IRDI") - to = this.typeObjectIrdi; - if (identification != null && identification.idType != null && identification.idType.Trim().ToUpper() == "CUSTOM") - to = this.typeObjectCustom; - return to; - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, ConceptDescription cd = null, AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None) - { - if (parent == null) - return null; - - // split directly because of complexity - if (mode == CreateMode.Type) - { - // not sure, if this will required, ever - return null; - } - else - { - // access - if (cd == null) - return null; - - // makeup name - var name = "ConceptDescription_" + Guid.NewGuid().ToString(); - - if (false) - { - // Conventional approach: build up a speaking name - // but: shall be target of "HasDictionaryEntry", therefore the __PURE__ identifications need to be the name! - if (cd.embeddedDataSpecification != null && cd.embeddedDataSpecification.dataSpecificationContent != null && cd.embeddedDataSpecification.dataSpecificationContent.dataSpecificationIEC61360 != null) - { - var ds = cd.embeddedDataSpecification.dataSpecificationContent.dataSpecificationIEC61360; - if (ds.shortName != null) - name = ds.shortName.GetDefaultStr(); - if (cd.identification != null) - name += "_" + cd.identification.ToString(); - } - name = AasUaUtils.ToOpcUaName(name); - } - else - { - // only identification (the type object will distinct between the id type) - if (cd.identification != null) - name = cd.identification.id; - } - - // containing element - var o = this.entityBuilder.CreateAddObject(parent, name, ReferenceTypeIds.HasComponent, this.GetTypeObjectFor(cd.identification)?.NodeId, modellingRule: modellingRule); - - // Referable - this.entityBuilder.AasTypes.Referable.CreateAddElements(o, CreateMode.Instance, cd); - // Identifiable - this.entityBuilder.AasTypes.Identification.CreateAddElements(o, CreateMode.Instance, cd.identification); - this.entityBuilder.AasTypes.Administration.CreateAddElements(o, CreateMode.Instance, cd.administration); - // IsCaseOf - if (cd.IsCaseOf != null) - foreach (var ico in cd.IsCaseOf) - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, ico, "IsCaseOf"); - // HasDataSpecification - if (cd.embeddedDataSpecification != null && cd.embeddedDataSpecification.dataSpecification != null) - this.entityBuilder.AasTypes.Reference.CreateAddElements(o, CreateMode.Instance, cd.embeddedDataSpecification.dataSpecification, "DataSpecification"); - - // data specification is a child - if (cd.embeddedDataSpecification != null && cd.embeddedDataSpecification.dataSpecificationContent != null && cd.embeddedDataSpecification.dataSpecificationContent.dataSpecificationIEC61360 != null) - { - var dso = this.entityBuilder.AasTypes.DataSpecificationIEC61360.CreateAddElements(o, CreateMode.Instance, cd.embeddedDataSpecification.dataSpecificationContent.dataSpecificationIEC61360); - } - - // remeber CD as NodeRecord - this.entityBuilder.AddNodeRecord(new AasEntityBuilder.NodeRecord(o, cd.identification)); - - return o; - } - } - } - - // - // Elements from the UA spc - // - - public class AasUaNamespaceZeroEntity : AasUaBaseEntity - { - public AasUaNamespaceZeroEntity(AasEntityBuilder entityBuilder, uint presetNumId = 0) - : base(entityBuilder) - { - // just set node id based on existing knowledge - this.typeObjectId = new NodeId(presetNumId, 0); - } - } - - public class AasUaNamespaceZeroReference : AasUaBaseEntity - { - public AasUaNamespaceZeroReference(AasEntityBuilder entityBuilder, uint presetNumId = 0) - : base(entityBuilder) - { - // just set node id based on existing knowledge - this.typeObjectId = new NodeId(presetNumId, 0); - } - - public void CreateAddInstanceReference(NodeState source, bool isInverse, ExpandedNodeId target) - { - if (source != null && target != null && this.GetTypeNodeId() != null) - source.AddReference(this.GetTypeNodeId(), isInverse, target); - } - } - - // - // References - // - - public class AasUaReferenceHasAasReference : AasUaBaseEntity - { - public AasUaReferenceHasAasReference(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddReferenceType("AASReference", "AASReferencedBy", preferredTypeNumId, useZeroNS: false); - } - - public NodeState CreateAddInstanceReference(NodeState parent) - { - return null; - } - } - - - // - // Interfaces - // - - public class AasUaInterfaceAASIdentifiableType : AasUaBaseEntity - { - public AasUaInterfaceAASIdentifiableType(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("IAASIdentifiableType", this.entityBuilder.AasTypes.IAASReferableType.GetTypeNodeId() /* ObjectTypeIds.BaseObjectType */, preferredTypeNumId, descriptionKey: "AAS:Identifiable"); - - // add some elements - this.entityBuilder.AasTypes.Identification.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Mandatory); - this.entityBuilder.AasTypes.Administration.CreateAddElements(this.typeObject, CreateMode.Type, modellingRule: AasUaNodeHelper.ModellingRule.Optional); - } - } - - public class AasUaInterfaceAASReferableType : AasUaBaseEntity - { - public AasUaInterfaceAASReferableType(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // create type object - this.typeObject = this.entityBuilder.CreateAddObjectType("IAASReferableType", this.entityBuilder.AasTypes.BaseInterfaceType.GetTypeNodeId() /* ObjectTypeIds.BaseObjectType */, preferredTypeNumId, descriptionKey: "AAS:Referable"); - - // some elements - this.entityBuilder.AasTypes.Referable.CreateAddElements(this.typeObject, CreateMode.Type); - } - } -} diff --git a/src/AasxServerStandardBib/AasUaEntityFileType.cs b/src/AasxServerStandardBib/AasUaEntityFileType.cs deleted file mode 100644 index 18a8fe363..000000000 --- a/src/AasxServerStandardBib/AasUaEntityFileType.cs +++ /dev/null @@ -1,391 +0,0 @@ -/* -Copyright (c) 2018-2019 Festo AG & Co. KG -Author: Michael Hoffmeister - -This source code is licensed under the Apache License 2.0 (see LICENSE.txt). - -This source code may use other Open Source software components (see LICENSE.txt). -*/ - -using AdminShellNS; -using Opc.Ua; -using System; -using System.Collections.Generic; -using System.IO; - -namespace AasOpcUaServer -{ - public class AasUaPackageFileHandler - { - private AdminShellPackageEnv package = null; - private AasCore.Aas3_0.File file = null; - - private class PackageFileHandle - { - public UInt32 handle = 0; - public UInt64 filepos = 0; - public Stream packStream = null; - - public int UaMode = 0; - public bool IsRead = true; - public bool IsWrite = true; - - public PackageFileHandle() { } - public PackageFileHandle(UInt32 handle) - { - this.handle = handle; - } - } - - private Dictionary handles = new Dictionary(); - - public AasUaPackageFileHandler(AdminShellPackageEnv package, AasCore.Aas3_0.File file) - { - this.package = package; - this.file = file; - } - - private UInt32 GetMaxHandle() - { - UInt32 mh = 0; - foreach (var x in handles.Keys) - mh = Math.Max(x, mh); - return mh; - } - - public UInt32 Open(Byte mode) - { - // access file handle - if (this.package == null || this.file == null) - throw new InvalidOperationException("no admin-shell package or file"); - var nh = GetMaxHandle() + 1; - var fh = new PackageFileHandle(nh); - fh.packStream = package.GetLocalStreamFromPackage(file.Value); - if (fh.packStream == null) - throw new InvalidOperationException("no admin-shell package or file"); - handles.Add(nh, fh); - - // care about the particularities of write - fh.UaMode = mode; - fh.IsRead = ((mode & 0x01) > 0); - fh.IsWrite = ((mode & 0x02) > 0); - if ((mode & 0x04) > 0) - { - // Erase existing - fh.packStream.Seek(0, SeekOrigin.Begin); - fh.packStream.SetLength(0); - fh.packStream.Flush(); - } - if ((mode & 0x08) > 0) - { - // Append - fh.packStream.Seek(0, SeekOrigin.End); - fh.packStream.Flush(); - } - - // done - return nh; - } - - public long GetLength(UInt32 handle) - { - if (!handles.ContainsKey(handle)) - throw new InvalidOperationException("handle is unknown"); - var h = handles[handle]; - return h.packStream.Length; - } - - public void Close(UInt32 handle) - { - if (!handles.ContainsKey(handle)) - throw new InvalidOperationException("handle is unknown"); - handles.Remove(handle); - } - - public void SetPosition(UInt32 handle, UInt64 pos) - { - if (!handles.ContainsKey(handle)) - throw new InvalidOperationException("handle is unknown"); - var h = handles[handle]; - h.filepos = pos; - } - - public UInt64 GetPosition(UInt32 handle) - { - if (!handles.ContainsKey(handle)) - throw new InvalidOperationException("handle is unknown"); - if (this.package == null || this.file == null) - throw new InvalidOperationException("no admin-shell package or file"); - var h = handles[handle]; - return h.filepos; - } - - public Byte[] Read(UInt32 handle, UInt32 readlen) - { - if (!handles.ContainsKey(handle)) - throw new InvalidOperationException("handle is unknown"); - if (this.package == null || this.file == null) - throw new InvalidOperationException("no admin-shell package or file"); - var h = handles[handle]; - if (h.packStream == null) - throw new InvalidOperationException("no open stream"); - if (h.filepos >= (ulong)h.packStream.Length) - throw new InvalidOperationException("invalid file position"); - - // Finding: 4.194.304 Bytes as requested by the UA Expert is too much - // Reduce zu 16bit Size, to show suitablility also for small devices - readlen = Math.Min(readlen, (2 << 15) - 1); - - byte[] res = new byte[readlen]; - h.packStream.Seek((long)h.filepos, SeekOrigin.Begin); - var redd = h.packStream.Read(res, 0, (int)readlen); - h.filepos += (UInt64)redd; - return res; - } - - public void Write(UInt32 handle, Byte[] data) - { - if (!handles.ContainsKey(handle)) - throw new InvalidOperationException("handle is unknown"); - if (this.package == null || this.file == null) - throw new InvalidOperationException("no admin-shell package or file"); - var h = handles[handle]; - if (h.packStream == null) - throw new InvalidOperationException("no open stream"); - - h.packStream.Write(data, 0, data.Length); - h.filepos += (ulong)data.Length; - } - } - - public class AasUaEntityFileType : AasUaBaseEntity - { - private class InstanceData - { - public AasUaPackageFileHandler packHandler = null; - public MethodState mOpen, mClose, mRead, mWrite, mSetPosition, mGetPosition; - public PropertyState nodeOpenCount = null; - public PropertyState nodeSize = null; - - public void UpdateSize(UInt64 size) - { - if (nodeSize != null) - nodeSize.Value = size; - } - } - - public AasUaEntityFileType(AasEntityBuilder entityBuilder, uint preferredTypeNumId = 0) - : base(entityBuilder) - { - // do NOT create type object, as they shall be all there in the UA constants - } - - /// - /// Checks, if a FileType node is advisable for representing an AASX file .. - /// Shall be TRUE for local, existing files .. - /// - /// - public bool CheckSuitablity(AdminShellPackageEnv package, AasCore.Aas3_0.File file) - { - // trivial - if (package == null || file == null) - return false; - - // try get a stream .. - Stream s = null; - try - { - s = package.GetLocalStreamFromPackage(file.Value); - } - catch (Exception ex) - { - AdminShellNS.LogInternally.That.SilentlyIgnoredError(ex); - return false; - } - - // ok? - return s != null; - } - - public NodeState CreateAddElements(NodeState parent, CreateMode mode, - AdminShellPackageEnv package = null, AasCore.Aas3_0.File file = null) - { - // access - if (parent == null) - return null; - - // for sake of complexity, differentiate early - if (mode == CreateMode.Type) - { - var o = this.entityBuilder.CreateAddObject( - parent, mode, "File", ReferenceTypeIds.HasComponent, ObjectTypeIds.FileType); - return o; - } - else - { - if (package == null || file == null) - return null; - - var instData = new InstanceData(); - instData.packHandler = new AasUaPackageFileHandler(package, file); - - // containing element - var o = this.entityBuilder.CreateAddObject( - parent, mode, "File", ReferenceTypeIds.HasComponent, ObjectTypeIds.FileType); - - - // this first information is to provide a "off-the-shelf" size information; a Open() will re-new this - var fileLen = Convert.ToUInt64(package.GetStreamSizeFromPackage(file.Value)); - - // populate attributes from the spec - this.entityBuilder.CreateAddPropertyState(o, mode, "MimeType", - DataTypeIds.String, file.ContentType, ReferenceTypeIds.HasProperty, VariableTypeIds.PropertyType); - instData.nodeOpenCount = this.entityBuilder.CreateAddPropertyState(o, mode, "OpenCount", - DataTypeIds.UInt16, 0, ReferenceTypeIds.HasProperty, VariableTypeIds.PropertyType); - instData.nodeSize = this.entityBuilder.CreateAddPropertyState(o, mode, "Size", - DataTypeIds.UInt64, fileLen, ReferenceTypeIds.HasProperty, VariableTypeIds.PropertyType, - valueRank: -1); - this.entityBuilder.CreateAddPropertyState(o, mode, "UserWritable", - DataTypeIds.Boolean, true, ReferenceTypeIds.HasProperty, VariableTypeIds.PropertyType); - this.entityBuilder.CreateAddPropertyState(o, mode, "Writable", - DataTypeIds.Boolean, true, ReferenceTypeIds.HasProperty, VariableTypeIds.PropertyType); - - // Open - instData.mOpen = this.entityBuilder.CreateAddMethodState(o, mode, "Open", - inputArgs: new[] { - new Argument("Mode", DataTypeIds.Byte, -1, "") - }, - outputArgs: new[] { - new Argument("FileHandle", DataTypeIds.UInt32, -1, "") - }, referenceTypeFromParentId: ReferenceTypeIds.HasComponent, - methodDeclarationId: MethodIds.FileType_Open, onCalled: this.OnMethodCalled); - - this.entityBuilder.AddNodeStateAnnotation(instData.mOpen, instData); - - // Close - instData.mClose = this.entityBuilder.CreateAddMethodState(o, mode, "Close", - inputArgs: new[] { - new Argument("FileHandle", DataTypeIds.UInt32, -1, "") - }, - outputArgs: null, - referenceTypeFromParentId: ReferenceTypeIds.HasComponent, - methodDeclarationId: MethodIds.FileType_Close, onCalled: this.OnMethodCalled); - - this.entityBuilder.AddNodeStateAnnotation(instData.mClose, instData); - - // Read - instData.mRead = this.entityBuilder.CreateAddMethodState(o, mode, "Read", - inputArgs: new[] { - new Argument("FileHandle", DataTypeIds.UInt32, -1, ""), - new Argument("Length", DataTypeIds.Int32, -1, "") - }, - outputArgs: new[] { - new Argument("Data", DataTypeIds.ByteString, -1, "") - }, referenceTypeFromParentId: ReferenceTypeIds.HasComponent, - methodDeclarationId: MethodIds.FileType_Read, onCalled: this.OnMethodCalled); - - this.entityBuilder.AddNodeStateAnnotation(instData.mRead, instData); - - // Write - instData.mWrite = this.entityBuilder.CreateAddMethodState(o, mode, "Write", - inputArgs: new[] { - new Argument("FileHandle", DataTypeIds.UInt32, -1, ""), - new Argument("Data", DataTypeIds.ByteString, -1, "") - }, - outputArgs: null, - referenceTypeFromParentId: ReferenceTypeIds.HasComponent, - methodDeclarationId: MethodIds.FileType_Write, onCalled: this.OnMethodCalled); - - this.entityBuilder.AddNodeStateAnnotation(instData.mWrite, instData); - - // GetPosition - instData.mGetPosition = this.entityBuilder.CreateAddMethodState(o, mode, "GetPosition", - inputArgs: new[] { - new Argument("FileHandle", DataTypeIds.UInt32, -1, ""), - }, - outputArgs: new[] { - new Argument("Position", DataTypeIds.UInt64, -1, "") - }, - referenceTypeFromParentId: ReferenceTypeIds.HasComponent, - methodDeclarationId: MethodIds.FileType_GetPosition, onCalled: this.OnMethodCalled); - - this.entityBuilder.AddNodeStateAnnotation(instData.mGetPosition, instData); - - // SetPosition - instData.mSetPosition = this.entityBuilder.CreateAddMethodState(o, mode, "SetPosition", - inputArgs: new[] { - new Argument("FileHandle", DataTypeIds.UInt32, -1, ""), - new Argument("Position", DataTypeIds.UInt64, -1, "") - }, - outputArgs: null, - referenceTypeFromParentId: ReferenceTypeIds.HasComponent, - methodDeclarationId: MethodIds.FileType_SetPosition, onCalled: this.OnMethodCalled); - - this.entityBuilder.AddNodeStateAnnotation(instData.mSetPosition, instData); - - // result - return o; - } - } - - private ServiceResult OnMethodCalled( - ISystemContext context, - MethodState method, - IList inputArguments, - IList outputArguments) - { - var instData = this.entityBuilder.FindNoteStateAnnotation(method); - if (instData == null || instData.packHandler == null) - return new ServiceResult(StatusCodes.BadInvalidArgument); - - try - { - if (method == instData.mOpen) - { - var fh = instData.packHandler.Open((byte)inputArguments[0]); - instData.UpdateSize(Convert.ToUInt64(instData.packHandler.GetLength(fh))); - outputArguments[0] = fh; - } - - if (method == instData.mClose) - { - instData.packHandler.Close((UInt32)inputArguments[0]); - } - - if (method == instData.mSetPosition) - { - instData.packHandler.SetPosition((UInt32)inputArguments[0], (UInt64)inputArguments[1]); - } - - if (method == instData.mGetPosition) - { - outputArguments[0] = instData.packHandler.GetPosition((UInt32)inputArguments[0]); - } - - if (method == instData.mRead) - { - var data = instData.packHandler.Read( - Convert.ToUInt32(inputArguments[0]), Convert.ToUInt32(inputArguments[1])); - outputArguments[0] = data; - } - - if (method == instData.mWrite) - { - var fh = Convert.ToUInt32(inputArguments[0]); - instData.packHandler.Write(fh, (byte[])inputArguments[1]); - instData.UpdateSize(Convert.ToUInt64(instData.packHandler.GetLength(fh))); - } - } - catch (Exception ex) - { - AdminShellNS.LogInternally.That.Error(ex, "The method could not be executed."); - - // treat every exception the same - return new ServiceResult(StatusCodes.BadInvalidArgument); - } - - return new ServiceResult(StatusCodes.Good); - } - - } -} diff --git a/src/AasxServerStandardBib/AasUaNodeHelper.cs b/src/AasxServerStandardBib/AasUaNodeHelper.cs deleted file mode 100644 index 6da08a2e7..000000000 --- a/src/AasxServerStandardBib/AasUaNodeHelper.cs +++ /dev/null @@ -1,146 +0,0 @@ -/******************************************************************************** -* Copyright (c) {2019 - 2024} Contributors to the Eclipse Foundation -* -* See the NOTICE file(s) distributed with this work for additional -* information regarding copyright ownership. -* -* This program and the accompanying materials are made available under the -* terms of the Apache License Version 2.0 which is available at -* https://www.apache.org/licenses/LICENSE-2.0 -* -* SPDX-License-Identifier: Apache-2.0 -********************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Opc.Ua; - -namespace AasOpcUaServer -{ - public class AasUaNodeHelper - { - /// - /// 4. The cardinality of an association or aggregation is specified via OPC Modelling rules. - /// The OPC modelling rule “Optional” is used if the cardinality is Zero or 1. - /// The OPC modelling rule “Mandatory” is used if the cardinality is One. - /// The OPC Modelling rule “OptionalPlaceholder” is used if the cardinality is zero, one or more than one element. - /// The OPC Modelling rule “MandatoryPlaceholder” ” is used if the cardinality is one or more than one element. - /// - public enum ModellingRule { None, Optional, OptionalPlaceholder, Mandatory, MandatoryPlaceholder } - - /// - /// Try find out the Description for a certain AAS literal/ refSemantics - /// - public static LocalizedText SetLocalizedTextWithDescription(LocalizedText l, string key) - { - var dk = AasEntityDescriptions.LookupDescription(key); - if (key != null) - l = new LocalizedText("en", dk); - return l; - } - - /// - /// Appply modelling rule to an arbitrary node - /// - public static NodeState CheckSetModellingRule(ModellingRule modellingRule, NodeState o) - { - if (o == null || modellingRule == ModellingRule.None) - return o; - if (modellingRule == ModellingRule.Optional) - o.AddReference(ReferenceTypeIds.HasModellingRule, false, ObjectIds.ModellingRule_Optional); - if (modellingRule == ModellingRule.OptionalPlaceholder) - o.AddReference(ReferenceTypeIds.HasModellingRule, false, ObjectIds.ModellingRule_OptionalPlaceholder); - if (modellingRule == ModellingRule.Mandatory) - o.AddReference(ReferenceTypeIds.HasModellingRule, false, ObjectIds.ModellingRule_Mandatory); - if (modellingRule == ModellingRule.MandatoryPlaceholder) - o.AddReference(ReferenceTypeIds.HasModellingRule, false, ObjectIds.ModellingRule_MandatoryPlaceholder); - return o; - } - - /// - /// Helper to create an ObjectType-Node. Note: __NO__ NodeId is created by the default! Must be done by outer functionality!! - /// - /// Name displayed in the node tree - /// Base class or similar - /// Preset the NodeId - /// Lookup a Description on AAS literal/ refSemantics - /// Modeling Rule, if not None - /// THe node - public static BaseObjectTypeState CreateObjectType( - string browseDisplayName, - NodeId superTypeId, - NodeId presetNodeId = null, - string descriptionKey = null, - ModellingRule modellingRule = ModellingRule.None) - { - var x = new BaseObjectTypeState(); - x.BrowseName = "" + browseDisplayName; - x.DisplayName = "" + browseDisplayName; - x.Description = new LocalizedText("en", browseDisplayName); - x.Description = SetLocalizedTextWithDescription(x.Description, descriptionKey); - x.SuperTypeId = superTypeId; - if (presetNodeId != null) - x.NodeId = presetNodeId; - CheckSetModellingRule(modellingRule, x); - return x; - } - - /// - /// Helper to create an ReferenceType-Node. Note: __NO__ NodeId is created by the default! Must be done by outer functionality!! - /// - /// Name displayed in the node tree - /// - /// Preset the NodeId - /// Preset the NodeId - /// - public static ReferenceTypeState CreateReferenceType( - string browseDisplayName, - string inverseName, - NodeId superTypeId, - NodeId presetNodeId = null) - { - // create node itself - var x = new ReferenceTypeState(); - x.BrowseName = browseDisplayName; - x.DisplayName = browseDisplayName; - x.InverseName = inverseName; - x.Symmetric = false; - x.IsAbstract = false; - x.SuperTypeId = superTypeId; - if (presetNodeId != null) - x.NodeId = presetNodeId; - return x; - } - - /// - /// Helper to create an Object-Node. Note: __NO__ NodeId is created by the default! Must be done by outer functionality!! - /// - /// Parent node - /// Name displayed in the node tree - /// Type of the Object - /// Modeling Rule, if not None - /// The node - public static BaseObjectState CreateObject( - NodeState parent, - string browseDisplayName, - NodeId typeDefinitionId = null, - AasUaNodeHelper.ModellingRule modellingRule = AasUaNodeHelper.ModellingRule.None, - string extraName = null) - { - var x = new BaseObjectState(parent); - x.BrowseName = "" + browseDisplayName; - x.DisplayName = "" + browseDisplayName; - if (extraName != null) - x.DisplayName = "" + extraName; - x.Description = new LocalizedText("en", browseDisplayName); - if (typeDefinitionId != null) - x.TypeDefinitionId = typeDefinitionId; - CheckSetModellingRule(modellingRule, x); - return x; - } - - } -} diff --git a/src/AasxServerStandardBib/AasUaUtils.cs b/src/AasxServerStandardBib/AasUaUtils.cs deleted file mode 100644 index 972b29782..000000000 --- a/src/AasxServerStandardBib/AasUaUtils.cs +++ /dev/null @@ -1,186 +0,0 @@ -/******************************************************************************** -* Copyright (c) {2019 - 2024} Contributors to the Eclipse Foundation -* -* See the NOTICE file(s) distributed with this work for additional -* information regarding copyright ownership. -* -* This program and the accompanying materials are made available under the -* terms of the Apache License Version 2.0 which is available at -* https://www.apache.org/licenses/LICENSE-2.0 -* -* SPDX-License-Identifier: Apache-2.0 -********************************************************************************/ - -using Opc.Ua; -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; - -namespace AasOpcUaServer -{ - public class AasUaUtils - { - public static string ToOpcUaName(string input) - { - var clean = Regex.Replace(input, @"[^a-zA-Z0-9\-_]", "_"); - while (true) - { - var len0 = clean.Length; - clean = clean.Replace("__", "_"); - if (len0 == clean.Length) - break; - } - return clean; - } - - public static string ToOpcUaReference(Reference refid) - { - if (refid == null || refid.Keys == null || refid.Keys.Count == 0) - return null; - - var semstr = ""; - foreach (var k in refid.Keys) - { - if (semstr != "") - semstr += ","; - semstr += String.Format("({0}){1}", - k.Type, k.Value); - } - - return semstr; - } - - - public static List ToOpcUaReferenceList(Reference refid) - { - if (refid == null || refid.Keys == null || refid.Keys.Count == 0) - return null; - - var res = new List(); - foreach (var k in refid.Keys) - { - res.Add(String.Format("{0}", k.Value)); - } - - return res; - } - - public static LocalizedText[] GetUaLocalizedTexts(List ls) - { - if (ls == null || ls.Count < 1) - return new LocalizedText[] { new LocalizedText("", "") }; - var res = new LocalizedText[ls.Count]; - for (int i = 0; i < ls.Count; i++) - res[i] = new LocalizedText(ls[i].Language, ls[i].Text); - return res; - } - - public static LocalizedText GetBestUaDescriptionFromAasDescription(List desc) - { - var res = new LocalizedText("", ""); - if (desc != null && desc != null) - { - var found = false; - foreach (var ls in desc) - if (!found || ls.Language.Trim().ToLower().StartsWith("en")) - { - found = true; - res = new LocalizedText(ls.Language, ls.Text); - } - } - return res; - } - - public static bool AasValueTypeToUaDataType(string valueType, out Type sharpType, out NodeId dataTypeId) - { - // defaults - sharpType = "".GetType(); - dataTypeId = DataTypeIds.String; - if (valueType == null) - return false; - - // parse - var vt = valueType.ToLower().Trim(); - if (vt == "boolean") - { - sharpType = typeof(bool); - dataTypeId = DataTypeIds.Boolean; - return true; - } - else if (vt == "datetime" || vt == "datetimestamp" || vt == "time") - { - sharpType = typeof(Int64); - dataTypeId = DataTypeIds.DateTime; - return true; - } - else if (vt == "decimal" || vt == "integer" || vt == "long" || vt == "nonpositiveinteger" || vt == "negativeinteger") - { - sharpType = typeof(Int64); - dataTypeId = DataTypeIds.Int64; - return true; - } - else if (vt == "int") - { - sharpType = typeof(Int32); - dataTypeId = DataTypeIds.Int32; - return true; - } - else if (vt == "short") - { - sharpType = typeof(Int16); - dataTypeId = DataTypeIds.Int16; - return true; - } - else if (vt == "byte") - { - sharpType = typeof(SByte); - dataTypeId = DataTypeIds.Byte; - return true; - } - else if (vt == "nonnegativeinteger" || vt == "positiveinteger" || vt == "unsignedlong") - { - sharpType = typeof(UInt64); - dataTypeId = DataTypeIds.UInt64; - return true; - } - else if (vt == "unsignedint") - { - sharpType = typeof(UInt32); - dataTypeId = DataTypeIds.UInt32; - return true; - } - else if (vt == "unsignedshort") - { - sharpType = typeof(UInt16); - dataTypeId = DataTypeIds.UInt16; - return true; - } - else if (vt == "unsignedbyte") - { - sharpType = typeof(Byte); - dataTypeId = DataTypeIds.Byte; - return true; - } - else if (vt == "double") - { - sharpType = typeof(double); - dataTypeId = DataTypeIds.Double; - return true; - } - else if (vt == "float") - { - sharpType = typeof(float); - dataTypeId = DataTypeIds.Float; - return true; - } - else if (vt == "string") - { - sharpType = typeof(string); - dataTypeId = DataTypeIds.String; - return true; - } - - return false; - } - } -} diff --git a/src/AasxServerStandardBib/AasxServerStandardBib.csproj b/src/AasxServerStandardBib/AasxServerStandardBib.csproj index bb0a80d8a..47ef632a6 100644 --- a/src/AasxServerStandardBib/AasxServerStandardBib.csproj +++ b/src/AasxServerStandardBib/AasxServerStandardBib.csproj @@ -19,11 +19,11 @@ true - + - + @@ -34,15 +34,14 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + - - - - + + + + @@ -52,18 +51,15 @@ true Never - + - + PreserveNewest PreserveNewest - - PreserveNewest - diff --git a/src/AasxServerStandardBib/AasxUaServerOptions.cs b/src/AasxServerStandardBib/AasxUaServerOptions.cs deleted file mode 100644 index e3016f0a7..000000000 --- a/src/AasxServerStandardBib/AasxUaServerOptions.cs +++ /dev/null @@ -1,117 +0,0 @@ -/******************************************************************************** -* Copyright (c) {2019 - 2024} Contributors to the Eclipse Foundation -* -* See the NOTICE file(s) distributed with this work for additional -* information regarding copyright ownership. -* -* This program and the accompanying materials are made available under the -* terms of the Apache License Version 2.0 which is available at -* https://www.apache.org/licenses/LICENSE-2.0 -* -* SPDX-License-Identifier: Apache-2.0 -********************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace AasOpcUaServer -{ - public class AasxUaServerOptions - { - public enum JobType { None, ExportNodesetXml } - - /// - /// This file shall be loaded at start of application - /// - public string AasxToLoad = null; - - /// - /// Set special action/ job to be executed by server - /// - public JobType SpecialJob = JobType.None; - - /// - /// File Name for exporting - /// - public string ExportFilename = ""; - - /// - /// If not Null, the Namespace index of exported nodes need to be in the list. - /// - public List ExportFilterNamespaceIndex = null; - - /// - /// Serialize reference as single string object instead of list of strings. - /// Note: set to TRUE for open62541 node-set-compiler - /// - public bool ReferenceKeysAsSingleString = false; - - /// - /// Filter duplicated node-ids in th export. - /// Note: set to TRUE for open62541 node-set-compiler - /// - public bool FilterForSingleNodeIds = false; - - /// - /// If not null, then executed after finalizing special jobs. Will be set-up during initialization of server. - /// - public Action FinalizeAction = null; - - /// - /// Parse args given by command line or plug-in arguments - /// - public void ParseArgs(string[] args) - { - if (args == null) - return; - - for (int index = 0; index < args.Length; index++) - { - var arg = args[index].Trim().ToLower(); - var morearg = (args.Length - 1) - index; - - // flags - if (arg == "-single-keys") - { - ReferenceKeysAsSingleString = true; - continue; - } - - if (arg == "-single-nodeids") - { - FilterForSingleNodeIds = true; - continue; - } - - // options - if (arg == "-ns" && morearg > 0) - { - int i; - if (Int32.TryParse(args[index + 1], out i)) - { - if (this.ExportFilterNamespaceIndex == null) - this.ExportFilterNamespaceIndex = new List(); - this.ExportFilterNamespaceIndex.Add((ushort)i); - } - index++; - continue; - } - if (arg == "-export-nodeset" && morearg > 0) - { - this.SpecialJob = JobType.ExportNodesetXml; - this.ExportFilename = args[index + 1]; - index++; - continue; - } - - // tail. last argument shall be file to load - if (System.IO.File.Exists(args[index])) - this.AasxToLoad = args[index]; - break; - } - } - } -} diff --git a/src/AasxServerStandardBib/DataChangeMonitoredItem.cs b/src/AasxServerStandardBib/DataChangeMonitoredItem.cs deleted file mode 100644 index 8859653f2..000000000 --- a/src/AasxServerStandardBib/DataChangeMonitoredItem.cs +++ /dev/null @@ -1,826 +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.Server; - -namespace Opc.Ua.Sample -{ - /// - /// Provides a basic monitored item implementation which does not support queuing. - /// - public class DataChangeMonitoredItem : IDataChangeMonitoredItem - { - #region Constructors - /// - /// Constructs a new instance. - /// - public DataChangeMonitoredItem( - MonitoredNode source, - uint id, - uint attributeId, - NumericRange indexRange, - QualifiedName dataEncoding, - DiagnosticsMasks diagnosticsMasks, - TimestampsToReturn timestampsToReturn, - MonitoringMode monitoringMode, - uint clientHandle, - double samplingInterval, - bool alwaysReportUpdates) - { - m_source = source; - m_id = id; - m_attributeId = attributeId; - m_indexRange = indexRange; - m_dataEncoding = dataEncoding; - m_timestampsToReturn = timestampsToReturn; - m_diagnosticsMasks = diagnosticsMasks; - m_monitoringMode = monitoringMode; - m_clientHandle = clientHandle; - m_samplingInterval = samplingInterval; - m_nextSampleTime = DateTime.UtcNow.Ticks; - m_readyToPublish = false; - m_readyToTrigger = false; - m_alwaysReportUpdates = alwaysReportUpdates; - } - - /// - /// Constructs a new instance. - /// - public DataChangeMonitoredItem( - MonitoredNode source, - uint id, - uint attributeId, - NumericRange indexRange, - QualifiedName dataEncoding, - DiagnosticsMasks diagnosticsMasks, - TimestampsToReturn timestampsToReturn, - MonitoringMode monitoringMode, - uint clientHandle, - double samplingInterval, - uint queueSize, - bool discardOldest, - DataChangeFilter filter, - Range range, - bool alwaysReportUpdates) - { - m_source = source; - m_id = id; - m_attributeId = attributeId; - m_indexRange = indexRange; - m_dataEncoding = dataEncoding; - m_timestampsToReturn = timestampsToReturn; - m_diagnosticsMasks = diagnosticsMasks; - m_monitoringMode = monitoringMode; - m_clientHandle = clientHandle; - m_samplingInterval = samplingInterval; - m_nextSampleTime = DateTime.UtcNow.Ticks; - m_readyToPublish = false; - m_readyToTrigger = false; - m_queue = null; - m_filter = filter; - m_range = 0; - m_alwaysReportUpdates = alwaysReportUpdates; - - if (range != null) - { - m_range = range.High - range.Low; - } - - if (queueSize > 1) - { - m_queue = new MonitoredItemQueue(); - m_queue.SetQueueSize(queueSize, discardOldest, diagnosticsMasks); - m_queue.SetSamplingInterval(samplingInterval); - } - } - #endregion - - #region Public Members - /// - /// Gets the id for the attribute being monitored. - /// - public uint AttributeId - { - get { return m_attributeId; } - } - - /// - /// Gets the index range used to selected a subset of the value. - /// - public NumericRange IndexRange - { - get { return m_indexRange; } - } - - /// - /// Gets the data encoding to use when returning the value. - /// - public QualifiedName DataEncoding - { - get { return m_dataEncoding; } - } - - /// - /// Whether the monitored item should report a value without checking if it was changed. - /// - public bool AlwaysReportUpdates - { - get { return m_alwaysReportUpdates; } - set { m_alwaysReportUpdates = value; } - } - - /// - /// The number of milliseconds until the next sample. - /// - public int TimeToNextSample - { - get - { - lock (m_lock) - { - if (m_monitoringMode == MonitoringMode.Disabled) - { - return Int32.MaxValue; - } - - DateTime now = DateTime.UtcNow; - - if (m_nextSampleTime <= now.Ticks) - { - return 0; - } - - return (int)((m_nextSampleTime - now.Ticks) / TimeSpan.TicksPerMillisecond); - } - } - } - - /// - /// The monitoring mode. - /// - public MonitoringMode MonitoringMode - { - get - { - return m_monitoringMode; - } - } - - /// - /// The sampling interval. - /// - public double SamplingInterval - { - get - { - lock (m_lock) - { - return m_samplingInterval; - } - } - } - - /// - /// Modifies the monitored item parameters, - /// - public ServiceResult Modify( - DiagnosticsMasks diagnosticsMasks, - TimestampsToReturn timestampsToReturn, - uint clientHandle, - double samplingInterval) - { - return Modify(diagnosticsMasks, timestampsToReturn, clientHandle, samplingInterval, 0, false, null, null); - } - - /// - /// Modifies the monitored item parameters, - /// - public ServiceResult Modify( - DiagnosticsMasks diagnosticsMasks, - TimestampsToReturn timestampsToReturn, - uint clientHandle, - double samplingInterval, - uint queueSize, - bool discardOldest, - DataChangeFilter filter, - Range range) - { - lock (m_lock) - { - m_diagnosticsMasks = diagnosticsMasks; - m_timestampsToReturn = timestampsToReturn; - m_clientHandle = clientHandle; - - // subtract the previous sampling interval. - long oldSamplingInterval = (long)(m_samplingInterval * TimeSpan.TicksPerMillisecond); - - if (oldSamplingInterval < m_nextSampleTime) - { - m_nextSampleTime -= oldSamplingInterval; - } - - m_samplingInterval = samplingInterval; - - // calculate the next sampling interval. - long newSamplingInterval = (long)(m_samplingInterval * TimeSpan.TicksPerMillisecond); - - if (m_samplingInterval > 0) - { - m_nextSampleTime += newSamplingInterval; - } - else - { - m_nextSampleTime = 0; - } - - // update the filter and the range. - m_filter = filter; - m_range = 0; - - if (range != null) - { - m_range = range.High - range.Low; - } - - // update the queue size. - if (queueSize > 1) - { - if (m_queue == null) - { - m_queue = new MonitoredItemQueue(); - } - - m_queue.SetQueueSize(queueSize, discardOldest, diagnosticsMasks); - m_queue.SetSamplingInterval(samplingInterval); - } - else - { - m_queue = null; - } - - return ServiceResult.Good; - } - } - - /// - /// Called when the attribute being monitored changed. Reads and queues the value. - /// - public void ValueChanged(ISystemContext context) - { - DataValue value = new DataValue(); - - ServiceResult error = m_source.Node.ReadAttribute(context, m_attributeId, NumericRange.Empty, null, value); - - if (ServiceResult.IsBad(error)) - { - value = new DataValue(error.StatusCode); - } - - value.ServerTimestamp = DateTime.UtcNow; - - QueueValue(value, error); - } - #endregion - - #region IMonitoredItem Members - /// - /// The node manager for the monitored item. - /// - public INodeManager NodeManager - { - get { return m_source.NodeManager; } - } - - /// - /// The session for the monitored item. - /// - public Session Session - { - get - { - ISubscription subscription = m_subscription; - - if (subscription != null) - { - return subscription.Session; - } - - return null; - } - } - - /// - /// The identifier for the subscription that the monitored item belongs to. - /// - public uint SubscriptionId - { - get - { - ISubscription subscription = m_subscription; - - if (subscription != null) - { - return subscription.Id; - } - - return 0; - } - } - - /// - /// The unique identifier for the monitored item. - /// - public uint Id - { - get { return m_id; } - } - - /// - /// The client handle. - /// - public uint ClientHandle - { - get { return m_clientHandle; } - } - - /// - /// The callback to use to notify the subscription when values are ready to publish. - /// - public ISubscription SubscriptionCallback - { - get - { - return m_subscription; - } - - set - { - m_subscription = value; - } - } - - /// - /// The handle assigned to the monitored item by the node manager. - /// - public object ManagerHandle - { - get { return m_source; } - } - - /// - /// The type of monitor item. - /// - public int MonitoredItemType - { - get { return MonitoredItemTypeMask.DataChange; } - } - - /// - /// Returns true if the item is ready to publish. - /// - public bool IsReadyToPublish - { - get - { - lock (m_lock) - { - // check if not ready to publish. - if (!m_readyToPublish) - { - return false; - } - - // check if monitoring was turned off. - if (m_monitoringMode != MonitoringMode.Reporting) - { - return false; - } - - // re-queue if too little time has passed since the last publish. - long now = DateTime.UtcNow.Ticks; - - if (m_nextSampleTime > now) - { - return false; - } - - return true; - } - } - } - - /// - /// Gets or Sets a value indicating whether the item is ready to trigger in case it has some linked items. - /// - public bool IsReadyToTrigger - { - get - { - lock (m_lock) - { - // only allow to trigger if sampling or reporting. - if (m_monitoringMode == MonitoringMode.Disabled) - { - return false; - } - - return m_readyToTrigger; - } - } - - set - { - lock (m_lock) - { - m_readyToTrigger = value; - } - } - } - - /// - /// Returns the results for the create request. - /// - public ServiceResult GetCreateResult(out MonitoredItemCreateResult result) - { - lock (m_lock) - { - result = new MonitoredItemCreateResult(); - - result.MonitoredItemId = m_id; - result.StatusCode = StatusCodes.Good; - result.RevisedSamplingInterval = m_samplingInterval; - result.RevisedQueueSize = 0; - result.FilterResult = null; - - if (m_queue != null) - { - result.RevisedQueueSize = m_queue.QueueSize; - } - - return ServiceResult.Good; - } - } - - /// - /// Returns the results for the modify request. - /// - public ServiceResult GetModifyResult(out MonitoredItemModifyResult result) - { - lock (m_lock) - { - result = new MonitoredItemModifyResult(); - - result.StatusCode = StatusCodes.Good; - result.RevisedSamplingInterval = m_samplingInterval; - result.RevisedQueueSize = 0; - result.FilterResult = null; - - if (m_queue != null) - { - result.RevisedQueueSize = m_queue.QueueSize; - } - - return ServiceResult.Good; - } - } - #endregion - - #region IDataChangeMonitoredItem Members - /// - /// Queues a new data change. - /// - public void QueueValue(DataValue value, ServiceResult error) - { - lock (m_lock) - { - // check if value has changed. - if (!m_alwaysReportUpdates) - { - if (!Opc.Ua.Server.MonitoredItem.ValueChanged(value, error, m_lastValue, m_lastError, m_filter, m_range)) - { - return; - } - } - - // make a shallow copy of the value. - if (value != null) - { - DataValue copy = new DataValue(); - - copy.WrappedValue = value.WrappedValue; - copy.StatusCode = value.StatusCode; - copy.SourceTimestamp = value.SourceTimestamp; - copy.SourcePicoseconds = value.SourcePicoseconds; - copy.ServerTimestamp = value.ServerTimestamp; - copy.ServerPicoseconds = value.ServerPicoseconds; - - value = copy; - - // ensure the data value matches the error status code. - if (error != null && error.StatusCode.Code != 0) - { - value.StatusCode = error.StatusCode; - } - } - - m_lastValue = value; - m_lastError = error; - - // queue value. - if (m_queue != null) - { - m_queue.QueueValue(value, error); - } - - // flag the item as ready to publish. - m_readyToPublish = true; - m_readyToTrigger = true; - } - } - - /// - /// Sets a flag indicating that the semantics for the monitored node have changed. - /// - /// - /// The StatusCode for next value reported by the monitored item will have the SemanticsChanged bit set. - /// - public void SetSemanticsChanged() - { - lock (m_lock) - { - m_semanticsChanged = true; - } - } - - /// - /// Sets a flag indicating that the structure of the monitored node has changed. - /// - /// - /// The StatusCode for next value reported by the monitored item will have the StructureChanged bit set. - /// - public void SetStructureChanged() - { - lock (m_lock) - { - m_structureChanged = true; - } - } - - /// - /// Changes the monitoring mode. - /// - public MonitoringMode SetMonitoringMode(MonitoringMode monitoringMode) - { - lock (m_lock) - { - MonitoringMode previousMode = m_monitoringMode; - - if (previousMode == monitoringMode) - { - return previousMode; - } - - if (previousMode == MonitoringMode.Disabled) - { - m_nextSampleTime = DateTime.UtcNow.Ticks; - m_lastError = null; - m_lastValue = null; - } - - m_monitoringMode = monitoringMode; - - if (monitoringMode == MonitoringMode.Disabled) - { - m_readyToPublish = false; - m_readyToTrigger = false; - } - - return previousMode; - } - } - - /// - /// No filters supported. - /// - public DataChangeFilter DataChangeFilter - { - get { return m_filter; } - } - - public bool IsResendData => throw new NotImplementedException(); - - /// - /// 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); - - if (m_nextSampleTime > 0) - { - long delta = now - m_nextSampleTime; - - if (samplingInterval > 0 && delta >= 0) - { - m_nextSampleTime += ((delta / samplingInterval) + 1) * samplingInterval; - } - } - - // set sampling time based on current time. - else - { - m_nextSampleTime = now + samplingInterval; - } - } - - /// - /// Called by the subscription to publish any notification. - /// - public bool Publish(OperationContext context, Queue notifications, Queue diagnostics) - { - lock (m_lock) - { - // check if not ready to publish. - if (!IsReadyToPublish) - { - return false; - } - - // update sample time. - IncrementSampleTime(); - - // update publish flag. - m_readyToPublish = false; - m_readyToTrigger = false; - - // check if queuing is enabled. - if (m_queue == null) - { - Publish(context, m_lastValue, m_lastError, notifications, diagnostics); - } - else - { - DataValue value = null; - ServiceResult error = null; - - while (m_queue.Publish(out value, out error)) - { - Publish(context, value, error, notifications, diagnostics); - } - } - - return true; - } - } - - /// - /// Publishes a value. - /// - private void Publish( - OperationContext context, - DataValue value, - ServiceResult error, - Queue notifications, - Queue diagnostics) - { - // set semantics changed bit. - if (m_semanticsChanged) - { - if (value != null) - { - value.StatusCode = value.StatusCode.SetSemanticsChanged(true); - } - - if (error != null) - { - error = new ServiceResult( - error.StatusCode.SetSemanticsChanged(true), - error.SymbolicId, - error.NamespaceUri, - error.LocalizedText, - error.AdditionalInfo, - error.InnerResult); - } - - m_semanticsChanged = false; - } - - // set structure changed bit. - if (m_structureChanged) - { - if (value != null) - { - value.StatusCode = value.StatusCode.SetStructureChanged(true); - } - - if (error != null) - { - error = new ServiceResult( - error.StatusCode.SetStructureChanged(true), - error.SymbolicId, - error.NamespaceUri, - error.LocalizedText, - error.AdditionalInfo, - error.InnerResult); - } - - m_structureChanged = false; - } - - // copy data value. - MonitoredItemNotification item = new MonitoredItemNotification(); - - item.ClientHandle = m_clientHandle; - item.Value = value; - - // apply timestamp filter. - if (m_timestampsToReturn != TimestampsToReturn.Server && m_timestampsToReturn != TimestampsToReturn.Both) - { - item.Value.ServerTimestamp = DateTime.MinValue; - } - - if (m_timestampsToReturn != TimestampsToReturn.Source && m_timestampsToReturn != TimestampsToReturn.Both) - { - item.Value.SourceTimestamp = DateTime.MinValue; - } - - notifications.Enqueue(item); - - // update diagnostic info. - DiagnosticInfo diagnosticInfo = null; - - if (m_lastError != null) - { - if ((m_diagnosticsMasks & DiagnosticsMasks.OperationAll) != 0) - { - diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_source.Server, context, m_lastError); - } - } - - diagnostics.Enqueue(diagnosticInfo); - } - - public void SetupResendDataTrigger() - { - throw new NotImplementedException(); - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private MonitoredNode m_source; - private ISubscription m_subscription; - private uint m_id; - private DataValue m_lastValue; - private ServiceResult m_lastError; - private uint m_attributeId; - private NumericRange m_indexRange; - private QualifiedName m_dataEncoding; - private TimestampsToReturn m_timestampsToReturn; - private DiagnosticsMasks m_diagnosticsMasks; - private uint m_clientHandle; - private double m_samplingInterval; - private MonitoredItemQueue m_queue; - private DataChangeFilter m_filter; - private double m_range; - private MonitoringMode m_monitoringMode; - private long m_nextSampleTime; - private bool m_readyToPublish; - private bool m_readyToTrigger; - private bool m_alwaysReportUpdates; - private bool m_semanticsChanged; - private bool m_structureChanged; - #endregion - } -} diff --git a/src/AasxServerStandardBib/MonitoredItemQueue.cs b/src/AasxServerStandardBib/MonitoredItemQueue.cs deleted file mode 100644 index 57ac1194f..000000000 --- a/src/AasxServerStandardBib/MonitoredItemQueue.cs +++ /dev/null @@ -1,386 +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.Sample -{ - /// - /// Provides a queue for data changes. - /// - public class MonitoredItemQueue - { - /// - /// Creates an empty queue. - /// - public MonitoredItemQueue() - { - m_values = null; - m_errors = null; - m_start = -1; - m_end = -1; - m_overflow = -1; - m_discardOldest = false; - m_nextSampleTime = 0; - m_samplingInterval = 0; - } - - #region Public Methods - /// - /// Gets the current queue size. - /// - public uint QueueSize - { - get - { - if (m_values == null) - { - return 0; - } - - return (uint)m_values.Length; - } - } - - /// - /// Sets the sampling interval used when queuing values. - /// - /// The new sampling interval. - public void SetSamplingInterval(double samplingInterval) - { - // substract the previous sampling interval. - if (m_samplingInterval < m_nextSampleTime) - { - m_nextSampleTime -= m_samplingInterval; - } - - // calculate the next sampling interval. - m_samplingInterval = (long)(samplingInterval * TimeSpan.TicksPerMillisecond); - - if (m_samplingInterval > 0) - { - m_nextSampleTime += m_samplingInterval; - } - else - { - m_nextSampleTime = 0; - } - } - - /// - /// Sets the queue size. - /// - /// The new queue size. - /// Whether to discard the oldest values if the queue overflows. - /// Specifies which diagnostics which should be kept in the queue. - public void SetQueueSize(uint queueSize, bool discardOldest, DiagnosticsMasks diagnosticsMasks) - { - int length = (int)queueSize; - - if (length < 1) - { - length = 1; - } - - int start = m_start; - int end = m_end; - - // create new queue. - DataValue[] values = new DataValue[length]; - ServiceResult[] errors = null; - - if ((diagnosticsMasks & DiagnosticsMasks.OperationAll) != 0) - { - errors = new ServiceResult[length]; - } - - // copy existing values. - List existingValues = null; - List existingErrors = null; - - if (m_start >= 0) - { - existingValues = new List(); - existingErrors = new List(); - - DataValue value = null; - ServiceResult error = null; - - while (Dequeue(out value, out error)) - { - existingValues.Add(value); - existingErrors.Add(error); - } - } - - // update internals. - m_values = values; - m_errors = errors; - m_start = -1; - m_end = 0; - m_overflow = -1; - m_discardOldest = discardOldest; - - // requeue the data. - if (existingValues != null) - { - for (int ii = 0; ii < existingValues.Count; ii++) - { - Enqueue(existingValues[ii], existingErrors[ii]); - } - } - } - - /// - /// Adds the value to the queue. - /// - /// The value to queue. - /// The error to queue. - public void QueueValue(DataValue value, ServiceResult error) - { - long now = DateTime.UtcNow.Ticks; - - if (m_start >= 0) - { - // check if too soon for another sample. - if (now < m_nextSampleTime) - { - int last = m_end - 1; - - if (last < 0) - { - last = m_values.Length - 1; - } - - // replace last value and error. - m_values[last] = value; - - if (m_errors != null) - { - m_errors[last] = error; - } - - return; - } - } - - // update next sample time. - if (m_nextSampleTime > 0) - { - long delta = now - m_nextSampleTime; - - if (m_samplingInterval > 0 && delta >= 0) - { - m_nextSampleTime += ((delta / m_samplingInterval) + 1) * m_samplingInterval; - } - } - else - { - m_nextSampleTime = now + m_samplingInterval; - } - - // queue next value. - Enqueue(value, error); - } - - /// - /// Publishes the oldest value in the queue. - /// - /// The value. - /// The error associated with the value. - /// True if a value was found. False if the queue is empty. - public bool Publish(out DataValue value, out ServiceResult error) - { - return Dequeue(out value, out error); - } - #endregion - - #region Private Methods - /// - /// Adds the value to the queue. Discards values if the queue is full. - /// - /// The value to add. - /// The error to add. - private void Enqueue(DataValue value, ServiceResult error) - { - // check for empty queue. - if (m_start < 0) - { - m_start = 0; - m_end = 1; - m_overflow = -1; - - m_values[m_start] = value; - - if (m_errors != null) - { - m_errors[m_start] = error; - } - - return; - } - - int next = m_end; - - // check for wrap around. - if (next >= m_values.Length) - { - next = 0; - } - - // check if queue is full. - if (m_start == next) - { - if (!m_discardOldest) - { - m_overflow = m_end - 1; - return; - } - - // remove oldest value. - m_start++; - - if (m_start >= m_values.Length) - { - m_start = 0; - } - - // set overflow bit. - m_overflow = m_start; - } - - // add value. - m_values[next] = value; - - if (m_errors != null) - { - m_errors[next] = error; - } - - m_end = next + 1; - } - - /// - /// Removes a value and an error from the queue. - /// - /// The value removed from the queue. - /// The error removed from the queue. - /// True if a value was found. False if the queue is empty. - private bool Dequeue(out DataValue value, out ServiceResult error) - { - value = null; - error = null; - - // check for empty queue. - if (m_start < 0) - { - return false; - } - - value = m_values[m_start]; - m_values[m_start] = null; - - if (m_errors != null) - { - error = m_errors[m_start]; - m_errors[m_start] = null; - } - - // set the overflow bit. - if (m_overflow == m_start) - { - SetOverflowBit(ref value, ref error); - m_overflow = -1; - } - - m_start++; - - // check if queue has been emptied. - if (m_start == m_end) - { - m_start = -1; - m_end = 0; - } - - // check for wrap around. - else if (m_start >= m_values.Length) - { - m_start = 0; - } - - return true; - } - - /// - /// Sets the overflow bit in the value and error. - /// - /// The value to update. - /// The error to update. - private void SetOverflowBit(ref DataValue value, ref ServiceResult error) - { - if (value != null) - { - StatusCode status = value.StatusCode; - status.Overflow = true; - value.StatusCode = status; - } - - if (error != null) - { - StatusCode status = error.StatusCode; - status.Overflow = true; - - // have to copy before updating because the ServiceResult is invariant. - ServiceResult copy = new ServiceResult( - status, - error.SymbolicId, - error.NamespaceUri, - error.LocalizedText, - error.AdditionalInfo, - error.InnerResult); - - error = copy; - } - } - #endregion - - #region Private Fields - private DataValue[] m_values; - private ServiceResult[] m_errors; - private int m_start; - private int m_end; - private int m_overflow; - private bool m_discardOldest; - private long m_nextSampleTime; - private long m_samplingInterval; - #endregion - } -} diff --git a/src/AasxServerStandardBib/MonitoredNode.cs b/src/AasxServerStandardBib/MonitoredNode.cs deleted file mode 100644 index b7ae90e80..000000000 --- a/src/AasxServerStandardBib/MonitoredNode.cs +++ /dev/null @@ -1,382 +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.Server; - -namespace Opc.Ua.Sample -{ - /// - /// Keeps track of the monitored items for a single node. - /// - public class MonitoredNode - { - #region Constructors - /// - /// Initializes the instance with the context for the node being monitored. - /// - public MonitoredNode( - IServerInternal server, - INodeManager nodeManager, - NodeState node) - { - m_server = server; - m_nodeManager = nodeManager; - m_node = node; - } - #endregion - - #region Public Properties - /// - /// The server that the node belongs to. - /// - public IServerInternal Server - { - get { return m_server; } - } - - /// - /// The node manager that the node belongs to. - /// - public INodeManager NodeManager - { - get { return m_nodeManager; } - } - - /// - /// The node being monitored. - /// - public NodeState Node - { - get { return m_node; } - } - - /// - /// Whether the node has any active monitored items for the specified attribute. - /// - public bool IsMonitoringRequired(uint attributeId) - { - if (m_monitoredItems != null) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - DataChangeMonitoredItem monitoredItem = m_monitoredItems[ii]; - - if (monitoredItem.AttributeId == attributeId && monitoredItem.MonitoringMode != MonitoringMode.Disabled) - { - return true; - } - } - } - - return false; - } - #endregion - - #region Public Methods - /// - /// Creates a new data change monitored item. - /// - /// The system context. - /// The unique identifier for the monitiored item. - /// The attribute to monitor. - /// The index range to use for array values. - /// The data encoding to return for structured values. - /// The diagnostics masks to use. - /// The timestamps to return. - /// The initial monitoring mode. - /// The handle assigned by the client. - /// The sampling interval. - /// The queue size. - /// Whether to discard the oldest values when the queue overflows. - /// The data change filter to use. - /// The range to use when evaluating a percentage deadband filter. - /// Whether the monitored item should skip the check for a change in value. - /// The new monitored item. - public DataChangeMonitoredItem CreateDataChangeItem( - ISystemContext context, - uint monitoredItemId, - uint attributeId, - NumericRange indexRange, - QualifiedName dataEncoding, - DiagnosticsMasks diagnosticsMasks, - TimestampsToReturn timestampsToReturn, - MonitoringMode monitoringMode, - uint clientHandle, - double samplingInterval, - uint queueSize, - bool discardOldest, - DataChangeFilter filter, - Range range, - bool alwaysReportUpdates) - { - DataChangeMonitoredItem monitoredItem = new DataChangeMonitoredItem( - this, - monitoredItemId, - attributeId, - indexRange, - dataEncoding, - diagnosticsMasks, - timestampsToReturn, - monitoringMode, - clientHandle, - samplingInterval, - queueSize, - discardOldest, - filter, - range, - alwaysReportUpdates); - - if (m_monitoredItems == null) - { - m_monitoredItems = new List(); - m_node.OnStateChanged = OnNodeChange; - } - - m_monitoredItems.Add(monitoredItem); - - return monitoredItem; - } - - /// - /// Creates a new data change monitored item. - /// - /// The system context. - /// The unique identifier for the monitiored item. - /// The attribute to monitor. - /// The index range to use for array values. - /// The data encoding to return for structured values. - /// The diagnostics masks to use. - /// The timestamps to return. - /// The initial monitoring mode. - /// The handle assigned by the client. - /// The sampling interval. - /// Whether the monitored item should skip the check for a change in value. - /// The new monitored item. - public DataChangeMonitoredItem CreateDataChangeItem( - ISystemContext context, - uint monitoredItemId, - uint attributeId, - NumericRange indexRange, - QualifiedName dataEncoding, - DiagnosticsMasks diagnosticsMasks, - TimestampsToReturn timestampsToReturn, - MonitoringMode monitoringMode, - uint clientHandle, - double samplingInterval, - bool alwaysReportUpdates) - { - return CreateDataChangeItem( - context, - monitoredItemId, - attributeId, - indexRange, - dataEncoding, - diagnosticsMasks, - timestampsToReturn, - monitoringMode, - clientHandle, - samplingInterval, - 0, - false, - null, - null, - alwaysReportUpdates); - } - - /// - /// Deletes the monitored item. - /// - public void DeleteItem(IMonitoredItem monitoredItem) - { - if (m_monitoredItems != null) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - if (Object.ReferenceEquals(monitoredItem, m_monitoredItems[ii])) - { - m_monitoredItems.RemoveAt(ii); - break; - } - } - } - } - - /// - /// Handles change events raised by the node. - /// - /// The system context. - /// The node that raised the event. - /// What caused the event to be raised - public void OnNodeChange(ISystemContext context, NodeState state, NodeStateChangeMasks masks) - { - if (m_monitoredItems != null) - { - for (int ii = 0; ii < m_monitoredItems.Count; ii++) - { - DataChangeMonitoredItem monitoredItem = m_monitoredItems[ii]; - - // check if the node has been deleted. - if ((masks & NodeStateChangeMasks.Deleted) != 0) - { - monitoredItem.QueueValue(null, StatusCodes.BadNodeIdUnknown); - continue; - } - - if (monitoredItem.AttributeId == Attributes.Value) - { - if ((masks & NodeStateChangeMasks.Value) != 0) - { - monitoredItem.ValueChanged(context); - } - } - else - { - if ((masks & NodeStateChangeMasks.NonValue) != 0) - { - monitoredItem.ValueChanged(context); - } - } - } - } - } - - /// - /// Subscribes to events produced by the node. - /// - public void SubscribeToEvents(ISystemContext context, IEventMonitoredItem eventSubscription) - { - if (m_eventSubscriptions == null) - { - m_eventSubscriptions = new List(); - } - - if (m_eventSubscriptions.Count == 0) - { - m_node.OnReportEvent = OnReportEvent; - m_node.SetAreEventsMonitored(context, true, true); - } - - for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) - { - if (Object.ReferenceEquals(eventSubscription, m_eventSubscriptions[ii])) - { - return; - } - } - - m_eventSubscriptions.Add(eventSubscription); - } - - /// - /// Unsubscribes to events produced by the node. - /// - public void UnsubscribeToEvents(ISystemContext context, IEventMonitoredItem eventSubscription) - { - if (m_eventSubscriptions != null) - { - for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) - { - if (Object.ReferenceEquals(eventSubscription, m_eventSubscriptions[ii])) - { - m_eventSubscriptions.RemoveAt(ii); - - if (m_eventSubscriptions.Count == 0) - { - m_node.SetAreEventsMonitored(context, false, true); - m_node.OnReportEvent = null; - } - - break; - } - } - } - } - - /// - /// Handles events reported by the node. - /// - /// The system context. - /// The node that raised the event. - /// The event to report. - public void OnReportEvent(ISystemContext context, NodeState state, IFilterTarget e) - { - if (m_eventSubscriptions != null) - { - for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) - { - m_eventSubscriptions[ii].QueueEvent(e); - } - } - } - - /// - /// Resends the events for any conditions belonging to the node or its children. - /// - /// The system context. - /// The item to refresh. - public void ConditionRefresh( - ISystemContext context, - IEventMonitoredItem monitoredItem) - { - if (m_eventSubscriptions != null) - { - for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) - { - // only process items monitoring this node. - if (!Object.ReferenceEquals(monitoredItem, m_eventSubscriptions[ii])) - { - continue; - } - - // get the set of condition events for the node and its children. - List events = new List(); - m_node.ConditionRefresh(context, events, true); - - // report the events to the monitored item. - for (int jj = 0; jj < events.Count; jj++) - { - monitoredItem.QueueEvent(events[jj]); - } - } - } - } - #endregion - - #region Private Fields - private IServerInternal m_server; - private INodeManager m_nodeManager; - private NodeState m_node; - private List m_eventSubscriptions; - private List m_monitoredItems; - #endregion - } -} diff --git a/src/AasxServerStandardBib/NodeStateCollection.cs b/src/AasxServerStandardBib/NodeStateCollection.cs deleted file mode 100644 index c909aedd4..000000000 --- a/src/AasxServerStandardBib/NodeStateCollection.cs +++ /dev/null @@ -1,627 +0,0 @@ -/* Copyright (c) 1996-2019 The OPC Foundation. All rights reserved. - The source code in this file is covered under a dual-license scenario: - - RCL: for OPC Foundation members in good-standing - - GPL V2: everybody else - RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/ - GNU General Public License as published by the Free Software Foundation; - version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2 - This source code is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -*/ -#if _hidden_ - -using System; -using System.Collections.Generic; -using System.Xml; -using System.Text; -using System.IO; -using System.Reflection; -using System.Runtime.Serialization; - -namespace Opc.Ua -{ - /// - /// Stores a collection of nodes. - /// - public class NodeStateCollection : List - { -#region Constructors - /// - /// Initializes a new instance of the class. - /// - public NodeStateCollection() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The initial capacity. - public NodeStateCollection(int capacity) : base(capacity) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The collection whose elements are copied to the new list. - /// - /// is null. - /// - public NodeStateCollection(IEnumerable collection) : base(collection) - { - } -#endregion - -#region Public Methods - /// - /// Writes the collection to a stream using the NodeSet schema. - /// - public void SaveAsNodeSet(ISystemContext context, Stream ostrm) - { - NodeTable nodeTable = new NodeTable(context.NamespaceUris, context.ServerUris, null); - - for (int ii = 0; ii < this.Count; ii++) - { - try - { - this[ii].Export(context, nodeTable); - } catch (Exception ex) - { - ; - } - } - - NodeSet nodeSet = new NodeSet(); - - foreach (ILocalNode node in nodeTable) - { - nodeSet.Add(node, nodeTable.NamespaceUris, nodeTable.ServerUris); - } - - XmlWriterSettings settings = new XmlWriterSettings(); - - settings.Encoding = Encoding.UTF8; - settings.CloseOutput = true; - settings.ConformanceLevel = ConformanceLevel.Document; - settings.Indent = true; - - using (XmlWriter writer = XmlWriter.Create(ostrm, settings)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(NodeSet)); - serializer.WriteObject(writer, nodeSet); - } - } - -#region Well-Known Aliases - /// - /// Stores a well known alias. - /// - private struct AliasToUse - { - public AliasToUse(string alias, NodeId nodeId) - { - Alias = alias; - NodeId = nodeId; - } - - public string Alias; - public NodeId NodeId; - } - - /// - /// The list of aliases to use. - /// - private AliasToUse[] s_AliasesToUse = new AliasToUse[] - { - new AliasToUse(BrowseNames.Boolean, DataTypeIds.Boolean), - new AliasToUse(BrowseNames.SByte, DataTypeIds.SByte), - new AliasToUse(BrowseNames.Byte, DataTypeIds.Byte), - new AliasToUse(BrowseNames.Int16, DataTypeIds.Int16), - new AliasToUse(BrowseNames.UInt16, DataTypeIds.UInt16), - new AliasToUse(BrowseNames.Int32, DataTypeIds.Int32), - new AliasToUse(BrowseNames.UInt32, DataTypeIds.UInt32), - new AliasToUse(BrowseNames.Int64, DataTypeIds.Int64), - new AliasToUse(BrowseNames.UInt64, DataTypeIds.UInt64), - new AliasToUse(BrowseNames.Float, DataTypeIds.Float), - new AliasToUse(BrowseNames.Double, DataTypeIds.Double), - new AliasToUse(BrowseNames.DateTime, DataTypeIds.DateTime), - new AliasToUse(BrowseNames.String, DataTypeIds.String), - new AliasToUse(BrowseNames.ByteString, DataTypeIds.ByteString), - new AliasToUse(BrowseNames.Guid, DataTypeIds.Guid), - new AliasToUse(BrowseNames.XmlElement, DataTypeIds.XmlElement), - new AliasToUse(BrowseNames.NodeId, DataTypeIds.NodeId), - new AliasToUse(BrowseNames.ExpandedNodeId, DataTypeIds.ExpandedNodeId), - new AliasToUse(BrowseNames.QualifiedName, DataTypeIds.QualifiedName), - new AliasToUse(BrowseNames.LocalizedText, DataTypeIds.LocalizedText), - new AliasToUse(BrowseNames.StatusCode, DataTypeIds.StatusCode), - new AliasToUse(BrowseNames.Structure, DataTypeIds.Structure), - new AliasToUse(BrowseNames.Number, DataTypeIds.Number), - new AliasToUse(BrowseNames.Integer, DataTypeIds.Integer), - new AliasToUse(BrowseNames.UInteger, DataTypeIds.UInteger), - new AliasToUse(BrowseNames.HasComponent, ReferenceTypeIds.HasComponent), - new AliasToUse(BrowseNames.HasProperty, ReferenceTypeIds.HasProperty), - new AliasToUse(BrowseNames.Organizes, ReferenceTypeIds.Organizes), - new AliasToUse(BrowseNames.HasEventSource, ReferenceTypeIds.HasEventSource), - new AliasToUse(BrowseNames.HasNotifier, ReferenceTypeIds.HasNotifier), - new AliasToUse(BrowseNames.HasSubtype, ReferenceTypeIds.HasSubtype), - new AliasToUse(BrowseNames.HasTypeDefinition, ReferenceTypeIds.HasTypeDefinition), - new AliasToUse(BrowseNames.HasModellingRule, ReferenceTypeIds.HasModellingRule), - new AliasToUse(BrowseNames.HasEncoding, ReferenceTypeIds.HasEncoding), - new AliasToUse(BrowseNames.HasDescription, ReferenceTypeIds.HasDescription) - }; -#endregion - - /// - /// Writes the collection to a stream using the Opc.Ua.Schema.UANodeSet schema. - /// - public void SaveAsNodeSet2(ISystemContext context, Stream ostrm) - { - SaveAsNodeSet2(context, ostrm, null, false); - } - - /// - /// Writes the collection to a stream using the Opc.Ua.Schema.UANodeSet schema. - /// - public void SaveAsNodeSet2(ISystemContext context, Stream ostrm, string version, bool filterSingleNodeIds) - { - Opc.Ua.Export.UANodeSet nodeSet = new Opc.Ua.Export.UANodeSet(); - nodeSet.LastModified = DateTime.UtcNow; - nodeSet.LastModifiedSpecified = true; - - for (int ii = 0; ii < s_AliasesToUse.Length; ii++) - { - nodeSet.AddAlias(context, s_AliasesToUse[ii].Alias, s_AliasesToUse[ii].NodeId); - } - - for (int ii = 0; ii < this.Count; ii++) - { - nodeSet.Export(context, this[ii]); - } - - /* - if (true) - { - var txt = new System.IO.StreamWriter("nodes.txt"); - foreach (var x in nodeSet.Items) - txt.WriteLine(x.NodeId); - txt.Close(); - } - */ - - if (filterSingleNodeIds) - { - // MIHO: There might be DOUBLE nodeIds in the the set!!!!!!!!!! WTF!!!!!!!!!!!!! - // Brutally eliminate them - var nodup = new List(); - foreach (var it in nodeSet.Items) - { - var found = false; - foreach (var it2 in nodup) - if (it.NodeId == it2.NodeId) - found = true; - if (found) - continue; - nodup.Add(it); - } - nodeSet.Items = nodup.ToArray(); - } - - nodeSet.Write(ostrm); - } - - /// - /// Writes the schema information to a static XML export file. - /// - public void SaveAsXml(ISystemContext context, Stream ostrm) - { - SaveAsXml(context, ostrm, false); - } - - /// - /// Writes the schema information to a static XML export file. - /// - public void SaveAsXml(ISystemContext context, Stream ostrm, bool keepStreamOpen) - { - XmlWriterSettings settings = new XmlWriterSettings(); - - settings.Encoding = Encoding.UTF8; - settings.CloseOutput = !keepStreamOpen; - settings.ConformanceLevel = ConformanceLevel.Document; - settings.Indent = true; - - ServiceMessageContext messageContext = new ServiceMessageContext(); - - messageContext.NamespaceUris = context.NamespaceUris; - messageContext.ServerUris = context.ServerUris; - messageContext.Factory = context.EncodeableFactory; - - using (XmlWriter writer = XmlWriter.Create(ostrm, settings)) - { - XmlQualifiedName root = new XmlQualifiedName("ListOfNodeState", Namespaces.OpcUaXsd); - XmlEncoder encoder = new XmlEncoder(root, writer, messageContext); - - encoder.SaveStringTable("NamespaceUris", "NamespaceUri", context.NamespaceUris); - encoder.SaveStringTable("ServerUris", "ServerUri", context.ServerUris); - - for (int ii = 0; ii < this.Count; ii++) - { - NodeState state = this[ii]; - - if (state != null) - { - state.SaveAsXml(context, encoder); - } - } - - encoder.Close(); - } - } - - /// - /// Writes the collection to a binary stream. The stream is closed by this method. - /// - public void SaveAsBinary(ISystemContext context, Stream ostrm) - { - ServiceMessageContext messageContext = new ServiceMessageContext(); - - messageContext.NamespaceUris = context.NamespaceUris; - messageContext.ServerUris = context.ServerUris; - messageContext.Factory = context.EncodeableFactory; - - BinaryEncoder encoder = new BinaryEncoder(ostrm, messageContext); - - encoder.SaveStringTable(context.NamespaceUris); - encoder.SaveStringTable(context.ServerUris); - - encoder.WriteInt32(null, this.Count); - - for (int ii = 0; ii < this.Count; ii++) - { - NodeState state = this[ii]; - state.SaveAsBinary(context, encoder); - } - - encoder.Close(); - } - - /// - /// Reads the schema information from a XML document. - /// - public void LoadFromBinary(ISystemContext context, Stream istrm, bool updateTables) - { - ServiceMessageContext messageContext = new ServiceMessageContext(); - - messageContext.NamespaceUris = context.NamespaceUris; - messageContext.ServerUris = context.ServerUris; - messageContext.Factory = context.EncodeableFactory; - - using (BinaryDecoder decoder = new BinaryDecoder(istrm, messageContext)) - { - // check if a namespace table was provided. - NamespaceTable namespaceUris = new NamespaceTable(); - - if (!decoder.LoadStringTable(namespaceUris)) - { - namespaceUris = null; - } - - // update namespace table. - if (updateTables) - { - if (namespaceUris != null && context.NamespaceUris != null) - { - for (int ii = 0; ii < namespaceUris.Count; ii++) - { - context.NamespaceUris.GetIndexOrAppend(namespaceUris.GetString((uint)ii)); - } - } - } - - // check if a server uri table was provided. - StringTable serverUris = new StringTable(); - - if (namespaceUris != null && namespaceUris.Count > 1) - { - serverUris.Append(namespaceUris.GetString(1)); - } - - if (!decoder.LoadStringTable(serverUris)) - { - serverUris = null; - } - - // update server table. - if (updateTables) - { - if (serverUris != null && context.ServerUris != null) - { - for (int ii = 0; ii < serverUris.Count; ii++) - { - context.ServerUris.GetIndexOrAppend(serverUris.GetString((uint)ii)); - } - } - } - - // setup the mappings to use during decoding. - decoder.SetMappingTables(namespaceUris, serverUris); - - int count = decoder.ReadInt32(null); - - for (int ii = 0; ii < count; ii++) - { - NodeState state = NodeState.LoadNode(context, decoder); - this.Add(state); - } - } - } - - /// - /// Reads the schema information from a XML document. - /// - public void LoadFromXml(ISystemContext context, Stream istrm, bool updateTables) - { - ServiceMessageContext messageContext = new ServiceMessageContext(); - - messageContext.NamespaceUris = context.NamespaceUris; - messageContext.ServerUris = context.ServerUris; - messageContext.Factory = context.EncodeableFactory; - - using (XmlReader reader = XmlReader.Create(istrm)) - { - XmlQualifiedName root = new XmlQualifiedName("ListOfNodeState", Namespaces.OpcUaXsd); - XmlDecoder decoder = new XmlDecoder(null, reader, messageContext); - - NamespaceTable namespaceUris = new NamespaceTable(); - - if (!decoder.LoadStringTable("NamespaceUris", "NamespaceUri", namespaceUris)) - { - namespaceUris = null; - } - - // update namespace table. - if (updateTables) - { - if (namespaceUris != null && context.NamespaceUris != null) - { - for (int ii = 0; ii < namespaceUris.Count; ii++) - { - context.NamespaceUris.GetIndexOrAppend(namespaceUris.GetString((uint)ii)); - } - } - } - - StringTable serverUris = new StringTable(); - - if (!decoder.LoadStringTable("ServerUris", "ServerUri", context.ServerUris)) - { - serverUris = null; - } - - // update server table. - if (updateTables) - { - if (serverUris != null && context.ServerUris != null) - { - for (int ii = 0; ii < serverUris.Count; ii++) - { - context.ServerUris.GetIndexOrAppend(serverUris.GetString((uint)ii)); - } - } - } - - // set mapping. - decoder.SetMappingTables(namespaceUris, serverUris); - - decoder.PushNamespace(Namespaces.OpcUaXsd); - - NodeState state = NodeState.LoadNode(context, decoder); - - while (state != null) - { - this.Add(state); - - state = NodeState.LoadNode(context, decoder); - } - - decoder.Close(); - } - } - - /// - /// Loads the nodes from an embedded resource. - /// - /// The context. - /// The resource path. - /// The assembly containing the resource. - /// if set to true the namespace and server tables are updated with any new URIs. - public void LoadFromResource(ISystemContext context, string resourcePath, Assembly assembly, bool updateTables) - { - if (resourcePath == null) throw new ArgumentNullException("resourcePath"); - - if (assembly == null) throw new ArgumentNullException("assembly"); - - Stream istrm = assembly.GetManifestResourceStream(resourcePath); - if (istrm == null) - { - // try to load from app directory - FileInfo file = new FileInfo(resourcePath); - istrm = file.OpenRead(); - if (istrm == null) - { - throw ServiceResultException.Create(StatusCodes.BadDecodingError, "Could not load nodes from resource: {0}", resourcePath); - } - } - - LoadFromXml(context, istrm, updateTables); - } - - /// - /// Loads the nodes from an embedded resource. - /// - /// The context. - /// The resource path. - /// The assembly containing the resource. - /// if set to true the namespace and server tables are updated with any new URIs. - public void LoadFromBinaryResource(ISystemContext context, string resourcePath, Assembly assembly, bool updateTables) - { - if (resourcePath == null) throw new ArgumentNullException("resourcePath"); - - if (assembly == null) throw new ArgumentNullException("assembly"); - - Stream istrm = assembly.GetManifestResourceStream(resourcePath); - if (istrm == null) - { - // try to load from app directory - FileInfo file = new FileInfo(resourcePath); - istrm = file.OpenRead(); - if (istrm == null) - { - throw ServiceResultException.Create(StatusCodes.BadDecodingError, "Could not load nodes from resource: {0}", resourcePath); - } - } - - LoadFromBinary(context, istrm, updateTables); - } -#endregion - } - - /// - /// A class that creates instances of nodes based on the paramters provided. - /// - public class NodeStateFactory - { - /// - /// Creates a new instance. - /// - /// The current context. - /// The parent. - /// The node class. - /// The browse name. - /// The reference type between the parent and the node. - /// The type definition. - /// Returns null if the type is not known. - public virtual NodeState CreateInstance( - ISystemContext context, - NodeState parent, - NodeClass nodeClass, - QualifiedName browseName, - NodeId referenceTypeId, - NodeId typeDefinitionId) - { - NodeState child = null; - - if (m_types != null && !NodeId.IsNull(typeDefinitionId)) - { - Type type = null; - - if (m_types.TryGetValue(typeDefinitionId, out type)) - { - return Activator.CreateInstance(type, parent) as NodeState; - } - } - - switch (nodeClass) - { - case NodeClass.Variable: - { - if (context.TypeTable != null && context.TypeTable.IsTypeOf(referenceTypeId, ReferenceTypeIds.HasProperty)) - { - child = new PropertyState(parent); - break; - } - - child = new BaseDataVariableState(parent); - break; - } - - case NodeClass.Object: - { - child = new BaseObjectState(parent); - break; - } - - case NodeClass.Method: - { - child = new MethodState(parent); - break; - } - - case NodeClass.ReferenceType: - { - child = new ReferenceTypeState(); - break; - } - - case NodeClass.ObjectType: - { - child = new BaseObjectTypeState(); - break; - } - - case NodeClass.VariableType: - { - child = new BaseDataVariableTypeState(); - break; - } - - case NodeClass.DataType: - { - child = new DataTypeState(); - break; - } - - case NodeClass.View: - { - child = new ViewState(); - break; - } - - default: - { - child = null; - break; - } - } - - return child; - } - - /// - /// Registers a type with the factory. - /// - /// The type definition. - /// The system type. - public void RegisterType(NodeId typeDefinitionId, Type type) - { - if (NodeId.IsNull(typeDefinitionId)) throw new ArgumentNullException("typeDefinitionId"); - if (type == null) throw new ArgumentNullException("type"); - - if (m_types == null) - { - m_types = new NodeIdDictionary(); - } - - m_types[typeDefinitionId] = type; - } - - /// - /// Unregisters a type with the factory. - /// - /// The type definition. - public void UnRegisterType(NodeId typeDefinitionId) - { - if (NodeId.IsNull(typeDefinitionId)) throw new ArgumentNullException("typeDefinitionId"); - - if (m_types != null) - { - m_types.Remove(typeDefinitionId); - } - } - - private NodeIdDictionary m_types; - } -} - -#endif diff --git a/src/AasxServerStandardBib/Opc.Ua.SampleClient.Config.xml b/src/AasxServerStandardBib/Opc.Ua.SampleClient.Config.xml deleted file mode 100644 index f0c060ec6..000000000 --- a/src/AasxServerStandardBib/Opc.Ua.SampleClient.Config.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - UA Core Sample Client - urn:localhost:OPCFoundation:CoreSampleClient - http://opcfoundation.org/UA/CoreSampleClient - Client_1 - - - - - - X509Store - CurrentUser\My - CN=UA Core Sample Client, C=US, S=Arizona, O=OPC Foundation, DC=localhost - - - - - Directory - %LocalApplicationData%/OPC Foundation/pki/issuer - - - - - Directory - %LocalApplicationData%/OPC Foundation/pki/trusted - - - - - Directory - %LocalApplicationData%/OPC Foundation/pki/rejected - - - - false - - - - - - - 600000 - 1048576 - 4194304 - 65535 - 4194304 - 65535 - 300000 - 3600000 - - - - - - - 600000 - - - - opc.tcp://{0}:4840/UADiscovery - - - - - - - 10000 - - - - %LocalApplicationData%/Logs/Opc.Ua.SampleClient.log.txt - true - - - - - - - - - - - - 519 - - - - true - - \ No newline at end of file diff --git a/src/AasxServerStandardBib/Opc.Ua.SampleServer.Config.xml b/src/AasxServerStandardBib/Opc.Ua.SampleServer.Config.xml deleted file mode 100644 index b04618e64..000000000 --- a/src/AasxServerStandardBib/Opc.Ua.SampleServer.Config.xml +++ /dev/null @@ -1,221 +0,0 @@ - - - UA Core Sample Server - urn:localhost:OPCFoundation:CoreSampleServer - http://opcfoundation.org/UA/CoreSampleServer - Server_0 - - - - - - X509Store - CurrentUser\My - CN=UA Core Sample Server, C=US, S=Arizona, O=OPC Foundation, DC=localhost - - - - - Directory - %LocalApplicationData%/OPC Foundation/pki/issuer - - - - - Directory - %LocalApplicationData%/OPC Foundation/pki/trusted - - - - - Directory - %LocalApplicationData%/OPC Foundation/pki/rejected - - - - false - - - - - - - 600000 - 1048576 - 4194304 - 65535 - 4194304 - 65535 - 300000 - 3600000 - - - - - opc.tcp://0.0.0.0:51210/UA/SampleServer - https://0.0.0.0:51212/UA/SampleServer/ - - - - - - - - SignAndEncrypt_3 - http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256 - - - - None_1 - http://opcfoundation.org/UA/SecurityPolicy#None - - - Sign_2 - - - - SignAndEncrypt_3 - - - - - 5 - 100 - 2000 - - - - Anonymous_0 - http://opcfoundation.org/UA/SecurityPolicy#None - - - UserName_1 - - - Certificate_2 - - - - false - 100 - 10000 - 3600000 - 10 - 10 - 100 - 6000000 - 100 - 3600000 - 50 - 3600000 - 100 - 100 - 1000 - 1000 - - - - opc.tcp://0.0.0.0:4840 - - opc.tcp://0.0.0.0:4840 - DiscoveryServer_3 - - opc.tcp://0.0.0.0:4840 - - - SignAndEncrypt_3 - - - - - 30000 - Opc.Ua.Server.nodes.xml - - 20 - 100 - 10000 - 10000 - - - - Standard UA Server Profile - Data Access Server Facet - Method Server Facet - - 5 - - DA - - - PFX - PEM - - 0 - false - - - - - - - - - UInt32 - 100 - UInt32 - - - Double - 100 - Double - - - - - - - - %LocalApplicationData%/Logs/Opc.Ua.CoreSampleServer.log.txt - true - - - - - - - - - - - - - - - - true - - diff --git a/src/AasxServerStandardBib/Program.cs b/src/AasxServerStandardBib/Program.cs index 320c4dbec..17bca9ef9 100644 --- a/src/AasxServerStandardBib/Program.cs +++ b/src/AasxServerStandardBib/Program.cs @@ -7,9 +7,6 @@ using Jose; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; -using Opc.Ua; -using Opc.Ua.Configuration; -using Opc.Ua.Server; using System; using System.Collections.Generic; using System.CommandLine; @@ -309,7 +306,7 @@ public static bool loadPackageForSubmodel(string submodelIdentifier, out ISubmod public static void changeDataVersion() { dataVersion++; } public static ulong getDataVersion() { return (dataVersion); } - static Dictionary OPCClients = new Dictionary(); + //static Dictionary OPCClients = new Dictionary(); static readonly object opcclientAddLock = new object(); // object for lock around connecting to an external opc server static MqttServer AASMqttServer = new MqttServer(); @@ -974,7 +971,7 @@ private static async Task Run(CommandLineArguments a) Console.WriteLine("MQTT Publisher started."); } - MySampleServer server = null; + /*MySampleServer server = null; if (a.Opc) { server = new MySampleServer(_autoAccept: true, _stopTimeout: 0, _aasxEnv: env); @@ -992,7 +989,7 @@ private static async Task Run(CommandLineArguments a) Console.WriteLine($"OPC client will be updating every: {a.OpcClientRate} milliseconds"); SetOPCClientTimer((double)a.OpcClientRate); // read again everytime timer expires - } + }*/ SetScriptTimer(1000); // also updates balzor view @@ -1040,9 +1037,9 @@ private static async Task Run(CommandLineArguments a) Program.signalNewData(3); - if (a.Opc && server != null) + if (a.Opc /*&& server != null*/ ) { - server.Run(); // wait for CTRL-C + //server.Run(); // wait for CTRL-C } else { @@ -2023,7 +2020,7 @@ public static int getSignalNewDataMode() } */ - public static void OnOPCClientNextTimedEvent() + /*public static void OnOPCClientNextTimedEvent() { ReadOPCClient(false); // RunScript(false); @@ -2035,7 +2032,7 @@ private static void OnOPCClientNextTimedEvent(Object source, ElapsedEventArgs e) ReadOPCClient(false); // RunScript(false); NewDataAvailable?.Invoke(null, EventArgs.Empty); - } + }*/ private static System.Timers.Timer scriptTimer; @@ -2228,7 +2225,7 @@ private static void OnRestTimedEvent(Object source, ElapsedEventArgs e) worker.RunWorkerAsync(); } - private static Boolean OPCWrite(string nodeId, object value) + /*private static Boolean OPCWrite(string nodeId, object value) /// /// Writes to (i.e. updates values of) Nodes in the AAS OPC Server /// @@ -2438,7 +2435,7 @@ string AASSubmodel } return true; - } + }*/ static void RunScript(bool init) { @@ -2754,7 +2751,7 @@ public static bool ParseJson(SubmodelElementCollection c, object o, List return ok; } - private static void WalkSubmodelElement(ISubmodelElement sme, string nodePath, string serverNodePrefix, SampleClient.UASampleClient client, int clientNamespace) + /*private static void WalkSubmodelElement(ISubmodelElement sme, string nodePath, string serverNodePrefix, SampleClient.UASampleClient client, int clientNamespace) { if (sme is Property) { @@ -2823,10 +2820,10 @@ private static void UpdatePropertyFromOPCClient(Property p, string serverNodeId, if (!OPCWrite(serverNodeId, value)) Console.WriteLine("OPC write not successful."); } - } + }*/ } - public class ApplicationMessageDlg : IApplicationMessageDlg + /*public class ApplicationMessageDlg : IApplicationMessageDlg { private string message = string.Empty; private bool ask = false; @@ -3047,5 +3044,5 @@ private async void StatusThread() await Task.Delay(1000); } } - } + }*/ } \ No newline at end of file diff --git a/src/AasxServerStandardBib/SampleNodeManager.cs b/src/AasxServerStandardBib/SampleNodeManager.cs deleted file mode 100644 index a413db5ac..000000000 --- a/src/AasxServerStandardBib/SampleNodeManager.cs +++ /dev/null @@ -1,3013 +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.Diagnostics; -using System.IO; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Xml; -using Opc.Ua.Server; - -namespace Opc.Ua.Sample -{ - /// - /// A node manager for a variety of test data. - /// - public class SampleNodeManager : INodeManager, INodeIdFactory, IDisposable - { - #region Constructors - /// - /// Initializes the node manager. - /// - public SampleNodeManager(IServerInternal server) - { - // save a reference to the server that owns the node manager. - m_server = server; - - // create the default context. - m_systemContext = m_server.DefaultSystemContext.Copy(); - - m_systemContext.SystemHandle = null; - m_systemContext.NodeIdFactory = this; - - // create the table of nodes. - m_predefinedNodes = new NodeIdDictionary(); - m_rootNotifiers = new List(); - m_sampledItems = new List(); - m_minimumSamplingInterval = 100; - } - #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_samplingTimer); - m_samplingTimer = null; - - foreach (NodeState node in m_predefinedNodes.Values) - { - Utils.SilentDispose(node); - } - } - } - } - #endregion - - #region INodeIdFactory Members - /// - /// Creates the NodeId for the specified node. - /// - /// The context. - /// The node. - /// The new NodeId. - public virtual NodeId New(ISystemContext context, NodeState node) - { - return node.NodeId; - } - #endregion - - #region Public Properties - /// - /// Acquires the lock on the node manager. - /// - public object Lock - { - get { return m_lock; } - } - #endregion - - #region Protected Members - /// - /// The server that the node manager belongs to. - /// - protected IServerInternal Server - { - get { return m_server; } - } - - /// - /// The default context to use. - /// - public ServerSystemContext SystemContext - { - get { return m_systemContext; } - } - - /// - /// The predefined nodes managed by the node manager. - /// - protected NodeIdDictionary PredefinedNodes - { - get { return m_predefinedNodes; } - } - - /// - /// The root notifiers for the node manager. - /// - protected List RootNotifiers - { - get { return m_rootNotifiers; } - } - - /// - /// Returns true if the namespace for the node id is one of the namespaces managed by the node manager. - /// - /// The node id to check. - /// True if the namespace is one of the nodes. - protected virtual bool IsNodeIdInNamespace(NodeId nodeId) - { - if (NodeId.IsNull(nodeId)) - { - return false; - } - - // quickly exclude nodes that not in the namespace. - for (int ii = 0; ii < m_namespaceIndexes.Length; ii++) - { - if (nodeId.NamespaceIndex == m_namespaceIndexes[ii]) - { - return true; - } - } - - return false; - } - - /// - /// Returns the node if the handle refers to a node managed by this manager. - /// - /// The handle to check. - /// Non-null if the handle belongs to the node manager. - protected virtual NodeState IsHandleInNamespace(object managerHandle) - { - NodeState source = managerHandle as NodeState; - - if (source == null) - { - return null; - } - - if (!IsNodeIdInNamespace(source.NodeId)) - { - return null; - } - - return source; - } - - /// - /// Returns the state object for the specified node if it exists. - /// - public NodeState Find(NodeId nodeId) - { - lock (Lock) - { - NodeState node = null; - - if (!PredefinedNodes.TryGetValue(nodeId, out node)) - { - return null; - } - - return node; - } - } - - /// - /// Creates a new instance and assigns unique identifiers to all children. - /// - /// The operation context. - /// An optional parent identifier. - /// The reference type from the parent. - /// The browse name. - /// The instance to create. - /// The new node id. - public NodeId CreateNode( - ServerSystemContext context, - NodeId parentId, - NodeId referenceTypeId, - QualifiedName browseName, - BaseInstanceState instance) - { - ServerSystemContext contextToUse = (ServerSystemContext)m_systemContext.Copy(context); - - lock (Lock) - { - instance.ReferenceTypeId = referenceTypeId; - - NodeState parent = null; - - if (parentId != null) - { - if (!PredefinedNodes.TryGetValue(parentId, out parent)) - { - throw ServiceResultException.Create( - StatusCodes.BadNodeIdUnknown, - "Cannot find parent with id: {0}", - parentId); - } - - parent.AddChild(instance); - } - - instance.Create(contextToUse, null, browseName, null, true); - AddPredefinedNode(contextToUse, instance); - - return instance.NodeId; - } - } - - /// - /// Deletes a node and all of its children. - /// - public bool DeleteNode( - ServerSystemContext context, - NodeId nodeId) - { - ServerSystemContext contextToUse = m_systemContext.Copy(context); - - bool found = false; - List referencesToRemove = new List(); - - lock (Lock) - { - NodeState node = null; - - if (PredefinedNodes.TryGetValue(nodeId, out node)) - { - RemovePredefinedNode(contextToUse, node, referencesToRemove); - found = true; - } - - RemoveRootNotifier(node); - } - - // must release the lock before removing cross references to other node managers. - if (referencesToRemove.Count > 0) - { - Server.NodeManager.RemoveReferences(referencesToRemove); - } - - return found; - } - #endregion - - #region INodeManager Members - /// - /// Returns the namespaces used by the node manager. - /// - /// - /// All NodeIds exposed by the node manager must be qualified by a namespace URI. This property - /// returns the URIs used by the node manager. In this example all NodeIds use a single URI. - /// - public virtual IEnumerable NamespaceUris - { - get - { - return m_namespaceUris; - } - - protected set - { - if (value != null) - { - m_namespaceUris = new List(value); - } - else - { - m_namespaceUris = new List(); - } - - m_namespaceIndexes = new ushort[m_namespaceUris.Count]; - } - } - - /// - /// 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 virtual void CreateAddressSpace(IDictionary> externalReferences) - { - lock (Lock) - { - // add the uris to the server's namespace table and cache the indexes. - for (int ii = 0; ii < m_namespaceUris.Count; ii++) - { - m_namespaceIndexes[ii] = m_server.NamespaceUris.GetIndexOrAppend(m_namespaceUris[ii]); - } - - LoadPredefinedNodes(m_systemContext, externalReferences); - } - } - - #region CreateAddressSpace Support Functions - /// - /// Loads a node set from a file or resource and addes them to the set of predefined nodes. - /// - public virtual void LoadPredefinedNodes( - ISystemContext context, - Assembly assembly, - string resourcePath, - IDictionary> externalReferences) - { - // load the predefined nodes from an XML document. - NodeStateCollection predefinedNodes = new NodeStateCollection(); - predefinedNodes.LoadFromResource(context, resourcePath, assembly, true); - - // add the predefined nodes to the node manager. - for (int ii = 0; ii < predefinedNodes.Count; ii++) - { - AddPredefinedNode(context, predefinedNodes[ii]); - } - - // ensure the reverse refernces exist. - AddReverseReferences(externalReferences); - } - - /// - /// Loads a node set from a file or resource and addes them to the set of predefined nodes. - /// - protected virtual NodeStateCollection LoadPredefinedNodes(ISystemContext context) - { - return new NodeStateCollection(); - } - - /// - /// Loads a node set from a file or resource and addes them to the set of predefined nodes. - /// - protected virtual void LoadPredefinedNodes( - ISystemContext context, - IDictionary> externalReferences) - { - // load the predefined nodes from an XML document. - NodeStateCollection predefinedNodes = LoadPredefinedNodes(context); - - // add the predefined nodes to the node manager. - for (int ii = 0; ii < predefinedNodes.Count; ii++) - { - AddPredefinedNode(context, predefinedNodes[ii]); - } - - // ensure the reverse refernces exist. - AddReverseReferences(externalReferences); - } - - /// - /// Replaces the generic node with a node specific to the model. - /// - protected virtual NodeState AddBehaviourToPredefinedNode(ISystemContext context, NodeState predefinedNode) - { - BaseObjectState passiveNode = predefinedNode as BaseObjectState; - - if (passiveNode == null) - { - return predefinedNode; - } - - return predefinedNode; - } - - /// - /// Recursively indexes the node and its children. - /// - public virtual void AddPredefinedNode(ISystemContext context, NodeState node) - { - NodeState activeNode = AddBehaviourToPredefinedNode(context, node); - m_predefinedNodes[activeNode.NodeId] = activeNode; - - BaseTypeState type = activeNode as BaseTypeState; - - if (type != null) - { - AddTypesToTypeTree(type); - } - - List children = new List(); - activeNode.GetChildren(context, children); - - for (int ii = 0; ii < children.Count; ii++) - { - AddPredefinedNode(context, children[ii]); - } - } - - /// - /// Recursively indexes the node and its children. - /// - protected virtual void RemovePredefinedNode( - ISystemContext context, - NodeState node, - List referencesToRemove) - { - m_predefinedNodes.Remove(node.NodeId); - node.UpdateChangeMasks(NodeStateChangeMasks.Deleted); - node.ClearChangeMasks(context, false); - OnNodeRemoved(node); - - // remove from the parent. - BaseInstanceState instance = node as BaseInstanceState; - - if (instance != null && instance.Parent != null) - { - instance.Parent.RemoveChild(instance); - } - - // remove children. - List children = new List(); - node.GetChildren(context, children); - - for (int ii = 0; ii < children.Count; ii++) - { - node.RemoveChild(children[ii]); - } - - for (int ii = 0; ii < children.Count; ii++) - { - RemovePredefinedNode(context, children[ii], referencesToRemove); - } - - // remove from type table. - BaseTypeState type = node as BaseTypeState; - - if (type != null) - { - m_server.TypeTree.Remove(type.NodeId); - } - - // remove inverse references. - List references = new List(); - node.GetReferences(context, references); - - for (int ii = 0; ii < references.Count; ii++) - { - IReference reference = references[ii]; - - if (reference.TargetId.IsAbsolute) - { - continue; - } - - LocalReference referenceToRemove = new LocalReference( - (NodeId)reference.TargetId, - reference.ReferenceTypeId, - reference.IsInverse, - node.NodeId); - - referencesToRemove.Add(referenceToRemove); - } - } - - /// - /// Called after a node has been deleted. - /// - protected virtual void OnNodeRemoved(NodeState node) - { - // overridden by the sub-class. - } - - /// - /// Add the node to the set of root notifiers. - /// - protected virtual void AddRootNotifier(NodeState notifier) - { - for (int ii = 0; ii < m_rootNotifiers.Count; ii++) - { - if (Object.ReferenceEquals(notifier, m_rootNotifiers[ii])) - { - return; - } - } - - m_rootNotifiers.Add(notifier); - - // subscribe to existing events. - if (m_server.EventManager != null) - { - IList monitoredItems = m_server.EventManager.GetMonitoredItems(); - - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - if (monitoredItems[ii].MonitoringAllEvents) - { - SubscribeToAllEvents( - SystemContext, - monitoredItems[ii], - true, - notifier); - } - } - } - } - - /// - /// Remove the node from the set of root notifiers. - /// - protected virtual void RemoveRootNotifier(NodeState notifier) - { - for (int ii = 0; ii < m_rootNotifiers.Count; ii++) - { - if (Object.ReferenceEquals(notifier, m_rootNotifiers[ii])) - { - m_rootNotifiers.RemoveAt(ii); - break; - } - } - } - - /// - /// Ensures that all reverse references exist. - /// - /// A list of references to add to external targets. - protected virtual void AddReverseReferences(IDictionary> externalReferences) - { - foreach (NodeState source in m_predefinedNodes.Values) - { - // assign a default value to any variable value. - BaseVariableState variable = source as BaseVariableState; - - if (variable != null && variable.Value == null) - { - variable.Value = TypeInfo.GetDefaultValue(variable.DataType, variable.ValueRank, Server.TypeTree); - } - - // add reference from supertype for type nodes. - - IList references = new List(); - source.GetReferences(SystemContext, references); - - for (int ii = 0; ii < references.Count; ii++) - { - IReference reference = references[ii]; - - // nothing to do with external nodes. - if (reference.TargetId == null || reference.TargetId.IsAbsolute) - { - continue; - } - - NodeId targetId = (NodeId)reference.TargetId; - - // add inverse reference to internal targets. - NodeState target = null; - - if (m_predefinedNodes.TryGetValue(targetId, out target)) - { - if (!target.ReferenceExists(reference.ReferenceTypeId, !reference.IsInverse, source.NodeId)) - { - target.AddReference(reference.ReferenceTypeId, !reference.IsInverse, source.NodeId); - } - - continue; - } - - // check for inverse references to external notifiers. - if (reference.IsInverse && reference.ReferenceTypeId == ReferenceTypeIds.HasNotifier) - { - AddRootNotifier(source); - } - - // nothing more to do for references to nodes managed by this manager. - if (IsNodeIdInNamespace(targetId)) - { - continue; - } - - // add external reference. - AddExternalReference( - targetId, - reference.ReferenceTypeId, - !reference.IsInverse, - source.NodeId, - externalReferences); - } - } - } - - /// - /// Adds an external reference to the dictionary. - /// - protected void AddExternalReference( - NodeId sourceId, - NodeId referenceTypeId, - bool isInverse, - NodeId targetId, - IDictionary> externalReferences) - { - // get list of references to external nodes. - IList referencesToAdd = null; - - if (!externalReferences.TryGetValue(sourceId, out referencesToAdd)) - { - externalReferences[sourceId] = referencesToAdd = new List(); - } - - // add reserve reference from external node. - ReferenceNode referenceToAdd = new ReferenceNode(); - - referenceToAdd.ReferenceTypeId = referenceTypeId; - referenceToAdd.IsInverse = isInverse; - referenceToAdd.TargetId = targetId; - - referencesToAdd.Add(referenceToAdd); - } - - // TODO: MIHO added this - - public void AddExternalReferencePublic( - NodeId sourceId, - NodeId referenceTypeId, - bool isInverse, - NodeId targetId, - IDictionary> externalReferences) - { - if (externalReferences != null) - AddExternalReference(sourceId, referenceTypeId, isInverse, targetId, externalReferences); - } - - /// - /// Recursively adds the types to the type tree. - /// - protected void AddTypesToTypeTree(BaseTypeState type) - { - if (!NodeId.IsNull(type.SuperTypeId)) - { - if (!Server.TypeTree.IsKnown(type.SuperTypeId)) - { - AddTypesToTypeTree(type.SuperTypeId); - } - } - - if (type.NodeClass != NodeClass.ReferenceType) - { - Server.TypeTree.AddSubtype(type.NodeId, type.SuperTypeId); - } - else - { - Server.TypeTree.AddReferenceSubtype(type.NodeId, type.SuperTypeId, type.BrowseName); - } - } - - /// - /// Recursively adds the types to the type tree. - /// - protected void AddTypesToTypeTree(NodeId typeId) - { - BaseTypeState type = Find(typeId) as BaseTypeState; - - if (type == null) - { - return; - } - - AddTypesToTypeTree(type); - } - - /// - /// Finds the specified and checks if it is of the expected type. - /// - /// Returns null if not found or not of the correct type. - public NodeState FindPredefinedNode(NodeId nodeId, Type expectedType) - { - if (nodeId == null) - { - return null; - } - - NodeState node = null; - - if (!PredefinedNodes.TryGetValue(nodeId, out node)) - { - return null; - } - - if (expectedType != null) - { - if (!expectedType.IsInstanceOfType(node)) - { - return null; - } - } - - return node; - } - #endregion - - /// - /// Frees any resources allocated for the address space. - /// - public virtual void DeleteAddressSpace() - { - lock (Lock) - { - m_predefinedNodes.Clear(); - } - } - - /// - /// Returns a unique handle for the node. - /// - /// - /// This must efficiently determine whether the node belongs to the node manager. If it does belong to - /// NodeManager it should return a handle that does not require the NodeId to be validated again when - /// the handle is passed into other methods such as 'Read' or 'Write'. - /// - public virtual object GetManagerHandle(NodeId nodeId) - { - lock (Lock) - { - return GetManagerHandle(m_systemContext, nodeId, null); - } - } - - /// - /// Returns a unique handle for the node. - /// - /// - /// This must efficiently determine whether the node belongs to the node manager. If it does belong to - /// NodeManager it should return a handle that does not require the NodeId to be validated again when - /// the handle is passed into other methods such as 'Read' or 'Write'. - /// - protected virtual object GetManagerHandle(ISystemContext context, NodeId nodeId, IDictionary cache) - { - lock (Lock) - { - // quickly exclude nodes that not in the namespace. - if (!IsNodeIdInNamespace(nodeId)) - { - return null; - } - - // lookup the node. - NodeState node = null; - - if (!m_predefinedNodes.TryGetValue(nodeId, out node)) - { - return null; - } - - return node; - } - } - - /// - /// This method is used to add bi-directional references to nodes from other node managers. - /// - /// - /// The additional references are optional, however, the NodeManager should support them. - /// - public virtual void AddReferences(IDictionary> references) - { - lock (Lock) - { - foreach (KeyValuePair> current in references) - { - // check for valid handle. - NodeState source = GetManagerHandle(m_systemContext, current.Key, null) as NodeState; - - if (source == null) - { - continue; - } - - // add reference to external target. - foreach (IReference reference in current.Value) - { - source.AddReference(reference.ReferenceTypeId, reference.IsInverse, reference.TargetId); - } - } - } - } - - /// - /// This method is used to delete bi-directional references to nodes from other node managers. - /// - public virtual ServiceResult DeleteReference( - object sourceHandle, - NodeId referenceTypeId, - bool isInverse, - ExpandedNodeId targetId, - bool deleteBiDirectional) - { - lock (Lock) - { - // check for valid handle. - NodeState source = IsHandleInNamespace(sourceHandle); - - if (source == null) - { - return StatusCodes.BadNodeIdUnknown; - } - - source.RemoveReference(referenceTypeId, isInverse, targetId); - - if (deleteBiDirectional) - { - // check if the target is also managed by the node manager. - if (!targetId.IsAbsolute) - { - NodeState target = GetManagerHandle(m_systemContext, (NodeId)targetId, null) as NodeState; - - if (target != null) - { - target.RemoveReference(referenceTypeId, !isInverse, source.NodeId); - } - } - } - - return ServiceResult.Good; - } - } - - /// - /// Returns the basic metadata for the node. Returns null if the node does not exist. - /// - /// - /// This method validates any placeholder handle. - /// - public virtual NodeMetadata GetNodeMetadata( - OperationContext context, - object targetHandle, - BrowseResultMask resultMask) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - - lock (Lock) - { - // check for valid handle. - NodeState target = IsHandleInNamespace(targetHandle); - - if (target == null) - { - return null; - } - - // validate node. - if (!ValidateNode(systemContext, target)) - { - return null; - } - - // read the attributes. - List values = target.ReadAttributes( - systemContext, - Attributes.WriteMask, - Attributes.UserWriteMask, - Attributes.DataType, - Attributes.ValueRank, - Attributes.ArrayDimensions, - Attributes.AccessLevel, - Attributes.UserAccessLevel, - Attributes.EventNotifier, - Attributes.Executable, - Attributes.UserExecutable); - - // construct the metadata object. - - NodeMetadata metadata = new NodeMetadata(target, target.NodeId); - - metadata.NodeClass = target.NodeClass; - metadata.BrowseName = target.BrowseName; - metadata.DisplayName = target.DisplayName; - - if (values[0] != null && values[1] != null) - { - metadata.WriteMask = (AttributeWriteMask)(((uint)values[0]) & ((uint)values[1])); - } - - metadata.DataType = (NodeId)values[2]; - - if (values[3] != null) - { - metadata.ValueRank = (int)values[3]; - } - - metadata.ArrayDimensions = (IList)values[4]; - - if (values[5] != null && values[6] != null) - { - metadata.AccessLevel = (byte)(((byte)values[5]) & ((byte)values[6])); - } - - if (values[7] != null) - { - metadata.EventNotifier = (byte)values[7]; - } - - if (values[8] != null && values[9] != null) - { - metadata.Executable = (((bool)values[8]) && ((bool)values[9])); - } - - // get instance references. - BaseInstanceState instance = target as BaseInstanceState; - - if (instance != null) - { - metadata.TypeDefinition = instance.TypeDefinitionId; - metadata.ModellingRule = instance.ModellingRuleId; - } - - // fill in the common attributes. - return metadata; - } - } - - /// - /// Browses the references from a node managed by the node manager. - /// - /// - /// The continuation point is created for every browse operation and contains the browse parameters. - /// The node manager can store its state information in the Data and Index properties. - /// - public virtual void Browse( - OperationContext context, - ref ContinuationPoint continuationPoint, - IList references) - { - if (continuationPoint == null) throw new ArgumentNullException("continuationPoint"); - if (references == null) throw new ArgumentNullException("references"); - - // check for view. - if (!ViewDescription.IsDefault(continuationPoint.View)) - { - throw new ServiceResultException(StatusCodes.BadViewIdUnknown); - } - - ServerSystemContext systemContext = m_systemContext.Copy(context); - - lock (Lock) - { - // verify that the node exists. - NodeState source = IsHandleInNamespace(continuationPoint.NodeToBrowse); - - if (source == null) - { - throw new ServiceResultException(StatusCodes.BadNodeIdUnknown); - } - - // validate node. - if (!ValidateNode(systemContext, source)) - { - throw new ServiceResultException(StatusCodes.BadNodeIdUnknown); - } - - // check for previous continuation point. - INodeBrowser browser = continuationPoint.Data as INodeBrowser; - - // fetch list of references. - if (browser == null) - { - // create a new browser. - browser = source.CreateBrowser( - systemContext, - continuationPoint.View, - continuationPoint.ReferenceTypeId, - continuationPoint.IncludeSubtypes, - continuationPoint.BrowseDirection, - null, - null, - false); - } - - // apply filters to references. - for (IReference reference = browser.Next(); reference != null; reference = browser.Next()) - { - // create the type definition reference. - ReferenceDescription description = GetReferenceDescription(context, reference, continuationPoint); - - if (description == null) - { - continue; - } - - // check if limit reached. - if (continuationPoint.MaxResultsToReturn != 0 && references.Count >= continuationPoint.MaxResultsToReturn) - { - browser.Push(reference); - continuationPoint.Data = browser; - return; - } - - references.Add(description); - } - - // release the continuation point if all done. - continuationPoint.Dispose(); - continuationPoint = null; - } - } - - #region Browse Support Functions - /// - /// Returns the references for the node that meets the criteria specified. - /// - private ReferenceDescription GetReferenceDescription( - OperationContext context, - IReference reference, - ContinuationPoint continuationPoint) - { - // create the type definition reference. - ReferenceDescription description = new ReferenceDescription(); - - description.NodeId = reference.TargetId; - description.SetReferenceType(continuationPoint.ResultMask, reference.ReferenceTypeId, !reference.IsInverse); - - // do not cache target parameters for remote nodes. - if (reference.TargetId.IsAbsolute) - { - // only return remote references if no node class filter is specified. - if (continuationPoint.NodeClassMask != 0) - { - return null; - } - - return description; - } - - NodeState target = null; - - // check for local reference. - NodeStateReference referenceInfo = reference as NodeStateReference; - - if (referenceInfo != null) - { - target = referenceInfo.Target; - } - - // check for internal reference. - if (target == null) - { - NodeId targetId = (NodeId)reference.TargetId; - - if (IsNodeIdInNamespace(targetId)) - { - if (!PredefinedNodes.TryGetValue(targetId, out target)) - { - target = null; - } - } - } - - // the target may be a reference to a node in another node manager. In these cases - // the target attributes must be fetched by the caller. The Unfiltered flag tells the - // caller to do that. - if (target == null) - { - description.Unfiltered = true; - return description; - } - - // apply node class filter. - if (continuationPoint.NodeClassMask != 0 && ((continuationPoint.NodeClassMask & (uint)target.NodeClass) == 0)) - { - return null; - } - - NodeId typeDefinition = null; - - BaseInstanceState instance = target as BaseInstanceState; - - if (instance != null) - { - typeDefinition = instance.TypeDefinitionId; - } - - // set target attributes. - description.SetTargetAttributes( - continuationPoint.ResultMask, - target.NodeClass, - target.BrowseName, - target.DisplayName, - typeDefinition); - - return description; - } - #endregion - - /// - /// Returns the target of the specified browse path fragment(s). - /// - /// - /// If reference exists but the node manager does not know the browse name it must - /// return the NodeId as an unresolvedTargetIds. The caller will try to check the - /// browse name. - /// - public virtual void TranslateBrowsePath( - OperationContext context, - object sourceHandle, - RelativePathElement relativePath, - IList targetIds, - IList unresolvedTargetIds) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - IDictionary operationCache = new NodeIdDictionary(); - - lock (Lock) - { - // verify that the node exists. - NodeState source = IsHandleInNamespace(sourceHandle); - - if (source == null) - { - return; - } - - // validate node. - if (!ValidateNode(systemContext, source)) - { - return; - } - - // get list of references that relative path. - INodeBrowser browser = source.CreateBrowser( - systemContext, - null, - relativePath.ReferenceTypeId, - relativePath.IncludeSubtypes, - (relativePath.IsInverse) ? BrowseDirection.Inverse : BrowseDirection.Forward, - relativePath.TargetName, - null, - false); - - // check the browse names. - try - { - for (IReference reference = browser.Next(); reference != null; reference = browser.Next()) - { - // ignore unknown external references. - if (reference.TargetId.IsAbsolute) - { - continue; - } - - NodeState target = null; - - // check for local reference. - NodeStateReference referenceInfo = reference as NodeStateReference; - - if (referenceInfo != null) - { - target = referenceInfo.Target; - } - - if (target == null) - { - NodeId targetId = (NodeId)reference.TargetId; - - // the target may be a reference to a node in another node manager. - if (!IsNodeIdInNamespace(targetId)) - { - unresolvedTargetIds.Add((NodeId)reference.TargetId); - continue; - } - - // look up the target manually. - target = GetManagerHandle(systemContext, targetId, operationCache) as NodeState; - - if (target == null) - { - continue; - } - } - - // check browse name. - if (target.BrowseName == relativePath.TargetName) - { - // ensure duplicate node ids are not added. - if (!targetIds.Contains(reference.TargetId)) - { - targetIds.Add(reference.TargetId); - } - } - } - } - finally - { - browser.Dispose(); - } - } - } - - /// - /// Reads the value for the specified attribute. - /// - public virtual void Read( - OperationContext context, - double maxAge, - IList nodesToRead, - IList values, - IList errors) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - IDictionary operationCache = new NodeIdDictionary(); - List nodesToValidate = new List(); - - lock (Lock) - { - for (int ii = 0; ii < nodesToRead.Count; ii++) - { - ReadValueId nodeToRead = nodesToRead[ii]; - - // skip items that have already been processed. - if (nodeToRead.Processed) - { - continue; - } - - // check for valid handle. - NodeState source = GetManagerHandle(systemContext, nodeToRead.NodeId, operationCache) as NodeState; - - if (source == null) - { - continue; - } - - // owned by this node manager. - nodeToRead.Processed = true; - - // create an initial value. - DataValue value = values[ii] = new DataValue(); - - value.Value = null; - value.ServerTimestamp = DateTime.UtcNow; - value.SourceTimestamp = DateTime.MinValue; - value.StatusCode = StatusCodes.Good; - - // check if the node is ready for reading. - if (source.ValidationRequired) - { - errors[ii] = StatusCodes.BadNodeIdUnknown; - - // must validate node in a seperate operation. - ReadWriteOperationState operation = new ReadWriteOperationState(); - - operation.Source = source; - operation.Index = ii; - - nodesToValidate.Add(operation); - - continue; - } - - // read the attribute value. - errors[ii] = source.ReadAttribute( - systemContext, - nodeToRead.AttributeId, - nodeToRead.ParsedIndexRange, - nodeToRead.DataEncoding, - value); - } - - // check for nothing to do. - if (nodesToValidate.Count == 0) - { - return; - } - - // validates the nodes (reads values from the underlying data source if required). - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - ReadWriteOperationState operation = nodesToValidate[ii]; - - if (!ValidateNode(systemContext, operation.Source)) - { - continue; - } - - ReadValueId nodeToRead = nodesToRead[operation.Index]; - DataValue value = values[operation.Index]; - - // update the attribute value. - errors[operation.Index] = operation.Source.ReadAttribute( - systemContext, - nodeToRead.AttributeId, - nodeToRead.ParsedIndexRange, - nodeToRead.DataEncoding, - value); - } - } - } - - /// - /// Stores the state of a call method operation. - /// - private struct ReadWriteOperationState - { - public NodeState Source; - public int Index; - } - - /// - /// Verifies that the specified node exists. - /// - protected virtual bool ValidateNode(ServerSystemContext context, NodeState node) - { - // validate node only if required. - if (node.ValidationRequired) - { - return node.Validate(context); - } - - return true; - } - - /// - /// Reads the history for the specified nodes. - /// - public virtual void HistoryRead( - OperationContext context, - HistoryReadDetails details, - TimestampsToReturn timestampsToReturn, - bool releaseContinuationPoints, - IList nodesToRead, - IList results, - IList errors) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - IDictionary operationCache = new NodeIdDictionary(); - List nodesToValidate = new List(); - List readsToComplete = new List(); - - lock (Lock) - { - for (int ii = 0; ii < nodesToRead.Count; ii++) - { - HistoryReadValueId nodeToRead = nodesToRead[ii]; - - // skip items that have already been processed. - if (nodeToRead.Processed) - { - continue; - } - - // check for valid handle. - NodeState source = GetManagerHandle(systemContext, nodeToRead.NodeId, operationCache) as NodeState; - - if (source == null) - { - continue; - } - - // owned by this node manager. - nodeToRead.Processed = true; - - // only variables supported. - BaseVariableState variable = source as BaseVariableState; - - if (variable == null) - { - errors[ii] = StatusCodes.BadHistoryOperationUnsupported; - continue; - } - - results[ii] = new HistoryReadResult(); - - ReadWriteOperationState operation = new ReadWriteOperationState(); - - operation.Source = source; - operation.Index = ii; - - // check if the node is ready for reading. - if (source.ValidationRequired) - { - // must validate node in a seperate operation. - errors[ii] = StatusCodes.BadNodeIdUnknown; - nodesToValidate.Add(operation); - continue; - } - - // read the data. - readsToComplete.Add(operation); - } - - // validates the nodes (reads values from the underlying data source if required). - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - ReadWriteOperationState operation = nodesToValidate[ii]; - - if (!ValidateNode(systemContext, operation.Source)) - { - continue; - } - - readsToComplete.Add(operation); - } - } - - // reads the data without holding onto the lock. - for (int ii = 0; ii < readsToComplete.Count; ii++) - { - ReadWriteOperationState operation = readsToComplete[ii]; - - errors[operation.Index] = HistoryRead( - systemContext, - operation.Source, - details, - timestampsToReturn, - releaseContinuationPoints, - nodesToRead[operation.Index], - results[operation.Index]); - } - } - - /// - /// Reads the history for a single node which has already been validated. - /// - protected virtual ServiceResult HistoryRead( - ISystemContext context, - NodeState source, - HistoryReadDetails details, - TimestampsToReturn timestampsToReturn, - bool releaseContinuationPoints, - HistoryReadValueId nodesToRead, - HistoryReadResult result) - { - // check for variable. - BaseVariableState variable = source as BaseVariableState; - - if (variable == null) - { - return StatusCodes.BadHistoryOperationUnsupported; - } - - // check for access. - lock (Lock) - { - if ((variable.AccessLevel & AccessLevels.HistoryRead) == 0) - { - return StatusCodes.BadNotReadable; - } - } - - // handle read raw. - ReadRawModifiedDetails readRawDetails = details as ReadRawModifiedDetails; - - if (readRawDetails != null) - { - return HistoryReadRaw( - context, - variable, - readRawDetails, - timestampsToReturn, - releaseContinuationPoints, - nodesToRead, - result); - } - - // handle read processed. - ReadProcessedDetails readProcessedDetails = details as ReadProcessedDetails; - - if (readProcessedDetails != null) - { - return HistoryReadProcessed( - context, - variable, - readProcessedDetails, - timestampsToReturn, - releaseContinuationPoints, - nodesToRead, - result); - } - - // handle read processed. - ReadAtTimeDetails readAtTimeDetails = details as ReadAtTimeDetails; - - if (readAtTimeDetails != null) - { - return HistoryReadAtTime( - context, - variable, - readAtTimeDetails, - timestampsToReturn, - releaseContinuationPoints, - nodesToRead, - result); - } - - return StatusCodes.BadHistoryOperationUnsupported; - } - - /// - /// Reads the raw history for the variable value. - /// - protected virtual ServiceResult HistoryReadRaw( - ISystemContext context, - BaseVariableState source, - ReadRawModifiedDetails details, - TimestampsToReturn timestampsToReturn, - bool releaseContinuationPoints, - HistoryReadValueId nodeToRead, - HistoryReadResult result) - { - return StatusCodes.BadHistoryOperationUnsupported; - } - - /// - /// Reads the processed history for the variable value. - /// - protected virtual ServiceResult HistoryReadProcessed( - ISystemContext context, - BaseVariableState source, - ReadProcessedDetails details, - TimestampsToReturn timestampsToReturn, - bool releaseContinuationPoints, - HistoryReadValueId nodeToRead, - HistoryReadResult result) - { - return StatusCodes.BadHistoryOperationUnsupported; - } - - /// - /// Reads the history for the variable value. - /// - protected virtual ServiceResult HistoryReadAtTime( - ISystemContext context, - BaseVariableState source, - ReadAtTimeDetails details, - TimestampsToReturn timestampsToReturn, - bool releaseContinuationPoints, - HistoryReadValueId nodeToRead, - HistoryReadResult result) - { - return StatusCodes.BadHistoryOperationUnsupported; - } - - - /// - /// Writes the value for the specified attributes. - /// - public virtual void Write( - OperationContext context, - IList nodesToWrite, - IList errors) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - IDictionary operationCache = new NodeIdDictionary(); - List nodesToValidate = new List(); - - lock (Lock) - { - for (int ii = 0; ii < nodesToWrite.Count; ii++) - { - WriteValue nodeToWrite = nodesToWrite[ii]; - - // skip items that have already been processed. - if (nodeToWrite.Processed) - { - continue; - } - - // check for valid handle. - NodeState source = GetManagerHandle(systemContext, nodeToWrite.NodeId, operationCache) as NodeState; - - if (source == null) - { - continue; - } - - // owned by this node manager. - nodeToWrite.Processed = true; - - // index range is not supported. - if (!String.IsNullOrEmpty(nodeToWrite.IndexRange)) - { - errors[ii] = StatusCodes.BadWriteNotSupported; - continue; - } - - // check if the node is ready for reading. - if (source.ValidationRequired) - { - errors[ii] = StatusCodes.BadNodeIdUnknown; - - // must validate node in a seperate operation. - ReadWriteOperationState operation = new ReadWriteOperationState(); - - operation.Source = source; - operation.Index = ii; - - nodesToValidate.Add(operation); - - continue; - } - - // write the attribute value. - errors[ii] = source.WriteAttribute( - systemContext, - nodeToWrite.AttributeId, - nodeToWrite.ParsedIndexRange, - nodeToWrite.Value); - - // updates to source finished - report changes to monitored items. - source.ClearChangeMasks(systemContext, false); - } - - // check for nothing to do. - if (nodesToValidate.Count == 0) - { - return; - } - - // validates the nodes (reads values from the underlying data source if required). - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - ReadWriteOperationState operation = nodesToValidate[ii]; - - if (!ValidateNode(systemContext, operation.Source)) - { - continue; - } - - WriteValue nodeToWrite = nodesToWrite[operation.Index]; - - // write the attribute value. - errors[operation.Index] = operation.Source.WriteAttribute( - systemContext, - nodeToWrite.AttributeId, - nodeToWrite.ParsedIndexRange, - nodeToWrite.Value); - - // updates to source finished - report changes to monitored items. - operation.Source.ClearChangeMasks(systemContext, false); - } - } - } - - /// - /// Updates the history for the specified nodes. - /// - public virtual void HistoryUpdate( - OperationContext context, - Type detailsType, - IList nodesToUpdate, - IList results, - IList errors) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - IDictionary operationCache = new NodeIdDictionary(); - List nodesToValidate = new List(); - - lock (Lock) - { - for (int ii = 0; ii < nodesToUpdate.Count; ii++) - { - HistoryUpdateDetails nodeToUpdate = nodesToUpdate[ii]; - - // skip items that have already been processed. - if (nodeToUpdate.Processed) - { - continue; - } - - // check for valid handle. - NodeState source = GetManagerHandle(systemContext, nodeToUpdate.NodeId, operationCache) as NodeState; - - if (source == null) - { - continue; - } - - // owned by this node manager. - nodeToUpdate.Processed = true; - - // check if the node is ready for reading. - if (source.ValidationRequired) - { - errors[ii] = StatusCodes.BadNodeIdUnknown; - - // must validate node in a seperate operation. - ReadWriteOperationState operation = new ReadWriteOperationState(); - - operation.Source = source; - operation.Index = ii; - - nodesToValidate.Add(operation); - - continue; - } - - // historical data not available. - errors[ii] = StatusCodes.BadHistoryOperationUnsupported; - } - - // check for nothing to do. - if (nodesToValidate.Count == 0) - { - return; - } - - // validates the nodes (reads values from the underlying data source if required). - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - ReadWriteOperationState operation = nodesToValidate[ii]; - - if (!ValidateNode(systemContext, operation.Source)) - { - continue; - } - - // historical data not available. - errors[ii] = StatusCodes.BadHistoryOperationUnsupported; - } - } - } - - /// - /// Calls a method on the specified nodes. - /// - public virtual void Call( - OperationContext context, - IList methodsToCall, - IList results, - IList errors) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - IDictionary operationCache = new NodeIdDictionary(); - List nodesToValidate = new List(); - - lock (Lock) - { - for (int ii = 0; ii < methodsToCall.Count; ii++) - { - CallMethodRequest methodToCall = methodsToCall[ii]; - - // skip items that have already been processed. - if (methodToCall.Processed) - { - continue; - } - - // check for valid handle. - NodeState source = GetManagerHandle(systemContext, methodToCall.ObjectId, operationCache) as NodeState; - - if (source == null) - { - continue; - } - - // owned by this node manager. - methodToCall.Processed = true; - - // find the method. - MethodState method = source.FindMethod(systemContext, methodToCall.MethodId); - - if (method == null) - { - // check for loose coupling. - if (source.ReferenceExists(ReferenceTypeIds.HasComponent, false, methodToCall.MethodId)) - { - method = (MethodState)FindPredefinedNode(methodToCall.MethodId, typeof(MethodState)); - } - - if (method == null) - { - errors[ii] = StatusCodes.BadMethodInvalid; - continue; - } - } - - CallMethodResult result = results[ii] = new CallMethodResult(); - - // check if the node is ready for reading. - if (source.ValidationRequired) - { - errors[ii] = StatusCodes.BadNodeIdUnknown; - - // must validate node in a seperate operation. - CallOperationState operation = new CallOperationState(); - - operation.Source = source; - operation.Method = method; - operation.Index = ii; - - nodesToValidate.Add(operation); - - continue; - } - - // call the method. - errors[ii] = Call( - systemContext, - methodToCall, - source, - method, - result); - } - - // check for nothing to do. - if (nodesToValidate.Count == 0) - { - return; - } - - // validates the nodes (reads values from the underlying data source if required). - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - CallOperationState operation = nodesToValidate[ii]; - - // validate the object. - if (!ValidateNode(systemContext, operation.Source)) - { - continue; - } - - // call the method. - CallMethodResult result = results[operation.Index]; - - errors[operation.Index] = Call( - systemContext, - methodsToCall[operation.Index], - operation.Source, - operation.Method, - result); - } - } - } - - /// - /// Stores the state of a call method operation. - /// - private struct CallOperationState - { - public NodeState Source; - public MethodState Method; - public int Index; - } - - /// - /// Calls a method on an object. - /// - protected virtual ServiceResult Call( - ISystemContext context, - CallMethodRequest methodToCall, - NodeState source, - MethodState method, - CallMethodResult result) - { - ServerSystemContext systemContext = context as ServerSystemContext; - List argumentErrors = new List(); - VariantCollection outputArguments = new VariantCollection(); - - ServiceResult error = method.Call( - context, - methodToCall.ObjectId, - methodToCall.InputArguments, - argumentErrors, - outputArguments); - - if (ServiceResult.IsBad(error)) - { - return error; - } - - // check for argument errors. - bool argumentsValid = true; - - for (int jj = 0; jj < argumentErrors.Count; jj++) - { - ServiceResult argumentError = argumentErrors[jj]; - - if (argumentError != null) - { - result.InputArgumentResults.Add(argumentError.StatusCode); - - if (ServiceResult.IsBad(argumentError)) - { - argumentsValid = false; - } - } - else - { - result.InputArgumentResults.Add(StatusCodes.Good); - } - - // only fill in diagnostic info if it is requested. - if ((systemContext.OperationContext.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0) - { - if (ServiceResult.IsBad(argumentError)) - { - argumentsValid = false; - result.InputArgumentDiagnosticInfos.Add(new DiagnosticInfo(argumentError, systemContext.OperationContext.DiagnosticsMask, false, systemContext.OperationContext.StringTable)); - } - else - { - result.InputArgumentDiagnosticInfos.Add(null); - } - } - } - - // check for validation errors. - if (!argumentsValid) - { - result.StatusCode = StatusCodes.BadInvalidArgument; - return result.StatusCode; - } - - // do not return diagnostics if there are no errors. - result.InputArgumentDiagnosticInfos.Clear(); - - // return output arguments. - result.OutputArguments = outputArguments; - - return ServiceResult.Good; - } - - /// - /// Subscribes or unsubscribes to events produced by the specified source. - /// - /// - /// This method is called when a event subscription is created or deletes. The node manager - /// must start/stop reporting events for the specified object and all objects below it in - /// the notifier hierarchy. - /// - public virtual ServiceResult SubscribeToEvents( - OperationContext context, - object sourceId, - uint subscriptionId, - IEventMonitoredItem monitoredItem, - bool unsubscribe) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - - lock (Lock) - { - // check for valid handle. - NodeState source = IsHandleInNamespace(sourceId); - - if (source == null) - { - return StatusCodes.BadNodeIdInvalid; - } - - // check if the object supports subscritions. - BaseObjectState instance = sourceId as BaseObjectState; - - if (instance == null || instance.EventNotifier != EventNotifiers.SubscribeToEvents) - { - return StatusCodes.BadNotSupported; - } - - MonitoredNode monitoredNode = instance.Handle as MonitoredNode; - - // handle unsubscribe. - if (unsubscribe) - { - if (monitoredNode != null) - { - monitoredNode.UnsubscribeToEvents(systemContext, monitoredItem); - - // do any post processing. - OnUnsubscribeToEvents(systemContext, monitoredNode, monitoredItem); - } - - return ServiceResult.Good; - } - - // subscribe to events. - if (monitoredNode == null) - { - instance.Handle = monitoredNode = new MonitoredNode(m_server, this, source); - } - - monitoredNode.SubscribeToEvents(systemContext, monitoredItem); - - // do any post processing. - OnSubscribeToEvents(systemContext, monitoredNode, monitoredItem); - - return ServiceResult.Good; - } - } - - /// - /// 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 virtual ServiceResult SubscribeToAllEvents( - OperationContext context, - uint subscriptionId, - IEventMonitoredItem monitoredItem, - bool unsubscribe) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - - lock (Lock) - { - // update root notifiers. - for (int ii = 0; ii < m_rootNotifiers.Count; ii++) - { - SubscribeToAllEvents( - systemContext, - monitoredItem, - unsubscribe, - m_rootNotifiers[ii]); - } - - return ServiceResult.Good; - } - } - - /// - /// Subscribes/unsubscribes to all events produced by the specified node. - /// - protected void SubscribeToAllEvents( - ISystemContext systemContext, - IEventMonitoredItem monitoredItem, - bool unsubscribe, - NodeState source) - { - MonitoredNode monitoredNode = source.Handle as MonitoredNode; - - // handle unsubscribe. - if (unsubscribe) - { - if (monitoredNode != null) - { - monitoredNode.UnsubscribeToEvents(systemContext, monitoredItem); - - // do any post processing. - OnUnsubscribeToEvents(systemContext, monitoredNode, monitoredItem); - } - - return; - } - - // subscribe to events. - if (monitoredNode == null) - { - source.Handle = monitoredNode = new MonitoredNode(m_server, this, source); - } - - monitoredNode.SubscribeToEvents(systemContext, monitoredItem); - - // do any post processing. - OnSubscribeToEvents(systemContext, monitoredNode, monitoredItem); - } - - /// - /// Does any processing after a monitored item is subscribed to. - /// - protected virtual void OnSubscribeToEvents( - ISystemContext systemContext, - MonitoredNode monitoredNode, - IEventMonitoredItem monitoredItem) - { - // does nothing. - } - - /// - /// Does any processing after a monitored item is subscribed to. - /// - protected virtual void OnUnsubscribeToEvents( - ISystemContext systemContext, - MonitoredNode monitoredNode, - IEventMonitoredItem monitoredItem) - { - // does nothing. - } - - /// - /// Tells the node manager to refresh any conditions associated with the specified monitored items. - /// - /// - /// This method is called when the condition refresh method is called for a subscription. - /// The node manager must create a refresh event for each condition monitored by the subscription. - /// - public virtual ServiceResult ConditionRefresh( - OperationContext context, - IList monitoredItems) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - - lock (Lock) - { - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - IEventMonitoredItem monitoredItem = monitoredItems[ii]; - - if (monitoredItem == null) - { - continue; - } - - // check for global subscription. - if (monitoredItem.MonitoringAllEvents) - { - for (int jj = 0; jj < m_rootNotifiers.Count; jj++) - { - MonitoredNode monitoredNode = m_rootNotifiers[jj].Handle as MonitoredNode; - - if (monitoredNode == null) - { - continue; - } - - monitoredNode.ConditionRefresh(systemContext, monitoredItem); - } - } - - // check for subscription to local node. - else - { - NodeState source = IsHandleInNamespace(monitoredItem.ManagerHandle); - - if (source == null) - { - continue; - } - - MonitoredNode monitoredNode = source.Handle as MonitoredNode; - - if (monitoredNode == null) - { - continue; - } - - monitoredNode.ConditionRefresh(systemContext, monitoredItem); - } - } - } - - return ServiceResult.Good; - } - - /// - /// 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. - /// - public virtual void CreateMonitoredItems( - OperationContext context, - uint subscriptionId, - double publishingInterval, - TimestampsToReturn timestampsToReturn, - IList itemsToCreate, - IList errors, - IList filterErrors, - IList monitoredItems, - ref long globalIdCounter) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - IDictionary operationCache = new NodeIdDictionary(); - List nodesToValidate = new List(); - - lock (Lock) - { - for (int ii = 0; ii < itemsToCreate.Count; ii++) - { - MonitoredItemCreateRequest itemToCreate = itemsToCreate[ii]; - - // skip items that have already been processed. - if (itemToCreate.Processed) - { - continue; - } - - ReadValueId itemToMonitor = itemToCreate.ItemToMonitor; - - // check for valid handle. - NodeState source = GetManagerHandle(systemContext, itemToMonitor.NodeId, operationCache) as NodeState; - - if (source == null) - { - continue; - } - - // owned by this node manager. - itemToCreate.Processed = true; - - // check if the node is ready for reading. - if (source.ValidationRequired) - { - errors[ii] = StatusCodes.BadNodeIdUnknown; - - // must validate node in a seperate operation. - ReadWriteOperationState operation = new ReadWriteOperationState(); - - operation.Source = source; - operation.Index = ii; - - nodesToValidate.Add(operation); - - continue; - } - - MonitoringFilterResult filterError = null; - IMonitoredItem monitoredItem = null; - - errors[ii] = CreateMonitoredItem( - systemContext, - source, - subscriptionId, - publishingInterval, - context.DiagnosticsMask, - timestampsToReturn, - itemToCreate, - ref globalIdCounter, - out filterError, - out monitoredItem); - - // save any filter error details. - filterErrors[ii] = filterError; - - if (ServiceResult.IsBad(errors[ii])) - { - continue; - } - - // save the monitored item. - monitoredItems[ii] = monitoredItem; - } - - // check for nothing to do. - if (nodesToValidate.Count == 0) - { - return; - } - - // validates the nodes (reads values from the underlying data source if required). - for (int ii = 0; ii < nodesToValidate.Count; ii++) - { - ReadWriteOperationState operation = nodesToValidate[ii]; - - // validate the object. - if (!ValidateNode(systemContext, operation.Source)) - { - continue; - } - - MonitoredItemCreateRequest itemToCreate = itemsToCreate[operation.Index]; - - MonitoringFilterResult filterError = null; - IMonitoredItem monitoredItem = null; - - errors[operation.Index] = CreateMonitoredItem( - systemContext, - operation.Source, - subscriptionId, - publishingInterval, - context.DiagnosticsMask, - timestampsToReturn, - itemToCreate, - ref globalIdCounter, - out filterError, - out monitoredItem); - - // save any filter error details. - filterErrors[operation.Index] = filterError; - - if (ServiceResult.IsBad(errors[operation.Index])) - { - continue; - } - - // save the monitored item. - monitoredItems[operation.Index] = monitoredItem; - } - } - } - - /// - /// Validates a data change filter provided by the client. - /// - /// The system context. - /// The node being monitored. - /// The attribute being monitored. - /// The requested monitoring filter. - /// The validated data change filter. - /// The EU range associated with the value if required by the filter. - /// Any error condition. Good if no errors occurred. - protected ServiceResult ValidateDataChangeFilter( - ISystemContext context, - NodeState source, - uint attributeId, - ExtensionObject requestedFilter, - out DataChangeFilter filter, - out Range range) - { - filter = null; - range = null; - - // check for valid filter type. - filter = requestedFilter.Body as DataChangeFilter; - - if (filter == null) - { - return StatusCodes.BadMonitoredItemFilterUnsupported; - } - - // only supported for value attributes. - if (attributeId != Attributes.Value) - { - return StatusCodes.BadMonitoredItemFilterUnsupported; - } - - // only supported for variables. - BaseVariableState variable = source as BaseVariableState; - - if (variable == null) - { - return StatusCodes.BadMonitoredItemFilterUnsupported; - } - - // check the datatype. - if (filter.DeadbandType != (uint)DeadbandType.None) - { - BuiltInType builtInType = TypeInfo.GetBuiltInType(variable.DataType, Server.TypeTree); - - if (!TypeInfo.IsNumericType(builtInType)) - { - return StatusCodes.BadMonitoredItemFilterUnsupported; - } - } - - // validate filter. - ServiceResult error = filter.Validate(); - - if (ServiceResult.IsBad(error)) - { - return error; - } - - if (filter.DeadbandType == (uint)DeadbandType.Percent) - { - BaseVariableState euRange = variable.FindChild(context, BrowseNames.EURange) as BaseVariableState; - - if (euRange == null) - { - return StatusCodes.BadMonitoredItemFilterUnsupported; - } - - range = euRange.Value as Range; - - if (range == null) - { - return StatusCodes.BadMonitoredItemFilterUnsupported; - } - } - - // all good. - return ServiceResult.Good; - } - - /// - /// 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 virtual ServiceResult CreateMonitoredItem( - ISystemContext context, - NodeState source, - uint subscriptionId, - double publishingInterval, - DiagnosticsMasks diagnosticsMasks, - TimestampsToReturn timestampsToReturn, - MonitoredItemCreateRequest itemToCreate, - ref long globalIdCounter, - out MonitoringFilterResult filterError, - out IMonitoredItem monitoredItem) - { - filterError = null; - monitoredItem = null; - ServiceResult error = null; - - // read initial value. - DataValue initialValue = new DataValue(); - - initialValue.Value = null; - initialValue.ServerTimestamp = DateTime.UtcNow; - initialValue.SourceTimestamp = DateTime.MinValue; - initialValue.StatusCode = StatusCodes.Good; - - error = source.ReadAttribute( - context, - itemToCreate.ItemToMonitor.AttributeId, - itemToCreate.ItemToMonitor.ParsedIndexRange, - itemToCreate.ItemToMonitor.DataEncoding, - initialValue); - - if (ServiceResult.IsBad(error)) - { - if (error.StatusCode == StatusCodes.BadAttributeIdInvalid) - { - return error; - } - - initialValue.StatusCode = error.StatusCode; - error = ServiceResult.Good; - } - - // validate parameters. - MonitoringParameters parameters = itemToCreate.RequestedParameters; - - // validate the data change filter. - DataChangeFilter filter = null; - Range range = null; - - if (!ExtensionObject.IsNull(parameters.Filter)) - { - error = ValidateDataChangeFilter( - context, - source, - itemToCreate.ItemToMonitor.AttributeId, - parameters.Filter, - out filter, - out range); - - if (ServiceResult.IsBad(error)) - { - return error; - } - } - - // create monitored node. - MonitoredNode monitoredNode = source.Handle as MonitoredNode; - - if (monitoredNode == null) - { - source.Handle = monitoredNode = new MonitoredNode(m_server, this, source); - } - - // 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; - } - - // check if the variable needs to be sampled. - bool samplingRequired = false; - - if (itemToCreate.ItemToMonitor.AttributeId == Attributes.Value) - { - BaseVariableState variable = source as BaseVariableState; - - if (variable.MinimumSamplingInterval > 0) - { - samplingInterval = CalculateSamplingInterval(variable, samplingInterval); - samplingRequired = true; - } - } - - // create the item. - DataChangeMonitoredItem datachangeItem = monitoredNode.CreateDataChangeItem( - context, - monitoredItemId, - itemToCreate.ItemToMonitor.AttributeId, - itemToCreate.ItemToMonitor.ParsedIndexRange, - itemToCreate.ItemToMonitor.DataEncoding, - diagnosticsMasks, - timestampsToReturn, - itemToCreate.MonitoringMode, - itemToCreate.RequestedParameters.ClientHandle, - samplingInterval, - itemToCreate.RequestedParameters.QueueSize, - itemToCreate.RequestedParameters.DiscardOldest, - filter, - range, - false); - - if (samplingRequired) - { - CreateSampledItem(samplingInterval, datachangeItem); - } - - // report the initial value. - datachangeItem.QueueValue(initialValue, null); - - // do any post processing. - OnCreateMonitoredItem(context, itemToCreate, monitoredNode, datachangeItem); - - // update monitored item list. - monitoredItem = datachangeItem; - - return ServiceResult.Good; - } - - /// - /// Calculates the sampling interval. - /// - private double CalculateSamplingInterval(BaseVariableState variable, double samplingInterval) - { - if (samplingInterval < variable.MinimumSamplingInterval) - { - samplingInterval = variable.MinimumSamplingInterval; - } - - if ((samplingInterval % m_minimumSamplingInterval) != 0) - { - samplingInterval = Math.Truncate(samplingInterval / m_minimumSamplingInterval); - samplingInterval += 1; - samplingInterval *= m_minimumSamplingInterval; - } - - return samplingInterval; - } - - /// - /// Creates a new sampled item. - /// - private void CreateSampledItem(double samplingInterval, DataChangeMonitoredItem monitoredItem) - { - m_sampledItems.Add(monitoredItem); - - if (m_samplingTimer == null) - { - m_samplingTimer = new Timer(DoSample, null, (int)m_minimumSamplingInterval, (int)m_minimumSamplingInterval); - } - } - - /// - /// Deletes a sampled item. - /// - private void DeleteSampledItem(DataChangeMonitoredItem monitoredItem) - { - for (int ii = 0; ii < m_sampledItems.Count; ii++) - { - if (Object.ReferenceEquals(monitoredItem, m_sampledItems[ii])) - { - m_sampledItems.RemoveAt(ii); - break; - } - } - - if (m_sampledItems.Count == 0) - { - if (m_samplingTimer != null) - { - m_samplingTimer.Dispose(); - m_samplingTimer = null; - } - } - } - - /// - /// Polls each monitored item which requires sample. - /// - private void DoSample(object state) - { - try - { - lock (m_lock) - { - for (int ii = 0; ii < m_sampledItems.Count; ii++) - { - DataChangeMonitoredItem monitoredItem = m_sampledItems[ii]; - - if (monitoredItem.TimeToNextSample < m_minimumSamplingInterval) - { - monitoredItem.ValueChanged(SystemContext); - } - } - } - } - catch (Exception e) - { - Utils.Trace(e, "Unexpected error during diagnostics scan."); - } - } - - /// - /// Does any processing after a monitored item is created. - /// - protected virtual void OnCreateMonitoredItem( - ISystemContext systemContext, - MonitoredItemCreateRequest itemToCreate, - MonitoredNode monitoredNode, - DataChangeMonitoredItem monitoredItem) - { - // does nothing. - } - - /// - /// Modifies the parameters for a set of monitored items. - /// - public virtual void ModifyMonitoredItems( - OperationContext context, - TimestampsToReturn timestampsToReturn, - IList monitoredItems, - IList itemsToModify, - IList errors, - IList filterErrors) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - - lock (Lock) - { - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - MonitoredItemModifyRequest itemToModify = itemsToModify[ii]; - - // skip items that have already been processed. - if (itemToModify.Processed) - { - continue; - } - - // modify the monitored item. - MonitoringFilterResult filterError = null; - - errors[ii] = ModifyMonitoredItem( - systemContext, - context.DiagnosticsMask, - timestampsToReturn, - monitoredItems[ii], - itemToModify, - out filterError); - - // save any filter error details. - filterErrors[ii] = filterError; - } - } - } - - /// - /// Modifies the parameters for a monitored item. - /// - protected virtual ServiceResult ModifyMonitoredItem( - ISystemContext context, - DiagnosticsMasks diagnosticsMasks, - TimestampsToReturn timestampsToReturn, - IMonitoredItem monitoredItem, - MonitoredItemModifyRequest itemToModify, - out MonitoringFilterResult filterError) - { - filterError = null; - ServiceResult error = null; - - // check for valid handle. - MonitoredNode monitoredNode = monitoredItem.ManagerHandle as MonitoredNode; - - if (monitoredNode == null) - { - return ServiceResult.Good; - } - - if (IsHandleInNamespace(monitoredNode.Node) == null) - { - return ServiceResult.Good; - } - - // owned by this node manager. - itemToModify.Processed = true; - - // check for valid monitored item. - DataChangeMonitoredItem datachangeItem = monitoredItem as DataChangeMonitoredItem; - - // validate parameters. - MonitoringParameters parameters = itemToModify.RequestedParameters; - - // validate the data change filter. - DataChangeFilter filter = null; - Range range = null; - - if (!ExtensionObject.IsNull(parameters.Filter)) - { - error = ValidateDataChangeFilter( - context, - monitoredNode.Node, - datachangeItem.AttributeId, - parameters.Filter, - out filter, - out range); - - if (ServiceResult.IsBad(error)) - { - return error; - } - } - - double previousSamplingInterval = datachangeItem.SamplingInterval; - - // check if the variable needs to be sampled. - double samplingInterval = itemToModify.RequestedParameters.SamplingInterval; - - if (datachangeItem.AttributeId == Attributes.Value) - { - BaseVariableState variable = monitoredNode.Node as BaseVariableState; - - if (variable.MinimumSamplingInterval > 0) - { - samplingInterval = CalculateSamplingInterval(variable, samplingInterval); - } - } - - // modify the monitored item parameters. - error = datachangeItem.Modify( - diagnosticsMasks, - timestampsToReturn, - itemToModify.RequestedParameters.ClientHandle, - samplingInterval, - itemToModify.RequestedParameters.QueueSize, - itemToModify.RequestedParameters.DiscardOldest, - filter, - range); - - // do any post processing. - OnModifyMonitoredItem( - context, - itemToModify, - monitoredNode, - datachangeItem, - previousSamplingInterval); - - return ServiceResult.Good; - } - - /// - /// Does any processing after a monitored item is created. - /// - protected virtual void OnModifyMonitoredItem( - ISystemContext systemContext, - MonitoredItemModifyRequest itemToModify, - MonitoredNode monitoredNode, - DataChangeMonitoredItem monitoredItem, - double previousSamplingInterval) - { - // does nothing. - } - - /// - /// Deletes a set of monitored items. - /// - public virtual void DeleteMonitoredItems( - OperationContext context, - IList monitoredItems, - IList processedItems, - IList errors) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - - lock (Lock) - { - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - // skip items that have already been processed. - if (processedItems[ii]) - { - continue; - } - - // delete the monitored item. - bool processed = false; - - errors[ii] = DeleteMonitoredItem( - systemContext, - monitoredItems[ii], - out processed); - - // indicate whether it was processed or not. - processedItems[ii] = processed; - } - } - } - - /// - /// Deletes a monitored item. - /// - protected virtual ServiceResult DeleteMonitoredItem( - ISystemContext context, - IMonitoredItem monitoredItem, - out bool processed) - { - processed = false; - - // check for valid handle. - MonitoredNode monitoredNode = monitoredItem.ManagerHandle as MonitoredNode; - - if (monitoredNode == null) - { - return ServiceResult.Good; - } - - if (IsHandleInNamespace(monitoredNode.Node) == null) - { - return ServiceResult.Good; - } - - // owned by this node manager. - processed = true; - - // get the source. - NodeState source = monitoredNode.Node; - - // check for valid monitored item. - DataChangeMonitoredItem datachangeItem = monitoredItem as DataChangeMonitoredItem; - - // check if the variable needs to be sampled. - if (datachangeItem.AttributeId == Attributes.Value) - { - BaseVariableState variable = monitoredNode.Node as BaseVariableState; - - if (variable.MinimumSamplingInterval > 0) - { - DeleteSampledItem(datachangeItem); - } - } - - // remove item. - monitoredNode.DeleteItem(datachangeItem); - - // do any post processing. - OnDeleteMonitoredItem(context, monitoredNode, datachangeItem); - - return ServiceResult.Good; - } - - /// - /// Does any processing after a monitored item is deleted. - /// - protected virtual void OnDeleteMonitoredItem( - ISystemContext systemContext, - MonitoredNode monitoredNode, - DataChangeMonitoredItem monitoredItem) - { - // does nothing. - } - - /// - /// Changes the monitoring mode for a set of monitored items. - /// - public virtual void SetMonitoringMode( - OperationContext context, - MonitoringMode monitoringMode, - IList monitoredItems, - IList processedItems, - IList errors) - { - ServerSystemContext systemContext = m_systemContext.Copy(context); - - lock (Lock) - { - for (int ii = 0; ii < monitoredItems.Count; ii++) - { - // skip items that have already been processed. - if (processedItems[ii]) - { - continue; - } - - // update monitoring mode. - bool processed = false; - - errors[ii] = SetMonitoringMode( - systemContext, - monitoredItems[ii], - monitoringMode, - out processed); - - // indicate whether it was processed or not. - processedItems[ii] = processed; - } - } - } - - /// - /// Changes the monitoring mode for an item. - /// - protected virtual ServiceResult SetMonitoringMode( - ISystemContext context, - IMonitoredItem monitoredItem, - MonitoringMode monitoringMode, - out bool processed) - { - processed = false; - - // check for valid handle. - MonitoredNode monitoredNode = monitoredItem.ManagerHandle as MonitoredNode; - - if (monitoredNode == null) - { - return ServiceResult.Good; - } - - if (IsHandleInNamespace(monitoredNode.Node) == null) - { - return ServiceResult.Good; - } - - // owned by this node manager. - processed = true; - - // check for valid monitored item. - DataChangeMonitoredItem datachangeItem = monitoredItem as DataChangeMonitoredItem; - - // update monitoring mode. - MonitoringMode previousMode = datachangeItem.SetMonitoringMode(monitoringMode); - - // need to provide an immediate update after enabling. - if (previousMode == MonitoringMode.Disabled && monitoringMode != MonitoringMode.Disabled) - { - DataValue initialValue = new DataValue(); - - initialValue.Value = null; - initialValue.ServerTimestamp = DateTime.UtcNow; - initialValue.SourceTimestamp = DateTime.MinValue; - initialValue.StatusCode = StatusCodes.Good; - - ServiceResult error = monitoredNode.Node.ReadAttribute( - context, - datachangeItem.AttributeId, - datachangeItem.IndexRange, - datachangeItem.DataEncoding, - initialValue); - - datachangeItem.QueueValue(initialValue, error); - } - - // do any post processing. - OnSetMonitoringMode(context, monitoredNode, datachangeItem, previousMode, monitoringMode); - - return ServiceResult.Good; - } - - /// - /// Does any processing after a monitored item is created. - /// - protected virtual void OnSetMonitoringMode( - ISystemContext systemContext, - MonitoredNode monitoredNode, - DataChangeMonitoredItem monitoredItem, - MonitoringMode previousMode, - MonitoringMode currentMode) - { - // does nothing. - } - - public void TransferMonitoredItems(OperationContext context, bool sendInitialValues, IList monitoredItems, IList processedItems, IList errors) - { - throw new NotImplementedException(); - } - #endregion - - #region Private Fields - private object m_lock = new object(); - private IServerInternal m_server; - private ServerSystemContext m_systemContext; - private IList m_namespaceUris; - private ushort[] m_namespaceIndexes; - private NodeIdDictionary m_predefinedNodes; - private List m_rootNotifiers; - - private Timer m_samplingTimer; - private List m_sampledItems; - private double m_minimumSamplingInterval; - #endregion - } -} diff --git a/src/AasxServerStandardBib/SampleServer.SampleModel.cs b/src/AasxServerStandardBib/SampleServer.SampleModel.cs deleted file mode 100644 index 6f362753e..000000000 --- a/src/AasxServerStandardBib/SampleServer.SampleModel.cs +++ /dev/null @@ -1,36 +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/ - * ======================================================================*/ - - -namespace AasOpcUaServer -{ - public partial class SampleServer - { - } -} diff --git a/src/AasxServerStandardBib/SampleServer.UserAuthentication.cs b/src/AasxServerStandardBib/SampleServer.UserAuthentication.cs deleted file mode 100644 index 560a183b3..000000000 --- a/src/AasxServerStandardBib/SampleServer.UserAuthentication.cs +++ /dev/null @@ -1,179 +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.Security.Cryptography.X509Certificates; -using Opc.Ua; -using Opc.Ua.Server; -using System.IdentityModel.Selectors; - -namespace AasOpcUaServer -{ - public partial class SampleServer - { - #region User Validation Functions - /// - /// Creates the objects used to validate the user identity tokens supported by the server. - /// - private void CreateUserIdentityValidators(ApplicationConfiguration configuration) - { - for (int ii = 0; ii < configuration.ServerConfiguration.UserTokenPolicies.Count; ii++) - { - UserTokenPolicy policy = configuration.ServerConfiguration.UserTokenPolicies[ii]; - - // create a validator for a certificate token policy. - if (policy.TokenType == UserTokenType.Certificate) - { - // check if user certificate trust lists are specified in configuration. - if (configuration.SecurityConfiguration.TrustedUserCertificates != null && - configuration.SecurityConfiguration.UserIssuerCertificates != null) - { - CertificateValidator certificateValidator = new CertificateValidator(); - certificateValidator.Update(configuration.SecurityConfiguration).Wait(); - certificateValidator.Update(configuration.SecurityConfiguration.UserIssuerCertificates, - configuration.SecurityConfiguration.TrustedUserCertificates, - configuration.SecurityConfiguration.RejectedCertificateStore); - - // set custom validator for user certificates. - m_certificateValidator = (X509CertificateValidator)certificateValidator.GetChannelValidator(); - } - } - } - } - - /// - /// Called when a client tries to change its user identity. - /// - private void SessionManager_ImpersonateUser(Session session, ImpersonateEventArgs args) - { - // check for a WSS token. - IssuedIdentityToken wssToken = args.NewIdentity as IssuedIdentityToken; - - // check for a user name token. - UserNameIdentityToken userNameToken = args.NewIdentity as UserNameIdentityToken; - - if (userNameToken != null) - { - VerifyPassword(userNameToken.UserName, userNameToken.DecryptedPassword); - args.Identity = new UserIdentity(userNameToken); - Utils.Trace("UserName Token Accepted: {0}", args.Identity.DisplayName); - return; - } - - // check for x509 user token. - X509IdentityToken x509Token = args.NewIdentity as X509IdentityToken; - - if (x509Token != null) - { - VerifyCertificate(x509Token.Certificate); - args.Identity = new UserIdentity(x509Token); - Utils.Trace("X509 Token Accepted: {0}", args.Identity.DisplayName); - return; - } - } - - /// - /// Validates the password for a username token. - /// - private void VerifyPassword(string userName, string password) - { - if (String.IsNullOrEmpty(password)) - { - // construct translation object with default text. - TranslationInfo info = new TranslationInfo( - "InvalidPassword", - "en-US", - "Specified password is not valid for user '{0}'.", - userName); - - // create an exception with a vendor defined sub-code. - throw new ServiceResultException(new ServiceResult( - StatusCodes.BadIdentityTokenRejected, - "InvalidPassword", - "http://opcfoundation.org/UA/Sample/", - new LocalizedText(info))); - } - } - - /// - /// Verifies that a certificate user token is trusted. - /// - private void VerifyCertificate(X509Certificate2 certificate) - { - try - { - if (m_certificateValidator != null) - { - m_certificateValidator.Validate(certificate); - } - else - { - CertificateValidator.Validate(certificate); - } - } - catch (Exception e) - { - TranslationInfo info; - StatusCode result = StatusCodes.BadIdentityTokenRejected; - ServiceResultException se = e as ServiceResultException; - if (se != null && se.StatusCode == StatusCodes.BadCertificateUseNotAllowed) - { - info = new TranslationInfo( - "InvalidCertificate", - "en-US", - "'{0}' is an invalid user certificate.", - certificate.Subject); - - result = StatusCodes.BadIdentityTokenInvalid; - } - else - { - // construct translation object with default text. - info = new TranslationInfo( - "UntrustedCertificate", - "en-US", - "'{0}' is not a trusted user certificate.", - certificate.Subject); - } - - // create an exception with a vendor defined sub-code. - throw new ServiceResultException(new ServiceResult( - result, - info.Key, - "http://opcfoundation.org/UA/Sample/", - new LocalizedText(info))); - } - } - #endregion - - #region Private Fields - private X509CertificateValidator m_certificateValidator; - #endregion - } -} diff --git a/src/AasxServerStandardBib/SampleServer.cs b/src/AasxServerStandardBib/SampleServer.cs deleted file mode 100644 index 8b1aa7df4..000000000 --- a/src/AasxServerStandardBib/SampleServer.cs +++ /dev/null @@ -1,209 +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/ - * ======================================================================*/ - -#define CUSTOM_NODE_MANAGER - -using System.Collections.Generic; -using System.Diagnostics; -using AdminShellNS; -using Opc.Ua; -using Opc.Ua.Server; - -namespace AasOpcUaServer -{ - /// - /// A class which implements an instance of a UA server. - /// - public partial class SampleServer : StandardServer - { - private AdminShellPackageEnv[] thePackageEnv = null; - private AasxUaServerOptions theServerOptions = null; - - public SampleServer() - : base() - { - } - - public SampleServer(AdminShellPackageEnv[] env, AasxUaServerOptions serverOptions = null) - : base() - { - thePackageEnv = env; - theServerOptions = serverOptions; - } - - #region Overridden Methods - /// - /// Initializes the server before it starts up. - /// - /// - /// This method is called before any startup processing occurs. The sub-class may update the - /// configuration object or do any other application specific startup tasks. - /// - protected override void OnServerStarting(ApplicationConfiguration configuration) - { - Utils.Trace("The server is starting."); - - base.OnServerStarting(configuration); - - // it is up to the application to decide how to validate user identity tokens. - // this function creates validator for X509 identity tokens. - CreateUserIdentityValidators(configuration); - } - - /// - /// Called after the server has been started. - /// - protected override void OnServerStarted(IServerInternal server) - { - base.OnServerStarted(server); - - // request notifications when the user identity is changed. all valid users are accepted by default. - server.SessionManager.ImpersonateUser += new ImpersonateEventHandler(SessionManager_ImpersonateUser); - - } - - /// - /// Cleans up before the server shuts down. - /// - /// - /// This method is called before any shutdown processing occurs. - /// - protected override void OnServerStopping() - { - Debug.WriteLine("The Server is stopping."); - - base.OnServerStopping(); - -#if INCLUDE_Sample - CleanSampleModel(); -#endif - } - -#if CUSTOM_NODE_MANAGER - /// - /// 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. - /// - /// Applications with small address spaces do not need to create their own NodeManagers and can add any - /// application specific nodes to the CoreNodeManager. Applications should use custom NodeManagers when - /// the structure of the address space is stored in another system or when the address space is too large - /// to keep in memory. - /// - protected override MasterNodeManager CreateMasterNodeManager(IServerInternal server, ApplicationConfiguration configuration) - { - Debug.WriteLine("Creating the Node Managers."); - - List nodeManagers = new List(); - - // create the custom node managers. - // TODO (MIHO, 2021-01-01): re-implement multi environment UA server again! - var aasnm = new global::AasOpcUaServer.AasModeManager(server, configuration, thePackageEnv, theServerOptions); - nodeManagers.Add(aasnm); - - // create master node manager. - var x = new MasterNodeManager(server, configuration, null, nodeManagers.ToArray()); - - // try to do some fixes - if (x.NodeManagers.Count > 0) - { - var cm = x.NodeManagers[0] as CustomNodeManager2; - } - - // ok - return x; - } -#endif - - /// - /// 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 SDK Samples"; - properties.ProductUri = "http://opcfoundation.org/UA/Samples/v1.0"; - properties.SoftwareVersion = Utils.GetAssemblySoftwareVersion(); - properties.BuildNumber = Utils.GetAssemblyBuildNumber(); - properties.BuildDate = Utils.GetAssemblyTimestamp(); - - - - - return properties; - } - - /// - /// Initializes the address space after the NodeManagers have started. - /// - /// - /// This method can be used to create any initialization that requires access to node managers. - /// - protected override void OnNodeManagerStarted(IServerInternal server) - { - Debug.WriteLine("The NodeManagers have started."); - - // allow base class processing to happen first. - base.OnNodeManagerStarted(server); - - // adds the sample information models to the core node manager. -#if INCLUDE_Sample - InitializeSampleModel(); -#endif - } - -#if USER_AUTHENTICATION - /// - /// Creates the resource manager for the server. - /// - protected override ResourceManager CreateResourceManager(IServerInternal server, ApplicationConfiguration configuration) - { - ResourceManager resourceManager = new ResourceManager(server, configuration); - - // add some localized strings to the resource manager to demonstrate that localization occurs. - resourceManager.Add("InvalidPassword", "de-DE", "Das Passwort ist nicht gültig für Konto '{0}'."); - resourceManager.Add("InvalidPassword", "es-ES", "La contraseña no es válida para la cuenta de '{0}'."); - - resourceManager.Add("UnexpectedUserTokenError", "fr-FR", "Une erreur inattendue s'est produite lors de la validation utilisateur."); - resourceManager.Add("UnexpectedUserTokenError", "de-DE", "Ein unerwarteter Fehler ist aufgetreten während des Anwenders."); - - return resourceManager; - } -#endif - #endregion - } -} diff --git a/src/AasxServerStandardBib/Services/MetamodelVerificationService.cs b/src/AasxServerStandardBib/Services/MetamodelVerificationService.cs index 3f1976125..2b8cfead0 100644 --- a/src/AasxServerStandardBib/Services/MetamodelVerificationService.cs +++ b/src/AasxServerStandardBib/Services/MetamodelVerificationService.cs @@ -33,7 +33,7 @@ public MetamodelVerificationService(IAppLogger log } public void VerifyRequestBody(IClass body) { - if (_configuration.GetValue("IsMetamodelVerificationStrict")) + /*if (_configuration.GetValue("IsMetamodelVerificationStrict")) { var errorList = Verification.Verify(body).ToList(); if (errorList.Any()) @@ -46,7 +46,7 @@ public void VerifyRequestBody(IClass body) else { _logger.LogDebug("Metamodel verification is not strict. Therefore, skipping the verification."); - } + }*/ } } } diff --git a/src/AasxServerStandardBib/TimeSeries.cs b/src/AasxServerStandardBib/TimeSeries.cs index 1af3b23d8..9aa301074 100644 --- a/src/AasxServerStandardBib/TimeSeries.cs +++ b/src/AasxServerStandardBib/TimeSeries.cs @@ -13,7 +13,6 @@ using AasxServer; using Extensions; -using Opc.Ua; using Org.Webpki.JsonCanonicalizer; using SampleClient; using System; @@ -500,7 +499,7 @@ private static void OnOPCClientNextTimedEvent(long ms) opcClientCount += ms; if (opcClientCount >= opcClientRate) { - AasxServer.Program.OnOPCClientNextTimedEvent(); + //AasxServer.Program.OnOPCClientNextTimedEvent(); opcClientCount = 0; } } @@ -1417,8 +1416,8 @@ static bool parseJSON(string url, string username, string password, SubmodelElem static List> table = null; static string ErrorMessage { get; set; } - static UASampleClient opc = null; - static Opc.Ua.Client.Session session = null; + //static UASampleClient opc = null; + //static Opc.Ua.Client.Session session = null; static DateTime startTime; static DateTime endTime; static List opcDAValues = null; @@ -1512,7 +1511,7 @@ public static int GetDAData(TimeSeriesBlock tsb) Console.WriteLine("Read OPC DA Data:"); try { - ErrorMessage = ""; + /*ErrorMessage = ""; if (session == null) Connect(tsb); if (session != null) @@ -1521,10 +1520,10 @@ public static int GetDAData(TimeSeriesBlock tsb) for (int i = 0; i < tsb.opcNodes.Count; i++) { string[] split = tsb.opcNodes[i].Split(','); - string value = opc.ReadSubmodelElementValue(split[1], (ushort)Convert.ToInt32(split[0])); - opcDAValues.Add(value); + //string value = opc.ReadSubmodelElementValue(split[1], (ushort)Convert.ToInt32(split[0])); + //opcDAValues.Add(value); } - } + }*/ } catch (Exception ex) { @@ -1542,7 +1541,7 @@ public static int GetDAData(TimeSeriesBlock tsb) public static void GetHistory(TimeSeriesBlock tsb) { - Console.WriteLine("Read OPC UA Historical Data:"); + /*Console.WriteLine("Read OPC UA Historical Data:"); try { ErrorMessage = ""; @@ -1551,7 +1550,7 @@ public static void GetHistory(TimeSeriesBlock tsb) startTime = tsb.opcLastTimeStamp; // get current time on server if (session != null) - endTime = (DateTime)session.ReadValue(new NodeId(2258, 0)).Value; + //endTime = (DateTime)session.ReadValue(new NodeId(2258, 0)).Value; GetData(tsb); } catch (Exception ex) @@ -1561,8 +1560,8 @@ public static void GetHistory(TimeSeriesBlock tsb) session?.Close(); session?.Dispose(); session = null; - opc = null; - } + //opc = null; + }*/ /* session?.Close(); session?.Dispose(); @@ -1573,11 +1572,11 @@ public static void GetHistory(TimeSeriesBlock tsb) public static void Connect(TimeSeriesBlock tsb) { Console.WriteLine("Connect OPC UA"); - if (opc == null) + /*if (opc == null) opc = new UASampleClient(tsb.sourceAddress, true, 10000, tsb.username, tsb.password); opc.ConsoleSampleClient().Wait(); - session = opc.session; - if (session == null) + session = opc.session;*/ + /*if (session == null) { Console.WriteLine("ERROR: Session not connected " + tsb.sourceAddress + " " + tsb.username + " " + tsb.password); @@ -1585,14 +1584,14 @@ public static void Connect(TimeSeriesBlock tsb) else { // get current time on server - tsb.opcLastTimeStamp = (DateTime)session.ReadValue(new NodeId(2258, 0)).Value; + //tsb.opcLastTimeStamp = (DateTime)session.ReadValue(new NodeId(2258, 0)).Value; tsb.opcLastTimeStamp -= TimeSpan.FromMinutes(1); - } + }*/ } public static void GetData(TimeSeriesBlock tsb) { - if (session != null) + /*if (session != null) { ReadRawModifiedDetails details = new ReadRawModifiedDetails(); details.StartTime = startTime; @@ -1690,7 +1689,7 @@ public static void GetData(TimeSeriesBlock tsb) nodesToRead[i].ContinuationPoint = results[i].ContinuationPoint; } } - } + }*/ } } } \ No newline at end of file diff --git a/src/AasxServerStandardBib/UASampleClient.cs b/src/AasxServerStandardBib/UASampleClient.cs deleted file mode 100644 index 1eeeb7496..000000000 --- a/src/AasxServerStandardBib/UASampleClient.cs +++ /dev/null @@ -1,230 +0,0 @@ -/* Copyright (c) 1996-2016, OPC Foundation. All rights reserved. - The source code in this file is covered under a dual-license scenario: - - RCL: for OPC Foundation members in good-standing - - GPL V2: everybody else - RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/ - GNU General Public License as published by the Free Software Foundation; - version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2 - This source code is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -*/ -using System; -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using AdminShellNS; -using Opc.Ua; -using Opc.Ua.Client; -using Opc.Ua.Configuration; - -namespace SampleClient -{ - public class UASampleClient - { - const int ReconnectPeriod = 10; - public Session session; - SessionReconnectHandler reconnectHandler; - string endpointURL; - int clientRunTime = Timeout.Infinite; - static bool autoAccept = true; - static ExitCode exitCode; - string userName; - string password; - - public UASampleClient(string _endpointURL, bool _autoAccept, int _stopTimeout, string _userName, string _password) - { - endpointURL = _endpointURL; - autoAccept = _autoAccept; - clientRunTime = _stopTimeout <= 0 ? Timeout.Infinite : _stopTimeout * 1000; - userName = _userName; - password = _password; - } - - public void Run() - { - try - { - ConsoleSampleClient().Wait(); - } - catch (Exception ex) - { - Utils.Trace("ServiceResultException:" + ex.Message); - Console.WriteLine("Exception: {0}", ex.Message); - Console.WriteLine("press any key to continue"); - return; - } - - ManualResetEvent quitEvent = new ManualResetEvent(false); - try - { - Console.CancelKeyPress += (sender, eArgs) => - { - quitEvent.Set(); - eArgs.Cancel = true; - }; - } - catch - { - } - - // wait for timeout or Ctrl-C - quitEvent.WaitOne(clientRunTime); - - // return error conditions - if (session.KeepAliveStopped) - { - exitCode = ExitCode.ErrorNoKeepAlive; - return; - } - - exitCode = ExitCode.Ok; - } - - public static ExitCode ExitCode { get => exitCode; } - - public async Task ConsoleSampleClient() - { - exitCode = ExitCode.ErrorCreateApplication; - - ApplicationInstance application = new ApplicationInstance - { - ApplicationName = "UA Core Sample Client", - ApplicationType = ApplicationType.Client, - ConfigSectionName = Utils.IsRunningOnMono() ? "Opc.Ua.MonoSampleClient" : "Opc.Ua.SampleClient" - }; - - // load the application configuration. - ApplicationConfiguration config = await application.LoadApplicationConfiguration(false); - - // check the application certificate. - bool haveAppCertificate = await application.CheckApplicationInstanceCertificate(false, 0); - if (!haveAppCertificate) - { - throw new Exception("Application instance certificate invalid!"); - } - - if (haveAppCertificate) - { - config.ApplicationUri = X509Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate); - if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) - { - autoAccept = true; - } - config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); - } - else - { - } - - exitCode = ExitCode.ErrorDiscoverEndpoints; - var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointURL, haveAppCertificate, 15000); - // Console.WriteLine(" Selected endpoint uses: {0}", - selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1); - - exitCode = ExitCode.ErrorCreateSession; - var endpointConfiguration = EndpointConfiguration.Create(config); - var endpoint = new ConfiguredEndpoint(null, selectedEndpoint, endpointConfiguration); - - if ((userName == "" || userName == null) && (password == "" || password == null)) - { - session = await Session.Create(config, endpoint, false, "OPC UA Console Client", 60000, new UserIdentity(new AnonymousIdentityToken()), null); - } - else - { - session = await Session.Create(config, endpoint, false, "OPC UA Console Client", 60000, new UserIdentity(userName, password), null); - } - - // register keep alive handler - session.KeepAlive += Client_KeepAlive; - } - - private void Client_KeepAlive(ISession sender, KeepAliveEventArgs e) - { - if (e.Status != null && ServiceResult.IsNotGood(e.Status)) - { - Console.WriteLine("{0} {1}/{2}", e.Status, sender.OutstandingRequestCount, sender.DefunctRequestCount); - - if (reconnectHandler == null) - { - Console.WriteLine("--- RECONNECTING ---"); - reconnectHandler = new SessionReconnectHandler(); - reconnectHandler.BeginReconnect(sender, ReconnectPeriod * 1000, Client_ReconnectComplete); - } - } - } - - private void Client_ReconnectComplete(object sender, EventArgs e) - { - // ignore callbacks from discarded objects. - if (!Object.ReferenceEquals(sender, reconnectHandler)) - { - return; - } - - session = (Session)reconnectHandler.Session; - reconnectHandler.Dispose(); - reconnectHandler = null; - - Console.WriteLine("--- RECONNECTED ---"); - } - - private static void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e) - { - foreach (var value in item.DequeueValues()) - { - Console.WriteLine("{0}: {1}, {2}, {3}", item.DisplayName, value.Value, value.SourceTimestamp, value.StatusCode); - } - } - - private static void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e) - { - if (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted) - { - e.Accept = autoAccept; - } - } - - public string ReadSubmodelElementValue(string nodeName, int index) - { - NodeId node = new NodeId(nodeName, (ushort)index); - return (session.ReadValue(node).ToString()); - } - - public string ReadSubmodelElementValue(NodeId nodeId) - { - return (session.ReadValue(nodeId).ToString(null, CultureInfo.InvariantCulture)); - } - - public void WriteSubmodelElementValue(NodeId nodeId, object value) - { - WriteValue nodeToWrite = new WriteValue(); - nodeToWrite.NodeId = nodeId; - nodeToWrite.AttributeId = Attributes.Value; - nodeToWrite.Value = new DataValue(); - nodeToWrite.Value.WrappedValue = new Variant(value); - - WriteValueCollection nodesToWrite = new WriteValueCollection(); - nodesToWrite.Add(nodeToWrite); - - // read the attributes. - StatusCodeCollection results = null; - DiagnosticInfoCollection diagnosticInfos = null; - - ResponseHeader responseHeader = session.Write( - null, - nodesToWrite, - out results, - out diagnosticInfos); - - ClientBase.ValidateResponse(results, nodesToWrite); - ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToWrite); - - // check for error. - if (StatusCode.IsBad(results[0])) - { - throw ServiceResultException.Create(results[0], 0, diagnosticInfos, responseHeader.StringTable); - } - } - } -}