Esempio n. 1
0
        public SimpleNodeManager(IServerInternal server, ApplicationConfiguration configuration)
            : base(server, configuration)
        {
            SystemContext.NodeIdFactory = this;

            List <string> namespaces = new List <string>();

            foreach (string nodesetFile in BrowserController._nodeSetFilenames)
            {
                // workaround for bug https://github.com/dotnet/runtime/issues/67622
                File.WriteAllText(nodesetFile, File.ReadAllText(nodesetFile).Replace("<Value/>", "<Value xsi:nil='true' />"));

                using (Stream stream = new FileStream(nodesetFile, FileMode.Open))
                {
                    UANodeSet nodeSet = UANodeSet.Read(stream);
                    if ((nodeSet.NamespaceUris != null) && (nodeSet.NamespaceUris.Length > 0))
                    {
                        foreach (string ns in nodeSet.NamespaceUris)
                        {
                            if (!namespaces.Contains(ns))
                            {
                                namespaces.Add(ns);
                            }
                        }
                    }

                    DTDL.Generate(nodeSet);
                }
            }

            NamespaceUris = namespaces.ToArray();
        }
Esempio n. 2
0
        private void ImportNodeset2Xml(IDictionary <NodeId, IList <IReference> > externalReferences, string resourcepath, int pass)
        {
            // workaround for bug https://github.com/dotnet/runtime/issues/67622
            File.WriteAllText(resourcepath, File.ReadAllText(resourcepath).Replace("<Value/>", "<Value xsi:nil='true' />"));

            using (Stream stream = new FileStream(resourcepath, FileMode.Open))
            {
                UANodeSet nodeSet = UANodeSet.Read(stream);

                NodeStateCollection predefinedNodes = new NodeStateCollection();
                nodeSet.Import(SystemContext, predefinedNodes);
# if DEBUG
                DebugOutput(nodeSet, predefinedNodes);
#endif
                for (int i = 0; i < predefinedNodes.Count; i++)
                {
                    try
                    {
                        AddPredefinedNode(SystemContext, predefinedNodes[i]);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Pass " + pass.ToString() + ": Importing node ns=" + predefinedNodes[i].NodeId.NamespaceIndex + ";i=" + predefinedNodes[i].NodeId.Identifier + " (" + predefinedNodes[i].DisplayName + ") failed with error: " + ex.Message);
                    }
                }
            }
Esempio n. 3
0
        public virtual void Initialise(CustomNodeManager2 nodeManager)
        {
            ApplicationNodeManager = nodeManager;
            if (string.IsNullOrEmpty(ResourcePath))
            {
                return;
            }
            NamespaceUris = new List <string>();
            NodeStateCollection predefinedNodeStateCollection = new NodeStateCollection();
            Stream    stream    = new FileStream(ResourcePath, FileMode.Open);
            UANodeSet uaNodeSet = UANodeSet.Read(stream);

            NamespaceUris.AddRange(ApplicationNodeManager.NamespaceUris);
            // Update namespace table
            if (uaNodeSet.NamespaceUris != null)
            {
                foreach (string namespaceUri in uaNodeSet.NamespaceUris)
                {
                    NamespaceUris.Add(namespaceUri);
                    ApplicationNodeManager.SystemContext.NamespaceUris.GetIndexOrAppend(namespaceUri);
                }
            }
            // Update server table
            if (uaNodeSet.ServerUris != null)
            {
                foreach (string serverUri in uaNodeSet.ServerUris)
                {
                    ServerUris.Add(serverUri);
                    ApplicationNodeManager.SystemContext.ServerUris.GetIndexOrAppend(serverUri);
                }
            }
            uaNodeSet.Import(ApplicationNodeManager.SystemContext, predefinedNodeStateCollection);
            NodeStateCollection = predefinedNodeStateCollection;
        }
Esempio n. 4
0
 public UANodeConverter(string filename, NamespaceTable SessionNamespaceURIs)
 {
     using (Stream stream = new FileStream(filename, FileMode.Open)){
         m_UANodeset       = UANodeSet.Read(stream);
         m_aliases         = m_UANodeset.Aliases;
         m_namespaceURIs   = m_UANodeset.NamespaceUris;
         out_nodeset       = new List <Node>();
         session_namespace = SessionNamespaceURIs;
     }
 }
Esempio n. 5
0
        public static List <ImportOPCModel> OrderImportsByDependencies(List <ImportOPCModel> importRequest)
        {
            var importsAndModels = importRequest.Select(importRequest =>
            {
                using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(importRequest.Data.Replace("<Value/>", "<Value xsi:nil='true' />"))))
                {
                    var nodeSet        = UANodeSet.Read(ms);
                    var modelUri       = nodeSet.Models?[0].ModelUri;
                    var requiredModels = nodeSet.Models?.SelectMany(m => m.RequiredModel?.Select(rm => rm.ModelUri) ?? new List <string>())?.ToList();
                    return(importRequest, modelUri, requiredModels);
                }
            }).ToList();

            var orderedImports = new List <(ImportOPCModel, string, List <string>)>();
            var standalone     = importsAndModels.Where(imr => imr.requiredModels.Any() != true).ToList();

            orderedImports.AddRange(standalone);
            foreach (var imr in standalone)
            {
                importsAndModels.Remove(imr);
            }

            bool modelAdded;

            do
            {
                modelAdded = false;
                for (int i = importsAndModels.Count - 1; i >= 0; i--)
                {
                    var  imr = importsAndModels[i];
                    bool bDependenciesSatisfied = true;
                    foreach (var dependency in imr.requiredModels)
                    {
                        if (!orderedImports.Any(imr => imr.Item2 == dependency))
                        {
                            bDependenciesSatisfied = false;
                            continue;
                        }
                    }
                    if (bDependenciesSatisfied)
                    {
                        orderedImports.Add(imr);
                        importsAndModels.RemoveAt(i);
                        modelAdded = true;
                    }
                }
            } while (importsAndModels.Count > 0 && modelAdded);

            //Assert.True(modelAdded, $"{importsAndModels.Count} nodesets require models not in the list.");
            orderedImports.AddRange(importsAndModels);
            var orderedImportRequest = orderedImports.Select(irm => irm.Item1).ToList();

            return(orderedImportRequest);
        }
