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(); }
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); } } }
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; }
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; } }
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); }
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); }
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); }
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]); } } }
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); } }
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); }
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); }
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 }
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); }