Esempio n. 6
0
        protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context)
        {
            var nodeStateCollection = new NodeStateCollection();

            using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ConverterSystems.Test.PredefinedNodes.xml"))
            {
                var nodeset = UANodeSet.Read(stream);
                nodeset.Import(context, nodeStateCollection);
            }
            return(nodeStateCollection);
        }
Esempio n. 7
0
        public UANodeConverter(JObject config, NamespaceTable SessionNamespaceURIs)
        {
            _config = config.ToObject <nodesConfigWrapper>().nodesLoader;

            using (Stream stream = new FileStream(_config.filename, FileMode.Open)){
                m_UANodeset       = UANodeSet.Read(stream);
                m_aliases         = m_UANodeset.Aliases;
                m_namespaceURIs   = m_UANodeset.NamespaceUris;
                out_nodeset       = new List <Node>();
                session_namespace = SessionNamespaceURIs;
            }

            selector = new NodesSelector(_config);
        }
Esempio n. 8
0
        private void ImportNodeset2Xml(IDictionary <NodeId, IList <IReference> > externalReferences, string resourcepath)
        {
            using (Stream stream = new FileStream(resourcepath, FileMode.Open))
            {
                UANodeSet nodeSet = UANodeSet.Read(stream);

                NodeStateCollection predefinedNodes = new NodeStateCollection();
                nodeSet.Import(SystemContext, predefinedNodes);

                for (int i = 0; i < predefinedNodes.Count; i++)
                {
                    AddPredefinedNode(SystemContext, predefinedNodes[i]);
                }
            }
        }
Esempio n. 9
0
        private static (NamespaceTable, Dictionary <string, string>) LoadNamespaces(string file)
        {
            var namespaces = new NamespaceTable(new[] { "http://opcfoundation.org/UA/" });

            using (var nodeSetStream = File.OpenRead(file))
            {
                UANodeSet nodeSet = UANodeSet.Read(nodeSetStream);
                var       aliases = nodeSet.Aliases?.ToDictionary(a => a.Alias, a => a.Value) ?? new Dictionary <string, string>();
                foreach (var ns in nodeSet.NamespaceUris)
                {
                    namespaces.GetIndexOrAppend(ns);
                }
                return(namespaces, aliases);
            }
        }
Esempio n. 10
0
        public StationNodeManager(IServerInternal server, ApplicationConfiguration configuration)
            : base(server, configuration)
        {
            SystemContext.NodeIdFactory = this;

            using (Stream stream = new FileStream("Station.NodeSet2.xml", FileMode.Open))
            {
                UANodeSet nodeSet = UANodeSet.Read(stream);
                NamespaceUris = nodeSet.NamespaceUris;
            }

            m_namespaceIndex = (ushort)(Server.NamespaceUris.Count - 1);
            m_lastUsedId     = 0;

            m_stationClock = new Timer(Tick, this, Timeout.Infinite, (int)m_actualCycleTime);
        }
Esempio n. 11
0
        public bool GetNodeSet(UANodeSetImportResult results, ModelNameAndVersion nameVersion, object AuthorID)
        {
            var authorToken          = AuthorID as UserToken;
            NodeSetFileModel myModel = GetProfileModel(nameVersion, authorToken);

            if (myModel != null)
            {
                // workaround for bug https://github.com/dotnet/runtime/issues/67622
                var fileCachepatched = myModel.FileCache.Replace("<Value/>", "<Value xsi:nil='true' />");
                using (var nodeSetStream = new System.IO.MemoryStream(Encoding.UTF8.GetBytes(fileCachepatched)))
                {
                    //nodeSetStream.Write(Encoding.UTF8.GetBytes(myModel.FileCache));
                    //nodeSetStream.Position = 0;
                    UANodeSet nodeSet = UANodeSet.Read(nodeSetStream);
                    foreach (var ns in nodeSet.Models)
                    {
                        results.AddModelAndDependencies(nodeSet, ns, null, false);
                        foreach (var model in results.Models)
                        {
                            if (model.NameVersion.CCacheId == null)
                            {
                                if (model.NameVersion.ModelUri == nameVersion.ModelUri && model.NameVersion.PublicationDate == nameVersion.PublicationDate)
                                {
                                    model.NameVersion.CCacheId = myModel;
                                }
                                else
                                {
                                    GetProfileModel(model.NameVersion, authorToken);
                                }
                            }
                        }
                    }
                }
                return(true);
            }
            return(false);
        }
Esempio n. 12
0
        public bool AddNodeSet(UANodeSetImportResult results, string nodeSetXml, object authorId)
        {
            bool WasNewSet = false;

            #region Comment Processing
            var doc      = XElement.Load(new StringReader(nodeSetXml));
            var comments = doc.DescendantNodes().OfType <XComment>();
            foreach (XComment comment in comments)
            {
                //inline XML Commments are not showing here...only real XML comments (not file comments with /**/)
                //Unfortunately all OPC UA License Comments are not using XML Comments but file-comments and therefore cannot be "preserved"
            }
            #endregion

            UANodeSet nodeSet;
            // workaround for bug https://github.com/dotnet/runtime/issues/67622
            var nodeSetXmlPatched = nodeSetXml.Replace("<Value/>", "<Value xsi:nil='true' />");
            using (var nodesetBytes = new MemoryStream(Encoding.UTF8.GetBytes(nodeSetXmlPatched)))
            {
                nodeSet = UANodeSet.Read(nodesetBytes);
            }

            if (nodeSet.Models?.Any() != true)
            {
                nodeSet.Models = new ModelTableEntry[] {
                    new ModelTableEntry {
                        ModelUri      = nodeSet.NamespaceUris?.FirstOrDefault(),
                        RequiredModel = new ModelTableEntry[] { new ModelTableEntry {
                                                                    ModelUri = "http://opcfoundation.org/UA/"
                                                                } },
                    }
                };
            }

            UANodeSet tOldNodeSet = null;
            foreach (var ns in nodeSet.Models)
            {
                UserToken userToken       = authorId as UserToken;
                var       authorToken     = userToken;
                bool      isGlobalNodeSet = CESMII.ProfileDesigner.OpcUa.OpcUaImporter._coreNodeSetUris.Contains(ns.ModelUri);
                if (isGlobalNodeSet)
                {
                    userToken   = UserToken.GetGlobalUser(userToken); // Write as a global node set shared acess user
                    authorToken = null;
                }
                NodeSetFileModel myModel = GetProfileModel(
                    new ModelNameAndVersion
                {
                    ModelUri        = ns.ModelUri,
                    ModelVersion    = ns.Version,
                    PublicationDate = ns.PublicationDate,
                },
                    userToken);
                if (myModel == null)
                {
                    myModel = results.Models.FirstOrDefault(m => m.NameVersion.IsNewerOrSame(new ModelNameAndVersion
                    {
                        ModelUri        = ns.ModelUri,
                        ModelVersion    = ns.Version,
                        PublicationDate = ns.PublicationDate,
                    }
                                                                                             ))?.NameVersion?.CCacheId as NodeSetFileModel;
                }
                bool CacheNewerVersion = true;
                if (myModel != null)
                {
                    CacheNewerVersion = false;
                    // workaround for bug https://github.com/dotnet/runtime/issues/67622
                    var fileCachepatched = myModel.FileCache.Replace("<Value/>", "<Value xsi:nil='true' />");
                    using (var nodeSetStream = new MemoryStream(Encoding.UTF8.GetBytes(fileCachepatched)))
                    {
                        if (tOldNodeSet == null)
                        {
                            tOldNodeSet = UANodeSet.Read(nodeSetStream);
                        }
                        var tns = tOldNodeSet.Models.Where(s => s.ModelUri == ns.ModelUri).OrderByDescending(s => s.PublicationDate).FirstOrDefault();
                        if (tns == null || ns.PublicationDate > tns.PublicationDate)
                        {
                            CacheNewerVersion = true; //Cache the new NodeSet if the old (file) did not contain the model or if the version of the new model is greater
                        }
                    }
                }
                int? cacheId     = myModel != null ? myModel.ID : 0;
                bool newInImport = false;
                if (CacheNewerVersion) //Cache only newer version
                {
                    if (myModel == null)
                    {
                        myModel = new NodeSetFileModel
                        {
                            ID              = cacheId,
                            FileName        = ns.ModelUri,
                            Version         = ns.Version,
                            PublicationDate = ns.PublicationDate,
                            // TODO clean up the dependency
                            AuthorId  = authorToken?.UserId,
                            FileCache = nodeSetXml
                        };
                        // Defer Upsert until later to make it part of a transaction
                        // _dalNodeSetFile.Upsert(myModel, userToken, false);
                        newInImport = true;
                    }
                    // Defer the updates to the import transaction
                    //var resIns = _dalNodeSetFile.Upsert(nsModel, (AuthorID == null) ? 0 : (int)AuthorID, true).GetAwaiter().GetResult();

                    //cacheId = resIns.Item1;
                    //newInImport = resIns.Item2;
                    WasNewSet = true;
                }
                var tModel = results.AddModelAndDependencies(nodeSet, ns, null, WasNewSet);
                if (tModel?.NameVersion != null && myModel != null)
                {
                    tModel.NameVersion.CCacheId = myModel;
                    tModel.NewInThisImport      = newInImport;
                }
                foreach (var model in results.Models)
                {
                    if (model.NameVersion.CCacheId == null)
                    {
                        GetProfileModel(model.NameVersion, userToken);
                    }
                }
            }
            return(WasNewSet);
        }
        private string ValidateNamespacesAndModels(bool autodownloadreferences)
        {
            // Collect all models as well as all required/referenced model namespace URIs listed in each file
            List <string> models          = new List <string>();
            List <string> modelreferences = new List <string>();

            foreach (string nodesetFile in _nodeSetFilenames)
            {
                // workaround for bug https://github.com/dotnet/runtime/issues/67622
                System.IO.File.WriteAllText(nodesetFile, System.IO.File.ReadAllText(nodesetFile).Replace("<Value/>", "<Value xsi:nil='true' />"));

                using (Stream stream = new FileStream(nodesetFile, FileMode.Open))
                {
                    UANodeSet nodeSet = UANodeSet.Read(stream);

                    // validate namespace URIs
                    if ((nodeSet.NamespaceUris != null) && (nodeSet.NamespaceUris.Length > 0))
                    {
                        foreach (string ns in nodeSet.NamespaceUris)
                        {
                            if (string.IsNullOrEmpty(ns) || !Uri.IsWellFormedUriString(ns, UriKind.Absolute))
                            {
                                return("Nodeset file " + nodesetFile + " contains an invalid Namespace URI: \"" + ns + "\"");
                            }
                        }
                    }
                    else
                    {
                        return("'NamespaceUris' entry missing in " + nodesetFile + ". Please add it!");
                    }

                    // validate model URIs
                    if ((nodeSet.Models != null) && (nodeSet.Models.Length > 0))
                    {
                        foreach (ModelTableEntry model in nodeSet.Models)
                        {
                            if (model != null)
                            {
                                if (Uri.IsWellFormedUriString(model.ModelUri, UriKind.Absolute))
                                {
                                    // ignore the default namespace which is always present and don't add duplicates
                                    if ((model.ModelUri != "http://opcfoundation.org/UA/") && !models.Contains(model.ModelUri))
                                    {
                                        models.Add(model.ModelUri);
                                    }
                                }
                                else
                                {
                                    return("Nodeset file " + nodesetFile + " contains an invalid Model Namespace URI: \"" + model.ModelUri + "\"");
                                }

                                if ((model.RequiredModel != null) && (model.RequiredModel.Length > 0))
                                {
                                    foreach (ModelTableEntry requiredModel in model.RequiredModel)
                                    {
                                        if (requiredModel != null)
                                        {
                                            if (Uri.IsWellFormedUriString(requiredModel.ModelUri, UriKind.Absolute))
                                            {
                                                // ignore the default namespace which is always required and don't add duplicates
                                                if ((requiredModel.ModelUri != "http://opcfoundation.org/UA/") && !modelreferences.Contains(requiredModel.ModelUri))
                                                {
                                                    modelreferences.Add(requiredModel.ModelUri);
                                                }
                                            }
                                            else
                                            {
                                                return("Nodeset file " + nodesetFile + " contains an invalid referenced Model Namespace URI: \"" + requiredModel.ModelUri + "\"");
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        return("'Model' entry missing in " + nodesetFile + ". Please add it!");
                    }
                }
            }

            // now check if we have all references for each model we want to load
            foreach (string modelreference in modelreferences)
            {
                if (!models.Contains(modelreference))
                {
                    if (!autodownloadreferences)
                    {
                        return("Referenced OPC UA model " + modelreference + " is missing from selected list of nodeset files, please add the corresponding nodeset file to the list of loaded files!");
                    }
                    else
                    {
                        try
                        {
                            // try to auto-download the missing references from the UA Cloud Library
                            string address = _client.BaseAddress + "infomodel/download/" + Uri.EscapeDataString(_namespacesInCloudLibrary[modelreference]);
                            HttpResponseMessage response     = _client.Send(new HttpRequestMessage(HttpMethod.Get, address));
                            AddressSpace        addressSpace = JsonConvert.DeserializeObject <AddressSpace>(response.Content.ReadAsStringAsync().GetAwaiter().GetResult());

                            // store the file on the webserver
                            string filePath = Path.Combine(Directory.GetCurrentDirectory(), "NodeSets", addressSpace.Category.Name + ".nodeset2.xml");
                            System.IO.File.WriteAllText(filePath, addressSpace.Nodeset.NodesetXml);
                            _nodeSetFilenames.Add(filePath);
                        }
                        catch (Exception ex)
                        {
                            return("Could not download referenced nodeset " + modelreference + ": " + ex.Message);
                        }
                    }
                }
            }

            return(string.Empty); // no error
        }
Esempio n. 14
0
        public bool ExportInternal(CESMII.ProfileDesigner.DAL.Models.ProfileModel profileModel, ProfileTypeDefinitionModel profileItem, Stream xmlNodeSet, UserToken userToken, UserToken authorId)
        {
            if (profileItem?.ProfileId != null)
            {
                profileModel = _nsDal.GetById(profileItem.ProfileId.Value, userToken);
                //if (!(profileModel.AuthorId == null || profileModel.AuthorId == userId))
                //{
                //    throw new Exception($"User does not have access to profile on profileItem {profileItem}");
                //}
            }
            //var uriToExport = nodeSetModel?.Namespace ?? profileItem.Namespace;
            var dalContext = new DALContext(this, userToken, authorId, false);

            _lastDalContext = dalContext;
            if (!NodesetModels.ContainsKey(strOpcNamespaceUri))
            {
                try
                {
                    // TODO find the right OPC version references in the nodeSet?
                    var opcNodeSetModel = _nsDal.Where(ns => ns.Namespace == strOpcNamespaceUri /*&& (ns.AuthorId == null || ns.AuthorId == userId)*/, userToken, null, null, false, true).Data.OrderByDescending(m => m.PublishDate).FirstOrDefault();
                    // workaround for bug https://github.com/dotnet/runtime/issues/67622
                    var fileCachePatched = opcNodeSetModel.NodeSetFiles[0].FileCache.Replace("<Value/>", "<Value xsi:nil='true' />");
                    using (MemoryStream nodeSetStream = new MemoryStream(Encoding.UTF8.GetBytes(fileCachePatched)))
                    //var nodeSetFilePath = Path.Combine(Path.GetDirectoryName(this.GetType().Assembly.Location), "Nodesets", "Opc.Ua.NodeSet2.xml");
                    //using (Stream nodeSetStream = new FileStream(nodeSetFilePath, FileMode.Open))
                    {
                        UANodeSet nodeSet = UANodeSet.Read(nodeSetStream);
                        _importedNodesByNodeId = null;
                        // Get aliases from base UA model
                        // TODO remove unused aliases later
                        //foreach (var alias in nodeSet.Aliases)
                        //{
                        //    this.Aliases[alias.Value] = alias.Alias;
                        //}
                        // TODO find a more elegant way to load OPC base data types (needed by DataTypeModel.GetBuiltinDataType)
                        var opcModel   = nodeSet.Models[0];
                        var opcProfile = _nsDal.Where(ns => ns.Namespace == opcModel.ModelUri /*&& ns.PublicationDate == opcModel.PublicationDate*/ /*&& (ns.AuthorId == null || ns.AuthorId == userId)*/, userToken, null, null).Data?.FirstOrDefault();
                        //TBD - this next line is time consuming.
                        this.LoadNodeSetAsync(nodeSet, opcProfile
                                              //    new OPCUANodeSetHelpers.ModelNameAndVersion
                                              //{
                                              //    ModelUri = opcModel.ModelUri,
                                              //    ModelVersion = opcModel.Version,
                                              //    PublicationDate = opcModel.PublicationDate,
                                              //    CacheId = opcNodeSetModel.ID,
                                              //}
                                              , true).Wait();
                    }
                }
                catch { }
            }

            if (profileItem == null)
            {
                var profileItemsResult = _dal.Where(pi => pi.ProfileId == profileModel.ID /*&& (pi.AuthorId == null || pi.AuthorId == userId)*/, userToken, null, null, false, true);
                if (profileItemsResult.Data != null)
                {
                    foreach (var profile in profileItemsResult.Data)
                    {
                        var nodeModel = NodeModelFromProfileFactory.Create(profile, this, dalContext);
                    }
                }
            }
            else
            {
                var nodeModel = NodeModelFromProfileFactory.Create(profileItem, this, dalContext);
            }

            // Export the nodesets
            var exportedNodeSet = new UANodeSet();

            foreach (var model in this.NodesetModels.Values.Where(model =>
                                                                  ((ProfileModel)model.CustomState).Namespace == profileModel.Namespace &&
                                                                  ((ProfileModel)model.CustomState).PublishDate == profileModel.PublishDate))
            {
                model.UpdateIndices();

                ExportNodeSet(exportedNodeSet, model, this.NodesetModels, this.Aliases);
            }
            // .Net6 changed the default to no-identation: https://github.com/dotnet/runtime/issues/64885
            using (StreamWriter writer = new StreamWriter(xmlNodeSet, Encoding.UTF8))
            {
                try
                {
                    var xmlWriter = XmlWriter.Create(writer, new XmlWriterSettings {
                        Indent = true,
                    });
                    XmlSerializer serializer = new XmlSerializer(typeof(UANodeSet));
                    serializer.Serialize(xmlWriter, exportedNodeSet);
                }
                finally
                {
                    writer.Flush();
                }
            }
            //exportedNodeSet.Write(xmlNodeSet);
            return(true);
        }