diff --git a/CESMII.OpcUa.NodeSetImporter/CESMII.OpcUa.NodeSetImporter.csproj b/CESMII.OpcUa.NodeSetImporter/CESMII.OpcUa.NodeSetImporter.csproj
deleted file mode 100644
index 2fe7f72a..00000000
--- a/CESMII.OpcUa.NodeSetImporter/CESMII.OpcUa.NodeSetImporter.csproj
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
- netstandard2.0;netstandard2.1
- latest
- Debug;Release;Staging
- true
- cesmii.png
- 0.1
- Chris Muench, Markus Horstmann
- CESMII
-
- en
- OPC UA Node Set Importer: stores nodeset files and their dependencies.
- Copyright © 2022 CESMII
- BSD-3-Clause
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/CESMII.OpcUa.NodeSetImporter/IUANodeSetCache.cs b/CESMII.OpcUa.NodeSetImporter/IUANodeSetCache.cs
deleted file mode 100644
index 05b6d75a..00000000
--- a/CESMII.OpcUa.NodeSetImporter/IUANodeSetCache.cs
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Author: Chris Muench, C-Labs
- * Last Update: 4/8/2022
- * License: MIT
- *
- * Some contributions thanks to CESMII – the Smart Manufacturing Institute, 2021
- */
-
-using CESMII.OpcUa.NodeSetModel.Factory.Opc;
-using CESMII.OpcUa.NodeSetModel.Opc.Extensions;
-using Microsoft.Extensions.Logging;
-using Opc.Ua.Export;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace CESMII.OpcUa.NodeSetImporter
-{
- public interface IUANodeSetCache
- {
- public bool GetNodeSet(UANodeSetImportResult results, ModelNameAndVersion nameVersion, object TenantID);
- public bool AddNodeSet(UANodeSetImportResult results, string nodeSetXml, object TenantID, bool requested);
- public string GetRawModelXML(ModelValue model);
- public void DeleteNewlyAddedNodeSetsFromCache(UANodeSetImportResult results);
- public UANodeSetImportResult FlushCache();
- public ModelValue GetNodeSetByID(string id);
- }
-
- ///
- /// Model Value containing all important fast access datapoints of a model
- ///
- public class ModelValue
- {
- ///
- /// The imported NodeSet - use this in your subsequent code
- ///
- public UANodeSet NodeSet { get; set; }
- public string HeaderComment { get; set; }
- ///
- /// File Path to the XML file cache of the NodeSet on the Server
- ///
- public string FilePath { get; set; }
- ///
- /// List of all Model URI (Namespace) dependencies of the Model
- ///
- public List Dependencies { get; set; } = new List();
- ///
- /// Name and Version of NodeSet
- ///
- public ModelNameAndVersion NameVersion { get; set; }
- ///
- /// a Flag telling the consumer that this model was just found and new to this import
- ///
- public bool NewInThisImport { get; set; }
-
- ///
- /// A flag telling the consumer that this model is one of the explicitly requested nodemodel, even if it already existed
- ///
- public bool RequestedForThisImport { get; set; }
-
- public override string ToString()
- {
- return $"{NameVersion}";
- }
- }
-
- ///
- /// Result-Set of this Importer
- /// Check "ErrorMessage" for issues during the import such as missing dependencies
- /// Check "MissingModels" as a list of Models that could not be resolved
- ///
- public class UANodeSetImportResult
- {
- ///
- /// Error Message in case the import was not successful or is missing dependencies
- ///
- public string ErrorMessage { get; set; } = "";
- ///
- /// All Imported Models - sorted from least amount of dependencies to most dependencies
- ///
- public List Models { get; set; } = new List();
- ///
- /// List if missing models listed as ModelUri strings
- ///
- public List MissingModels { get; set; } = new List();
- ///
- /// A NodeSet author might add custom "Extensions" to a NodeSet.
- ///
- public Dictionary Extensions { get; set; } = new Dictionary();
-
-
- ///
- /// Parses Dependencies and creates the Models- and MissingModels collection
- ///
- ///
- ///
- ///
- ///
- ///
- /// The ModelValue created or found in the results
- public (ModelValue Model, bool Added) AddModelAndDependencies(UANodeSet nodeSet, string headerComment, ModelTableEntry ns, string filePath, bool wasNewFile, ILogger logger = null)
- {
- NodeModelUtils.FixupNodesetVersionFromMetadata(nodeSet, logger);
- bool bAdded = false;
- var tModel = GetMatchingOrHigherModel(ns.ModelUri, ns.GetNormalizedPublicationDate(), ns.Version);
- if (tModel == null)
- {
- // Remove any previous models with this ModelUri, as we have found a newer one
- if (this.Models.RemoveAll(m => m.NameVersion.ModelUri == ns.ModelUri) > 0)
- {
- // superceded
- }
-
- tModel = new ModelValue { NodeSet = nodeSet, HeaderComment = headerComment, NameVersion = new ModelNameAndVersion(ns), FilePath = filePath, NewInThisImport = wasNewFile };
- this.Models.Add(tModel);
- bAdded = true;
- }
- if (ns.RequiredModel?.Any() == true)
- {
- foreach (var tDep in ns.RequiredModel)
- {
- tModel.Dependencies.Add(tDep.ModelUri);
- if (!this.MissingModels.Any(s => s.HasNameAndVersion(tDep.ModelUri, tDep.GetNormalizedPublicationDate(), tDep.Version)))
- {
- this.MissingModels.Add(new ModelNameAndVersion(tDep));
- }
- }
- }
- return (tModel, bAdded);
- }
-
- private ModelValue GetMatchingOrHigherModel(string modelUri, DateTime? publicationDate, string version)
- {
- var matchingNodeSetsForUri = this.Models
- .Where(s => s.NameVersion.ModelUri == modelUri)
- .Select(m =>
- new NodeSetModel.NodeSetModel
- {
- ModelUri = m.NameVersion.ModelUri,
- PublicationDate = m.NameVersion.PublicationDate,
- Version = m.NameVersion.ModelVersion,
- CustomState = m,
- });
- var matchingNodeSet = NodeSetModel.NodeSetVersionUtils.GetMatchingOrHigherNodeSet(matchingNodeSetsForUri, publicationDate, version);
- var tModel = matchingNodeSet?.CustomState as ModelValue;
- if (tModel == null && matchingNodeSet != null)
- {
- throw new InvalidCastException("Internal error: CustomState not preserved");
- }
- return tModel;
- }
-
- ///
- /// Updates missing dependencies of NodesSets based on all loaded nodsets
- ///
- ///
- public void ResolveDependencies()
- {
- if (this?.Models?.Count > 0 && this?.MissingModels?.Count > 0)
- {
- for (int i = this.MissingModels.Count - 1; i >= 0; i--)
- {
- if (this.Models.Any(s => s.NameVersion.IsNewerOrSame(this.MissingModels[i])))
- {
- this.MissingModels.RemoveAt(i);
- }
- }
- }
- }
-
- }
-
-}
diff --git a/CESMII.OpcUa.NodeSetImporter/IUANodeSetResolver.cs b/CESMII.OpcUa.NodeSetImporter/IUANodeSetResolver.cs
deleted file mode 100644
index 731151a6..00000000
--- a/CESMII.OpcUa.NodeSetImporter/IUANodeSetResolver.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Author: Markus Horstmann, C-Labs
- * Last Update: 4/13/2022
- * License: MIT
- *
- * Some contributions thanks to CESMII – the Smart Manufacturing Institute, 2022
- */
-
-using System.Collections.Generic;
-using System.IO;
-using System.Threading.Tasks;
-
-namespace CESMII.OpcUa.NodeSetImporter
-{
- public interface IUANodeSetResolver
- {
- Task> ResolveNodeSetsAsync(List missingModels);
- }
-}
diff --git a/CESMII.OpcUa.NodeSetImporter/ModelNameAndVersion.cs b/CESMII.OpcUa.NodeSetImporter/ModelNameAndVersion.cs
deleted file mode 100644
index e72eedb4..00000000
--- a/CESMII.OpcUa.NodeSetImporter/ModelNameAndVersion.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Author: Chris Muench, C-Labs
- * Last Update: 4/8/2022
- * License: MIT
- *
- * Some contributions thanks to CESMII – the Smart Manufacturing Institute, 2021
- */
-
-using CESMII.OpcUa.NodeSetModel.Opc.Extensions;
-using Opc.Ua.Export;
-using System;
-
-namespace CESMII.OpcUa.NodeSetImporter
-{
- ///
- /// Simplified class containing all important information of a NodeSet
- ///
- public class ModelNameAndVersion
- {
- ///
- /// The main Model URI (Namespace)
- ///
- public string ModelUri { get; set; }
- ///
- /// Version of the NodeSet
- ///
- public string ModelVersion { get; set; }
- ///
- /// Publication date of the NodeSet
- ///
- public DateTime? PublicationDate { get; set; }
- ///
- /// This is not a valid OPC UA Field and might be hidden inside the "Extensions" node - not sure if its the best way to add this here
- ///
- public string Author { get; set; }
- ///
- /// Set to !=0 if this Model is an official OPC Foundation Model and points to an index in a lookup table or cloudlib id
- /// This requires a call to the CloudLib or another Model validation table listing all officially released UA Models
- ///
- public int? UAStandardModelID { get; set; }
- ///
- /// Key into the Cache Table
- ///
- public object CCacheId { get; set; }
-
-
- public ModelNameAndVersion(ModelTableEntry model)
- {
- ModelUri = model.ModelUri;
- ModelVersion = model.Version;
- PublicationDate = model.GetNormalizedPublicationDate();
- }
- ///
- /// Compares two NodeSetNameAndVersion using ModelUri and Version.
- ///
- /// Compares this to ThanThis
- ///
- public bool IsNewerOrSame(ModelNameAndVersion thanThis)
- {
- if (thanThis == null)
- return false;
- if (ModelUri != thanThis.ModelUri)
- {
- return false;
- }
- return NodeSetModel.NodeSetVersionUtils.IsMatchingOrHigherNodeSet(ModelUri, PublicationDate, ModelVersion, thanThis.PublicationDate, thanThis.ModelVersion) ?? false;
- }
-
- ///
- /// Compares this NameAndVersion to incoming Name and Version prarameters
- ///
- /// ModelUri of version
- /// Publish Date of NodeSet
- ///
- public bool HasNameAndVersion(string ofModelUri, DateTime ofPublicationDate, string ofModelVersion)
- {
- if (string.IsNullOrEmpty(ofModelUri))
- return false;
- if (ModelUri != ofModelUri)
- {
- return false;
- }
- return NodeSetModel.NodeSetVersionUtils.IsMatchingOrHigherNodeSet(ModelUri, PublicationDate, ModelVersion, ofPublicationDate, ofModelVersion) ?? false;
- }
-
- public override string ToString()
- {
- string uaStandardIdLabel = UAStandardModelID.HasValue ? $", UA-ID: {UAStandardModelID.Value}" : "";
- return $"{ModelUri} (Version: {ModelVersion}, PubDate: {PublicationDate?.ToShortDateString()}{uaStandardIdLabel})";
- }
- }
-}
diff --git a/CESMII.OpcUa.NodeSetImporter/UANodeSetCacheManager.cs b/CESMII.OpcUa.NodeSetImporter/UANodeSetCacheManager.cs
deleted file mode 100644
index 30e3c988..00000000
--- a/CESMII.OpcUa.NodeSetImporter/UANodeSetCacheManager.cs
+++ /dev/null
@@ -1,226 +0,0 @@
-/* Author: Chris Muench, C-Labs
- * Last Update: 4/8/2022
- * License: MIT
- *
- * Some contributions thanks to CESMII – the Smart Manufacturing Institute, 2021
- */
-
-using Opc.Ua.Export;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-
-namespace CESMII.OpcUa.NodeSetImporter
-{
- //Glossary of Terms:
- //-----------------------------------
- //NodeSet - Container File of one or more Models
- //Model - a unique OPC UA Model identified with a unique NamespaceUri/ModelUri. A model can be spanned across multiple NodeSet (files)
- //Namespace - the unique identifier of a Model (also called ModelUri)
- //UAStandardModel - A Model that has been standardized by the OPC UA Foundation and can be found in the official schema store: https://files.opcfoundation.org/schemas/
- //UANodeSetImporter - Imports one or more OPC UA NodeSets resulting in a "NodeSetImportResult" containing all found Models and a list of missing dependencies
-
- ///
- /// Main Importer class importing NodeSets
- ///
- public class UANodeSetCacheManager
- {
-
- UANodeSetImportResult _results = new();
- private readonly IUANodeSetCache _nodeSetCacheSystem;
- private readonly IUANodeSetResolver _nodeSetResolver;
-
- public UANodeSetCacheManager()
- {
- _nodeSetCacheSystem = new UANodeSetFileCache();
- _nodeSetResolver = null;
- }
- public UANodeSetCacheManager(IUANodeSetCache nodeSetCacheSystem)
- {
- _nodeSetCacheSystem = nodeSetCacheSystem;
- _nodeSetResolver = null;
- }
- public UANodeSetCacheManager(IUANodeSetCache nodeSetCacheSystem, IUANodeSetResolver nodeSetResolver)
- {
- _nodeSetCacheSystem = nodeSetCacheSystem;
- _nodeSetResolver = nodeSetResolver;
- }
-
- ///
- /// Imports NodeSets from Files resolving dependencies using already uploaded NodeSets
- ///
- /// This interface can be used to override the default file cache of the Importer, i.e with a Database cache
- /// If null, a new resultset will be created. If not null already uploaded NodeSets can be augmented with New NodeSets referred in the FileNames
- /// List of full paths to uploaded NodeSets
- /// List of streams containing NodeSets
- /// Default behavior is that all Models in NodeSets are returned even if they have been imported before. If set to true, the importer will fail if it has imported a nodeset before and does not cache nodeset if they have missing dependencies
- /// If the import has Multi-Tenant Cache, the tenant ID has to be set here
- ///
- public UANodeSetImportResult ImportNodeSetFiles(List nodeSetFilenames, bool FailOnExisting = false, object TenantID = null)
- {
- return ImportNodeSets(nodeSetFilenames.Select(f => File.ReadAllText(f)), FailOnExisting, TenantID);
- }
- ///
- /// Imports NodeSets from Files resolving dependencies using already uploaded NodeSets
- ///
- /// This interface can be used to override the default file cache of the Importer, i.e with a Database cache
- /// If null, a new resultset will be created. If not null already uploaded NodeSets can be augmented with New NodeSets referred in the FileNames
- /// List of full paths to uploaded NodeSets
- /// List of streams containing NodeSets
- /// Default behavior is that all Models in NodeSets are returned even if they have been imported before. If set to true, the importer will fail if it has imported a nodeset before and does not cache nodeset if they have missing dependencies
- /// If the import has Multi-Tenant Cache, the tenant ID has to be set here
- ///
- public UANodeSetImportResult ImportNodeSets(IEnumerable nodeSetStreams, bool FailOnExisting = false, object TenantID = null)
- {
- return ImportNodeSets(nodeSetStreams.Select(s =>
- {
- using (var sr = new StreamReader(s, Encoding.UTF8))
- {
- return sr.ReadToEnd();
- }
- }), FailOnExisting, TenantID);
- }
- ///
- /// Imports NodeSets from Files resolving dependencies using already uploaded NodeSets
- ///
- /// This interface can be used to override the default file cache of the Importer, i.e with a Database cache
- /// If null, a new resultset will be created. If not null already uploaded NodeSets can be augmented with New NodeSets referred in the FileNames
- /// List of full paths to uploaded NodeSets
- /// List of streams containing NodeSets
- /// Default behavior is that all Models in NodeSets are returned even if they have been imported before. If set to true, the importer will fail if it has imported a nodeset before and does not cache nodeset if they have missing dependencies
- /// If the import has Multi-Tenant Cache, the tenant ID has to be set here
- ///
- public UANodeSetImportResult ImportNodeSets(IEnumerable nodeSetsXml, bool FailOnExisting = false, object TenantID = null)
- {
- _results.ErrorMessage = "";
- List previousMissingModels = new List();
- try
- {
- bool rerun;
- do
- {
- rerun = false;
- bool NewNodeSetFound = false;
- if (nodeSetsXml != null)
- {
- // Must enumerate the nodeSetsXml only once in case the caller creates/loads strings as needed (streams of files)
- foreach (var nodeSetXml in nodeSetsXml)
- {
- var JustFoundNewNodeSet = _nodeSetCacheSystem.AddNodeSet(_results, nodeSetXml, TenantID, true);
- NewNodeSetFound |= JustFoundNewNodeSet;
- }
- nodeSetsXml = null;
- }
-
- if (!NewNodeSetFound && FailOnExisting)
- {
- string names = string.Join(", ", _results.Models.Select(m => m.NameVersion));
- _results.ErrorMessage = $"All selected NodeSets or newer versions of them ({names}) have already been imported";
- return _results;
- }
- if (_results.Models.Count == 0)
- {
- _results.ErrorMessage = "No Nodesets specified in either nodeSetFilenames or nodeSetStreams";
- return _results;
- }
- _results.ResolveDependencies();
-
- if (_results?.MissingModels?.Any() == true)
- {
- foreach (var t in _results.MissingModels.ToList())
- {
- rerun |= _nodeSetCacheSystem.GetNodeSet(_results, t, TenantID);
- }
- _results.ResolveDependencies();
-
- if (_results.MissingModels.Any())
- {
- if (_results.MissingModels.SequenceEqual(previousMissingModels))
- {
- rerun = false;
- continue;
- }
- previousMissingModels = _results.MissingModels.ToList();
- // No more cached models were added, but we are still missing models: invoke the resolver if provided
- if (_nodeSetResolver != null)
- {
- try
- {
- var newNodeSetsXml = _nodeSetResolver.ResolveNodeSetsAsync(_results.MissingModels.ToList()).Result;
- if (newNodeSetsXml?.Any() == true)
- {
- nodeSetsXml = newNodeSetsXml;
- rerun = true;
- continue;
- }
- }
- catch (Exception ex)
- {
- if (_results.ErrorMessage.Length > 0) _results.ErrorMessage += ", ";
- _results.ErrorMessage += $"Error resolving missing nodesets: {ex.Message}";
- }
- }
- if (_results.ErrorMessage.Length > 0) _results.ErrorMessage += ", ";
- _results.ErrorMessage += string.Join(",", _results.MissingModels);
- }
- if (!string.IsNullOrEmpty(_results.ErrorMessage))
- {
- _results.ErrorMessage = $"The following NodeSets are required: " + _results.ErrorMessage;
- //We must delete newly cached models as they need to be imported again into the backend
- if (FailOnExisting)
- _nodeSetCacheSystem.DeleteNewlyAddedNodeSetsFromCache(_results);
- }
- }
-
- _results.Models = OrderByDependencies(_results.Models); // _results.Models.OrderBy(s => s.Dependencies.Count).ToList();
- } while (rerun && _results.MissingModels.Any());
- }
- catch (Exception ex)
- {
- _results.ErrorMessage = ex.Message;
- }
-
- return _results;
- }
-
- static List OrderByDependencies(List models)
- {
- var remainingModels = new List(models);
- var orderedModels = new List();
-
- bool modelAdded;
- do
- {
- modelAdded = false;
- for (int i = 0; i < remainingModels.Count;)
- {
- var remainingModel = remainingModels[i];
- bool bDependenciesSatisfied = true;
- foreach (var dependency in remainingModel.Dependencies)
- {
- if (!orderedModels.Any(m => m.NameVersion.ModelUri == dependency))
- {
- bDependenciesSatisfied = false;
- break;
- }
- }
- if (bDependenciesSatisfied)
- {
- orderedModels.Add(remainingModel);
- remainingModels.RemoveAt(i);
- modelAdded = true;
- }
- else
- {
- i++;
- }
- }
- } while (remainingModels.Count > 0 && modelAdded);
-
- orderedModels.AddRange(remainingModels); // Add any remaining models (dependencies not satisfied, not ordered)
- return orderedModels;
- }
- }
-}
diff --git a/CESMII.OpcUa.NodeSetImporter/UANodeSetFileCache.cs b/CESMII.OpcUa.NodeSetImporter/UANodeSetFileCache.cs
deleted file mode 100644
index ccd6ec41..00000000
--- a/CESMII.OpcUa.NodeSetImporter/UANodeSetFileCache.cs
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Author: Chris Muench, C-Labs
- * Last Update: 4/8/2022
- * License: MIT
- *
- * Some contributions thanks to CESMII – the Smart Manufacturing Institute, 2021
- */
-using CESMII.OpcUa.NodeSetModel;
-using CESMII.OpcUa.NodeSetModel.Factory.Opc;
-using CESMII.OpcUa.NodeSetModel.Opc.Extensions;
-using Opc.Ua.Export;
-using System;
-using System.IO;
-using System.Linq;
-using System.Text;
-
-namespace CESMII.OpcUa.NodeSetImporter
-{
-
- ///
- /// Implementation of File Cache - can be replaced with Database cache if necessary
- ///
- public class UANodeSetFileCache : IUANodeSetCache
- {
- public UANodeSetFileCache()
- {
- RootFolder = Path.Combine(Directory.GetCurrentDirectory(), "NodeSetCache");
- }
-
- public UANodeSetFileCache(string pRootFolder)
- {
- RootFolder = pRootFolder;
- }
- static string RootFolder = null;
- ///
- /// Not Supported on File Cache
- ///
- ///
- ///
- public ModelValue GetNodeSetByID(string id)
- {
- return null;
- }
-
- ///
- /// By default the Imporater caches all imported NodeSets in a directory called "/NodeSets" under the correct bin directory
- /// This function can be called to flush this cache (for debugging and development purpose only!)
- ///
- ///
- public UANodeSetImportResult FlushCache()
- {
- UANodeSetImportResult ret = new UANodeSetImportResult();
- string tPath = Path.Combine(RootFolder, "NodeSets");
- try
- {
- var tFiles = Directory.GetFiles(tPath);
- foreach (var tfile in tFiles)
- {
- File.Delete(tfile);
- }
- }
- catch (Exception e)
- {
- ret.ErrorMessage = $"Flushing Cache failed: {e}";
- }
- return ret;
- }
-
- ///
- /// After the NodeSets were returned by the Importer the succeeding code might fail during processing.
- /// This function allows to remove NodeSets from the cache if the succeeding call failed
- ///
- /// Set to the result-set coming from the ImportNodeSets message to remove newly added NodeSets from the cache
- public void DeleteNewlyAddedNodeSetsFromCache(UANodeSetImportResult results)
- {
- if (results?.Models?.Count > 0)
- {
- foreach (var tMod in results.Models)
- {
- if (tMod.NewInThisImport)
- File.Delete(tMod.FilePath);
- }
- }
- }
-
- ///
- /// Returns the content of a cached NodeSet
- ///
- ///
- ///
- public string GetRawModelXML(ModelValue model)
- {
- if (!File.Exists(model?.FilePath))
- return null;
- return File.ReadAllText(model.FilePath);
- }
-
- ///
- /// Loads a NodeSet From File.
- ///
- ///
- ///
- public void AddNodeSetFile(UANodeSetImportResult results, string nodesetFileName, object tenantId)
- {
- if (!File.Exists(nodesetFileName))
- return;
- var nodeSetXml = File.ReadAllText(nodesetFileName);
- AddNodeSet(results, nodeSetXml, tenantId, false);
- }
-
- public bool GetNodeSet(UANodeSetImportResult results, ModelNameAndVersion nameVersion, object TenantID)
- {
- //Try to find already uploaded NodeSets using cached NodeSets in the "NodeSets" Folder.
- string tFileName = GetCacheFileName(nameVersion, TenantID);
- if (File.Exists(tFileName))
- {
- AddNodeSetFile(results, tFileName, TenantID);
- return true;
- }
- return false;
- }
-
- private static string GetCacheFileName(ModelNameAndVersion nameVersion, object TenantID)
- {
- string tPath = Path.Combine(RootFolder, "NodeSets");
- if (!Directory.Exists(tPath))
- Directory.CreateDirectory(tPath);
- if (TenantID != null && (int)TenantID > 0)
- {
- tPath = Path.Combine(tPath, $"{(int)TenantID}");
- if (!Directory.Exists(tPath))
- Directory.CreateDirectory(tPath);
- }
- string tFile = nameVersion.ModelUri.Replace("http://", "");
- tFile = tFile.Replace('/', '.');
- if (!tFile.EndsWith(".")) tFile += ".";
- string filePath = Path.Combine(tPath, $"{tFile}NodeSet2.xml");
- return filePath;
- }
-
- ///
- /// Loads NodeSets from a given byte array and saves new NodeSets to the cache
- ///
- ///
- ///
-
- ///
- public bool AddNodeSet(UANodeSetImportResult results, string nodeSetXml, object TenantID, bool requested)
- {
- bool WasNewSet = false;
- // UANodeSet.Read disposes the stream. We need it later on so create a copy
- UANodeSet nodeSet;
-
- // workaround for bug https://github.com/dotnet/runtime/issues/67622
- var patchedXML = nodeSetXml.Replace("", "");
- using (var nodesetBytes = new MemoryStream(Encoding.UTF8.GetBytes(patchedXML)))
- {
- nodeSet = UANodeSet.Read(nodesetBytes);
- }
-
- #region Comment processing
- var headerComment = NodeModelUtils.ReadHeaderComment(patchedXML);
- #endregion
-
- UANodeSet tOldNodeSet = null;
- if (nodeSet?.Models == null)
- {
- results.ErrorMessage = $"No Nodeset found in bytes";
- return false;
- }
- foreach (var importedModel in nodeSet.Models)
- {
- //Caching the streams to a "NodeSets" subfolder using the Model Name
- //Even though "Models" is an array, most NodeSet files only contain one model.
- //In case a NodeSet stream does contain multiple models, the same file will be cached with each Model Name
- string filePath = GetCacheFileName(new ModelNameAndVersion(importedModel), TenantID);
-
- bool CacheNewerVersion = true;
- if (File.Exists(filePath))
- {
- CacheNewerVersion = false;
- using (Stream nodeSetStream = new FileStream(filePath, FileMode.Open))
- {
- if (tOldNodeSet == null)
- tOldNodeSet = UANodeSet.Read(nodeSetStream);
- }
- var tOldModel = tOldNodeSet.Models.Where(s => s.ModelUri == importedModel.ModelUri).OrderByDescending(s => s.GetNormalizedPublicationDate()).FirstOrDefault();
- if (tOldModel == null
- || NodeSetVersionUtils.CompareNodeSetVersion(
- importedModel.ModelUri,
- importedModel.GetNormalizedPublicationDate(), importedModel.Version,
- tOldModel.GetNormalizedPublicationDate(), tOldModel.Version) > 0)
- {
- 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
- }
- }
- if (CacheNewerVersion) //Cache only newer version
- {
- File.WriteAllText(filePath, nodeSetXml);
- WasNewSet = true;
- }
- var modelInfo = results.AddModelAndDependencies(nodeSet, headerComment, importedModel, filePath, WasNewSet);
- modelInfo.Model.RequestedForThisImport = requested;
- }
- return WasNewSet;
- }
- }
-}
diff --git a/CESMII.OpcUa.NodeSetImporter/UANodeSetModelExporter.cs b/CESMII.OpcUa.NodeSetImporter/UANodeSetModelExporter.cs
deleted file mode 100644
index 84e21173..00000000
--- a/CESMII.OpcUa.NodeSetImporter/UANodeSetModelExporter.cs
+++ /dev/null
@@ -1,341 +0,0 @@
-/* Author: Chris Muench, C-Labs
- * Last Update: 4/8/2022
- * License: MIT
- *
- * Some contributions thanks to CESMII – the Smart Manufacturing Institute, 2021
- */
-
-using Opc.Ua.Export;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using CESMII.OpcUa.NodeSetModel.Export.Opc;
-using CESMII.OpcUa.NodeSetModel.Opc.Extensions;
-using Opc.Ua;
-using System.Xml.Serialization;
-using System.Xml;
-using Microsoft.Extensions.Logging;
-
-namespace CESMII.OpcUa.NodeSetModel
-{
- ///
- /// Exporter helper class
- ///
- public class UANodeSetModelExporter
- {
- public static string ExportNodeSetAsXml(NodeSetModel nodesetModel, Dictionary nodesetModels, ILogger logger = null, Dictionary aliases = null, bool encodeJsonScalarsAsValue = false)
- {
- return ExportNodeSetAsXmlAndNodeSet(nodesetModel, nodesetModels, logger, aliases, encodeJsonScalarsAsValue).NodeSetXml;
- }
- public static (string NodeSetXml, UANodeSet NodeSet) ExportNodeSetAsXmlAndNodeSet(NodeSetModel nodesetModel, Dictionary nodesetModels, ILogger logger = null, Dictionary aliases = null, bool encodeJsonScalarsAsValue = false)
- {
- var exportedNodeSet = ExportNodeSet(nodesetModel, nodesetModels, logger, aliases, encodeJsonScalarsAsValue: encodeJsonScalarsAsValue);
-
- string exportedNodeSetXml;
- // .Net6 changed the default to no-identation: https://github.com/dotnet/runtime/issues/64885
- using (var ms = new MemoryStream())
- {
- using (var writer = new StreamWriter(ms, Encoding.UTF8))
- {
- try
- {
- using (var xmlWriter = XmlWriter.Create(writer, new XmlWriterSettings { Indent = true, }))
- {
- XmlSerializer serializer = new XmlSerializer(typeof(UANodeSet));
- serializer.Serialize(xmlWriter, exportedNodeSet);
- }
- }
- finally
- {
- writer.Flush();
- }
- }
- var xmlBytes = ms.ToArray();
- if (string.IsNullOrEmpty(nodesetModel.HeaderComments))
- {
- exportedNodeSetXml = Encoding.UTF8.GetString(xmlBytes);
- }
- else
- {
- int secondLineIndex;
- for (secondLineIndex = 0; secondLineIndex < xmlBytes.Length; secondLineIndex++)
- {
- if (xmlBytes[secondLineIndex] == '\r' || xmlBytes[secondLineIndex] == '\n')
- {
- secondLineIndex++;
- if (xmlBytes[secondLineIndex + 1] == '\n')
- {
- secondLineIndex++;
- }
- break;
- }
- }
- if (secondLineIndex < xmlBytes.Length - 1)
- {
- var sb = new StringBuilder();
- sb.Append(Encoding.UTF8.GetString(xmlBytes, 0, secondLineIndex));
- if (nodesetModel.HeaderComments.EndsWith("\r\n"))
- {
- sb.Append(nodesetModel.HeaderComments);
- }
- else
- {
- sb.AppendLine(nodesetModel.HeaderComments);
- }
- sb.Append(Encoding.UTF8.GetString(xmlBytes, secondLineIndex, xmlBytes.Length - secondLineIndex));
- exportedNodeSetXml = sb.ToString();
- }
- else
- {
- exportedNodeSetXml = Encoding.UTF8.GetString(ms.ToArray());
- }
- }
- }
- return (exportedNodeSetXml, exportedNodeSet);
- }
- public static UANodeSet ExportNodeSet(NodeSetModel nodeSetModel, Dictionary nodeSetModels, ILogger logger, Dictionary aliases = null, bool encodeJsonScalarsAsValue = false)
- {
- if (aliases == null)
- {
- aliases = new();
- }
-
- var exportedNodeSet = new UANodeSet();
- exportedNodeSet.LastModified = DateTime.UtcNow;
- exportedNodeSet.LastModifiedSpecified = true;
-
- var namespaceUris = nodeSetModel.AllNodesByNodeId.Values.Select(v => v.Namespace).Distinct().ToList();
-
- var requiredModels = new List();
-
- var context = new ExportContext(logger, nodeSetModels)
- {
- Aliases = aliases,
- ReencodeExtensionsAsJson = true,
- EncodeJsonScalarsAsValue = encodeJsonScalarsAsValue,
- _nodeIdsUsed = new HashSet(),
- _exportedSoFar = new Dictionary(),
- };
-
- foreach (var nsUri in namespaceUris)
- {
- context.NamespaceUris.GetIndexOrAppend(nsUri);
- }
- var items = ExportAllNodes(nodeSetModel, context);
-
- // remove unused aliases
- var usedAliases = aliases.Where(pk => context._nodeIdsUsed.Contains(pk.Key)).ToDictionary(kv => kv.Key, kv => kv.Value);
-
- // Add aliases for all nodeids from other namespaces: aliases can only be used on references, not on the definitions
- var currentNodeSetNamespaceIndex = context.NamespaceUris.GetIndex(nodeSetModel.ModelUri);
- bool bAliasesAdded = false;
- foreach (var nodeId in context._nodeIdsUsed)
- {
- var parsedNodeId = NodeId.Parse(nodeId);
- if (parsedNodeId.NamespaceIndex != currentNodeSetNamespaceIndex
- && !usedAliases.ContainsKey(nodeId))
- {
- var namespaceUri = context.NamespaceUris.GetString(parsedNodeId.NamespaceIndex);
- var nodeIdWithUri = new ExpandedNodeId(parsedNodeId, namespaceUri).ToString();
- var nodeModel = nodeSetModels.Select(nm => nm.Value.AllNodesByNodeId.TryGetValue(nodeIdWithUri, out var model) ? model : null).FirstOrDefault(n => n != null);
- var displayName = nodeModel?.DisplayName?.FirstOrDefault()?.Text;
- if (displayName != null && !(nodeModel is InstanceModelBase))
- {
- if (!usedAliases.ContainsValue(displayName))
- {
- usedAliases.Add(nodeId, displayName);
- aliases.Add(nodeId, displayName);
- bAliasesAdded = true;
- }
- else
- {
- // name collision: number them
- int i;
- for (i = 1; i < 10000; i++)
- {
- var numberedDisplayName = $"{displayName}_{i}";
- if (!usedAliases.ContainsValue(numberedDisplayName))
- {
- usedAliases.Add(nodeId, numberedDisplayName);
- aliases.Add(nodeId, numberedDisplayName);
- bAliasesAdded = true;
- break;
- }
- }
- if (i >= 10000)
- {
-
- }
- }
- }
- }
- }
-
- var aliasList = usedAliases
- .Select(alias => new NodeIdAlias { Alias = alias.Value, Value = alias.Key })
- .OrderBy(kv => GetNodeIdForSorting(kv.Value))
- .ToList();
- exportedNodeSet.Aliases = aliasList.ToArray();
-
- if (bAliasesAdded)
- {
- context._nodeIdsUsed = null; // No need to track anymore
- // Re-export with new aliases
- items = ExportAllNodes(nodeSetModel, context);
- }
-
- var allNamespaces = context.NamespaceUris.ToArray();
- if (allNamespaces.Length > 1)
- {
- exportedNodeSet.NamespaceUris = allNamespaces.Where(ns => ns != Namespaces.OpcUa).ToArray();
- }
- else
- {
- exportedNodeSet.NamespaceUris = allNamespaces;
- }
-
- // Export all referenced nodesets to capture any of their dependencies that may not be used in the model being exported
- foreach (var otherModel in nodeSetModels.Values.Where(m => m.ModelUri != Namespaces.OpcUa && !namespaceUris.Contains(m.ModelUri)))
- {
- // Only need to update the namespaces table
- context.Aliases = null;
- context._nodeIdsUsed = null;
- _ = ExportAllNodes(otherModel, context);
- }
- var allNamespacesIncludingDependencies = context.NamespaceUris.ToArray();
-
- foreach (var uaNamespace in allNamespacesIncludingDependencies.Except(namespaceUris))
- {
- if (!requiredModels.Any(m => m.ModelUri == uaNamespace))
- {
- if (nodeSetModels.TryGetValue(uaNamespace, out var requiredNodeSetModel))
- {
- var requiredModel = new ModelTableEntry
- {
- ModelUri = uaNamespace,
- Version = requiredNodeSetModel.Version,
- PublicationDate = requiredNodeSetModel.PublicationDate.GetNormalizedPublicationDate(),
- PublicationDateSpecified = requiredNodeSetModel.PublicationDate != null,
- RolePermissions = null,
- AccessRestrictions = 0,
- };
- requiredModels.Add(requiredModel);
- }
- else
- {
- // The model was not loaded. This can happen if the only reference to the model is in an extension object that only gets parsed but not turned into a node model (Example: onboarding nodeset refernces GDS ns=2;i=1)
- var requiredModel = new ModelTableEntry
- {
- ModelUri = uaNamespace,
- };
- requiredModels.Add(requiredModel);
- }
- }
- }
-
- var model = new ModelTableEntry
- {
- ModelUri = nodeSetModel.ModelUri,
- RequiredModel = requiredModels.ToArray(),
- AccessRestrictions = 0,
- PublicationDate = nodeSetModel.PublicationDate.GetNormalizedPublicationDate(),
- PublicationDateSpecified = nodeSetModel.PublicationDate != null,
- RolePermissions = null,
- Version = nodeSetModel.Version,
- XmlSchemaUri = nodeSetModel.XmlSchemaUri != nodeSetModel.ModelUri ? nodeSetModel.XmlSchemaUri : null
- };
- if (exportedNodeSet.Models != null)
- {
- var models = exportedNodeSet.Models.ToList();
- models.Add(model);
- exportedNodeSet.Models = models.ToArray();
- }
- else
- {
- exportedNodeSet.Models = new ModelTableEntry[] { model };
- }
- if (exportedNodeSet.Items != null)
- {
- var newItems = exportedNodeSet.Items.ToList();
- newItems.AddRange(items);
- exportedNodeSet.Items = newItems.ToArray();
- }
- else
- {
- exportedNodeSet.Items = items.ToArray();
- }
- return exportedNodeSet;
- }
-
- private static string GetNodeIdForSorting(string nodeId)
- {
- var intIdIndex = nodeId?.IndexOf("i=");
- if (intIdIndex >= 0 && int.TryParse(nodeId.Substring(intIdIndex.Value + "i=".Length), out var intIdValue))
- {
- return $"{nodeId.Substring(0, intIdIndex.Value)}i={intIdValue:D10}";
- }
- return nodeId;
- }
-
- private static List ExportAllNodes(NodeSetModel nodesetModel, ExportContext context)
- {
- context._exportedSoFar = new Dictionary();
- var itemsOrdered = new List();
- var itemsOrderedSet = new HashSet();
- foreach (var nodeModel in nodesetModel.AllNodesByNodeId.Values
- .OrderBy(GetNodeModelSortOrder)
- .ThenBy(n => GetNodeIdForSorting(n.NodeId)))
- {
- var result = NodeModelExportOpc.GetUANode(nodeModel, context);
- if (result.ExportedNode != null)
- {
- if (context._exportedSoFar.TryAdd(result.ExportedNode.NodeId, result.ExportedNode) || !itemsOrderedSet.Contains(result.ExportedNode))
- {
- itemsOrdered.Add(result.ExportedNode);
- itemsOrderedSet.Add(result.ExportedNode);
- }
- else
- {
- if (context._exportedSoFar[result.ExportedNode.NodeId] != result.ExportedNode)
- {
-
- }
- }
- }
- if (result.AdditionalNodes != null)
- {
- result.AdditionalNodes.ForEach(n =>
- {
- if (context._exportedSoFar.TryAdd(n.NodeId, n) || !itemsOrderedSet.Contains(n))
- {
- itemsOrdered.Add(n);
- itemsOrderedSet.Add(n);
- }
- else
- {
- if (context._exportedSoFar[n.NodeId] != n)
- {
-
- }
-
- }
- });
- }
- }
- return itemsOrdered;
- }
-
- static int GetNodeModelSortOrder(NodeModel nodeModel)
- {
- if (nodeModel is ReferenceTypeModel) return 1;
- if (nodeModel is DataTypeModel) return 2;
- if (nodeModel is ObjectTypeModel) return 3;
- if (nodeModel is VariableTypeModel) return 4;
- return 5;
- }
-
-
- }
-}
diff --git a/CESMII.OpcUa.NodeSetImporter/UANodeSetModelImporter.cs b/CESMII.OpcUa.NodeSetImporter/UANodeSetModelImporter.cs
deleted file mode 100644
index 3aa2a92d..00000000
--- a/CESMII.OpcUa.NodeSetImporter/UANodeSetModelImporter.cs
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Author: Chris Muench, C-Labs
- * Last Update: 4/8/2022
- * License: MIT
- *
- * Some contributions thanks to CESMII – the Smart Manufacturing Institute, 2021
- */
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
-using CESMII.OpcUa.NodeSetModel.Factory.Opc;
-using CESMII.OpcUa.NodeSetImporter;
-using Opc.Ua.Export;
-using Microsoft.Extensions.Logging;
-using Opc.Ua;
-
-namespace CESMII.OpcUa.NodeSetModel
-{
- ///
- /// Main Importer class importing NodeSets
- ///
- public class UANodeSetModelImporter
- {
- private readonly IUANodeSetCache _nodeSetCache;
- private readonly UANodeSetCacheManager _nodeSetCacheManager;
- private readonly IOpcUaContext _opcContext;
-
- public UANodeSetModelImporter(ILogger logger)
- {
- _opcContext = new DefaultOpcUaContext(logger);
- _nodeSetCache = new UANodeSetFileCache();
- _nodeSetCacheManager = new UANodeSetCacheManager(_nodeSetCache);
- }
- public UANodeSetModelImporter(ILogger logger, IUANodeSetResolver resolver)
- {
- _opcContext = new DefaultOpcUaContext(logger);
- _nodeSetCache = new UANodeSetFileCache();
- _nodeSetCacheManager = new UANodeSetCacheManager(_nodeSetCache, resolver);
- }
- public UANodeSetModelImporter(IOpcUaContext opcContext)
- {
- _opcContext = opcContext;
- _nodeSetCache = new UANodeSetFileCache();
- _nodeSetCacheManager = new UANodeSetCacheManager(_nodeSetCache);
- }
- public UANodeSetModelImporter(IOpcUaContext opcContext, IUANodeSetCache nodeSetCache)
- {
- _opcContext = opcContext;
- _nodeSetCache = nodeSetCache;
- _nodeSetCacheManager = new UANodeSetCacheManager(_nodeSetCache);
- }
- public UANodeSetModelImporter(IOpcUaContext opcContext, IUANodeSetCache nodeSetCache, UANodeSetCacheManager nodeSetCacheManager)
- {
- _opcContext = opcContext;
- _nodeSetCache = nodeSetCache;
- _nodeSetCacheManager = nodeSetCacheManager;
- }
-
- ///
- ///
- ///
- /// nodeset to be imported.
- /// optional identifier to be attached to the nodeset. For use by the application.
- /// optional identifier to be used by the nodeSetCache to distinguish between tenants in a multi-tenant system
- /// Fail if the nodeset already exists in the nodeSetCache.
- /// Fully load all dependent models. Otherwise, dependent types will only be resolved when referenced by a subsequently imported nodeset.
- ///
- ///
- public async Task> ImportNodeSetModelAsync(string nodeSetXML, string identifier = null, object tenantId = null, bool failOnExistingNodeSet = false, bool loadAllDependentModels = false)
- {
- _opcContext.NamespaceUris.GetIndexOrAppend(Namespaces.OpcUa);
- var resolvedNodeSets = _nodeSetCacheManager.ImportNodeSets(new List { nodeSetXML }, failOnExistingNodeSet, tenantId);
- if (!string.IsNullOrEmpty(resolvedNodeSets.ErrorMessage))
- {
- throw new NodeSetResolverException($"{resolvedNodeSets.ErrorMessage}");
- }
-
- var firstNewNodeset = resolvedNodeSets.Models.FirstOrDefault(m => m.NewInThisImport || m.RequestedForThisImport);
- if (firstNewNodeset?.NodeSet?.NamespaceUris?.Any() == true)
- {
- // Ensure namespaces are in the context and in proper order
- var namespaces = firstNewNodeset.NodeSet.NamespaceUris.ToList();
- if (namespaces[0] != Namespaces.OpcUa)
- {
- namespaces.Insert(0, Namespaces.OpcUa);
- }
- namespaces.ForEach(n => _opcContext.NamespaceUris.GetIndexOrAppend(n));
- if (!namespaces.Take(_opcContext.NamespaceUris.Count).SequenceEqual(_opcContext.NamespaceUris.ToArray().Take(namespaces.Count)))
- {
- throw new Exception($"Namespace table for {firstNewNodeset} is not in the order required by the nodeset.");
- }
- }
-
- List allLoadedNodesetModels = new();
-
- try
- {
- foreach (var resolvedModel in resolvedNodeSets.Models)
- {
- if (loadAllDependentModels || resolvedModel.RequestedForThisImport || resolvedModel.NewInThisImport)
- {
- List loadedNodesetModels = await LoadNodeSetModelAsync(_opcContext, resolvedModel.NodeSet);
- foreach (var nodeSetModel in loadedNodesetModels)
- {
- nodeSetModel.Identifier = identifier;
- nodeSetModel.HeaderComments = resolvedModel.HeaderComment;
- if (_opcContext.UseLocalNodeIds)
- {
- nodeSetModel.NamespaceIndex = _opcContext.NamespaceUris.GetIndex(nodeSetModel.ModelUri);
- }
- }
- allLoadedNodesetModels.AddRange(loadedNodesetModels);
- }
- else
- {
- var existingNodeSetModel = _opcContext.GetOrAddNodesetModel(resolvedModel.NodeSet.Models.FirstOrDefault(), false);
-
- if (existingNodeSetModel == null)
- {
- throw new ArgumentException($"Required NodeSet {existingNodeSetModel} not in database: Inconsistency between file store and db?");
- }
- // Get the node state for required models so that UANodeSet.Import works
- _opcContext.ImportUANodeSet(resolvedModel.NodeSet);
- }
- }
- }
- catch
- {
- _nodeSetCache.DeleteNewlyAddedNodeSetsFromCache(resolvedNodeSets);
- throw;
- }
- return allLoadedNodesetModels;
- }
-
- ///
- /// Loads a nodeset into the opcContext, without requiring cache. All dependent nodesets must be loaded previously (or their nodestates must be populated using _opcContext.ImportUANodeSet if only actually referenced types from those nodesets are required)
- ///
- ///
- ///
- ///
- public async Task> LoadNodeSetModelAsync(IOpcUaContext opcContext, UANodeSet nodeSet)
- {
- return await NodeModelFactoryOpc.LoadNodeSetAsync(opcContext, nodeSet, null, new Dictionary(), true);
- }
- }
-}
diff --git a/CESMII.OpcUa.NodeSetModel.EF/CESMII.OpcUa.NodeSetModel.EF.csproj b/CESMII.OpcUa.NodeSetModel.EF/CESMII.OpcUa.NodeSetModel.EF.csproj
deleted file mode 100644
index ddcfbc65..00000000
--- a/CESMII.OpcUa.NodeSetModel.EF/CESMII.OpcUa.NodeSetModel.EF.csproj
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
- net6.0
- Debug;Release;Staging
- true
- cesmii.png
- 0.1
- Markus Horstmann
- CESMII
-
- en
- OPC UA Node Set Model mapping for Entity Framework
- Copyright © 2022 CESMII
- BSD-3-Clause
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/CESMII.OpcUa.NodeSetModel.EF/DbOpcUaContext.cs b/CESMII.OpcUa.NodeSetModel.EF/DbOpcUaContext.cs
deleted file mode 100644
index 4a1418cc..00000000
--- a/CESMII.OpcUa.NodeSetModel.EF/DbOpcUaContext.cs
+++ /dev/null
@@ -1,178 +0,0 @@
-/* ========================================================================
- * Copyright (c) 2005-2022 The OPC Foundation, Inc. All rights reserved.
- *
- * OPC Foundation MIT License 1.00
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * The complete license agreement can be found here:
- * http://opcfoundation.org/License/MIT/1.00/
- * ======================================================================*/
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using CESMII.OpcUa.NodeSetModel;
-using CESMII.OpcUa.NodeSetModel.Factory.Opc;
-using CESMII.OpcUa.NodeSetModel.Opc.Extensions;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Logging;
-using Opc.Ua;
-using Opc.Ua.Export;
-
-namespace CESMII.OpcUa.NodeSetModel.EF
-{
- public class DbOpcUaContext : DefaultOpcUaContext
- {
- protected DbContext _dbContext;
- protected Func _nodeSetFactory;
- protected List<(string ModelUri, DateTime? PublicationDate)> _namespacesInDb;
-
- public DbOpcUaContext(DbContext appDbContext, ILogger logger, Func nodeSetFactory = null)
- : base(logger)
- {
- this._dbContext = appDbContext;
- this._nodeSetFactory = nodeSetFactory;
- // Get all namespaces with at least one node: used for avoiding DB lookups
- this._namespacesInDb = _dbContext.Set().Select(nm => new { nm.NodeSet.ModelUri, nm.NodeSet.PublicationDate }).Distinct().AsEnumerable().Select(n => (n.ModelUri, n.PublicationDate)).ToList();
- }
- public DbOpcUaContext(DbContext appDbContext, SystemContext systemContext, NodeStateCollection importedNodes, Dictionary nodesetModels, ILogger logger, Func nodeSetFactory = null)
- : base(systemContext, importedNodes, nodesetModels, logger)
- {
- this._dbContext = appDbContext;
- this._nodeSetFactory = nodeSetFactory;
- }
-
- public override TNodeModel GetModelForNode(string nodeId)
- {
- var model = base.GetModelForNode(nodeId);
- if (model != null) return model;
-
- var uaNamespace = NodeModelUtils.GetNamespaceFromNodeId(nodeId);
- NodeModel nodeModelDb;
- if (_nodesetModels.TryGetValue(uaNamespace, out var nodeSet))
- {
- if (!_namespacesInDb.Contains((nodeSet.ModelUri, nodeSet.PublicationDate)))
- {
- // namespace was not in DB when the context was created: assume it's being imported
- return null;
- }
- else
- {
- // Preexisting namespace: find an entity if already in EF cache
- int retryCount = 0;
- bool lookedUp = false;
- do
- {
- try
- {
- nodeModelDb = _dbContext.Set().Local.FirstOrDefault(nm => nm.NodeId == nodeId && nm.NodeSet.ModelUri == nodeSet.ModelUri && nm.NodeSet.PublicationDate == nodeSet.PublicationDate);
- lookedUp = true;
- }
- catch (InvalidOperationException)
- {
- // re-try in case the NodeSet access caused a database query that modified the local cache
- nodeModelDb = null;
- }
- retryCount++;
- } while (!lookedUp && retryCount < 100);
- if (nodeModelDb == null)
- {
- // Not in EF cache: assume it's in the database and attach a proxy with just primary key values
- // This avoids a database lookup for each referenced node (or the need to pre-fetch all nodes in the EF cache)
- nodeModelDb = _dbContext.CreateProxy(nm =>
- {
- nm.NodeSet = nodeSet;
- nm.NodeId = nodeId;
- }
- );
- _dbContext.Attach(nodeModelDb);
- }
- }
- nodeModelDb?.NodeSet.AllNodesByNodeId.Add(nodeModelDb.NodeId, nodeModelDb);
- }
- else
- {
- nodeModelDb = _dbContext.Set().FirstOrDefault(nm => nm.NodeId == nodeId && nm.NodeSet.ModelUri == uaNamespace);
- if (nodeModelDb != null)
- {
- nodeSet = GetOrAddNodesetModel(new ModelTableEntry { ModelUri = nodeModelDb.NodeSet.ModelUri, PublicationDate = nodeModelDb.NodeSet.PublicationDate ?? DateTime.MinValue, PublicationDateSpecified = nodeModelDb.NodeSet.PublicationDate != null });
- nodeModelDb?.NodeSet.AllNodesByNodeId.Add(nodeModelDb.NodeId, nodeModelDb);
- }
- }
- if (!(nodeModelDb is TNodeModel))
- {
- _logger.LogWarning($"Nodemodel {nodeModelDb} is of type {nodeModelDb.GetType()} when type {typeof(TNodeModel)} was requested. Returning null.");
- }
- return nodeModelDb as TNodeModel;
- }
-
- public override NodeSetModel GetOrAddNodesetModel(ModelTableEntry model, bool createNew = true)
- {
- if (!_nodesetModels.TryGetValue(model.ModelUri, out var nodesetModel))
- {
- var existingNodeSet = GetMatchingOrHigherNodeSetAsync(model.ModelUri, model.GetNormalizedPublicationDate(), model.Version).Result;
- if (existingNodeSet != null)
- {
- _nodesetModels.Add(existingNodeSet.ModelUri, existingNodeSet);
- nodesetModel = existingNodeSet;
- }
- }
- if (nodesetModel == null && createNew)
- {
- if (_nodeSetFactory == null)
- {
- nodesetModel = base.GetOrAddNodesetModel(model, createNew);
- if (nodesetModel.PublicationDate == null)
- {
- // Primary Key value can not be null
- nodesetModel.PublicationDate = DateTime.MinValue;
- }
- }
- else
- {
- nodesetModel = _nodeSetFactory.Invoke(model);
- if (nodesetModel != null)
- {
- if (nodesetModel.ModelUri != model.ModelUri)
- {
- throw new ArgumentException($"Created mismatching nodeset: expected {model.ModelUri} created {nodesetModel.ModelUri}");
- }
- _nodesetModels.Add(nodesetModel.ModelUri, nodesetModel);
- }
- }
- }
- return nodesetModel;
- }
-
- public Task GetMatchingOrHigherNodeSetAsync(string modelUri, DateTime? publicationDate, string version)
- {
- return GetMatchingOrHigherNodeSetAsync(_dbContext, modelUri, publicationDate, version);
- }
- public static async Task GetMatchingOrHigherNodeSetAsync(DbContext dbContext, string modelUri, DateTime? publicationDate, string version)
- {
- var matchingNodeSets = await dbContext.Set()
- .Where(nsm => nsm.ModelUri == modelUri).ToListAsync();
- return NodeSetVersionUtils.GetMatchingOrHigherNodeSet(matchingNodeSets, publicationDate, version);
- }
- }
-}
diff --git a/CESMII.OpcUa.NodeSetModel.EF/NodeSetModelContext.cs b/CESMII.OpcUa.NodeSetModel.EF/NodeSetModelContext.cs
deleted file mode 100644
index bb7c0f63..00000000
--- a/CESMII.OpcUa.NodeSetModel.EF/NodeSetModelContext.cs
+++ /dev/null
@@ -1,315 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using System;
-using System.Collections.Generic;
-using System.Linq.Expressions;
-
-namespace CESMII.OpcUa.NodeSetModel.EF
-{
- public class NodeSetModelContext : DbContext
- {
- protected bool CascadeDelete { get; set; }
- public NodeSetModelContext(DbContextOptions options) : base(options)
- {
- // Blank
- }
-
- protected NodeSetModelContext(DbContextOptions options)
- {
- // Blank
- }
-
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- => optionsBuilder
- .UseLazyLoadingProxies()
- ;
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- base.OnModelCreating(modelBuilder);
- CreateModel(modelBuilder, CascadeDelete);
-
- }
- public static void CreateModel(ModelBuilder modelBuilder, bool cascadeDelete = false, bool methodArgs = false)
- {
- modelBuilder.Owned();
- modelBuilder.Owned();
- modelBuilder.Owned();
- modelBuilder.Owned();
- modelBuilder.Owned();
- modelBuilder.Owned();
-
- modelBuilder.Entity()
- .ToTable("NodeSets")
- .Ignore(nsm => nsm.AllNodesByNodeId)
- .Ignore(nsm => nsm.CustomState)
- .Ignore(nm => nm.NamespaceIndex)
- .HasKey(nsm => new { nsm.ModelUri, nsm.PublicationDate })
- ;
- var rmb = modelBuilder.Entity()
- .OwnsMany(nsm => nsm.RequiredModels)
- ;
- rmb.WithOwner()
- .HasForeignKey("DependentModelUri", "DependentPublicationDate");
- if (cascadeDelete)
- {
- rmb.HasOne(rm => rm.AvailableModel).WithMany()
- .OnDelete(DeleteBehavior.SetNull);
- }
- modelBuilder.Entity()
- .Ignore(nm => nm.CustomState)
- .Ignore(nm => nm.ReferencesNotResolved)
- .Property("NodeSetPublicationDate") // EF tooling does not properly infer the type of this auto-generated property when using it in a foreign key: workaround declare explcitly
- ;
- modelBuilder.Entity()
- .ToTable("Nodes")
- // This syntax is not supported by EF: use without typing
- //.HasKey(nm => new { nm.NodeId, nm.NodeSet.ModelUri, nm.NodeSet.PublicationDate })
- .HasKey(
- nameof(NodeModel.NodeId),
- $"{nameof(NodeModel.NodeSet)}{nameof(NodeSetModel.ModelUri)}",// Foreign key with auto-generated PK of the NodeModel.NodeSet property
- $"{nameof(NodeModel.NodeSet)}{nameof(NodeSetModel.PublicationDate)}")
- ;
- modelBuilder.Entity()
- .ToTable("ObjectTypes")
- ;
- var dtm = modelBuilder.Entity()
- .ToTable("DataTypes");
- if (cascadeDelete)
- {
- dtm.OwnsMany(dt => dt.StructureFields)
- .HasOne(sf => sf.DataType).WithMany().OnDelete(DeleteBehavior.Cascade)
- ;
- }
- var vtm = modelBuilder.Entity()
- .ToTable("VariableTypes")
- ;
- if (cascadeDelete)
- {
- vtm.HasOne(vt => vt.DataType).WithMany().OnDelete(DeleteBehavior.Cascade);
- }
- var dvmParentFk = modelBuilder.Entity()
- .ToTable("DataVariables")
- .HasOne(dv => dv.Parent).WithMany()
- .HasForeignKey("ParentNodeId", "ParentModelUri", "ParentPublicationDate")
- ;
- if (cascadeDelete)
- {
- dvmParentFk.OnDelete(DeleteBehavior.Cascade);
- }
-
- var pmParentFk = modelBuilder.Entity()
- .ToTable("Properties")
- .HasOne(dv => dv.Parent).WithMany()
- .HasForeignKey("ParentNodeId", "ParentModelUri", "ParentPublicationDate")
- ;
- if (cascadeDelete)
- {
- pmParentFk.OnDelete(DeleteBehavior.Cascade);
- }
- var omTd = modelBuilder.Entity()
- .ToTable("Objects")
- .HasOne(o => o.TypeDefinition).WithMany()
- ;
- if (cascadeDelete)
- {
- omTd.OnDelete(DeleteBehavior.Cascade);
- }
- var omParentFk = modelBuilder.Entity()
- .HasOne(dv => dv.Parent).WithMany()
- .HasForeignKey("ParentNodeId", "ParentModelUri", "ParentPublicationDate")
- ;
- if (cascadeDelete)
- {
- omParentFk.OnDelete(DeleteBehavior.Cascade);
- }
- modelBuilder.Entity()
- .ToTable("Interfaces")
- ;
- modelBuilder.Entity()
- .ToTable("Variables")
- .OwnsOne(v => v.EngineeringUnit).Property(v => v.NamespaceUri).IsRequired()
- ;
- if (cascadeDelete)
- {
- modelBuilder.Entity()
- .HasOne(vm => vm.DataType).WithMany().OnDelete(DeleteBehavior.Cascade);
- modelBuilder.Entity()
- .HasOne(vm => vm.TypeDefinition).WithMany().OnDelete(DeleteBehavior.Cascade);
- }
- var btmSt = modelBuilder.Entity()
- .ToTable("BaseTypes")
- .HasOne(bt => bt.SuperType).WithMany(bt => bt.SubTypes)
- ;
- if (cascadeDelete)
- {
- btmSt.OnDelete(DeleteBehavior.Cascade);
- }
- modelBuilder.Entity()
- .ToTable("DataTypes");
- modelBuilder.Entity()
- .ToTable("ObjectTypes");
- modelBuilder.Entity()
- .ToTable("Interfaces");
- modelBuilder.Entity()
- .ToTable("VariableTypes");
- modelBuilder.Entity()
- .ToTable("ReferenceTypes");
-
- if (!methodArgs)
- {
- modelBuilder.Entity()
- .Ignore(m => m.InputArguments)
- .Ignore(m => m.OutputArguments);
- }
- var mmParentFk = modelBuilder.Entity()
- .ToTable("Methods")
- .HasOne(dv => dv.Parent).WithMany()
- .HasForeignKey("ParentNodeId", "ParentModelUri", "ParentPublicationDate")
- ;
- if (cascadeDelete)
- {
- mmParentFk.OnDelete(DeleteBehavior.Cascade);
- }
- if (cascadeDelete)
- {
- modelBuilder.Entity()
- .HasOne(mm => mm.TypeDefinition).WithMany().OnDelete(DeleteBehavior.Cascade);
- }
- modelBuilder.Entity()
- .ToTable("ReferenceTypes")
- ;
-
- #region NodeSetModel collections
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.ObjectTypes, cascadeDelete);
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.VariableTypes, cascadeDelete);
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.DataTypes, cascadeDelete);
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.ReferenceTypes, cascadeDelete);
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.Objects, cascadeDelete);
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.Methods, cascadeDelete);
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.Interfaces, cascadeDelete);
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.Properties, cascadeDelete);
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.DataVariables, cascadeDelete);
- DeclareNodeSetCollection(modelBuilder, nsm => nsm.UnknownNodes, cascadeDelete);
- #endregion
-
- #region NodeModel collections
- // Unclear why these collection require declarations while the others just work
- modelBuilder.Entity()
- .HasMany(dv => dv.NodesWithDataVariables).WithMany(nm => nm.DataVariables);
- modelBuilder.Entity()
- .HasMany(nm => nm.Properties).WithMany(v => v.NodesWithProperties);
- modelBuilder.Entity()
- .HasMany(nm => nm.Interfaces).WithMany(v => v.NodesWithInterface);
-
- #endregion
-
- {
- var orn = modelBuilder.Entity()
- .OwnsMany(nm => nm.OtherReferencedNodes)
- ;
- orn.WithOwner()
- .HasForeignKey("OwnerNodeId", "OwnerModelUri", "OwnerPublicationDate")
- ;
- orn.Property("ReferencedNodeId");
- orn.Property("ReferencedModelUri");
- orn.Property("ReferencedPublicationDate");
- var ornFK = orn.HasOne(nr => nr.Node).WithMany()
- .HasForeignKey("ReferencedNodeId", "ReferencedModelUri", "ReferencedPublicationDate")
- ;
- if (cascadeDelete)
- {
- ornFK.OnDelete(DeleteBehavior.Cascade);
- }
- orn.Property("OwnerNodeId");
- orn.Property("OwnerModelUri");
- orn.Property("OwnerPublicationDate");
-
- //orn.Ignore(nr => nr.ReferenceType);
- orn.Property("ReferenceTypeNodeId");
- orn.Property("ReferenceTypeModelUri");
- orn.Property("ReferenceTypePublicationDate");
- //orn.Property(nr => nr.ReferenceType)
- // .HasConversion()
- // //.HasColumnType(typeof(NodeModel).FullName)
- // //.HasColumnType(typeof(NodeModel).FullName)
- // ;
- var ornRTFK = orn.HasOne(nr => nr.ReferenceType).WithMany()
- .HasForeignKey("ReferenceTypeNodeId", "ReferenceTypeModelUri", "ReferenceTypePublicationDate")
- //.HasPrincipalKey("NodeId", "ModelUri", "PublicationDate")
- ;
- if (cascadeDelete)
- {
- ornRTFK.OnDelete(DeleteBehavior.Cascade);
- }
- }
- {
- var orn = modelBuilder.Entity()
- .OwnsMany(nm => nm.OtherReferencingNodes)
- ;
- orn.WithOwner()
- .HasForeignKey("OwnerNodeId", "OwnerModelUri", "OwnerPublicationDate")
- ;
- orn.Property("ReferencingNodeId");
- orn.Property("ReferencingModelUri");
- orn.Property("ReferencingPublicationDate");
- var ornFK = orn.HasOne(nr => nr.Node).WithMany()
- .HasForeignKey("ReferencingNodeId", "ReferencingModelUri", "ReferencingPublicationDate")
- ;
- if (cascadeDelete)
- {
- ornFK.OnDelete(DeleteBehavior.Cascade);
- }
- orn.Property("OwnerNodeId");
- orn.Property("OwnerModelUri");
- orn.Property("OwnerPublicationDate");
-
- orn.Property("ReferenceTypeNodeId");
- orn.Property("ReferenceTypeModelUri");
- orn.Property("ReferenceTypePublicationDate");
- // TODO figure out why this does not work if ReferenceType is declared as ReferenceTypeModel instead of NodeModel
- //orn.Property(nr => nr.ReferenceType)
- // .HasConversion()
- // //.HasColumnType(typeof(NodeModel).FullName)
- // //.HasColumnType(typeof(NodeModel).FullName)
- // ;
- var ornRTFK = orn.HasOne(nr => nr.ReferenceType).WithMany()
- .HasForeignKey("ReferenceTypeNodeId", "ReferenceTypeModelUri", "ReferenceTypePublicationDate")
- ;
- if (cascadeDelete)
- {
- ornRTFK.OnDelete(DeleteBehavior.Cascade);
- }
-
- }
- }
-
- private static void DeclareNodeSetCollection(ModelBuilder modelBuilder, Expression>> collection, bool cascadeDelete) where TEntity : NodeModel
- {
- var collectionName = (collection.Body as MemberExpression).Member.Name;
- var modelProp = $"NodeSet{collectionName}ModelUri";
- var pubDateProp = $"NodeSet{collectionName}PublicationDate";
- modelBuilder.Entity().Property(modelProp);
- modelBuilder.Entity().Property(pubDateProp);
- var propFK = modelBuilder.Entity().HasOne("CESMII.OpcUa.NodeSetModel.NodeSetModel", null)
- .WithMany(collectionName)
- .HasForeignKey(modelProp, pubDateProp);
- if (cascadeDelete)
- {
- propFK.OnDelete(DeleteBehavior.Cascade);
- }
- // With this typed declaration the custom property names are not picked up for some reason
- //modelBuilder.Entity()
- // .HasOne(nm => nm.NodeSet).WithMany(collection)
- // .HasForeignKey(modelProp, pubDateProp)
- // ;
- //modelBuilder.Entity()
- // .HasMany(collection).WithOne(nm => nm.NodeSet)
- // .HasForeignKey(modelProp, pubDateProp)
- // ;
- }
-
- public DbSet NodeSets { get; set; }
- public DbSet NodeModels { get; set; }
- }
-
-}
\ No newline at end of file
diff --git a/CESMII.OpcUa.NodeSetModel.EF/readme.md b/CESMII.OpcUa.NodeSetModel.EF/readme.md
deleted file mode 100644
index d8de03e3..00000000
--- a/CESMII.OpcUa.NodeSetModel.EF/readme.md
+++ /dev/null
@@ -1,19 +0,0 @@
-Install tools into project:
-```
-cd ProfileDesigner\api\CESMIINodeSetUtilities
-dotnet tool install --global dotnet-ef
-dotnet tool update --global dotnet-ef
-```
-Create migration/database schema
-```
-dotnet ef migrations add InitialCreate --context NodeSetModelContext
-dotnet ef database update --context NodeSetModelContext
-```
-
-Recreate database:
-```
-del .\Migrations\*
-dotnet ef migrations add InitialCreate --context NodeSetModelContext
-dotnet ef database drop --context NodeSetModelContext
-dotnet ef database update --context NodeSetModelContext
-```
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/CESMII.OpcUa.NodeSetModel.Factory.Opc.csproj b/CESMII.OpcUa.NodeSetModel.Factory.Opc/CESMII.OpcUa.NodeSetModel.Factory.Opc.csproj
deleted file mode 100644
index 9b39eea9..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/CESMII.OpcUa.NodeSetModel.Factory.Opc.csproj
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
- netstandard2.0;netstandard2.1
- Debug;Release;Staging
- latest
- true
- cesmii.png
- 0.1
- Markus Horstmann
- CESMII
-
- en
- OPC UA Node Set Model factory: creates a Node Set Model from an OPC UA node set file.
- Copyright © 2022 CESMII
- BSD-3-Clause
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Never
-
-
-
-
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/DefaultOpcUaContext.cs b/CESMII.OpcUa.NodeSetModel.Factory.Opc/DefaultOpcUaContext.cs
deleted file mode 100644
index 15fbd370..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/DefaultOpcUaContext.cs
+++ /dev/null
@@ -1,220 +0,0 @@
-using Opc.Ua;
-
-using System.Collections.Generic;
-using System.Linq;
-using Microsoft.Extensions.Logging;
-using Opc.Ua.Export;
-using CESMII.OpcUa.NodeSetModel.Opc.Extensions;
-using CESMII.OpcUa.NodeSetModel.Export.Opc;
-using Microsoft.Extensions.Logging.Abstractions;
-
-namespace CESMII.OpcUa.NodeSetModel.Factory.Opc
-{
- public class DefaultOpcUaContext : IOpcUaContext
- {
- private readonly ISystemContext _systemContext;
- private readonly NodeStateCollection _importedNodes;
- protected readonly Dictionary _nodesetModels;
- protected readonly ILogger _logger;
-
- public DefaultOpcUaContext(ILogger logger)
- {
- _importedNodes = new NodeStateCollection();
- _nodesetModels = new Dictionary();
- _logger = logger ?? NullLogger.Instance;
-
- var namespaceTable = new NamespaceTable();
- namespaceTable.GetIndexOrAppend(Namespaces.OpcUa);
- var typeTable = new TypeTable(namespaceTable);
- _systemContext = new SystemContext()
- {
- NamespaceUris = namespaceTable,
- TypeTable = typeTable,
- EncodeableFactory = new DynamicEncodeableFactory(EncodeableFactory.GlobalFactory),
- };
- }
-
- public DefaultOpcUaContext(Dictionary nodesetModels, ILogger logger) : this(logger)
- {
- _nodesetModels = nodesetModels;
- _logger = logger ?? NullLogger.Instance;
- }
- public DefaultOpcUaContext(ISystemContext systemContext, NodeStateCollection importedNodes, Dictionary nodesetModels, ILogger logger)
- : this(nodesetModels, logger)
- {
- _systemContext = systemContext;
- _importedNodes = importedNodes;
- }
-
- public bool ReencodeExtensionsAsJson { get; set; }
- public bool EncodeJsonScalarsAsValue { get; set; }
-
- private Dictionary _importedNodesByNodeId;
- private Dictionary _importedUANodeSetsByUri = new();
-
- public NamespaceTable NamespaceUris { get => _systemContext.NamespaceUris; }
-
- public ILogger Logger => _logger;
-
- public bool UseLocalNodeIds { get; set; }
- public Dictionary NodeSetModels => _nodesetModels;
-
- public virtual string GetModelNodeId(NodeId nodeId)
- {
- string namespaceUri;
- namespaceUri = GetNamespaceUri(nodeId.NamespaceIndex);
- if (string.IsNullOrEmpty(namespaceUri))
- {
- throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "Namespace Index ({0}) for node id {1} is not in the namespace table.", nodeId.NamespaceIndex, nodeId);
- }
- if (UseLocalNodeIds)
- {
- return nodeId.ToString();
- }
- var nodeIdWithUri = new ExpandedNodeId(nodeId, namespaceUri).ToString();
- return nodeIdWithUri;
- }
-
- public virtual NodeState GetNode(ExpandedNodeId expandedNodeId)
- {
- var nodeId = ExpandedNodeId.ToNodeId(expandedNodeId, _systemContext.NamespaceUris);
- return GetNode(nodeId);
- }
-
- public virtual NodeState GetNode(NodeId nodeId)
- {
- _importedNodesByNodeId ??= _importedNodes.ToDictionary(n => n.NodeId);
- NodeState nodeStateDict = null;
- if (nodeId != null)
- {
- _importedNodesByNodeId.TryGetValue(nodeId, out nodeStateDict);
- }
- return nodeStateDict;
- }
-
- public virtual string GetNamespaceUri(ushort namespaceIndex)
- {
- return _systemContext.NamespaceUris.GetString(namespaceIndex);
- }
-
- public virtual TNodeModel GetModelForNode(string nodeId) where TNodeModel : NodeModel
- {
- foreach (var nodeSetModel in _nodesetModels.Values)
- {
- if (nodeSetModel.AllNodesByNodeId.TryGetValue(nodeId, out var nodeModel))
- {
- var result = nodeModel as TNodeModel;
- return result;
- }
- }
- return null;
- }
-
- public virtual NodeSetModel GetOrAddNodesetModel(ModelTableEntry model, bool createNew = true)
- {
- if (!_nodesetModels.TryGetValue(model.ModelUri, out var nodesetModel))
- {
- nodesetModel = new NodeSetModel();
- nodesetModel.ModelUri = model.ModelUri;
- nodesetModel.PublicationDate = model.GetNormalizedPublicationDate();
- nodesetModel.Version = model.Version;
- if (!string.IsNullOrEmpty(model.XmlSchemaUri))
- {
- nodesetModel.XmlSchemaUri = model.XmlSchemaUri;
- }
- if (UseLocalNodeIds)
- {
- nodesetModel.NamespaceIndex = NamespaceUris.GetIndexOrAppend(nodesetModel.ModelUri);
- }
- if (model.RequiredModel != null)
- {
- foreach (var requiredModel in model.RequiredModel)
- {
- var existingNodeSet = GetOrAddNodesetModel(requiredModel);
- var requiredModelInfo = new RequiredModelInfo
- {
- ModelUri = requiredModel.ModelUri,
- PublicationDate = requiredModel.GetNormalizedPublicationDate(),
- Version = requiredModel.Version,
- AvailableModel = existingNodeSet,
- };
- nodesetModel.RequiredModels.Add(requiredModelInfo);
- }
- }
- _nodesetModels.Add(nodesetModel.ModelUri, nodesetModel);
- }
- return nodesetModel;
- }
-
- public virtual List ImportUANodeSet(UANodeSet nodeSet)
- {
- var previousNodes = _importedNodes.ToList();
- if (nodeSet.Items?.Any() == true)
- {
- nodeSet.Import(_systemContext, _importedNodes);
- }
- var newlyImportedNodes = _importedNodes.Except(previousNodes).ToList();
- if (newlyImportedNodes.Any())
- {
- _importedNodesByNodeId = null;
- }
- var modelUri = nodeSet.Models?.FirstOrDefault()?.ModelUri;
- if (modelUri != null)
- {
- _importedUANodeSetsByUri.Add(modelUri, nodeSet);
- }
- return newlyImportedNodes;
- }
- public virtual UANodeSet GetUANodeSet(string modeluri)
- {
- if (_importedUANodeSetsByUri.TryGetValue(modeluri, out var nodeSet))
- {
- return nodeSet;
- }
- return null;
- }
-
- public virtual List GetHierarchyReferences(NodeState nodeState)
- {
- var hierarchy = new Dictionary();
- var references = new List();
- nodeState.GetHierarchyReferences(_systemContext, null, hierarchy, references);
- return references;
- }
-
- public virtual (string Json, bool IsScalar) JsonEncodeVariant(Variant wrappedValue, DataTypeModel dataType = null)
- {
- return NodeModelUtils.JsonEncodeVariant(_systemContext, wrappedValue, dataType, ReencodeExtensionsAsJson, EncodeJsonScalarsAsValue);
- }
-
- public virtual Variant JsonDecodeVariant(string jsonVariant, DataTypeModel dataType = null)
- {
- dataType ??= this.GetModelForNode(this.GetModelNodeId(DataTypeIds.String));
- var variant = NodeModelUtils.JsonDecodeVariant(jsonVariant, new ServiceMessageContext { NamespaceUris = _systemContext.NamespaceUris }, dataType, EncodeJsonScalarsAsValue);
- return variant;
- }
-
- public string GetModelBrowseName(QualifiedName browseName)
- {
- if (UseLocalNodeIds)
- {
- return browseName.ToString();
- }
- return $"{NamespaceUris.GetString(browseName.NamespaceIndex)};{browseName.Name}";
- }
-
- public QualifiedName GetBrowseNameFromModel(string modelBrowseName)
- {
- if (UseLocalNodeIds)
- {
- return QualifiedName.Parse(modelBrowseName);
- }
- var parts = modelBrowseName.Split(new[] { ';' }, 2);
- if (parts.Length == 1)
- {
- return new QualifiedName(parts[0]);
- }
- return new QualifiedName(parts[1], (ushort)NamespaceUris.GetIndex(parts[0]));
- }
- }
-}
\ No newline at end of file
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/DynamicComplexType.cs b/CESMII.OpcUa.NodeSetModel.Factory.Opc/DynamicComplexType.cs
deleted file mode 100644
index 0090611a..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/DynamicComplexType.cs
+++ /dev/null
@@ -1,895 +0,0 @@
-/* ========================================================================
- * Copyright (c) 2005-2022 The OPC Foundation, Inc. All rights reserved.
- *
- * OPC Foundation MIT License 1.00
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * The complete license agreement can be found here:
- * http://opcfoundation.org/License/MIT/1.00/
- * ======================================================================*/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Text;
-using System.Xml;
-using CESMII.OpcUa.NodeSetModel;
-using CESMII.OpcUa.NodeSetModel.Export.Opc;
-
-namespace Opc.Ua.Client.ComplexTypes
-{
- ///
- /// A complex type that performs encoding and decoding based on NodeSetModel type information, without requiring a concrete CLR type
- ///
- public class DynamicComplexType :
- IEncodeable, IJsonEncodeable, IFormattable, IComplexTypeInstance, IDynamicComplexTypeInstance
- {
- #region Constructors
- ///
- ///
- ///
- public DynamicComplexType()
- {
-
- }
-
- #endregion Constructors
-
- #region Public Properties
- ///
- public ExpandedNodeId TypeId { get; set; }
- ///
- public ExpandedNodeId BinaryEncodingId { get; set; }
- ///
- public ExpandedNodeId XmlEncodingId { get; set; }
- ///
- public ExpandedNodeId JsonEncodingId { get; set; }
-
- ///
- /// Makes a deep copy of the object.
- ///
- ///
- /// A new object that is a copy of this instance.
- ///
- public new virtual object MemberwiseClone()
- {
- throw new NotImplementedException();
- //Type thisType = this.GetType();
- //BaseComplexType clone = Activator.CreateInstance(thisType) as BaseComplexType;
-
- //clone.TypeId = TypeId;
- //clone.BinaryEncodingId = BinaryEncodingId;
- //clone.XmlEncodingId = XmlEncodingId;
-
- //// clone all properties of derived class
- //foreach (var property in GetPropertyEnumerator())
- //{
- // property.SetValue(clone, Utils.Clone(property.GetValue(this)));
- //}
-
- //return clone;
- }
-
- ///
- public virtual void Encode(IEncoder encoder)
- {
- InitializeDynamicEncodeable(encoder.Context);
-
- encoder.PushNamespace(XmlNamespace);
- foreach (DynamicTypePropertyInfo property in m_propertyList)
- {
- EncodeProperty(encoder, property);
- if (m_IsUnion && m_propertyDict.TryGetValue("SwitchField", out var sfObject) && sfObject is UInt32 sf && sf == 0)
- {
- // No fields
- break;
- }
- }
- encoder.PopNamespace();
- }
-
- ///
- public virtual void Decode(IDecoder decoder)
- {
- InitializeDynamicEncodeable(decoder.Context);
- decoder.PushNamespace(XmlNamespace);
- UInt32? encodingMask = null;
- UInt32 currentBit = 0;
-
- foreach (DynamicTypePropertyInfo property in m_propertyList)
- {
- if (encodingMask == null)
- {
- DecodeProperty(decoder, property);
- if (currentBit == 0 && property.Name == "EncodingMask")
- {
- // read encoding mask, but only if it's the first property (currentBit != 0 on subsequent iterations)
- encodingMask = (UInt32)m_propertyDict["EncodingMask"];
- }
- currentBit = 0x01;
- }
- else
- {
- if (!property.IsOptional || (currentBit & encodingMask ?? UInt32.MaxValue) != 0)
- {
- // Only decode non-optional properties or optional properties that are in encoding mask
- DecodeProperty(decoder, property);
- }
- if (property.IsOptional)
- {
- currentBit <<= 1;
- }
- }
- if (m_IsUnion && m_propertyDict.TryGetValue("SwitchField", out var sfObject) && sfObject is UInt32 sf && sf == 0)
- {
- // No fields
- break;
- }
- }
-
- decoder.PopNamespace();
- }
-
- private void InitializeDynamicEncodeable(IServiceMessageContext context)
- {
- if (m_propertyDict == null && this.TypeId != null && context.Factory is IDynamicEncodeableFactory dynamicFactory)
- {
- var dataType = dynamicFactory.GetDataTypeForEncoding(this.TypeId);
- if (dataType == null)
- {
- dataType = dynamicFactory.GetDataTypeForEncoding(this.XmlEncodingId);
- }
- if (dataType == null)
- {
- dataType = dynamicFactory.GetDataTypeForEncoding(this.BinaryEncodingId);
- }
- if (dataType == null)
- {
- dataType = dynamicFactory.GetDataTypeForEncoding(this.JsonEncodingId);
- }
- if (dataType != null)
- {
- var dtExpandedNodeId = ExpandedNodeId.Parse(dataType.NodeId);
- var dtNodeId = ExpandedNodeId.ToNodeId(dtExpandedNodeId, context.NamespaceUris);
- var builtInType = TypeInfo.GetBuiltInType(dtNodeId);
- if (builtInType != BuiltInType.Null && builtInType != BuiltInType.ExtensionObject)
- {
- return;
- }
-
- if (XmlNamespace == null)
- {
- XmlNamespace = GetXmlNamespace(dataType.NodeSet);
- }
- if (_xmlName == null)
- {
- var typeName = dataType.SymbolicName ?? dataType.DisplayName?.FirstOrDefault()?.Text;
- _xmlName = new XmlQualifiedName(typeName, XmlNamespace);
- }
-
- if (BinaryEncodingId == null)
- {
- var binaryEncodingId = dataType.OtherReferencedNodes.FirstOrDefault(rn =>
- rn.ReferenceType?.NodeId == new ExpandedNodeId(ReferenceTypeIds.HasEncoding, Namespaces.OpcUa).ToString()
- && rn.Node.BrowseName == $"{Namespaces.OpcUa};{BrowseNames.DefaultBinary}"
- )?.Node.NodeId;
- if (binaryEncodingId != null)
- {
- BinaryEncodingId = ExpandedNodeId.Parse(binaryEncodingId, context.NamespaceUris);
- }
- else
- {
- BinaryEncodingId = this.TypeId;
- }
- }
- if (XmlEncodingId == null)
- {
- var xmlEncodingId = dataType.OtherReferencedNodes.FirstOrDefault(rn =>
- rn.ReferenceType?.NodeId == new ExpandedNodeId(ReferenceTypeIds.HasEncoding, Namespaces.OpcUa).ToString()
- && rn.Node.BrowseName == $"{Namespaces.OpcUa};{BrowseNames.DefaultXml}"
- )?.Node.NodeId;
- if (xmlEncodingId != null)
- {
- XmlEncodingId = ExpandedNodeId.Parse(xmlEncodingId, context.NamespaceUris);
- }
- else
- {
- XmlEncodingId = this.TypeId;
- }
- }
- if (JsonEncodingId == null)
- {
- var jsonEncodingId = dataType.OtherReferencedNodes.FirstOrDefault(rn =>
- rn.ReferenceType?.NodeId == new ExpandedNodeId(ReferenceTypeIds.HasEncoding, Namespaces.OpcUa).ToString()
- && rn.Node.BrowseName == $"{Namespaces.OpcUa};{BrowseNames.DefaultJson}"
- )?.Node.NodeId;
- if (jsonEncodingId != null)
- {
- JsonEncodingId = ExpandedNodeId.Parse(jsonEncodingId, context.NamespaceUris);
- }
- else
- {
- JsonEncodingId = this.TypeId;
- }
- }
-
- var propertyTypeInfo = GetEncodeableTypeInfo(dataType, dynamicFactory, context.NamespaceUris);
-
- m_propertyList = propertyTypeInfo.ToList();
- m_propertyDict = m_propertyList.ToDictionary(p => p.Name, p => (object)null);
- }
- }
- }
-
- private static string GetXmlNamespace(NodeSetModel nodeSet)
- {
- return nodeSet.XmlSchemaUri ?? $"{nodeSet.ModelUri.TrimEnd('/')}/Types.xsd";
- }
-
- public List GetEncodeableTypeInfo(DataTypeModel dataType, IDynamicEncodeableFactory dynamicFactory, NamespaceTable namespaceUris)
- {
- List properties = new();
- var fields = dataType.GetStructureFieldsInherited();
- if (dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.Union}"))
- {
- m_IsUnion = true;
- if (!fields.Any(f => f.Name == "StructureField"))
- {
- // Union: add switchfield
- var property = new DynamicTypePropertyInfo
- {
- Name = "SwitchField",
- TypeId = DataTypeIds.UInt32,
- ValueRank = -1,
- BuiltInType = BuiltInType.UInt32,
- IsOptional = false,
- };
- properties.Add(property);
- }
- }
- if (fields.Any() /* || dataType.HasBaseType(new ExpandedNodeId(DataTypeIds.Structure, Namespaces.OpcUa).ToString())*/)
- {
- bool hasOptionalFields = false;
- foreach (var field in fields)
- {
- var fieldDt = field.DataType as DataTypeModel;
- if (field.IsOptional)
- {
- hasOptionalFields = true;
- }
- DynamicTypePropertyInfo property = GetPropertyTypeInfo(field.SymbolicName ?? field.Name, fieldDt, field.IsOptional, field.AllowSubTypes, field.ValueRank, dynamicFactory, namespaceUris);
- property.XmlSchemaUri = field.Owner.NodeSet.XmlSchemaUri;
- properties.Add(property);
- }
- if (hasOptionalFields)
- {
- properties.Insert(0, new DynamicTypePropertyInfo { BuiltInType = BuiltInType.UInt32, IsOptional = true, Name = "EncodingMask", ValueRank = -1 });
- }
- }
- else if (dataType.EnumFields?.Any() == true || dataType.HasBaseType(new ExpandedNodeId(DataTypeIds.Enumeration, Namespaces.OpcUa).ToString()))
- {
- DynamicTypePropertyInfo property = GetPropertyTypeInfo(dataType.BrowseName, dataType, false, false, null, dynamicFactory, namespaceUris);
- property.IsEnum = true;
- properties.Add(property);
- }
- return properties;
- }
-
- private static DynamicTypePropertyInfo GetPropertyTypeInfo(string propertyName, DataTypeModel dataType, bool isOptional, bool allowSubTypes, int? valueRank, IDynamicEncodeableFactory dynamicFactory, NamespaceTable namespaceUris)
- {
- var builtInType = DynamicEncodeableFactory.GetBuiltInType(dataType as DataTypeModel, namespaceUris);
- Type systemType = builtInType != BuiltInType.Null ? null : typeof(DynamicComplexType);
- bool isEnum = false;
- if (builtInType == BuiltInType.Null && dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.Enumeration}"))
- {
- isEnum = true;
- // Get the current application domain for the current thread.
- AppDomain currentDomain = AppDomain.CurrentDomain;
-
- // Create a dynamic assembly in the current application domain,
- // and allow it to be executed and saved to disk.
- var aName = new AssemblyName("TempAssembly");
- var ab = AssemblyBuilder.DefineDynamicAssembly(
- aName, AssemblyBuilderAccess.Run);
-
- // Define a dynamic module in "TempAssembly" assembly. For a single-
- // module assembly, the module has the same name as the assembly.
- ModuleBuilder mb = ab.DefineDynamicModule(aName.Name);
-
- // Define a public enumeration with the name "Elevation" and an
- // underlying type of Integer.
- EnumBuilder eb = mb.DefineEnum(dataType.SymbolicName ?? dataType.DisplayName.FirstOrDefault().Text, TypeAttributes.Public, typeof(int));
- foreach (var enumField in dataType.EnumFields)
- {
- eb.DefineLiteral(enumField.Name, (int)enumField.Value);
- }
- // Create the type and save the assembly.
- systemType = eb.CreateTypeInfo().AsType();
- }
- var encodings = dynamicFactory.AddEncodingsForDataType(dataType, namespaceUris);
- ExpandedNodeId binaryEncodingId = null, xmlEncodingId = null, jsonEncodingId = null;
- if (encodings != null)
- {
- encodings.TryGetValue(BrowseNames.DefaultBinary, out binaryEncodingId);
- encodings.TryGetValue(BrowseNames.DefaultXml, out xmlEncodingId);
- encodings.TryGetValue(BrowseNames.DefaultJson, out jsonEncodingId);
- }
- var property = new DynamicTypePropertyInfo
- {
- Name = propertyName,
- TypeId = DynamicEncodeableFactory.NormalizeNodeIdForEncodableFactory(ExpandedNodeId.Parse(dataType.NodeId), namespaceUris),
- BinaryEncodingId = binaryEncodingId,
- XmlEncodingId = xmlEncodingId,
- JsonEncodingId = jsonEncodingId,
- ValueRank = valueRank ?? -1,
- BuiltInType = builtInType,
- SystemType = systemType,
- IsOptional = isOptional,
- AllowSubTypes = allowSubTypes,
- IsEnum = isEnum,
- };
- return property;
- }
-
- ///
- public virtual bool IsEqual(IEncodeable encodeable)
- {
- if (Object.ReferenceEquals(this, encodeable))
- {
- return true;
- }
-
- if (!(encodeable is DynamicComplexType valueBaseType))
- {
- return false;
- }
-
- var valueType = valueBaseType.GetType();
- if (this.GetType() != valueType)
- {
- return false;
- }
- throw new NotImplementedException();
- //foreach (var property in GetPropertyEnumerator())
- //{
- // if (!Utils.IsEqual(property.GetValue(this), property.GetValue(valueBaseType)))
- // {
- // return false;
- // }
- //}
-
- //return true;
- }
-
- ///
- public override string ToString()
- {
- return ToString(null, null);
- }
- #endregion Public Properties
-
- #region IFormattable Members
- ///
- /// Returns the string representation of the complex type.
- ///
- /// (Unused). Leave this as null
- /// The provider of a mechanism for retrieving an object to control formatting.
- ///
- /// A containing the value of the current embeded instance in the specified format.
- ///
- /// Thrown if the format parameter is not null
- public virtual string ToString(string format, IFormatProvider formatProvider)
- {
- if (format == null)
- {
- StringBuilder body = new StringBuilder();
-
- foreach (var property in m_propertyList)
- {
- AppendPropertyValue(formatProvider, body, m_propertyDict[property.Name], property.ValueRank);
- }
-
- if (body.Length > 0)
- {
- return body.Append('}').ToString();
- }
-
- if (!NodeId.IsNull(this.TypeId))
- {
- return String.Format(formatProvider, "{{{0}}}", this.TypeId);
- }
-
- return "(null)";
- }
-
- throw new FormatException(Utils.Format("Invalid format string: '{0}'.", format));
- }
- #endregion IFormattable Members
-
- #region IComplexTypeProperties
- ///
- public virtual int GetPropertyCount()
- {
- return m_propertyList?.Count ?? 0;
- }
-
- ///
- ///
- public virtual object this[int index]
- {
- get => m_propertyDict[m_propertyList.ElementAt(index).Name];
- set => m_propertyDict[m_propertyList.ElementAt(index).Name] = value;
- }
-
- ///
- public virtual object this[string name]
- {
- get => m_propertyDict[name];
- set => m_propertyDict[name] = value;
- }
-
- #endregion IComplexTypeProperties
-
- #region Private Members
- ///
- /// Formatting helper.
- ///
- private void AddSeparator(StringBuilder body)
- {
- if (body.Length == 0)
- {
- body.Append('{');
- }
- else
- {
- body.Append('|');
- }
- }
-
- ///
- /// Append a property to the value string.
- /// Handle arrays and enumerations.
- ///
- protected void AppendPropertyValue(
- IFormatProvider formatProvider,
- StringBuilder body,
- object value,
- int valueRank)
- {
- AddSeparator(body);
- if (valueRank >= 0 && value is Array array)
- {
- var rank = array.Rank;
- var dimensions = new int[rank];
- var mods = new int[rank];
- for (int ii = 0; ii < rank; ii++)
- {
- dimensions[ii] = array.GetLength(ii);
- }
-
- for (int ii = rank - 1; ii >= 0; ii--)
- {
- mods[ii] = dimensions[ii];
- if (ii < rank - 1)
- {
- mods[ii] *= mods[ii + 1];
- }
- }
-
- int count = 0;
- foreach (var item in array)
- {
- bool needSeparator = true;
- for (int dc = 0; dc < rank; dc++)
- {
- if ((count % mods[dc]) == 0)
- {
- body.Append('[');
- needSeparator = false;
- }
- }
- if (needSeparator)
- {
- body.Append(',');
- }
- AppendPropertyValue(formatProvider, body, item);
- count++;
- needSeparator = false;
- for (int dc = 0; dc < rank; dc++)
- {
- if ((count % mods[dc]) == 0)
- {
- body.Append(']');
- needSeparator = true;
- }
- }
- if (needSeparator && count < array.Length)
- {
- body.Append(',');
- }
- }
- }
- else if (valueRank >= 0 && value is IEnumerable enumerable)
- {
- bool first = true;
- body.Append('[');
- foreach (var item in enumerable)
- {
- if (!first)
- {
- body.Append(',');
- }
- AppendPropertyValue(formatProvider, body, item);
- first = false;
- }
- body.Append(']');
- }
- else
- {
- AppendPropertyValue(formatProvider, body, value);
- }
- }
-
- ///
- /// Append a property to the value string.
- ///
- private void AppendPropertyValue(
- IFormatProvider formatProvider,
- StringBuilder body,
- object value)
- {
- if (value is byte[] x)
- {
- body.AppendFormat(formatProvider, "Byte[{0}]", x.Length);
- return;
- }
-
- if (value is XmlElement xmlElements)
- {
- body.AppendFormat(formatProvider, "<{0}>", xmlElements.Name);
- return;
- }
-
- body.AppendFormat(formatProvider, "{0}", value);
- }
-
- ///
- /// Encode a property based on the property type and value rank.
- ///
- protected void EncodeProperty(
- IEncoder encoder,
- DynamicTypePropertyInfo property
- )
- {
- int valueRank = property.ValueRank;
- BuiltInType builtInType = property.BuiltInType;
- var propertyValue = m_propertyDict[property.Name];
- if (propertyValue == null)
- {
- return;
- }
- if (property.XmlSchemaUri != null && property.XmlSchemaUri != XmlNamespace)
- {
- encoder.PushNamespace(property.XmlSchemaUri);
- }
- if (valueRank == ValueRanks.Scalar)
- {
- EncodeProperty(encoder, property.Name, propertyValue, builtInType, property.SystemType, false, property.AllowSubTypes);
- }
- else if (valueRank >= ValueRanks.OneDimension)
- {
- EncodePropertyArray(encoder, property.Name, propertyValue, builtInType, valueRank, false);
- }
- else
- {
- throw ServiceResultException.Create(StatusCodes.BadEncodingError,
- "Cannot encode a property with unsupported ValueRank {0}.", valueRank);
- }
- if (property.XmlSchemaUri != null && property.XmlSchemaUri != XmlNamespace)
- {
- encoder.PopNamespace();
- }
- }
-
- ///
- /// Encode a scalar property based on the property type.
- ///
- private void EncodeProperty(IEncoder encoder, string name, object propertyValue, BuiltInType builtInType, Type systemType, bool isEnum, bool allowSubTypes)
- {
- if (systemType?.IsEnum == true)
- {
- isEnum = true;
- builtInType = BuiltInType.Enumeration;
- }
- switch (builtInType)
- {
- case BuiltInType.Boolean: encoder.WriteBoolean(name, (Boolean)propertyValue); break;
- case BuiltInType.SByte: encoder.WriteSByte(name, (SByte)propertyValue); break;
- case BuiltInType.Byte: encoder.WriteByte(name, (Byte)propertyValue); break;
- case BuiltInType.Int16: encoder.WriteInt16(name, (Int16)propertyValue); break;
- case BuiltInType.UInt16: encoder.WriteUInt16(name, (UInt16)propertyValue); break;
- case BuiltInType.Int32: encoder.WriteInt32(name, (Int32)propertyValue); break;
- case BuiltInType.UInt32: encoder.WriteUInt32(name, (UInt32)propertyValue); break;
- case BuiltInType.Int64: encoder.WriteInt64(name, (Int64)propertyValue); break;
- case BuiltInType.UInt64: encoder.WriteUInt64(name, (UInt64)propertyValue); break;
- case BuiltInType.Float: encoder.WriteFloat(name, (Single)propertyValue); break;
- case BuiltInType.Double: encoder.WriteDouble(name, (Double)propertyValue); break;
- case BuiltInType.String: encoder.WriteString(name, (String)propertyValue); break;
- case BuiltInType.DateTime: encoder.WriteDateTime(name, (DateTime)propertyValue); break;
- case BuiltInType.Guid: encoder.WriteGuid(name, (Uuid)propertyValue); break;
- case BuiltInType.ByteString: encoder.WriteByteString(name, (Byte[])propertyValue); break;
- case BuiltInType.XmlElement: encoder.WriteXmlElement(name, (XmlElement)propertyValue); break;
- case BuiltInType.NodeId: encoder.WriteNodeId(name, (NodeId)propertyValue); break;
- case BuiltInType.ExpandedNodeId: encoder.WriteExpandedNodeId(name, (ExpandedNodeId)propertyValue); break;
- case BuiltInType.StatusCode: encoder.WriteStatusCode(name, (StatusCode)propertyValue); break;
- case BuiltInType.DiagnosticInfo: encoder.WriteDiagnosticInfo(name, (DiagnosticInfo)propertyValue); break;
- case BuiltInType.QualifiedName: encoder.WriteQualifiedName(name, (QualifiedName)propertyValue); break;
- case BuiltInType.LocalizedText: encoder.WriteLocalizedText(name, (LocalizedText)propertyValue); break;
- case BuiltInType.DataValue: encoder.WriteDataValue(name, (DataValue)propertyValue); break;
- case BuiltInType.Variant: encoder.WriteVariant(name, (Variant)propertyValue); break;
- case BuiltInType.ExtensionObject: encoder.WriteExtensionObject(name, (ExtensionObject)propertyValue); break;
- case BuiltInType.Enumeration:
- if (isEnum)
- {
- encoder.WriteEnumerated(name, propertyValue as Enum);
- break;
- }
- goto case BuiltInType.Int32;
- default:
- if (propertyValue is IEncodeable encodableValue)
- {
- if (allowSubTypes)
- {
- encoder.WriteExtensionObject(name, new ExtensionObject(encodableValue));
- }
- else
- {
- encoder.WriteEncodeable(name, encodableValue, systemType);
- }
- break;
- }
- throw ServiceResultException.Create(StatusCodes.BadEncodingError,
- "Cannot encode unknown type {0}.", propertyValue?.GetType());
- }
- }
-
- ///
- /// Encode an array property based on the base property type.
- ///
- private void EncodePropertyArray(IEncoder encoder, string name, object propertyValue, BuiltInType builtInType, int valueRank, bool isEnum)
- {
- if (isEnum)
- {
- builtInType = BuiltInType.Enumeration;
- }
- if (propertyValue != null)
- {
- encoder.WriteArray(name, propertyValue, valueRank, builtInType);
- }
- }
-
- ///
- /// Decode a property based on the property type and value rank.
- ///
- protected void DecodeProperty(
- IDecoder decoder,
- DynamicTypePropertyInfo property)
- {
-
- if (property.XmlSchemaUri != null && property.XmlSchemaUri != XmlNamespace)
- {
- decoder.PushNamespace(property.XmlSchemaUri);
- }
-
- int valueRank = property.ValueRank;
- if (valueRank == ValueRanks.Scalar)
- {
- DecodeProperty(decoder, property.Name, property.BuiltInType, property.SystemType, property.IsEnum, property.AllowSubTypes, property.TypeId);
- }
- else if (valueRank >= ValueRanks.OneDimension)
- {
- DecodePropertyArray(decoder, property.Name, property.BuiltInType, property.SystemType, valueRank, property.IsEnum, property.TypeId);
- }
- else
- {
- throw ServiceResultException.Create(StatusCodes.BadDecodingError,
- "Cannot decode a property with unsupported ValueRank {0}.", valueRank);
- }
- if (property.XmlSchemaUri != null && property.XmlSchemaUri != XmlNamespace)
- {
- decoder.PopNamespace();
- }
- }
-
- ///
- /// Decode a scalar property based on the property type.
- ///
- private void DecodeProperty(IDecoder decoder, string name, BuiltInType builtInType, Type systemType, bool isEnum, bool allowSubTypes, ExpandedNodeId typeId)
- {
- //var propertyType = property.PropertyType;
- if (systemType?.IsEnum == true)
- {
- isEnum = true;
- builtInType = BuiltInType.Enumeration;
- }
- switch (builtInType)
- {
- case BuiltInType.Boolean: m_propertyDict[name] = decoder.ReadBoolean(name); break;
- case BuiltInType.SByte: m_propertyDict[name] = decoder.ReadSByte(name); break;
- case BuiltInType.Byte: m_propertyDict[name] = decoder.ReadByte(name); break;
- case BuiltInType.Int16: m_propertyDict[name] = decoder.ReadInt16(name); break;
- case BuiltInType.UInt16: m_propertyDict[name] = decoder.ReadUInt16(name); break;
- case BuiltInType.Int32: m_propertyDict[name] = decoder.ReadInt32(name); break;
- case BuiltInType.UInt32: m_propertyDict[name] = decoder.ReadUInt32(name); break;
- case BuiltInType.Int64: m_propertyDict[name] = decoder.ReadInt64(name); break;
- case BuiltInType.UInt64: m_propertyDict[name] = decoder.ReadUInt64(name); break;
- case BuiltInType.Float: m_propertyDict[name] = decoder.ReadFloat(name); break;
- case BuiltInType.Double: m_propertyDict[name] = decoder.ReadDouble(name); break;
- case BuiltInType.String: m_propertyDict[name] = decoder.ReadString(name); break;
- case BuiltInType.DateTime: m_propertyDict[name] = decoder.ReadDateTime(name); break;
- case BuiltInType.Guid: m_propertyDict[name] = decoder.ReadGuid(name); break;
- case BuiltInType.ByteString: m_propertyDict[name] = decoder.ReadByteString(name); break;
- case BuiltInType.XmlElement: m_propertyDict[name] = decoder.ReadXmlElement(name); break;
- case BuiltInType.NodeId: m_propertyDict[name] = decoder.ReadNodeId(name); break;
- case BuiltInType.ExpandedNodeId: m_propertyDict[name] = decoder.ReadExpandedNodeId(name); break;
- case BuiltInType.StatusCode: m_propertyDict[name] = decoder.ReadStatusCode(name); break;
- case BuiltInType.QualifiedName: m_propertyDict[name] = decoder.ReadQualifiedName(name); break;
- case BuiltInType.LocalizedText: m_propertyDict[name] = decoder.ReadLocalizedText(name); break;
- case BuiltInType.DataValue: m_propertyDict[name] = decoder.ReadDataValue(name); break;
- case BuiltInType.Variant: m_propertyDict[name] = decoder.ReadVariant(name); break;
- case BuiltInType.DiagnosticInfo: m_propertyDict[name] = decoder.ReadDiagnosticInfo(name); break;
- case BuiltInType.ExtensionObject:
- m_propertyDict[name] = decoder.ReadExtensionObject(name);
- break;
- case BuiltInType.Enumeration:
- if (isEnum)
- {
- m_propertyDict[name] = decoder.ReadEnumerated(name, systemType); break;
- }
- goto case BuiltInType.Int32;
- default:
- Type encodeableType = null;
- if (!decoder.Context.Factory.EncodeableTypes.TryGetValue(typeId, out encodeableType))
- {
- if (typeof(IEncodeable).IsAssignableFrom(systemType))
- {
- encodeableType = systemType;
- }
- }
- if (encodeableType != null)
- {
- if (allowSubTypes)
- {
- m_propertyDict[name] = decoder.ReadExtensionObject(name)?.Body;
- }
- else
- {
- m_propertyDict[name] = decoder.ReadEncodeable(name, encodeableType, typeId);
- }
- }
- else
- {
- throw ServiceResultException.Create(StatusCodes.BadDecodingError,
- "Cannot decode unknown type {0} with encoding {1}.", systemType, typeId);
- //m_propertyDict[name] = decoder.ReadEncodeable(name, typeof(DynamicComplexType), typeId);
- }
- break;
- }
- }
-
- ///
- /// Decode an array property based on the base property type.
- ///
- private void DecodePropertyArray(IDecoder decoder, string name, BuiltInType builtInType, Type systemType, int valueRank, bool isEnum, ExpandedNodeId typeId)
- {
- if (isEnum)
- {
- builtInType = BuiltInType.Enumeration;
- }
- Array decodedArray = decoder.ReadArray(name, valueRank, builtInType/*, elementType*/, systemType, typeId);
- m_propertyDict[name] = decodedArray;
- }
-
- ///
- ///
- ///
- ///
- public XmlQualifiedName GetXmlName(IServiceMessageContext context)
- {
- InitializeDynamicEncodeable(context);
- return _xmlName;
- }
-
- public object Clone()
- {
- throw new NotImplementedException();
- }
-
- private XmlQualifiedName _xmlName;
-
- #endregion Private Members
-
- #region Protected Properties
- ///
- /// Provide XmlNamespace
- ///
- public string XmlNamespace { get; set; }
-
- #endregion
-
- #region Protected Fields
- ///
- /// The list of properties of this complex type.
- ///
- protected IList m_propertyList;
-
- ///
- /// The list of properties as dictionary.
- ///
- protected Dictionary m_propertyDict;
- private bool m_IsUnion;
- #endregion Protected Fields
-
- #region Private Fields
- //private XmlQualifiedName m_xmlName;
- #endregion Private Fields
- }
-
- ///
- ///
- ///
- public class DynamicTypePropertyInfo
- {
- ///
- public int ValueRank { get; set; }
- ///
- public BuiltInType BuiltInType { get; set; }
- public Type SystemType { get; set; }
- ///
- public string Name { get; set; }
- ///
- /// Indicates optional structure field: important for JSON and XML encodingmask
- ///
- public bool IsOptional { get; set; }
- ///
- /// Indicates if subtypes are allowed: uses ExtensionObject encoding to capture the type/encoding id
- ///
- public bool AllowSubTypes { get; set; }
- ///
- public ExpandedNodeId TypeId { get; set; }
- ///
- public ExpandedNodeId BinaryEncodingId { get; set; }
- ///
- public ExpandedNodeId XmlEncodingId { get; set; }
- ///
- public ExpandedNodeId JsonEncodingId { get; set; }
- public bool IsEnum { get; set; }
- public string XmlSchemaUri { get; set; }
-
- public override string ToString() => $"{Name} {TypeId} {XmlEncodingId} {XmlSchemaUri}";
- }
-
-
-}//namespace
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/DynamicEncodeableFactory.cs b/CESMII.OpcUa.NodeSetModel.Factory.Opc/DynamicEncodeableFactory.cs
deleted file mode 100644
index 8b48bb80..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/DynamicEncodeableFactory.cs
+++ /dev/null
@@ -1,126 +0,0 @@
-using Opc.Ua;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Xml;
-
-using Opc.Ua.Client.ComplexTypes;
-using System.Runtime.Serialization;
-using R = System.Reflection;
-using System.Reflection.Emit;
-//using Opc.Ua.Gds;
-
-namespace CESMII.OpcUa.NodeSetModel.Export.Opc
-{
-
- ///
- ///
- ///
- public interface IDynamicEncodeableFactory
- {
- public DataTypeModel GetDataTypeForEncoding(ExpandedNodeId typeId);
- Dictionary AddEncodingsForDataType(DataTypeModel dataType, NamespaceTable namespaceUris);
- }
-
- public class DynamicEncodeableFactory : EncodeableFactory, IDynamicEncodeableFactory
- {
- Dictionary _dynamicDataTypes = new();
-
- public DynamicEncodeableFactory(IEncodeableFactory factory) : base(factory)
- {
- }
-
- public DataTypeModel GetDataTypeForEncoding(ExpandedNodeId typeId)
- {
- if (typeId != null)
- {
- if (_dynamicDataTypes.TryGetValue(typeId, out var dataType))
- {
- return dataType;
- }
- }
- return null;
- }
-
- public Dictionary AddEncodingsForDataType(DataTypeModel dataType, NamespaceTable namespaceUris)
- {
- bool bTypeAlreadyProcessed = false;
- var dataTypeExpandedNodeId = ExpandedNodeId.Parse(dataType.NodeId);
- dataTypeExpandedNodeId = NormalizeNodeIdForEncodableFactory(dataTypeExpandedNodeId, namespaceUris);
-
- if (_dynamicDataTypes.ContainsKey(dataTypeExpandedNodeId))
- {
- // Used later to break recursion for recursive data structures
- bTypeAlreadyProcessed = true;
- }
- BuiltInType builtInType = GetBuiltInType(dataType, namespaceUris);
- if (builtInType != BuiltInType.Null && builtInType != BuiltInType.ExtensionObject)
- {
- return null;
- }
-
- _dynamicDataTypes[dataTypeExpandedNodeId] = dataType;
-
- var encodingsDict = new Dictionary();
- var encodings = dataType.OtherReferencedNodes.Where(rn => rn.ReferenceType?.NodeId == new ExpandedNodeId(ReferenceTypeIds.HasEncoding, Namespaces.OpcUa).ToString());
- foreach(var encoding in encodings)
- {
- var encodingExpandedNodeId = ExpandedNodeId.Parse(encoding.Node.NodeId);
- encodingExpandedNodeId = NormalizeNodeIdForEncodableFactory(encodingExpandedNodeId, namespaceUris);
-
- var encodingName = encoding.Node.BrowseName.Replace($"{Namespaces.OpcUa};", "");
- if (!encodingsDict.ContainsKey(encodingName))
- {
- encodingsDict.Add(encodingName, encodingExpandedNodeId);
- }
- if (!EncodeableTypes.ContainsKey(encodingExpandedNodeId))
- {
- this.AddEncodeableType(encodingExpandedNodeId, typeof(DynamicComplexType));
- _dynamicDataTypes[encodingExpandedNodeId] = dataType;
- }
- }
- if (!this.EncodeableTypes.ContainsKey(dataTypeExpandedNodeId))
- {
- this.AddEncodeableType(dataTypeExpandedNodeId, typeof(DynamicComplexType));
- }
-
- if (!bTypeAlreadyProcessed && dataType.StructureFields?.Any() == true)
- {
- foreach (var field in dataType.StructureFields)
- {
- AddEncodingsForDataType(field.DataType as DataTypeModel, namespaceUris);
- }
- }
- return encodingsDict;
- }
-
- public static ExpandedNodeId NormalizeNodeIdForEncodableFactory(ExpandedNodeId expandedNodeId, NamespaceTable namespaceUris)
- {
- // check for default namespace.
- if (expandedNodeId.NamespaceUri == Namespaces.OpcUa)
- {
- // EncodableFactory expects namespace 0 nodeids to have no URI, and all others to provide the URI
- expandedNodeId = NodeId.ToExpandedNodeId(ExpandedNodeId.ToNodeId(expandedNodeId, namespaceUris), namespaceUris);
- }
- return expandedNodeId;
- }
-
- public static BuiltInType GetBuiltInType(DataTypeModel dataType, NamespaceTable namespaceUris)
- {
- var dtNodeId = ExpandedNodeId.Parse(dataType.NodeId, namespaceUris);
- var builtInType = TypeInfo.GetBuiltInType(dtNodeId);
- if (builtInType == BuiltInType.Null && dataType.SuperType != null)
- {
- var superTypeBuiltInType = GetBuiltInType(dataType.SuperType as DataTypeModel, namespaceUris);
- if (superTypeBuiltInType == BuiltInType.ExtensionObject || superTypeBuiltInType == BuiltInType.Enumeration)
- {
- return BuiltInType.Null;
- }
- return superTypeBuiltInType;
- }
- return builtInType;
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/ExportContext.cs b/CESMII.OpcUa.NodeSetModel.Factory.Opc/ExportContext.cs
deleted file mode 100644
index bc3686bd..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/ExportContext.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System.Collections.Generic;
-using Opc.Ua.Export;
-using CESMII.OpcUa.NodeSetModel.Factory.Opc;
-using Microsoft.Extensions.Logging;
-
-namespace CESMII.OpcUa.NodeSetModel.Export.Opc
-{
- public class ExportContext : DefaultOpcUaContext
- {
- public ExportContext(ILogger logger, Dictionary nodeSetModels) : base(nodeSetModels, logger)
- {
- }
- public Dictionary Aliases;
- ///
- /// Assumes that any VariableModel.Value or VariableTypeModel.Value that contain scalars just contain the scalar value, rather than the OPC JSON encoding
- ///
-
- public HashSet _nodeIdsUsed;
- public Dictionary _exportedSoFar;
- }
-
-}
\ No newline at end of file
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/IOpcUaContext.cs b/CESMII.OpcUa.NodeSetModel.Factory.Opc/IOpcUaContext.cs
deleted file mode 100644
index 333a4bd1..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/IOpcUaContext.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using Opc.Ua;
-
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.Logging;
-using Opc.Ua.Export;
-
-namespace CESMII.OpcUa.NodeSetModel.Factory.Opc
-{
- public interface IOpcUaContext
- {
- // OPC utilities
- NamespaceTable NamespaceUris { get; }
- ///
- /// NodeIds in the NodeModel will not use namespace URIs ("nsu=", absolute NodeIds) but namespace indices ("ns=", local NodeIds).
- /// Use only if the NodeModel is generated in the context of a specific OPC server, or in a specific set of nodesets that are loaded in a specific order.
- ///
- bool UseLocalNodeIds { get; }
- ///
- /// /
- ///
- ///
- ///
- ///
- string GetModelNodeId(NodeId nodeId);
-
- // OPC NodeState cache
- NodeState GetNode(NodeId nodeId);
- NodeState GetNode(ExpandedNodeId expandedNodeId);
- List GetHierarchyReferences(NodeState nodeState);
-
- // NodesetModel cache
- NodeSetModel GetOrAddNodesetModel(ModelTableEntry model, bool createNew = true);
- TNodeModel GetModelForNode(string nodeId) where TNodeModel : NodeModel;
- ILogger Logger { get; }
- (string Json, bool IsScalar) JsonEncodeVariant(Variant wrappedValue, DataTypeModel dataType = null);
- Variant JsonDecodeVariant(string jsonVariant, DataTypeModel dataType = null);
- List ImportUANodeSet(UANodeSet nodeSet);
- UANodeSet GetUANodeSet(string modeluri);
-
- string GetModelBrowseName(QualifiedName browseName);
- QualifiedName GetBrowseNameFromModel(string modelBrowseName);
-
- Dictionary NodeSetModels { get; }
- }
-}
\ No newline at end of file
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeModelOpcExtensions.cs b/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeModelOpcExtensions.cs
deleted file mode 100644
index 6aa2bddc..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeModelOpcExtensions.cs
+++ /dev/null
@@ -1,494 +0,0 @@
-using Opc.Ua;
-using ua = Opc.Ua;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-using NotVisualBasic.FileIO;
-using System.Reflection;
-using Opc.Ua.Export;
-using System;
-
-using CESMII.OpcUa.NodeSetModel.Factory.Opc;
-using Newtonsoft.Json;
-using Microsoft.Extensions.Logging;
-
-namespace CESMII.OpcUa.NodeSetModel.Opc.Extensions
-{
- public static class NodeModelOpcExtensions
- {
- public static string GetDisplayNamePath(this InstanceModelBase model)
- {
- return model.GetDisplayNamePath(new List());
- }
- public static DateTime GetNormalizedPublicationDate(this ModelTableEntry model)
- {
- return model.PublicationDateSpecified ? DateTime.SpecifyKind(model.PublicationDate, DateTimeKind.Utc) : default;
- }
- public static DateTime GetNormalizedPublicationDate(this DateTime? publicationDate)
- {
- return publicationDate != null ? DateTime.SpecifyKind(publicationDate.Value, DateTimeKind.Utc) : default;
- }
- public static string GetDisplayNamePath(this InstanceModelBase model, List nodesVisited)
- {
- if (nodesVisited.Contains(model))
- {
- return "(cycle)";
- }
- nodesVisited.Add(model);
- if (model.Parent is InstanceModelBase parent)
- {
- return $"{parent.GetDisplayNamePath(nodesVisited)}.{model.DisplayName.FirstOrDefault()?.Text}";
- }
- return model.DisplayName.FirstOrDefault()?.Text;
- }
- public static string GetUnqualifiedBrowseName(this NodeModel _this)
- {
- var browseName = _this.GetBrowseName();
- var parts = browseName.Split(new[] { ';' }, 2);
- if (parts.Length > 1)
- {
- return parts[1];
- }
- return browseName;
- }
-
- public enum JsonValueType
- {
- ///
- /// JSON object
- ///
- Object,
- ///
- /// Scalar, to be quoted
- ///
- String,
- ///
- /// Scalar, not to be quoted
- ///
- Value
- }
-
- public static bool IsJsonScalar(this DataTypeModel dataType)
- {
- return GetJsonValueType(dataType) != JsonValueType.Object;
- }
- public static JsonValueType GetJsonValueType(this DataTypeModel dataType)
- {
- if (dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.String}")
- || dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.Int64}") // numeric, but encoded as string
- || dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.UInt64}") // numeric, but encoded as string
- || dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.DateTime}")
- || dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.ByteString}")
- || dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.String}")
- )
- {
- return JsonValueType.String;
- }
- if (dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.Boolean}")
- || (dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.Number}")
- && !dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.Decimal}") // numeric, but encoded as Scale/Value object
- )
- || dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.StatusCode}")
- || dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.Enumeration}")
- )
- {
- return JsonValueType.Value;
- }
- return JsonValueType.Object;
- }
-
- internal static void SetEngineeringUnits(this VariableModel model, EUInformation euInfo)
- {
- model.EngineeringUnit = new VariableModel.EngineeringUnitInfo
- {
- DisplayName = euInfo.DisplayName?.ToModelSingle(),
- Description = euInfo.Description?.ToModelSingle(),
- NamespaceUri = euInfo.NamespaceUri,
- UnitId = euInfo.UnitId,
- };
- }
-
- internal static void SetRange(this VariableModel model, ua.Range euRange)
- {
- model.MinValue = euRange.Low;
- model.MaxValue = euRange.High;
- }
- internal static void SetInstrumentRange(this VariableModel model, ua.Range range)
- {
- model.InstrumentMinValue = range.Low;
- model.InstrumentMaxValue = range.High;
- }
-
- private const string strUNECEUri = "http://www.opcfoundation.org/UA/units/un/cefact";
-
- static List _UNECEEngineeringUnits;
- public static List UNECEEngineeringUnits
- {
- get
- {
- if (_UNECEEngineeringUnits == null)
- {
- // Load UNECE units if not already loaded
- _UNECEEngineeringUnits = new List();
- var fileName = Path.Combine(Path.GetDirectoryName(typeof(VariableModel).Assembly.Location), "NodeSets", "UNECE_to_OPCUA.csv");
- Stream fileStream;
- if (File.Exists(fileName))
- {
- fileStream = File.OpenRead(fileName);
- }
- else
- {
- fileStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("CESMII.OpcUa.NodeSetModel.Factory.Opc.NodeSets.UNECE_to_OPCUA.csv");
- }
- var parser = new CsvTextFieldParser(fileStream);
- if (!parser.EndOfData)
- {
- var headerFields = parser.ReadFields();
- }
- while (!parser.EndOfData)
- {
- var parts = parser.ReadFields();
- if (parts.Length != 4)
- {
- // error
- }
- var UNECECode = parts[0];
- var UnitId = parts[1];
- var DisplayName = parts[2];
- var Description = parts[3];
- var newEuInfo = new EUInformation(DisplayName, Description, strUNECEUri)
- {
- UnitId = int.Parse(UnitId),
- };
- _UNECEEngineeringUnits.Add(newEuInfo);
- }
- }
-
- return _UNECEEngineeringUnits;
- }
- }
-
- static Dictionary> _euInformationByDescription;
- static Dictionary> EUInformationByDescription
- {
- get
- {
- if (_euInformationByDescription == null)
- {
- _euInformationByDescription = new Dictionary>();
- foreach (var aEuInformation in UNECEEngineeringUnits)
- {
- if (!_euInformationByDescription.ContainsKey(aEuInformation.Description.Text))
- {
- _euInformationByDescription.Add(aEuInformation.Description.Text, new List { aEuInformation });
- }
- else
- {
- _euInformationByDescription[aEuInformation.DisplayName.Text].Add(aEuInformation);
- }
- }
- }
- return _euInformationByDescription;
- }
- }
-
- static Dictionary> _euInformationByDisplayName;
- static Dictionary> EUInformationByDisplayName
- {
- get
- {
- if (_euInformationByDisplayName == null)
- {
- _euInformationByDisplayName = new Dictionary>();
- foreach (var aEuInformation in UNECEEngineeringUnits)
- {
- if (!_euInformationByDisplayName.ContainsKey(aEuInformation.DisplayName.Text))
- {
- _euInformationByDisplayName.Add(aEuInformation.DisplayName.Text, new List { aEuInformation });
- }
- else
- {
- _euInformationByDisplayName[aEuInformation.DisplayName.Text].Add(aEuInformation);
- }
- }
- }
- return _euInformationByDisplayName;
- }
- }
-
- public static EUInformation GetEUInformation(VariableModel.EngineeringUnitInfo engineeringUnitDescription)
- {
- if (engineeringUnitDescription == null) return null;
-
- List euInfoList;
- if (!string.IsNullOrEmpty(engineeringUnitDescription.DisplayName?.Text)
- && engineeringUnitDescription.UnitId == null
- && engineeringUnitDescription.Description == null
- && (string.IsNullOrEmpty(engineeringUnitDescription.NamespaceUri) || engineeringUnitDescription.NamespaceUri == strUNECEUri))
- {
- // If we only have a displayname, assume it's a UNECE unit
- // Try to lookup engineering unit by description
- if (EUInformationByDescription.TryGetValue(engineeringUnitDescription.DisplayName.Text, out euInfoList))
- {
- return euInfoList.FirstOrDefault();
- }
- // Try to lookup engineering unit by display name
- else if (EUInformationByDisplayName.TryGetValue(engineeringUnitDescription.DisplayName.Text, out euInfoList))
- {
- return euInfoList.FirstOrDefault();
- }
- else
- {
- // No unit found: just use the displayname
- return new EUInformation(engineeringUnitDescription.DisplayName.Text, engineeringUnitDescription.DisplayName.Text, null);
- }
- }
- else
- {
- // Custom EUInfo: use what was specified without further validation
- EUInformation euInfo = new EUInformation(engineeringUnitDescription.DisplayName?.Text, engineeringUnitDescription.Description?.Text, engineeringUnitDescription.NamespaceUri);
- if (engineeringUnitDescription.UnitId != null)
- {
- euInfo.UnitId = engineeringUnitDescription.UnitId.Value;
- }
- return euInfo;
- }
- }
-
- public static void UpdateAllMethodArgumentVariables(this NodeSetModel nodeSetModel, IOpcUaContext opcContext)
- {
- foreach(var nodeModel in nodeSetModel.AllNodesByNodeId.SelectMany(kv => kv.Value.Methods))
- {
- UpdateMethodArgumentVariables(nodeModel as MethodModel, opcContext);
- }
- }
-
- public static void UpdateMethodArgumentVariables(MethodModel methodModel, IOpcUaContext opcContext)
- {
- UpdateMethodArgumentVariable(methodModel, BrowseNames.InputArguments, methodModel.InputArguments, opcContext);
- UpdateMethodArgumentVariable(methodModel, BrowseNames.OutputArguments, methodModel.OutputArguments, opcContext);
- }
- private static void UpdateMethodArgumentVariable(MethodModel methodModel, string browseName, List modelArguments, IOpcUaContext opcContext)
- {
- var argumentProperty = GetArgumentProperty(methodModel, browseName, modelArguments, opcContext);
- if (argumentProperty != null)
- {
- var existingArgumentProperty = methodModel.Properties.FirstOrDefault(p => p.BrowseName == browseName);
- if (existingArgumentProperty == null)
- {
- methodModel.Properties.Add(argumentProperty);
- }
- else
- {
- // Update arguments in existing property
- if (existingArgumentProperty.Value != argumentProperty.Value)
- {
- opcContext.Logger.LogInformation($"Updated {browseName} for method {methodModel}");
- opcContext.Logger.LogTrace($"Updated {browseName} for method {methodModel}. Previous arguments: {existingArgumentProperty.Value}. New arguments: {argumentProperty.Value}");
- existingArgumentProperty.Value = argumentProperty.Value;
- }
- }
- }
-
- }
- internal static PropertyModel GetArgumentProperty(MethodModel methodModel, string browseName, List modelArguments, IOpcUaContext opcContext)
- {
- List arguments = new List();
- if (modelArguments?.Any() == true)
- {
- foreach (var modelArgument in modelArguments)
- {
- UInt32Collection arrayDimensions = null;
- if (modelArgument.ArrayDimensions != null)
- {
- arrayDimensions = JsonConvert.DeserializeObject($"[{modelArgument.ArrayDimensions}]");
- }
-
- var argument = new Argument
- {
- Name = modelArgument.BrowseName,
- ArrayDimensions = arrayDimensions,
- // TODO parse into array ArrayDimensions = inputArg.ArrayDimensions,
- ValueRank = modelArgument.ValueRank ?? -1,
- DataType = ExpandedNodeId.Parse(modelArgument.DataType.NodeId, opcContext.NamespaceUris),
- Description = new ua.LocalizedText(modelArgument.Description?.FirstOrDefault()?.Text),
- };
- if (modelArgument.Value != null || modelArgument.Description.Count > 1 || modelArgument.ModellingRule == "Optional")
- {
- // TODO Create or update argumentDescription
- }
- arguments.Add(argument);
- }
- }
- if (arguments.Any())
- {
- var argumentDataType = opcContext.GetModelForNode($"nsu={Namespaces.OpcUa};{DataTypeIds.Argument}");
- var argumentPropertyJson = opcContext.JsonEncodeVariant(
- new Variant(arguments.Select(a => new ExtensionObject(a)).ToArray()),
- argumentDataType);
- var argumentProperty = new PropertyModel
- {
- NodeSet = modelArguments[0].NodeSet,
- NodeId = modelArguments[0].NodeId,
- CustomState = modelArguments[0].CustomState,
- BrowseName = opcContext.GetModelBrowseName(browseName),
- DisplayName = NodeModel.LocalizedText.ListFromText(browseName),
- Description = new(),
- Parent = methodModel,
- DataType = argumentDataType,
- TypeDefinition = opcContext.GetModelForNode($"nsu={Namespaces.OpcUa};{VariableTypeIds.PropertyType}"),
- ValueRank = 1,
- ArrayDimensions = $"{arguments.Count}",
- Value = argumentPropertyJson.Json,
- ModellingRule = "Mandatory",
- };
- return argumentProperty;
- }
- return null;
- }
-
- ///
- /// Updates or creates the object of type NamespaceMetaDataType as described in https://reference.opcfoundation.org/Core/Part5/v105/docs/6.3.13
- ///
- ///
- public static bool UpdateNamespaceMetaData(this NodeSetModel _this, IOpcUaContext opcContext, bool createIfNotExist = true)
- {
- bool addedMetadata = false;
- var metaDataTypeNodeId = opcContext.GetModelNodeId(ObjectTypeIds.NamespaceMetadataType);
- var serverNamespacesNodeId = opcContext.GetModelNodeId(ObjectIds.Server_Namespaces);
- var metadataObjects = _this.Objects.Where(o => o.TypeDefinition.HasBaseType(metaDataTypeNodeId) && o.Parent.NodeId == serverNamespacesNodeId).ToList();
- var metadataObject = metadataObjects.FirstOrDefault();
- if (metadataObject == null)
- {
- if (!createIfNotExist)
- {
- return false;
- }
- var parent = opcContext.GetModelForNode($"nsu={Namespaces.OpcUa};{ObjectIds.Server}");
- metadataObject = new ObjectModel
- {
- NodeSet = _this,
- NodeId = GetNewNodeId(_this.ModelUri),
- DisplayName = new ua.LocalizedText(_this.ModelUri).ToModel(),
- BrowseName = opcContext.GetModelBrowseName(BrowseNames.NamespaceMetadataType), // $"{Namespaces.OpcUa};{nameof(ObjectTypeIds.NamespaceMetadataType)}",
- Parent = parent,
- OtherReferencingNodes = new List
- {
- new NodeModel.NodeAndReference
- {
- ReferenceType = opcContext.GetModelForNode($"nsu={Namespaces.OpcUa};{ReferenceTypeIds.HasComponent}"),
- Node = parent,
- }
- }
- };
- _this.Objects.Add(metadataObject);
- addedMetadata = true;
- }
- addedMetadata |= CreateOrReplaceMetaDataProperty(_this, opcContext, metadataObject, BrowseNames.NamespaceUri, _this.ModelUri, true);
- addedMetadata |= CreateOrReplaceMetaDataProperty(_this, opcContext, metadataObject, BrowseNames.NamespacePublicationDate, _this.PublicationDate, true);
- addedMetadata |= CreateOrReplaceMetaDataProperty(_this, opcContext, metadataObject, BrowseNames.NamespaceVersion, _this.Version, true);
-
- // Only create if not already authored
- addedMetadata |= CreateOrReplaceMetaDataProperty(_this, opcContext, metadataObject, BrowseNames.IsNamespaceSubset, "false", false);
- addedMetadata |= CreateOrReplaceMetaDataProperty(_this, opcContext, metadataObject, BrowseNames.StaticNodeIdTypes, null, false);
- addedMetadata |= CreateOrReplaceMetaDataProperty(_this, opcContext, metadataObject, BrowseNames.StaticNumericNodeIdRange, null, false);
- addedMetadata |= CreateOrReplaceMetaDataProperty(_this, opcContext, metadataObject, BrowseNames.StaticStringNodeIdPattern, null, false);
- return addedMetadata;
- }
-
- private static bool CreateOrReplaceMetaDataProperty(NodeSetModel _this, IOpcUaContext context, ObjectModel metadataObject, QualifiedName browseName, object value, bool replaceIfExists)
- {
- string modelBrowseName = context.GetModelBrowseName(browseName);
- var previousProp = metadataObject.Properties.FirstOrDefault(p => p.BrowseName == modelBrowseName);
- if (replaceIfExists || previousProp == null)
- {
- string encodedValue;
- if (value is DateTime)
- {
- encodedValue = $"{{\"Value\":{{\"Type\":13,\"Body\":\"{value:O}\"}}}}";
- }
- else
- {
- encodedValue = $"{{\"Value\":{{\"Type\":12,\"Body\":\"{value}\"}}}}";
- }
- if (previousProp != null)
- {
- previousProp.Value = encodedValue;
- }
- else
- {
- metadataObject.Properties.Add(new PropertyModel
- {
- NodeSet = _this,
- NodeId = GetNewNodeId(_this.ModelUri),
- BrowseName = modelBrowseName,
- DisplayName = new ua.LocalizedText(browseName.Name).ToModel(),
- Value = encodedValue,
- });
- }
- return true;
- }
- return false;
- }
-
- public static List UpdateEncodings(this NodeSetModel _this, IOpcUaContext context)
- {
- var missingEncodings = new List();
- foreach (var dataType in _this.DataTypes)
- {
- if (dataType.StructureFields?.Any() == true)
- {
- // Ensure there's an encoding for the data type
- var hasEncodingNodeId = context.GetModelNodeId(ReferenceTypeIds.HasEncoding);
- var encodingReferences = dataType.OtherReferencedNodes.Where(nr => (nr.ReferenceType as ReferenceTypeModel).HasBaseType(hasEncodingNodeId)).ToList();
-
- foreach (var encodingBrowseName in new[] { BrowseNames.DefaultXml, BrowseNames.DefaultJson, BrowseNames.DefaultBinary })
- {
- var encodingModelBrowseName = context.GetModelBrowseName(encodingBrowseName);
- if (!encodingReferences.Any(nr => nr.Node.BrowseName == encodingModelBrowseName))
- {
- var encodingId = NodeModelOpcExtensions.GetNewNodeId(dataType.Namespace);
- var encoding = new ObjectModel
- {
- NodeSet = dataType.NodeSet,
- NodeId = encodingId,
- BrowseName = encodingModelBrowseName,
- DisplayName = new ua.LocalizedText(encodingBrowseName).ToModel(),
- TypeDefinition = context.GetModelForNode($"nsu={Namespaces.OpcUa};{ObjectTypeIds.DataTypeEncodingType}"),
- Parent = dataType,
- };
- // According to https://reference.opcfoundation.org/Core/Part6/v105/docs/F.4 only one direction of the reference is required: using inverse reference on the encoding only to keep the data type XML cleaner
- encoding.OtherReferencingNodes.Add(new NodeModel.NodeAndReference
- {
- ReferenceType = context.GetModelForNode($"nsu={Namespaces.OpcUa};{ReferenceTypeIds.HasEncoding}"),
- Node = dataType,
- });
- _this.Objects.Add(encoding);
- missingEncodings.Add($"{dataType}: {encoding}");
- }
- }
- }
- }
- return missingEncodings;
- }
-
- public static string GetNewNodeId(string nameSpace)
- {
- return new ExpandedNodeId(Guid.NewGuid(), nameSpace).ToString();
- }
- public static string ToModel(this QualifiedName qName, NamespaceTable namespaceUris)
- {
- return $"{namespaceUris.GetString(qName.NamespaceIndex)};{qName.Name}";
- }
-
- public static string GetNodeClass(this NodeModel nodeModel)
- {
- var type = nodeModel.GetType().Name;
- var nodeClass = type.Substring(0, type.Length - "Model".Length);
- return nodeClass;
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeModelUtils.cs b/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeModelUtils.cs
deleted file mode 100644
index f2a2e8bd..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeModelUtils.cs
+++ /dev/null
@@ -1,489 +0,0 @@
-using Opc.Ua;
-using export = Opc.Ua.Export;
-using System.Collections.Generic;
-using System.Xml;
-using System.Linq;
-using CESMII.OpcUa.NodeSetModel.Export.Opc;
-using System;
-using Microsoft.Extensions.Logging;
-using CESMII.OpcUa.NodeSetModel.Opc.Extensions;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System.IO;
-using System.Text;
-using System.Threading.Tasks;
-using System.Threading;
-
-namespace CESMII.OpcUa.NodeSetModel.Factory.Opc
-{
- public static class NodeModelUtils
- {
- public static string GetNodeIdIdentifier(string nodeId)
- {
- return nodeId.Substring(nodeId.LastIndexOf(';') + 1);
- }
-
- public static string GetNamespaceFromNodeId(string nodeId)
- {
- var parsedNodeId = ExpandedNodeId.Parse(nodeId);
- var namespaceUri = parsedNodeId.NamespaceUri;
- return namespaceUri;
- }
-
- public static string JsonEncodeVariant(Variant value, bool reencodeExtensionsAsJson = false)
- {
- return JsonEncodeVariant(null, value, null, reencodeExtensionsAsJson = false).Json;
- }
- public static string JsonEncodeVariant(ISystemContext systemContext, Variant value, bool reencodeExtensionsAsJson = false)
- {
- return JsonEncodeVariant(systemContext, value, null, reencodeExtensionsAsJson).Json;
- }
- public static (string Json, bool IsScalar) JsonEncodeVariant(ISystemContext systemContext, Variant value, DataTypeModel dataType, bool reencodeExtensionsAsJson = false, bool encodeJsonScalarsAsValues = false)
- {
- bool isScalar = false;
-
- ServiceMessageContext context;
- if (systemContext != null)
- {
- context = new ServiceMessageContext { NamespaceUris = systemContext.NamespaceUris, Factory = systemContext.EncodeableFactory };
- }
- else
- {
- context = ServiceMessageContext.GlobalContext;
- }
- if (reencodeExtensionsAsJson)
- {
- if (dataType != null && systemContext.EncodeableFactory is DynamicEncodeableFactory lookupContext)
- {
- lookupContext.AddEncodingsForDataType(dataType, systemContext.NamespaceUris);
- }
-
- // Reencode extension objects as JSON
- if (value.Value is ExtensionObject extObj && extObj.Encoding == ExtensionObjectEncoding.Xml && extObj.Body is XmlElement extXmlBody)
- {
- var xmlDecoder = new XmlDecoder(extXmlBody, context);
- var parsedBody = xmlDecoder.ReadExtensionObjectBody(extObj.TypeId);
- value.Value = new ExtensionObject(extObj.TypeId, parsedBody);
- }
- else if (value.Value is ExtensionObject[] extObjList && extObjList.Any(e => e.Encoding == ExtensionObjectEncoding.Xml && e.Body is XmlElement))
- {
- var newExtObjList = new ExtensionObject[extObjList.Length];
- int i = 0;
- bool bReencoded = false;
- foreach (var extObj2 in extObjList)
- {
- if (extObj2.Encoding == ExtensionObjectEncoding.Xml && extObj2.Body is XmlElement extObj2XmlBody)
- {
- var xmlDecoder = new XmlDecoder(extObj2XmlBody, context);
- var parsedBody = xmlDecoder.ReadExtensionObjectBody(extObj2.TypeId);
- newExtObjList[i] = new ExtensionObject(extObj2.TypeId, parsedBody);
- bReencoded = true;
- }
- else
- {
- newExtObjList[i] = extObj2;
- }
- i++;
- }
- if (bReencoded)
- {
- value.Value = newExtObjList;
- }
- }
- else if (value.Value is byte[] byteArray && value.TypeInfo.BuiltInType == BuiltInType.ByteString && dataType?.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.Byte}")== true)
- {
- // The XML decoder returns byte arrays as a bytestring variant: fix it up so we don't get a base64 encoded JSON value
- value = new Variant(byteArray, new TypeInfo(BuiltInType.Byte, ValueRanks.OneDimension));
- }
- }
- using (var encoder = new JsonEncoder(context, true))
- {
- encoder.ForceNamespaceUri = true;
- encoder.ForceNamespaceUriForIndex1 = true;
- encoder.WriteVariant("Value", value);
-
- var encodedVariant = encoder.CloseAndReturnText();
- var parsedValue = JsonConvert.DeserializeObject(encodedVariant, new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.None });
-
- string encodedValue;
- NodeModelOpcExtensions.JsonValueType jsonValueType;
- if (encodeJsonScalarsAsValues && dataType != null &&
- ((jsonValueType = dataType.GetJsonValueType()) == NodeModelOpcExtensions.JsonValueType.Value || jsonValueType == NodeModelOpcExtensions.JsonValueType.String))
- {
- isScalar = true;
- if (parsedValue["Value"]["Body"] is JValue jValue)
- {
- if (jValue.Value is string stringValue)
- {
- encodedValue = stringValue;
- }
- else if (jValue.Value is bool boolValue)
- {
- // Ensure proper casing, ToString() return True/False vs. json's true/false
- encodedValue = JsonConvert.SerializeObject(jValue, Newtonsoft.Json.Formatting.None);
- }
- else
- {
- encodedValue = JsonConvert.SerializeObject(jValue, Newtonsoft.Json.Formatting.None);
- encodedValue = encodedValue.Trim('"');
- var encodedValue2 = jValue.Value?.ToString();
- if (encodedValue != encodedValue2 && !(jValue.Value is DateTime))
- {
-
- }
- }
- }
- else if (parsedValue["Value"]["Body"] is JArray jArray)
- {
- encodedValue = JsonConvert.SerializeObject(jArray, Newtonsoft.Json.Formatting.None);
- }
- else
- {
- encodedValue = null;
- }
- if (encodedValue.Length >= 2 && encodedValue.StartsWith("\"") && encodedValue.EndsWith("'\""))
- {
- encodedValue = encodedValue.Substring(1, encodedValue.Length - 2);
- }
- }
- else
- {
- encodedValue = parsedValue["Value"]?.ToString(Newtonsoft.Json.Formatting.None);
- }
-
- return (encodedValue, isScalar);
- }
- }
-
- //private static Dictionary ParseStructureValues(XmlElement extXmlBody, int nestingLevel)
- //{
- // if (nestingLevel > 100)
- // {
- // throw new System.Exception("Nested structure of more than 100 levels not supported.");
- // }
- // Dictionary defaultValues = new Dictionary();
- // foreach (var child in extXmlBody.ChildNodes)
- // {
- // if (child is XmlElement elementChild)
- // {
- // if (elementChild.ChildNodes.OfType().Any())
- // {
- // defaultValues.Add(elementChild.Name, ParseStructureValues(elementChild, nestingLevel + 1));
- // }
- // else
- // {
- // defaultValues.Add(elementChild.Name, elementChild.InnerText);
- // }
- // }
- // }
- // return defaultValues;
- //}
-
- public static Variant JsonDecodeVariant(string jsonVariant, IServiceMessageContext context, DataTypeModel dataType = null, bool EncodeJsonScalarsAsString = false)
- {
- if (jsonVariant == null)
- {
- return Variant.Null;
- }
- if ((jsonVariant?.TrimStart()?.StartsWith("{\"Value\"") == false))
- {
- NodeModelOpcExtensions.JsonValueType? jsonValueType;
- if (EncodeJsonScalarsAsString && ((jsonValueType = dataType?.GetJsonValueType()) == NodeModelOpcExtensions.JsonValueType.Value || jsonValueType == NodeModelOpcExtensions.JsonValueType.String))
- {
- uint? dataTypeId = null;
- if (dataType.HasBaseType($"nsu={Namespaces.OpcUa};{DataTypeIds.Enumeration}"))
- {
- dataTypeId = DataTypes.Int32;
- }
- else
- {
- var dtNodeId = ExpandedNodeId.Parse(dataType.NodeId, context.NamespaceUris);
- var builtInType = TypeInfo.GetBuiltInType(dtNodeId, new PartialTypeTree(dataType, context.NamespaceUris));
- if (builtInType != BuiltInType.Null)
- {
- dataTypeId = (uint)builtInType;
- }
-
- else
- {
- if (dtNodeId.IdType == IdType.Numeric && dtNodeId.NamespaceIndex == 0)
- {
- dataTypeId = (uint)dtNodeId.Identifier;
- }
- }
- }
- if (dataTypeId != null)
- {
- // TODO more reliable check for array (handle a scalar string that starts with [ ).
- if (jsonValueType == NodeModelOpcExtensions.JsonValueType.String && !jsonVariant.StartsWith("["))
- {
- // encode and quote it
- jsonVariant = JsonConvert.ToString(jsonVariant);
- }
- jsonVariant = $"{{\"Value\":{{\"Type\":{dataTypeId},\"Body\":{jsonVariant}}}}}";
- }
- }
- else
- {
- jsonVariant = $"{{\"Value\":{jsonVariant}";
- }
- }
- using (var decoder = new JsonDecoder(jsonVariant, context))
- {
- var variant = decoder.ReadVariant("Value");
- return variant;
- }
- }
- public static XmlElement JsonDecodeVariantToXml(string jsonVariant, IServiceMessageContext context, DataTypeModel dataType = null, bool EncodeJsonScalarsAsString = false)
- {
- var variant = JsonDecodeVariant(jsonVariant, context, dataType, EncodeJsonScalarsAsString);
- var xml = GetVariantAsXML(variant, context);
- return xml;
- }
-
- public static System.Xml.XmlElement GetExtensionObjectAsXML(object extensionBody)
- {
- var extension = new ExtensionObject(extensionBody);
- var context = new ServiceMessageContext();
- var ms = new System.IO.MemoryStream();
- using (var xmlWriter = new System.Xml.XmlTextWriter(ms, System.Text.Encoding.UTF8))
- {
- xmlWriter.WriteStartDocument();
-
- using (var encoder = new XmlEncoder(new System.Xml.XmlQualifiedName("uax:ExtensionObject", null), xmlWriter, context))
- {
- encoder.WriteExtensionObject(null, extension);
- xmlWriter.WriteEndDocument();
- xmlWriter.Flush();
- }
- }
- var xml = System.Text.Encoding.UTF8.GetString(ms.ToArray());
- var doc = new System.Xml.XmlDocument();
- doc.LoadXml(xml.Substring(1));
- var xmlElem = doc.DocumentElement;
- return xmlElem;
- }
- public static System.Xml.XmlElement EncodeAsXML(Action encode)
- {
- var context = new ServiceMessageContext();
- var ms = new System.IO.MemoryStream();
- using (var xmlWriter = new System.Xml.XmlTextWriter(ms, System.Text.Encoding.UTF8))
- {
- xmlWriter.WriteStartDocument();
-
- using (var encoder = new XmlEncoder(new System.Xml.XmlQualifiedName("uax:ExtensionObject", null), xmlWriter, context))
- {
- encode(encoder);
- xmlWriter.WriteEndDocument();
- xmlWriter.Flush();
- }
- }
- var xml = System.Text.Encoding.UTF8.GetString(ms.ToArray());
- var doc = new System.Xml.XmlDocument();
- // Skip any BOM markers or the XML loader fails
- doc.LoadXml(xml[0] > 255 ? xml.Substring(1) : xml);
- var xmlElem = doc.DocumentElement;
- return xmlElem;
- }
-
- public static System.Xml.XmlElement GetVariantAsXML(Variant value, IServiceMessageContext context)
- {
- var ms = new System.IO.MemoryStream();
- using (var xmlWriter = new System.Xml.XmlTextWriter(ms, System.Text.Encoding.UTF8))
- {
- xmlWriter.WriteStartDocument();
- using (var encoder = new XmlEncoder(new System.Xml.XmlQualifiedName("myRoot"/*, "http://opcfoundation.org/UA/2008/02/Types.xsd"*/), xmlWriter, context))
- {
- encoder.WriteVariant("value", value);
- xmlWriter.WriteEndDocument();
- xmlWriter.Flush();
- }
- }
- var xml = System.Text.Encoding.UTF8.GetString(ms.ToArray());
- var doc = new System.Xml.XmlDocument();
-
- doc.LoadXml(xml.Substring(1));
- var xmlElem = doc.DocumentElement;
- var xmlValue = xmlElem.FirstChild?.FirstChild?.FirstChild as System.Xml.XmlElement;
- return xmlValue;
- }
-
- public static ServiceMessageContext GetContextWithDynamicEncodeableFactory(DataTypeModel dataType, NamespaceTable namespaces)
- {
- DynamicEncodeableFactory dynamicFactory = new(EncodeableFactory.GlobalFactory);
- dynamicFactory.AddEncodingsForDataType(dataType, namespaces);
- var messageContext = new ServiceMessageContext { Factory = dynamicFactory, NamespaceUris = namespaces };
- return messageContext;
- }
-
- ///
- /// Reads a missing nodeset version from a NamespaceVersion object
- ///
- ///
- public static void FixupNodesetVersionFromMetadata(export.UANodeSet nodeSet, ILogger logger)
- {
- if (nodeSet?.Models == null)
- {
- return;
- }
- foreach (var model in nodeSet.Models)
- {
- if (string.IsNullOrEmpty(model.Version))
- {
- var namespaceVersionObject = nodeSet.Items?.FirstOrDefault(n => n is export.UAVariable && n.BrowseName == BrowseNames.NamespaceVersion) as export.UAVariable;
- var version = namespaceVersionObject?.Value?.InnerText;
- if (!string.IsNullOrEmpty(version))
- {
- model.Version = version;
- if (logger != null)
- {
- logger.LogWarning($"Nodeset {model.ModelUri} did not specify a version, but contained a NamespaceVersion property with value {version}.");
- }
- }
- }
- }
- }
-
- public static DataTypeModel GetDataTypeModel(IOpcUaContext opcContext, Variant field)
- {
- var builtinType = field.TypeInfo.BuiltInType;
- var dataTypeNodeId = opcContext.GetModelNodeId(new NodeId((uint)builtinType));
- var dataTypeModel = opcContext.GetModelForNode(dataTypeNodeId);
- return dataTypeModel;
- }
-
- public static string ReadHeaderComment(string nodeSetXml)
- {
- string headerComments = "";
- using (var nodesetXmlReader = new StringReader(nodeSetXml))
- {
- var firstLine = nodesetXmlReader.ReadLine();
- if (!firstLine.StartsWith(""));
- sbHeaderComment.AppendLine(firstLine);
- headerComments = sbHeaderComment.ToString();
- }
- //var doc = XElement.Load(nodesetXmlReader);
- //var comments = doc.DescendantNodes().OfType();
- //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"
- //}
- }
- return headerComments;
- }
-
- private class PartialTypeTree : ITypeTable
- {
- private DataTypeModel _dataType;
- private NamespaceTable _namespaceUris;
-
- public PartialTypeTree(DataTypeModel dataType, NamespaceTable namespaceUris)
- {
- this._dataType = dataType;
- this._namespaceUris = namespaceUris;
- }
-
- public NodeId FindSuperType(NodeId typeId)
- {
- var type = this._dataType;
- do
- {
- if (ExpandedNodeId.Parse(type.NodeId, _namespaceUris) == typeId)
- {
- return ExpandedNodeId.Parse(type.SuperType.NodeId, _namespaceUris);
- }
- type = type.SuperType as DataTypeModel;
- } while (type != null);
- return null;
- }
- public Task FindSuperTypeAsync(NodeId typeId, CancellationToken ct = default)
- {
- return Task.FromResult(FindSuperType(typeId));
- }
-
-
- public NodeId FindDataTypeId(ExpandedNodeId encodingId)
- {
- throw new NotImplementedException();
- }
-
- public NodeId FindDataTypeId(NodeId encodingId)
- {
- throw new NotImplementedException();
- }
-
- public NodeId FindReferenceType(QualifiedName browseName)
- {
- throw new NotImplementedException();
- }
-
- public QualifiedName FindReferenceTypeName(NodeId referenceTypeId)
- {
- throw new NotImplementedException();
- }
-
- public IList FindSubTypes(ExpandedNodeId typeId)
- {
- throw new NotImplementedException();
- }
-
- public NodeId FindSuperType(ExpandedNodeId typeId)
- {
- throw new NotImplementedException();
- }
- public Task FindSuperTypeAsync(ExpandedNodeId typeId, CancellationToken ct = default)
- {
- throw new NotImplementedException();
- }
-
-
- public bool IsEncodingFor(NodeId expectedTypeId, ExtensionObject value)
- {
- throw new NotImplementedException();
- }
-
- public bool IsEncodingFor(NodeId expectedTypeId, object value)
- {
- throw new NotImplementedException();
- }
-
- public bool IsEncodingOf(ExpandedNodeId encodingId, ExpandedNodeId datatypeId)
- {
- throw new NotImplementedException();
- }
-
- public bool IsKnown(ExpandedNodeId typeId)
- {
- throw new NotImplementedException();
- }
-
- public bool IsKnown(NodeId typeId)
- {
- throw new NotImplementedException();
- }
-
- public bool IsTypeOf(ExpandedNodeId subTypeId, ExpandedNodeId superTypeId)
- {
- throw new NotImplementedException();
- }
-
- public bool IsTypeOf(NodeId subTypeId, NodeId superTypeId)
- {
- throw new NotImplementedException();
- }
- }
- }
-
-}
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeSetResolverException.cs b/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeSetResolverException.cs
deleted file mode 100644
index 5c12bd9b..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeSetResolverException.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace CESMII.OpcUa.NodeSetModel.Factory.Opc
-{
- [Serializable]
- public class NodeSetResolverException : Exception
- {
- public NodeSetResolverException()
- {
- }
-
- public NodeSetResolverException(string message) : base(message)
- {
- }
-
- public NodeSetResolverException(string message, Exception innerException) : base(message, innerException)
- {
- }
-
- protected NodeSetResolverException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-}
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeSets/UNECE_to_OPCUA original.csv b/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeSets/UNECE_to_OPCUA original.csv
deleted file mode 100644
index 253b0511..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeSets/UNECE_to_OPCUA original.csv
+++ /dev/null
@@ -1,1828 +0,0 @@
-UNECECode,UnitId,DisplayName,Description
-C81,4405297,"rad","radian"
-C25,4403765,"mrad","milliradian"
-B97,4340023,"µrad","microradian"
-DD,17476,"°","degree [unit of angle]"
-D61,4470321,"'","minute [unit of angle]"
-D62,4470322,"""","second [unit of angle]"
-A91,4274481,"gon","gon"
-M43,5059635,"mil","mil"
-M44,5059636,"rev","revolution"
-D27,4469303,"sr","steradian"
-H57,4732215,"in/revolution","inch per two pi radiant"
-MTR,5067858,"m","metre"
-E96,4536630,"°/s","degree per second"
-H27,4731447,"°/m","degree per metre"
-M55,5059893,"m/rad","metre per radiant"
-DMT,4476244,"dm","decimetre"
-CMT,4410708,"cm","centimetre"
-4H,13384,"µm","micrometre (micron)"
-MMT,5066068,"mm","millimetre"
-HMT,4738388,"hm","hectometre"
-KMT,4934996,"km","kilometre"
-C45,4404277,"nm","nanometre"
-C52,4404530,"pm","picometre"
-A71,4273969,"fm","femtometre"
-A45,4273205,"dam","decametre"
-NMI,5131593,"n mile","nautical mile"
-A11,4272433,"Å","angstrom"
-A12,4272434,"ua","astronomical unit"
-C63,4404787,"pc","parsec"
-F52,4601138,"m/K","metre per kelvin"
-F50,4601136,"µm/K","micrometre per kelvin"
-F51,4601137,"cm/K","centimetre per kelvin"
-G06,4665398,"mm/bar","millimetre per bar"
-H84,4732980,"g·mm","gram millimetre"
-G04,4665396,"cm/bar","centimetre per bar"
-G05,4665397,"m/bar","metre per bar"
-H79,4732729,"Fg","French gauge"
-AK,16715,"fth","fathom"
-X1,22577,"ch (UK)","Gunter's chain"
-INH,4804168,"in","inch"
-M7,19767,"µin","micro-inch"
-FOT,4607828,"ft","foot"
-YRD,5853764,"yd","yard"
-SMI,5459273,"mile","mile (statute mile)"
-77,14135,"mil","milli-inch"
-B57,4338999,"ly","light year"
-F49,4600889,"rd (US)","rod [unit of distance]"
-MAM,5062989,"Mm","megametre"
-K13,4927795,"ft/°F","foot per degree Fahrenheit"
-K17,4927799,"ft/psi","foot per psi"
-K45,4928565,"in/°F","inch per degree Fahrenheit"
-K46,4928566,"in/psi","inch per psi"
-L98,4995384,"yd/°F","yard per degree Fahrenheit"
-L99,4995385,"yd/psi","yard per psi"
-M49,5059641,"ch (US survey)","chain (based on U.S. survey foot)"
-M50,5059888,"fur","furlong"
-M51,5059889,"ft (US survey)","foot (U.S. survey)"
-M52,5059890,"mi (US survey)","mile (based on U.S. survey foot)"
-M53,5059891,"m/Pa","metre per pascal"
-MTK,5067851,"m²","square metre"
-KMK,4934987,"km²","square kilometre"
-H30,4731696,"µm²","square micrometre (square micron)"
-H59,4732217,"m²/N","square metre per newton"
-DAA,4473153,"daa","decare"
-CMK,4410699,"cm²","square centimetre"
-DMK,4476235,"dm²","square decimetre"
-H16,4731190,"dam²","square decametre"
-H18,4731192,"hm²","square hectometre"
-MMK,5066059,"mm²","square millimetre"
-ARE,4280901,"a","are"
-HAR,4735314,"ha","hectare"
-INK,4804171,"in²","square inch"
-FTK,4609099,"ft²","square foot"
-YDK,5850187,"yd²","square yard"
-MIK,5065035,"mi²","square mile (statute mile)"
-M48,5059640,"mi² (US survey)","square mile (based on U.S. survey foot)"
-ACR,4277074,"acre","acre"
-M47,5059639,"cmil","circular mil"
-MTQ,5067857,"m³","cubic metre"
-MAL,5062988,"Ml","megalitre"
-LTR,5002322,"l","litre"
-MMQ,5066065,"mm³","cubic millimetre"
-CMQ,4410705,"cm³","cubic centimetre"
-DMQ,4476241,"dm³","cubic decimetre"
-MLT,5065812,"ml","millilitre"
-HLT,4738132,"hl","hectolitre"
-CLT,4410452,"cl","centilitre"
-DMA,4476225,"dam³","cubic decametre"
-H19,4731193,"hm³","cubic hectometre"
-H20,4731440,"km³","cubic kilometre"
-M71,5060401,"m³/Pa","cubic metre per pascal"
-DLT,4475988,"dl","decilitre"
-4G,13383,"µl","microlitre"
-K6,19254,"kl","kilolitre"
-A44,4273204,"dal","decalitre"
-G94,4667700,"cm³/bar","cubic centimetre per bar"
-G95,4667701,"l/bar","litre per bar"
-G96,4667702,"m³/bar","cubic metre per bar"
-G97,4667703,"ml/bar","millilitre per bar"
-INQ,4804177,"in³","cubic inch"
-FTQ,4609105,"ft³","cubic foot"
-YDQ,5850193,"yd³","cubic yard"
-GLI,4672585,"gal (UK)","gallon (UK)"
-GLL,4672588,"gal (US)","gallon (US)"
-PT,20564,"pt (US)","pint (US)"
-PTI,5264457,"pt (UK)","pint (UK)"
-QTI,5329993,"qt (UK)","quart (UK)"
-PTL,5264460,"liq pt (US)","liquid pint (US)"
-QTL,5329996,"liq qt (US)","liquid quart (US)"
-PTD,5264452,"dry pt (US)","dry pint (US)"
-OZI,5200457,"fl oz (UK)","fluid ounce (UK)"
-QT,20820,"qt (US)","quart (US)"
-J57,4863287,"bbl (UK liq.)","barrel (UK petroleum)"
-K21,4928049,"ft³/°F","cubic foot per degree Fahrenheit"
-K23,4928051,"ft³/psi","cubic foot per psi"
-L43,4994099,"pk (UK)","peck (UK)"
-L84,4995124,"British shipping ton","ton (UK shipping)"
-L86,4995126,"(US) shipping ton","ton (US shipping)"
-M11,5058865,"yd³/°F","cubic yard per degree Fahrenheit"
-M14,5058868,"yd³/psi","cubic yard per psi"
-OZA,5200449,"fl oz (US)","fluid ounce (US)"
-BUI,4347209,"bushel (UK)","bushel (UK)"
-BUA,4347201,"bu (US)","bushel (US)"
-BLL,4344908,"barrel (US)","barrel (US)"
-BLD,4344900,"bbl (US)","dry barrel (US)"
-GLD,4672580,"dry gal (US)","dry gallon (US)"
-QTD,5329988,"dry qt (US)","dry quart (US)"
-G26,4665910,"st","stere"
-G21,4665905,"cup (US)","cup [unit of volume]"
-G24,4665908,"tablespoon (US)","tablespoon (US)"
-G25,4665909,"teaspoon (US)","teaspoon (US)"
-G23,4665907,"pk (US)","peck"
-M67,5060151,"acre-ft (US survey)","acre-foot (based on U.S. survey foot)"
-M68,5060152,"cord","cord (128 ft3)"
-M69,5060153,"mi³","cubic mile (UK statute)"
-M70,5060400,"RT","ton, register"
-G27,4665911,"cm³/K","cubic centimetre per kelvin"
-G29,4665913,"m³/K","cubic metre per kelvin"
-G28,4665912,"l/K","litre per kelvin"
-G30,4666160,"ml/K","millilitre per kelvin"
-J36,4862774,"µl/l","microlitre per litre"
-J87,4864055,"cm³/m³","cubic centimetre per cubic metre"
-J91,4864305,"dm³/m³","cubic decimetre per cubic metre"
-K62,4929074,"l/l","litre per litre"
-L19,4993337,"ml/l","millilitre per litre"
-L21,4993585,"mm³/m³","cubic millimetre per cubic metre"
-SEC,5457219,"s","second [unit of time]"
-MIN,5065038,"min","minute [unit of time]"
-HUR,4740434,"h","hour"
-DAY,4473177,"d","day"
-B52,4338994,"ks","kilosecond"
-C26,4403766,"ms","millisecond"
-H70,4732720,"ps","picosecond"
-B98,4340024,"µs","microsecond"
-C47,4404279,"ns","nanosecond"
-WEE,5719365,"wk","week"
-MON,5066574,"mo","month"
-ANN,4279886,"y","year"
-D42,4469810,"y (tropical)","tropical year"
-L95,4995381,"y (365 days)","common year"
-L96,4995382,"y (sidereal)","sidereal year"
-M56,5059894,"shake","shake"
-2A,12865,"rad/s","radian per second"
-M46,5059638,"r/min","revolution per minute"
-2B,12866,"rad/s²","radian per second squared"
-M45,5059637,"°/s²","degree [unit of angle] per second squared"
-MTS,5067859,"m/s","metre per second"
-KNT,4935252,"kn","knot"
-KMH,4934984,"km/h","kilometre per hour"
-C16,4403510,"mm/s","millimetre per second"
-2M,12877,"cm/s","centimetre per second"
-H49,4731961,"cm/h","centimetre per hour"
-H81,4732977,"mm/min","millimetre per minute"
-2X,12888,"m/min","metre per minute"
-M59,5059897,"(m/s)/Pa","metre per second pascal"
-H66,4732470,"mm/y","millimetre per year"
-H67,4732471,"mm/h","millimetre per hour"
-FR,18002,"ft/min","foot per minute"
-IU,18773,"in/s","inch per second"
-FS,18003,"ft/s","foot per second"
-HM,18509,"mile/h","mile per hour (statute mile)"
-J84,4864052,"(cm/s)/K","centimetre per second kelvin"
-J85,4864053,"(cm/s)/bar","centimetre per second bar"
-K14,4927796,"ft/h","foot per hour"
-K18,4927800,"(ft/s)/°F","foot per second degree Fahrenheit"
-K19,4927801,"(ft/s)/psi","foot per second psi"
-K47,4928567,"(in/s)/°F","inch per second degree Fahrenheit"
-K48,4928568,"(in/s)/psi","inch per second psi"
-L12,4993330,"(m/s)/K","metre per second kelvin"
-L13,4993331,"(m/s)/bar","metre per second bar"
-M22,5059122,"(ml/min)/cm²","millilitre per square centimetre minute"
-M57,5059895,"mi/min","mile per minute"
-M58,5059896,"mi/s","mile per second"
-M60,5060144,"m/h","metre per hour"
-M61,5060145,"in/y","inch per year"
-M62,5060146,"km/s","kilometre per second"
-M63,5060147,"in/min","inch per minute"
-M64,5060148,"yd/s","yard per second"
-M65,5060149,"yd/min","yard per minute"
-M66,5060150,"yd/h","yard per hour"
-MSK,5067595,"m/s²","metre per second squared"
-A76,4273974,"Gal","gal"
-C11,4403505,"mGal","milligal"
-M38,5059384,"km/s²","kilometre per second squared"
-M39,5059385,"cm/s²","centimetre per second squared"
-M41,5059633,"mm/s²","millimetre per second squared"
-A73,4273971,"ft/s²","foot per second squared"
-IV,18774,"in/s²","inch per second squared"
-K40,4928560,"gn","standard acceleration of free fall"
-M40,5059632,"yd/s²","yard per second squared"
-M42,5059634,"mi/s²","mile (statute mile) per second squared"
-C92,4405554,"m⁻¹","reciprocal metre"
-Q32,5321522,"fl","femtolitre"
-Q33,5321523,"pl","picolitre"
-Q34,5321524,"nl","nanolitre"
-AWG,4282183,"AWG","american wire gauge"
-NM3,5131571,"Normalised cubic metre","Normalised cubic metre"
-SM3,5459251,"Standard cubic metre","Standard cubic metre"
-HTZ,4740186,"Hz","hertz"
-KHZ,4933722,"kHz","kilohertz"
-MHZ,5064794,"MHz","megahertz"
-D29,4469305,"THz","terahertz"
-A86,4274230,"GHz","gigahertz"
-MTZ,5067866,"mHz","millihertz"
-H10,4731184,"1/h","reciprocal hour"
-H11,4731185,"1/mo","reciprocal month"
-H09,4730937,"1/y","reciprocal year"
-H85,4732981,"1/wk","reciprocal week"
-C97,4405559,"s⁻¹","reciprocal second"
-RPS,5394515,"r/s","revolutions per second"
-RPM,5394509,"r/min","revolutions per minute"
-C94,4405556,"min⁻¹","reciprocal minute"
-C50,4404528,"Np","neper"
-2N,12878,"dB","decibel"
-M72,5060402,"B","bel"
-C51,4404529,"Np/s","neper per second"
-KGM,4933453,"kg","kilogram"
-MC,19779,"µg","microgram"
-DJ,17482,"dag","decagram"
-DG,17479,"dg","decigram"
-GRM,4674125,"g","gram"
-CGM,4409165,"cg","centigram"
-TNE,5525061,"t","tonne (metric ton)"
-DTN,4478030,"dt or dtn","decitonne"
-MGM,5064525,"mg","milligram"
-HGM,4736845,"hg","hectogram"
-KTN,4936782,"kt","kilotonne"
-2U,12885,"Mg","megagram"
-LBR,4997714,"lb","pound"
-GRN,4674126,"gr","grain"
-ONZ,5197402,"oz","ounce (avoirdupois)"
-CWI,4413257,"cwt (UK)","hundred weight (UK)"
-CWA,4413249,"cwt (US)","hundred pound (cwt) / hundred weight (US)"
-LTN,5002318,"ton (UK)","ton (UK) or long ton (US)"
-STI,5461065,"st","stone (UK)"
-STN,5461070,"ton (US)","ton (US) or short ton (UK/US)"
-APZ,4280410,"tr oz","troy ounce or apothecary ounce"
-F13,4600115,"slug","slug"
-K64,4929076,"lb/°F","pound (avoirdupois) per degree Fahrenheit"
-L69,4994617,"t/K","tonne per kelvin"
-L87,4995127,"ton (US)/°F","ton short per degree Fahrenheit"
-M85,5060661,"ton, assay","ton, assay"
-M86,5060662,"pfd","pfund"
-KMQ,4934993,"kg/m³","kilogram per cubic metre"
-23,12851,"g/cm³","gram per cubic centimetre"
-D41,4469809,"t/m³","tonne per cubic metre"
-GJ,18250,"g/ml","gram per millilitre"
-B35,4338485,"kg/l or kg/L","kilogram per litre"
-GL,18252,"g/l","gram per litre"
-A93,4274483,"g/m³","gram per cubic metre"
-GP,18256,"mg/m³","milligram per cubic metre"
-B72,4339506,"Mg/m³","megagram per cubic metre"
-B34,4338484,"kg/dm³","kilogram per cubic decimetre"
-H64,4732468,"mg/g","milligram per gram"
-H29,4731449,"µg/l","microgram per litre"
-M1,19761,"mg/l","milligram per litre"
-GQ,18257,"µg/m³","microgram per cubic metre"
-G11,4665649,"g/(cm³·bar)","gram per cubic centimetre bar"
-G33,4666163,"g/(cm³·K)","gram per cubic centimetre kelvin"
-F23,4600371,"g/dm³","gram per cubic decimetre"
-G12,4665650,"g/(dm³·bar)","gram per cubic decimetre bar"
-G34,4666164,"g/(dm³·K)","gram per cubic decimetre kelvin"
-G14,4665652,"g/(m³·bar)","gram per cubic metre bar"
-G36,4666166,"g/(m³·K)","gram per cubic metre kelvin"
-G13,4665651,"g/(l·bar)","gram per litre bar"
-G35,4666165,"g/(l·K)","gram per litre kelvin"
-G15,4665653,"g/(ml·bar)","gram per millilitre bar"
-G37,4666167,"g/(ml·K)","gram per millilitre kelvin"
-G31,4666161,"kg/cm³","kilogram per cubic centimetre"
-G16,4665654,"kg/(cm³·bar)","kilogram per cubic centimetre bar"
-G38,4666168,"kg/(cm³·K)","kilogram per cubic centimetre kelvin"
-G18,4665656,"kg/(m³·bar)","kilogram per cubic metre bar"
-G40,4666416,"kg/(m³·K)","kilogram per cubic metre kelvin"
-H54,4732212,"(kg/dm³)/K","kilogram per cubic decimetre kelvin"
-H55,4732213,"(kg/dm³)/bar","kilogram per cubic decimetre bar"
-F14,4600116,"g/K","gram per kelvin"
-F15,4600117,"kg/K","kilogram per kelvin"
-F24,4600372,"kg/kmol","kilogram per kilomole"
-G17,4665655,"kg/(l·bar)","kilogram per litre bar"
-G39,4666169,"kg/(l·K)","kilogram per litre kelvin"
-H53,4732211,"kg/bar","kilogram per bar"
-F18,4600120,"kg·cm²","kilogram square centimetre"
-F19,4600121,"kg·mm²","kilogram square millimetre"
-F74,4601652,"g/bar","gram per bar"
-F75,4601653,"mg/bar","milligram per bar"
-F16,4600118,"mg/K","milligram per kelvin"
-M73,5060403,"(kg/m³)/Pa","kilogram per cubic metre pascal"
-87,14391,"lb/ft³","pound per cubic foot"
-GE,18245,"lb/gal (US)","pound per gallon (US)"
-LA,19521,"lb/in³","pound per cubic inch"
-G32,4666162,"oz/yd³","ounce (avoirdupois) per cubic yard"
-J34,4862772,"(µg/m³)/K","microgram per cubic metre kelvin"
-J35,4862773,"(µg/m³)/bar","microgram per cubic metre bar"
-K41,4928561,"gr/gal (US)","grain per gallon (US)"
-K69,4929081,"(lb/ft³)/°F","pound (avoirdupois) per cubic foot degree Fahrenheit"
-K70,4929328,"(lb/ft³)/psi","pound (avoirdupois) per cubic foot psi"
-K71,4929329,"lb/gal (UK)","pound (avoirdupois) per gallon (UK)"
-K75,4929333,"(lb/in³)/°F","pound (avoirdupois) per cubic inch degree Fahrenheit"
-K76,4929334,"(lb/in³)/psi","pound (avoirdupois) per cubic inch psi"
-K84,4929588,"lb/yd³","pound per cubic yard"
-L17,4993335,"(mg/m³)/K","milligram per cubic metre kelvin"
-L18,4993336,"(mg/m³)/bar","milligram per cubic metre bar"
-L37,4993847,"oz/gal (UK)","ounce (avoirdupois) per gallon (UK)"
-L38,4993848,"oz/gal (US)","ounce (avoirdupois) per gallon (US)"
-L39,4993849,"oz/in³","ounce (avoirdupois) per cubic inch"
-L65,4994613,"slug/ft³","slug per cubic foot"
-L76,4994870,"(t/m³)/K","tonne per cubic metre kelvin"
-L77,4994871,"(t/m³)/bar","tonne per cubic metre bar"
-L92,4995378,"ton.l/yd³ (UK)","ton (UK long) per cubic yard"
-L93,4995379,"ton.s/yd³ (US)","ton (US short) per cubic yard"
-K77,4929335,"lb/psi","pound (avoirdupois) per psi"
-L70,4994864,"t/bar","tonne per bar"
-L91,4995377,"ton (US)/psi","ton short per psi"
-M74,5060404,"kg/Pa","kilogram per pascal"
-C62,4404786,"1","one"
-A39,4272953,"m³/kg","cubic metre per kilogram"
-22,12850,"dl/g","decilitre per gram"
-H65,4732469,"ml/m³","millilitre per cubic metre"
-H83,4732979,"l/kg","litre per kilogram"
-KX,19288,"ml/kg","millilitre per kilogram"
-H15,4731189,"cm²/g","square centimetre per gram"
-N28,5124664,"dm³/kg","cubic decimetre per kilogram"
-N29,5124665,"ft³/lb","cubic foot per pound"
-N30,5124912,"in³/lb","cubic inch per pound"
-KL,19276,"kg/m","kilogram per metre"
-GF,18246,"g/m","gram per metre (gram per 100 centimetres)"
-H76,4732726,"g/mm","gram per millimetre"
-KW,19287,"kg/mm","kilogram per millimetre"
-C12,4403506,"mg/m","milligram per metre"
-M31,5059377,"kg/km","kilogram per kilometre"
-P2,20530,"lb/ft","pound per foot"
-PO,20559,"lb/in","pound per inch of length"
-M83,5060659,"den","denier"
-M84,5060660,"lb/yd","pound per yard"
-GO,18255,"mg/m²","milligram per square metre"
-25,12853,"g/cm²","gram per square centimetre"
-H63,4732467,"mg/cm²","milligram per square centimetre"
-GM,18253,"g/m²","gram per square metre"
-28,12856,"kg/m²","kilogram per square metre"
-D5,17461,"kg/cm²","kilogram per square centimetre"
-ON,20302,"oz/yd²","ounce per square yard"
-37,13111,"oz/ft²","ounce per square foot"
-B31,4338481,"kg·m/s","kilogram metre per second"
-M98,5060920,"kg·(cm/s)","kilogram centimetre per second"
-M99,5060921,"g·(cm/s)","gram centimetre per second"
-N10,5124400,"lb·(ft/s)","pound foot per second"
-N11,5124401,"lb·(in/s)","pound inch per second"
-B33,4338483,"kg·m²/s","kilogram metre squared per second"
-B32,4338482,"kg·m²","kilogram metre squared"
-F20,4600368,"lb·in²","pound inch squared"
-K65,4929077,"lb·ft²","pound (avoirdupois) square foot"
-NEW,5129559,"N","newton"
-B73,4339507,"MN","meganewton"
-B47,4338743,"kN","kilonewton"
-C20,4403760,"mN","millinewton"
-B92,4340018,"µN","micronewton"
-DU,17493,"dyn","dyne"
-C78,4405048,"lbf","pound-force"
-B37,4338487,"kgf","kilogram-force"
-B51,4338993,"kp","kilopond"
-L40,4994096,"ozf","ounce (avoirdupois)-force"
-L94,4995380,"ton.sh-force","ton-force (US short)"
-M75,5060405,"kip","kilopound-force"
-M76,5060406,"pdl","poundal"
-M77,5060407,"kg·m/s²","kilogram metre per second squared"
-M78,5060408,"p","pond"
-F17,4600119,"lbf/ft","pound-force per foot"
-F48,4600888,"lbf/in","pound-force per inch"
-C54,4404532,"N·m²/kg²","newton metre squared per kilogram squared"
-NU,20053,"N·m","newton metre"
-H40,4731952,"N/A","newton per ampere"
-B74,4339508,"MN·m","meganewton metre"
-B48,4338744,"kN·m","kilonewton metre"
-D83,4470835,"mN·m","millinewton metre"
-B93,4340019,"µN·m","micronewton metre"
-DN,17486,"dN·m","decinewton metre"
-J72,4863794,"cN·m","centinewton metre"
-M94,5060916,"kg·m","kilogram metre"
-F88,4601912,"N·cm","newton centimetre"
-F90,4602160,"N·m/A","newton metre per ampere"
-F89,4601913,"Nm/°","newton metre per degree"
-G19,4665657,"N·m/kg","newton metre per kilogram"
-F47,4600887,"N/mm","newton per millimetre"
-M93,5060915,"N·m/rad","newton metre per radian"
-H41,4731953,"N·m·W⁻⁰‧⁵","newton metre watt to the power minus 0,5"
-B38,4338488,"kgf·m","kilogram-force metre"
-IA,18753,"in·lb","inch pound (pound inch)"
-4Q,13393,"oz·in","ounce inch"
-4R,13394,"oz·ft","ounce foot"
-F22,4600370,"lbf·ft/A","pound-force foot per ampere"
-F21,4600369,"lbf·in","pound-force inch"
-G20,4665904,"lbf·ft/lb","pound-force foot per pound"
-J94,4864308,"dyn·cm","dyne centimetre"
-L41,4994097,"ozf·in","ounce (avoirdupois)-force inch"
-M92,5060914,"lbf·ft","pound-force foot"
-M95,5060917,"pdl·ft","poundal foot"
-M96,5060918,"pdl·in","poundal inch"
-M97,5060919,"dyn·m","dyne metre"
-C57,4404535,"N·s","newton second"
-C53,4404531,"N·m·s","newton metre second"
-74,14132,"mPa","millipascal"
-MPA,5066817,"MPa","megapascal"
-PAL,5259596,"Pa","pascal"
-KPA,4935745,"kPa","kilopascal"
-BAR,4342098,"bar","bar [unit of pressure]"
-HBA,4735553,"hbar","hectobar"
-MBR,5063250,"mbar","millibar"
-KBA,4932161,"kbar","kilobar"
-ATM,4281421,"atm","standard atmosphere"
-A89,4274233,"GPa","gigapascal"
-B96,4340022,"µPa","micropascal"
-A97,4274487,"hPa","hectopascal"
-H75,4732725,"daPa","decapascal"
-B85,4339765,"µbar","microbar"
-C55,4404533,"N/m²","newton per square metre"
-C56,4404534,"N/mm²","newton per square millimetre"
-H07,4730935,"Pa·s/bar","pascal second per bar"
-F94,4602164,"hPa·m³/s","hectopascal cubic metre per second"
-F93,4602163,"hPa·l/s","hectopascal litre per second"
-F82,4601906,"hPa/K","hectopascal per kelvin"
-F83,4601907,"kPa/K","kilopascal per kelvin"
-F98,4602168,"MPa·m³/s","megapascal cubic metre per second"
-F97,4602167,"MPa·l/s","megapascal litre per second"
-F85,4601909,"MPa/K","megapascal per kelvin"
-F96,4602166,"mbar·m³/s","millibar cubic metre per second"
-F95,4602165,"mbar·l/s","millibar litre per second"
-F84,4601908,"mbar/K","millibar per kelvin"
-G01,4665393,"Pa·m³/s","pascal cubic metre per second"
-F99,4602169,"Pa·l/s","pascal litre per second"
-F77,4601655,"Pa.s/K","pascal second per kelvin"
-E01,4534321,"N/cm²","newton per square centimetre"
-FP,18000,"lb/ft²","pound per square foot"
-PS,20563,"lbf/in²","pound-force per square inch"
-B40,4338736,"kgf/m²","kilogram-force per square metre"
-UA,21825,"Torr","torr"
-ATT,4281428,"at","technical atmosphere"
-80,14384,"lb/in²","pound per square inch absolute"
-H78,4732728,"cm H₂O","conventional centimetre of water"
-HP,18512,"mm H₂O","conventional millimetre of water"
-HN,18510,"mm Hg","conventional millimetre of mercury"
-F79,4601657,"inHg","inch of mercury"
-F78,4601656,"inH₂O","inch of water"
-J89,4864057,"cm Hg","centimetre of mercury"
-K24,4928052,"ft H₂O","foot of water"
-K25,4928053,"ft Hg","foot of mercury"
-K31,4928305,"gf/cm²","gram-force per square centimetre"
-E42,4535346,"kgf/cm²","kilogram-force per square centimetre"
-E41,4535345,"kgf·m/cm²","kilogram-force per square millimetre"
-K85,4929589,"lbf/ft²","pound-force per square foot"
-K86,4929590,"psi/°F","pound-force per square inch degree Fahrenheit"
-84,14388,"klbf/in²","kilopound-force per square inch"
-N13,5124403,"cmHg (0 ºC)","centimetre of mercury (0 ºC)"
-N14,5124404,"cmH₂O (4 °C)","centimetre of water (4 ºC)"
-N15,5124405,"ftH₂O (39,2 ºF)","foot of water (39.2 ºF)"
-N16,5124406,"inHG (32 ºF)","inch of mercury (32 ºF)"
-N17,5124407,"inHg (60 ºF)","inch of mercury (60 ºF)"
-N18,5124408,"inH₂O (39,2 ºF)","inch of water (39.2 ºF)"
-N19,5124409,"inH₂O (60 ºF)","inch of water (60 ºF)"
-N20,5124656,"ksi","kip per square inch"
-N21,5124657,"pdl/ft²","poundal per square foot"
-N22,5124658,"oz/in²","ounce (avoirdupois) per square inch"
-N23,5124659,"mH₂O","conventional metre of water"
-N24,5124660,"g/mm²","gram per square millimetre"
-N25,5124661,"lb/yd²","pound per square yard"
-N26,5124662,"pdl/in²","poundal per square inch"
-E99,4536633,"hPa/bar","hectopascal per bar"
-F05,4599861,"MPa/bar","megapascal per bar"
-F04,4599860,"mbar/bar","millibar per bar"
-F07,4599863,"Pa/bar","pascal per bar"
-F03,4599859,"kPa/bar","kilopascal per bar"
-L52,4994354,"psi/psi","psi per psi"
-J56,4863286,"bar/bar","bar per bar"
-C96,4405558,"Pa⁻¹","reciprocal pascal or pascal to the power minus one"
-F58,4601144,"1/bar","reciprocal bar"
-B83,4339763,"m⁴","metre to the fourth power"
-G77,4667191,"mm⁴","millimetre to the fourth power"
-D69,4470329,"in⁴","inch to the fourth power"
-N27,5124663,"ft⁴","foot to the fourth power"
-C65,4404789,"Pa·s","pascal second"
-N37,5124919,"kg/(m·s)","kilogram per metre second"
-N38,5124920,"kg/(m·min)","kilogram per metre minute"
-C24,4403764,"mPa·s","millipascal second"
-N36,5124918,"(N/m²)·s","newton second per square metre"
-N39,5124921,"kg/(m·d)","kilogram per metre day"
-N40,5125168,"kg/(m·h)","kilogram per metre hour"
-N41,5125169,"g/(cm·s)","gram per centimetre second"
-89,14393,"P","poise"
-C7,17207,"cP","centipoise"
-F06,4599862,"P/bar","poise per bar"
-F86,4601910,"P/K","poise per kelvin"
-J32,4862770,"µP","micropoise"
-J73,4863795,"cP/K","centipoise per kelvin"
-J74,4863796,"cP/bar","centipoise per bar"
-K67,4929079,"lb/(ft·h)","pound per foot hour"
-K68,4929080,"lb/(ft·s)","pound per foot second"
-K91,4929841,"lbf·s/ft²","pound-force second per square foot"
-K92,4929842,"lbf·s/in²","pound-force second per square inch"
-L15,4993333,"mPa·s/K","millipascal second per kelvin"
-L16,4993334,"mPa·s/bar","millipascal second per bar"
-L64,4994612,"slug/(ft·s)","slug per foot second"
-N34,5124916,"(pdl/ft²)·s","poundal second per square foot"
-N35,5124917,"P/Pa","poise per pascal"
-N42,5125170,"(pdl/in²)·s","poundal second per square inch"
-N43,5125171,"lb/(ft·min)","pound per foot minute"
-N44,5125172,"lb/(ft·d)","pound per foot day"
-S4,21300,"m²/s","square metre per second"
-M82,5060658,"(m²/s)/Pa","square metre per second pascal"
-C17,4403511,"mm²/s","millimetre squared per second"
-G41,4666417,"m²/(s·bar)","square metre per second bar"
-G09,4665401,"m²/(s·K)","square metre per second kelvin"
-91,14641,"St","stokes"
-4C,13379,"cSt","centistokes"
-G46,4666422,"St/bar","stokes per bar"
-G10,4665648,"St/K","stokes per kelvin"
-S3,21299,"ft²/s","square foot per second"
-G08,4665400,"in²/s","square inch per second"
-M79,5060409,"ft²/h","square foot per hour"
-M80,5060656,"St/Pa","stokes per pascal"
-M81,5060657,"cm²/s","square centimetre per second"
-4P,13392,"N/m","newton per metre"
-C22,4403762,"mN/m","millinewton per metre"
-M23,5059123,"N/cm","newton per centimetre"
-N31,5124913,"kN/m","kilonewton per metre"
-DX,17496,"dyn/cm","dyne per centimetre"
-N32,5124914,"pdl/in","poundal per inch"
-N33,5124915,"lbf/yd","pound-force per yard"
-M34,5059380,"N·m/m²","newton metre per square metre"
-JOU,4869973,"J","joule"
-KJO,4934223,"kJ","kilojoule"
-A68,4273720,"EJ","exajoule"
-C68,4404792,"PJ","petajoule"
-D30,4469552,"TJ","terajoule"
-GV,18262,"GJ","gigajoule"
-3B,13122,"MJ","megajoule"
-C15,4403509,"mJ","millijoule"
-A70,4273968,"fJ","femtojoule"
-A13,4272435,"aJ","attojoule"
-WHR,5720146,"W·h","watt hour"
-MWH,5068616,"MW·h","megawatt hour (1000 kW.h)"
-KWH,4937544,"kW·h","kilowatt hour"
-GWH,4675400,"GW·h","gigawatt hour"
-D32,4469554,"TW·h","terawatt hour"
-A53,4273459,"eV","electronvolt"
-B71,4339505,"MeV","megaelectronvolt"
-A85,4274229,"GeV","gigaelectronvolt"
-B29,4338233,"keV","kiloelectronvolt"
-A57,4273463,"erg","erg"
-85,14389,"ft·lbf","foot pound-force"
-N46,5125174,"ft·pdl","foot poundal"
-N47,5125175,"in·pdl","inch poundal"
-WTT,5723220,"W","watt"
-KWT,4937556,"kW","kilowatt"
-MAW,5062999,"MW","megawatt"
-A90,4274480,"GW","gigawatt"
-C31,4404017,"mW","milliwatt"
-D80,4470832,"µW","microwatt"
-F80,4601904,"water horse power","water horse power"
-A63,4273715,"erg/s","erg per second"
-A74,4273972,"ft·lbf/s","foot pound-force per second"
-B39,4338489,"kgf·m/s","kilogram-force metre per second"
-HJ,18506,"metric hp","metric horse power"
-A25,4272693,"CV","cheval vapeur"
-BHP,4343888,"BHP","brake horse power"
-K15,4927797,"ft·lbf/h","foot pound-force per hour"
-K16,4927798,"ft·lbf/min","foot pound-force per minute"
-K42,4928562,"boiler hp","horsepower (boiler)"
-N12,5124402,"PS","Pferdestaerke"
-KGS,4933459,"kg/s","kilogram per second"
-H56,4732214,"kg/(m²·s)","kilogram per square metre second"
-M87,5060663,"(kg/s)/Pa","kilogram per second pascal"
-4M,13389,"mg/h","milligram per hour"
-F26,4600374,"g/d","gram per day"
-F62,4601394,"g/(d·bar)","gram per day bar"
-F35,4600629,"g/(d·K)","gram per day kelvin"
-F27,4600375,"g/h","gram per hour"
-F63,4601395,"g/(h·bar)","gram per hour bar"
-F36,4600630,"g/(h·K)","gram per hour kelvin"
-F28,4600376,"g/min","gram per minute"
-F64,4601396,"g/(min·bar)","gram per minute bar"
-F37,4600631,"g/(min·K)","gram per minute kelvin"
-F29,4600377,"g/s","gram per second"
-F65,4601397,"g/(s·bar)","gram per second bar"
-F38,4600632,"g/(s·K)","gram per second kelvin"
-F30,4600624,"kg/d","kilogram per day"
-F66,4601398,"kg/(d·bar)","kilogram per day bar"
-F39,4600633,"kg/(d·K)","kilogram per day kelvin"
-E93,4536627,"kg/h","kilogram per hour"
-F67,4601399,"kg/(h·bar)","kilogram per hour bar"
-F40,4600880,"kg/(h·K)","kilogram per hour kelvin"
-F31,4600625,"kg/min","kilogram per minute"
-F68,4601400,"kg/(min·bar)","kilogram per minute bar"
-F41,4600881,"kg/(min·K)","kilogram per minute kelvin"
-F69,4601401,"kg/(s·bar)","kilogram per second bar"
-F42,4600882,"kg/(s·K)","kilogram per second kelvin"
-F32,4600626,"mg/d","milligram per day"
-F70,4601648,"mg/(d·bar)","milligram per day bar"
-F43,4600883,"mg/(d·K)","milligram per day kelvin"
-F71,4601649,"mg/(h·bar)","milligram per hour bar"
-F44,4600884,"mg/(h·K)","milligram per hour kelvin"
-F33,4600627,"mg/min","milligram per minute"
-F72,4601650,"mg/(min·bar)","milligram per minute bar"
-F45,4600885,"mg/(min·K)","milligram per minute kelvin"
-F34,4600628,"mg/s","milligram per second"
-F73,4601651,"mg/(s·bar)","milligram per second bar"
-F46,4600886,"mg/(s·K)","milligram per second kelvin"
-F25,4600373,"g/Hz","gram per hertz"
-4W,13399,"ton (US) /h","ton (US) per hour"
-4U,13397,"lb/h","pound per hour"
-K66,4929078,"lb/d","pound (avoirdupois) per day"
-K73,4929331,"(lb/h)/°F","pound (avoirdupois) per hour degree Fahrenheit"
-K74,4929332,"(lb/h)/psi","pound (avoirdupois) per hour psi"
-K78,4929336,"lb/min","pound (avoirdupois) per minute"
-K79,4929337,"lb/(min·°F)","pound (avoirdupois) per minute degree Fahrenheit"
-K80,4929584,"(lb/min)/psi","pound (avoirdupois) per minute psi"
-K81,4929585,"lb/s","pound (avoirdupois) per second"
-K82,4929586,"(lb/s)/°F","pound (avoirdupois) per second degree Fahrenheit"
-K83,4929587,"(lb/s)/psi","pound (avoirdupois) per second psi"
-L33,4993843,"oz/d","ounce (avoirdupois) per day"
-L34,4993844,"oz/h","ounce (avoirdupois) per hour"
-L35,4993845,"oz/min","ounce (avoirdupois) per minute"
-L36,4993846,"oz/s","ounce (avoirdupois) per second"
-L63,4994611,"slug/d","slug per day"
-L66,4994614,"slug/h","slug per hour"
-L67,4994615,"slug/min","slug per minute"
-L68,4994616,"slug/s","slug per second"
-L71,4994865,"t/d","tonne per day"
-L72,4994866,"(t/d)/K","tonne per day kelvin"
-L73,4994867,"(t/d)/bar","tonne per day bar"
-E18,4534584,"t/h","tonne per hour"
-L74,4994868,"(t/h)/K","tonne per hour kelvin"
-L75,4994869,"(t/h)/bar","tonne per hour bar"
-L78,4994872,"t/min","tonne per minute"
-L79,4994873,"(t/min)/K","tonne per minute kelvin"
-L80,4995120,"(t/min)/bar","tonne per minute bar"
-L81,4995121,"t/s","tonne per second"
-L82,4995122,"(t/s)/K","tonne per second kelvin"
-L83,4995123,"(t/s)/bar","tonne per second bar"
-L85,4995125,"ton (UK)/d","ton long per day"
-L88,4995128,"ton (US)/d","ton short per day"
-L89,4995129,"ton (US)/(h·°F)","ton short per hour degree Fahrenheit"
-L90,4995376,"(ton (US)/h)/psi","ton short per hour psi"
-M88,5060664,"t/mo","tonne per month"
-M89,5060665,"t/y","tonne per year"
-M90,5060912,"klb/h","kilopound per hour"
-J33,4862771,"µg/kg","microgram per kilogram"
-L32,4993842,"ng/kg","nanogram per kilogram"
-NA,20033,"mg/kg","milligram per kilogram"
-M29,5059129,"kg/kg","kilogram per kilogram"
-M91,5060913,"lb/lb","pound per pound"
-MQS,5067091,"m³/s","cubic metre per second"
-MQH,5067080,"m³/h","cubic metre per hour"
-40,13360,"ml/s","millilitre per second"
-41,13361,"ml/min","millilitre per minute"
-LD,19524,"l/d","litre per day"
-2J,12874,"cm³/s","cubic centimetre per second"
-4X,13400,"kl/h","kilolitre per hour"
-L2,19506,"l/min","litre per minute"
-G47,4666423,"cm³/d","cubic centimetre per day"
-G78,4667192,"cm³/(d·bar)","cubic centimetre per day bar"
-G61,4666929,"cm³/(d·K)","cubic centimetre per day kelvin"
-G48,4666424,"cm³/h","cubic centimetre per hour"
-G79,4667193,"cm³/(h·bar)","cubic centimetre per hour bar"
-G62,4666930,"cm³/(h·K)","cubic centimetre per hour kelvin"
-G49,4666425,"cm³/min","cubic centimetre per minute"
-G80,4667440,"cm³/(min·bar)","cubic centimetre per minute bar"
-G63,4666931,"cm³/(min·K)","cubic centimetre per minute kelvin"
-G81,4667441,"cm³/(s·bar)","cubic centimetre per second bar"
-G64,4666932,"cm³/(s·K)","cubic centimetre per second kelvin"
-E92,4536626,"dm³/h","cubic decimetre per hour"
-G52,4666674,"m³/d","cubic metre per day"
-G86,4667446,"m³/(d·bar)","cubic metre per day bar"
-G69,4666937,"m³/(d·K)","cubic metre per day kelvin"
-G87,4667447,"m³/(h·bar)","cubic metre per hour bar"
-G70,4667184,"m³/(h·K)","cubic metre per hour kelvin"
-G53,4666675,"m³/min","cubic metre per minute"
-G88,4667448,"m³/(min·bar)","cubic metre per minute bar"
-G71,4667185,"m³/(min·K)","cubic metre per minute kelvin"
-G89,4667449,"m³/(s·bar)","cubic metre per second bar"
-G72,4667186,"m³/(s·K)","cubic metre per second kelvin"
-G82,4667442,"l/(d·bar)","litre per day bar"
-G65,4666933,"l/(d·K)","litre per day kelvin"
-G83,4667443,"l/(h·bar)","litre per hour bar"
-G66,4666934,"l/(h·K)","litre per hour kelvin"
-G84,4667444,"l/(min·bar)","litre per minute bar"
-G67,4666935,"l/(min·K)","litre per minute kelvin"
-G51,4666673,"l/s","litre per second"
-G85,4667445,"l/(s·bar)","litre per second bar"
-G68,4666936,"l/(s·K)","litre per second kelvin"
-G54,4666676,"ml/d","millilitre per day"
-G90,4667696,"ml/(d·bar)","millilitre per day bar"
-G73,4667187,"ml/(d·K)","millilitre per day kelvin"
-G55,4666677,"ml/h","millilitre per hour"
-G91,4667697,"ml/(h·bar)","millilitre per hour bar"
-G74,4667188,"ml/(h·K)","millilitre per hour kelvin"
-G92,4667698,"ml/(min·bar)","millilitre per minute bar"
-G75,4667189,"ml/(min·K)","millilitre per minute kelvin"
-G93,4667699,"ml/(s·bar)","millilitre per second bar"
-G76,4667190,"ml/(s·K)","millilitre per second kelvin"
-2K,12875,"ft³/h","cubic foot per hour"
-2L,12876,"ft³/min","cubic foot per minute"
-5A,13633,"barrel (US)/min","barrel (US) per minute"
-G2,18226,"gal (US) /min","US gallon per minute"
-G3,18227,"gal (UK) /min","Imperial gallon per minute"
-G56,4666678,"in³/h","cubic inch per hour"
-G57,4666679,"in³/min","cubic inch per minute"
-G58,4666680,"in³/s","cubic inch per second"
-G50,4666672,"gal/h","gallon (US) per hour"
-J58,4863288,"bbl (UK liq.)/min","barrel (UK petroleum) per minute"
-J59,4863289,"bbl (UK liq.)/d","barrel (UK petroleum) per day"
-J60,4863536,"bbl (UK liq.)/h","barrel (UK petroleum) per hour"
-J61,4863537,"bbl (UK liq.)/s","barrel (UK petroleum) per second"
-J62,4863538,"bbl (US)/h","barrel (US petroleum) per hour"
-J63,4863539,"bbl (US)/s","barrel (US petroleum) per second"
-J64,4863540,"bu (UK)/d","bushel (UK) per day"
-J65,4863541,"bu (UK)/h","bushel (UK) per hour"
-J66,4863542,"bu (UK)/min","bushel (UK) per minute"
-J67,4863543,"bu (UK)/s","bushel (UK) per second"
-J68,4863544,"bu (US dry)/d","bushel (US dry) per day"
-J69,4863545,"bu (US dry)/h","bushel (US dry) per hour"
-J70,4863792,"bu (US dry)/min","bushel (US dry) per minute"
-J71,4863793,"bu (US dry)/s","bushel (US dry) per second"
-J90,4864304,"dm³/d","cubic decimetre per day"
-J92,4864306,"dm³/min","cubic decimetre per minute"
-J93,4864307,"dm³/s","cubic decimetre per second"
-N45,5125173,"(m³/s)/Pa","cubic metre per second pascal"
-J95,4864309,"fl oz (UK)/d","ounce (UK fluid) per day"
-J96,4864310,"fl oz (UK)/h","ounce (UK fluid) per hour"
-J97,4864311,"fl oz (UK)/min","ounce (UK fluid) per minute"
-J98,4864312,"fl oz (UK)/s","ounce (UK fluid) per second"
-J99,4864313,"fl oz (US)/d","ounce (US fluid) per day"
-K10,4927792,"fl oz (US)/h","ounce (US fluid) per hour"
-K11,4927793,"fl oz (US)/min","ounce (US fluid) per minute"
-K12,4927794,"fl oz (US)/s","ounce (US fluid) per second"
-K22,4928050,"ft³/d","cubic foot per day"
-K26,4928054,"gal (UK)/d","gallon (UK) per day"
-K27,4928055,"gal (UK)/h","gallon (UK) per hour"
-K28,4928056,"gal (UK)/s","gallon (UK) per second"
-K30,4928304,"gal (US liq.)/s","gallon (US liquid) per second"
-K32,4928306,"gi (UK)/d","gill (UK) per day"
-K33,4928307,"gi (UK)/h","gill (UK) per hour"
-K34,4928308,"gi (UK)/min","gill (UK) per minute"
-K35,4928309,"gi (UK)/s","gill (UK) per second"
-K36,4928310,"gi (US)/d","gill (US) per day"
-K37,4928311,"gi (US)/h","gill (US) per hour"
-K38,4928312,"gi (US)/min","gill (US) per minute"
-K39,4928313,"gi (US)/s","gill (US) per second"
-K94,4929844,"qt (UK liq.)/d","quart (UK liquid) per day"
-K95,4929845,"qt (UK liq.)/h","quart (UK liquid) per hour"
-K96,4929846,"qt (UK liq.)/min","quart (UK liquid) per minute"
-K97,4929847,"qt (UK liq.)/s","quart (UK liquid) per second"
-K98,4929848,"qt (US liq.)/d","quart (US liquid) per day"
-K99,4929849,"qt (US liq.)/h","quart (US liquid) per hour"
-L10,4993328,"qt (US liq.)/min","quart (US liquid) per minute"
-L11,4993329,"qt (US liq.)/s","quart (US liquid) per second"
-L44,4994100,"pk (UK)/d","peck (UK) per day"
-L45,4994101,"pk (UK)/h","peck (UK) per hour"
-L46,4994102,"pk (UK)/min","peck (UK) per minute"
-L47,4994103,"pk (UK)/s","peck (UK) per second"
-L48,4994104,"pk (US dry)/d","peck (US dry) per day"
-L49,4994105,"pk (US dry)/h","peck (US dry) per hour"
-L50,4994352,"pk (US dry)/min","peck (US dry) per minute"
-L51,4994353,"pk (US dry)/s","peck (US dry) per second"
-L53,4994355,"pt (UK)/d","pint (UK) per day"
-L54,4994356,"pt (UK)/h","pint (UK) per hour"
-L55,4994357,"pt (UK)/min","pint (UK) per minute"
-L56,4994358,"pt (UK)/s","pint (UK) per second"
-L57,4994359,"pt (US liq.)/d","pint (US liquid) per day"
-L58,4994360,"pt (US liq.)/h","pint (US liquid) per hour"
-L59,4994361,"pt (US liq.)/min","pint (US liquid) per minute"
-L60,4994608,"pt (US liq.)/s","pint (US liquid) per second"
-M12,5058866,"yd³/d","cubic yard per day"
-M13,5058867,"yd³/h","cubic yard per hour"
-M15,5058869,"yd³/min","cubic yard per minute"
-M16,5058870,"yd³/s","cubic yard per second"
-H60,4732464,"m³/m³","cubic metre per cubic metre"
-F92,4602162,"bar·m³/s","bar cubic metre per second"
-F91,4602161,"bar·l/s","bar litre per second"
-K87,4929591,"psi·in³/s","psi cubic inch per second"
-K88,4929592,"psi·l/s","psi litre per second"
-K89,4929593,"psi·m³/s","psi cubic metre per second"
-K90,4929840,"psi·yd³/s","psi cubic yard per second"
-Q29,5321273,"µg/hg","microgram per hectogram"
-Q37,5321527,"Standard cubic metre per day","Standard cubic metre per day"
-Q38,5321528,"Standard cubic metre per hour","Standard cubic metre per hour"
-Q39,5321529,"Normalized cubic metre per day","Normalized cubic metre per day"
-Q40,5321776,"Normalized cubic metre per hour","Normalized cubic metre per hour"
-KWN,4937550,"Kilowatt hour per normalized cubic metre","Kilowatt hour per normalized cubic metre"
-KWS,4937555,"Kilowatt hour per standard cubic metre","Kilowatt hour per standard cubic metre"
-Q41,5321777,"Joule per normalised cubic metre","Joule per normalised cubic metre"
-Q42,5321778,"Joule per standard cubic metre","Joule per standard cubic metre"
-MNJ,5066314,"MJ/m³","Mega Joule per Normalised cubic Metre"
-KEL,4932940,"K","kelvin"
-CEL,4408652,"°C","degree Celsius"
-H12,4731186,"°C/h","degree Celsius per hour"
-F60,4601392,"°C/bar","degree Celsius per bar"
-E98,4536632,"°C/K","degree Celsius per kelvin"
-H13,4731187,"°C/min","degree Celsius per minute"
-H14,4731188,"°C/s","degree Celsius per second"
-F61,4601393,"K/bar","kelvin per bar"
-F10,4600112,"K/h","kelvin per hour"
-F02,4599858,"K/K","kelvin per kelvin"
-F11,4600113,"K/min","kelvin per minute"
-F12,4600114,"K/s","kelvin per second"
-N79,5125945,"K/Pa","kelvin per pascal"
-J20,4862512,"°F/K","degree Fahrenheit per kelvin"
-J21,4862513,"°F/bar","degree Fahrenheit per bar"
-J26,4862518,"1/°F","reciprocal degree Fahrenheit"
-A48,4273208,"°R","degree Rankine"
-FAH,4604232,"°F","degree Fahrenheit"
-J23,4862515,"°F/h","degree Fahrenheit per hour"
-J24,4862516,"°F/min","degree Fahrenheit per minute"
-J25,4862517,"°F/s","degree Fahrenheit per second"
-J28,4862520,"°R/h","degree Rankine per hour"
-J29,4862521,"°R/min","degree Rankine per minute"
-J30,4862768,"°R/s","degree Rankine per second"
-C91,4405553,"K⁻¹","reciprocal kelvin or kelvin to the power minus one"
-M20,5059120,"1/MK","reciprocal megakelvin or megakelvin to the power minus one"
-C64,4404788,"Pa/K","pascal per kelvin"
-F81,4601905,"bar/K","bar per kelvin"
-J55,4863285,"W·s","watt second"
-BTU,4346965,"BtuIT","British thermal unit (international table)"
-A1,16689,"cal₁₅","15 °C calorie"
-D70,4470576,"calIT","calorie (international table)"
-J39,4862777,"Btu","British thermal unit (mean)"
-J75,4863797,"cal","calorie (mean)"
-K51,4928817,"kcal","kilocalorie (mean)"
-E14,4534580,"kcalIT","kilocalorie (international table)"
-K53,4928819,"kcalth","kilocalorie (thermochemical)"
-N66,5125686,"Btu (39 ºF)","British thermal unit (39 ºF)"
-N67,5125687,"Btu (59 ºF)","British thermal unit (59 ºF)"
-N68,5125688,"Btu (60 ºF)","British thermal unit (60 ºF)"
-N69,5125689,"cal₂₀","calorie (20 ºC)"
-N70,5125936,"quad","quad (1015 BtuIT)"
-N71,5125937,"thm (EC)","therm (EC)"
-N72,5125938,"thm (US)","therm (U.S.)"
-D35,4469557,"calth","calorie (thermochemical)"
-2I,12873,"BtuIT/h","British thermal unit (international table) per hour"
-J44,4863028,"BtuIT/min","British thermal unit (international table) per minute"
-J45,4863029,"BtuIT/s","British thermal unit (international table) per second"
-J47,4863031,"Btuth/h","British thermal unit (thermochemical) per hour"
-J51,4863281,"Btuth/min","British thermal unit (thermochemical) per minute"
-J52,4863282,"Btuth/s","British thermal unit (thermochemical) per second"
-J81,4864049,"calth/min","calorie (thermochemical) per minute"
-J82,4864050,"calth/s","calorie (thermochemical) per second"
-E15,4534581,"kcalth/h","kilocalorie (thermochemical) per hour"
-K54,4928820,"kcalth/min","kilocalorie (thermochemical) per minute"
-K55,4928821,"kcalth/s","kilocalorie (thermochemical) per second"
-D54,4470068,"W/m²","watt per square metre"
-N48,5125176,"W/cm²","watt per square centimetre"
-N49,5125177,"W/in²","watt per square inch"
-N50,5125424,"BtuIT/(ft²·h)","British thermal unit (international table) per square foot hour"
-N51,5125425,"Btuth/(ft²·h)","British thermal unit (thermochemical) per square foot hour"
-N52,5125426,"Btuth/(ft²·min)","British thermal unit (thermochemical) per square foot minute"
-N53,5125427,"BtuIT/(ft²·s)","British thermal unit (international table) per square foot second"
-N54,5125428,"Btuth/(ft²·s)","British thermal unit (thermochemical) per square foot second"
-N55,5125429,"BtuIT/(in²·s)","British thermal unit (international table) per square inch second"
-N56,5125430,"calth/(cm²·min)","calorie (thermochemical) per square centimetre minute"
-N57,5125431,"calth/(cm²·s)","calorie (thermochemical) per square centimetre second"
-D53,4470067,"W/(m·K)","watt per metre kelvin"
-N80,5126192,"W/(m·°C)","watt per metre degree Celsius"
-N81,5126193,"kW/(m·K)","kilowatt per metre kelvin"
-N82,5126194,"kW/(m·°C)","kilowatt per metre degree Celsius"
-A22,4272690,"BtuIT/(s·ft·°R)","British thermal unit (international table) per second foot degree Rankine"
-D71,4470577,"calIT/(s·cm·K)","calorie (international table) per second centimetre kelvin"
-D38,4469560,"calth/(s·cm·K)","calorie (thermochemical) per second centimetre kelvin"
-J40,4863024,"BtuIT·ft/(h·ft²·°F)","British thermal unit (international table) foot per hour square foot degree Fahrenheit"
-J41,4863025,"BtuIT·in/(h·ft²·°F)","British thermal unit (international table) inch per hour square foot degree Fahrenheit"
-J42,4863026,"BtuIT·in/(s·ft²·°F)","British thermal unit (international table) inch per second square foot degree Fahrenheit"
-J46,4863030,"Btuth·ft/(h·ft²·°F)","British thermal unit (thermochemical) foot per hour square foot degree Fahrenheit"
-J48,4863032,"Btuth·in/(h·ft²·°F)","British thermal unit (thermochemical) inch per hour square foot degree Fahrenheit"
-J49,4863033,"Btuth·in/(s·ft²·°F)","British thermal unit (thermochemical) inch per second square foot degree Fahrenheit"
-J78,4863800,"calth/(cm·s·°C)","calorie (thermochemical) per centimetre second degree Celsius"
-K52,4928818,"kcal/(m·h·°C)","kilocalorie (international table) per hour metre degree Celsius"
-D55,4470069,"W/(m²·K)","watt per square metre kelvin"
-N78,5125944,"kW/(m²·K)","kilowatt per square metre kelvin"
-D72,4470578,"calIT/(s·cm²·K)","calorie (international table) per second square centimetre kelvin"
-D39,4469561,"calth/(s·cm²·K)","calorie (thermochemical) per second square centimetre kelvin"
-A20,4272688,"BtuIT/(s·ft²·°R)","British thermal unit (international table) per second square foot degree Rankine"
-A23,4272691,"BtuIT/(h·ft²·°R)","British thermal unit (international table) per hour square foot degree Rankine"
-N74,5125940,"BtuIT/(h·ft²·ºF)","British thermal unit (international table) per hour square foot degree Fahrenheit"
-N75,5125941,"Btuth/(h·ft²·ºF)","British thermal unit (thermochemical) per hour square foot degree Fahrenheit"
-N76,5125942,"BtuIT/(s·ft²·ºF)","British thermal unit (international table) per second square foot degree Fahrenheit"
-N77,5125943,"Btuth/(s·ft²·ºF)","British thermal unit (thermochemical) per second square foot degree Fahrenheit"
-D19,4469049,"m²·K/W","square metre kelvin per watt"
-J19,4862265,"°F·h·ft²/Btuth","degree Fahrenheit hour square foot per British thermal unit (thermochemical)"
-J22,4862514,"°F·h·ft²/BtuIT","degree Fahrenheit hour square foot per British thermal unit (international table)"
-J83,4864051,"clo","clo"
-L14,4993332,"m²·h·°C/kcal","square metre hour degree Celsius per kilocalorie (international table)"
-B21,4338225,"K/W","kelvin per watt"
-H35,4731701,"K·m/W","kelvin metre per watt"
-N84,5126196,"ºF/(BtuIT/h)","degree Fahrenheit hour per British thermal unit (international table)"
-N85,5126197,"ºF/(Btuth/h)","degree Fahrenheit hour per British thermal unit (thermochemical)"
-N86,5126198,"ºF/(BtuIT/s)","degree Fahrenheit second per British thermal unit (international table)"
-N87,5126199,"ºF/(Btuth/s)","degree Fahrenheit second per British thermal unit (thermochemical)"
-N88,5126200,"ºF·h·ft²/(BtuIT·in)","degree Fahrenheit hour square foot per British thermal unit (international table) inch"
-N89,5126201,"ºF·h·ft²/(Btuth·in)","degree Fahrenheit hour square foot per British thermal unit (thermochemical) inch"
-D52,4470066,"W/K","watt per kelvin"
-E97,4536631,"mm/(°C·m)","millimetre per degree Celcius metre"
-F53,4601139,"mm/K","millimetre per kelvin"
-N83,5126195,"m/(°C·m)","metre per degree Celcius metre"
-JE,19013,"J/K","joule per kelvin"
-B41,4338737,"kJ/K","kilojoule per kelvin"
-J43,4863027,"BtuIT/(lb·°F)","British thermal unit (international table) per pound degree Fahrenheit"
-J50,4863280,"Btuth/(lb·°F)","British thermal unit (thermochemical) per pound degree Fahrenheit"
-J76,4863798,"calIT/(g·°C)","calorie (international table) per gram degree Celsius"
-J79,4863801,"calth/(g·°C)","calorie (thermochemical) per gram degree Celsius"
-N60,5125680,"BtuIT/ºF","British thermal unit (international table) per degree Fahrenheit"
-N61,5125681,"Btuth/ºF","British thermal unit (thermochemical) per degree Fahrenheit"
-N62,5125682,"BtuIT/ºR","British thermal unit (international table) per degree Rankine"
-N63,5125683,"Btuth/ºR","British thermal unit (thermochemical) per degree Rankine"
-N64,5125684,"(Btuth/°R)/lb","British thermal unit (thermochemical) per pound degree Rankine"
-N65,5125685,"(kcalIT/K)/g","kilocalorie (international table) per gram kelvin"
-B11,4337969,"J/(kg·K)","joule per kilogram kelvin"
-B43,4338739,"kJ/(kg·K)","kilojoule per kilogram kelvin"
-A21,4272689,"Btu/IT(lb·°R)","British thermal unit (international table) per pound degree Rankine"
-D76,4470582,"calIT/(g·K)","calorie (international table) per gram kelvin"
-D37,4469559,"calth/(g·K)","calorie (thermochemical) per gram kelvin"
-J2,18994,"J/kg","joule per kilogram"
-D95,4471093,"J/g","joule per gram"
-JK,19019,"MJ/kg","megajoule per kilogram"
-B42,4338738,"kJ/kg","kilojoule per kilogram"
-AZ,16730,"BtuIT/lb","British thermal unit (international table) per pound"
-D75,4470581,"calIT/g","calorie (international table) per gram"
-N73,5125939,"Btuth/lb","British thermal unit (thermochemical) per pound"
-B36,4338486,"calth/g","calorie (thermochemical) per gram"
-N58,5125432,"BtuIT/ft³","British thermal unit (international table) per cubic foot"
-N59,5125433,"Btuth/ft³","British thermal unit (thermochemical) per cubic foot"
-Q31,5321521,"kJ/g","kilojoule per gram"
-AMP,4279632,"A","ampere"
-B22,4338226,"kA","kiloampere"
-H38,4731704,"MA","megaampere"
-4K,13387,"mA","milliampere"
-B84,4339764,"µA","microampere"
-C39,4404025,"nA","nanoampere"
-C70,4405040,"pA","picoampere"
-N96,5126454,"Bi","biot"
-N97,5126455,"Gi","gilbert"
-COU,4411221,"C","coulomb"
-A8,16696,"A·s","ampere second"
-H32,4731698,"A²·s","ampere squared second"
-AMH,4279624,"A·h","ampere hour"
-TAH,5521736,"kA·h","kiloampere hour (thousand ampere hour)"
-D77,4470583,"MC","megacoulomb"
-D86,4470838,"mC","millicoulomb"
-B26,4338230,"kC","kilocoulomb"
-B86,4339766,"µC","microcoulomb"
-C40,4404272,"nC","nanocoulomb"
-C71,4405041,"pC","picocoulomb"
-E09,4534329,"mA·h","milliampere hour"
-N95,5126453,"A·min","ampere minute"
-N94,5126452,"Fr","franklin"
-A29,4272697,"C/m³","coulomb per cubic metre"
-A84,4274228,"GC/m³","gigacoulomb per cubic metre"
-A30,4272944,"C/mm³","coulomb per cubic millimetre"
-B69,4339257,"MC/m³","megacoulomb per cubic metre"
-A28,4272696,"C/cm³","coulomb per cubic centimetre"
-B27,4338231,"kC/m³","kilocoulomb per cubic metre"
-D88,4470840,"mC/m³","millicoulomb per cubic metre"
-B87,4339767,"µC/m³","microcoulomb per cubic metre"
-A34,4272948,"C/m²","coulomb per square metre"
-B70,4339504,"MC/m²","megacoulomb per square metre"
-A35,4272949,"C/mm²","coulomb per square millimetre"
-A33,4272947,"C/cm²","coulomb per square centimetre"
-B28,4338232,"kC/m²","kilocoulomb per square metre"
-D89,4470841,"mC/m²","millicoulomb per square metre"
-B88,4339768,"µC/m²","microcoulomb per square metre"
-D50,4470064,"V/m","volt per metre"
-H45,4731957,"V·s/m","volt second per metre"
-D45,4469813,"V²/K²","volt squared per kelvin squared"
-D51,4470065,"V/mm","volt per millimetre"
-H24,4731444,"V/µs","volt per microsecond"
-H62,4732466,"mV/min","millivolt per minute"
-H46,4731958,"V/s","volt per second"
-B79,4339513,"MV/m","megavolt per metre"
-B55,4338997,"kV/m","kilovolt per metre"
-D47,4469815,"V/cm","volt per centimetre"
-C30,4404016,"mV/m","millivolt per metre"
-C3,17203,"µV/m","microvolt per metre"
-G60,4666928,"V/bar","volt per bar"
-N98,5126456,"V/Pa","volt per pascal"
-F87,4601911,"V/(l·min)","volt per litre minute"
-H22,4731442,"V/(lbf/in²)","volt square inch per pound-force"
-H23,4731443,"V/in","volt per inch"
-VLT,5655636,"V","volt"
-B78,4339512,"MV","megavolt"
-KVT,4937300,"kV","kilovolt"
-2Z,12890,"mV","millivolt"
-D82,4470834,"µV","microvolt"
-N99,5126457,"pV","picovolt"
-FAR,4604242,"F","farad"
-H48,4731960,"aF","attofarad"
-C10,4403504,"mF","millifarad"
-4O,13391,"µF","microfarad"
-C41,4404273,"nF","nanofarad"
-4T,13396,"pF","picofarad"
-N90,5126448,"kF","kilofarad"
-A69,4273721,"F/m","farad per metre"
-H28,4731448,"µF/km","microfarad per kilometre"
-H33,4731699,"F/km","farad per kilometre"
-B89,4339769,"µF/m","microfarad per metre"
-C42,4404274,"nF/m","nanofarad per metre"
-C72,4405042,"pF/m","picofarad per metre"
-A26,4272694,"C·m","coulomb metre"
-A41,4273201,"A/m²","ampere per square metre"
-H31,4731697,"A/kg","ampere per kilogram"
-B66,4339254,"MA/m²","megaampere per square metre"
-A7,16695,"A/mm²","ampere per square millimetre"
-A4,16692,"A/cm²","ampere per square centimetre"
-B23,4338227,"kA/m²","kiloampere per square metre"
-G59,4666681,"mA/(l·min)","milliampere per litre minute"
-N93,5126451,"A/Pa","ampere per pascal"
-F57,4601143,"mA/(lbf/in²)","milliampere per pound-force per square inch"
-F59,4601145,"mA/bar","milliampere per bar"
-AE,16709,"A/m","ampere per metre"
-B24,4338228,"kA/m","kiloampere per metre"
-A3,16691,"A/mm","ampere per millimetre"
-A2,16690,"A/cm","ampere per centimetre"
-F76,4601654,"mA/mm","milliampere per millimetre"
-F08,4599864,"mA/in","milliampere per inch"
-P10,5255472,"C/m","coulomb per metre"
-D33,4469555,"T","tesla"
-C29,4403769,"mT","millitesla"
-D81,4470833,"µT","microtesla"
-C48,4404280,"nT","nanotesla"
-P13,5255475,"kT","kilotesla"
-P12,5255474,"γ","gamma"
-WEB,5719362,"Wb","weber"
-C33,4404019,"mWb","milliweber"
-P11,5255473,"kWb","kiloweber"
-D59,4470073,"Wb/m","weber per metre"
-B56,4338998,"kWb/m","kiloweber per metre"
-D60,4470320,"Wb/mm","weber per millimetre"
-81,14385,"H","henry"
-C14,4403508,"mH","millihenry"
-B90,4340016,"µH","microhenry"
-C43,4404275,"nH","nanohenry"
-C73,4405043,"pH","picohenry"
-H03,4730931,"H/kΩ","henry per kiloohm"
-H04,4730932,"H/Ω","henry per ohm"
-G98,4667704,"µH/kΩ","microhenry per kiloohm"
-G99,4667705,"µH/Ω","microhenry per ohm"
-H05,4730933,"mH/kΩ","millihenry per kiloohm"
-H06,4730934,"mH/Ω","millihenry per ohm"
-P24,5255732,"kH","kilohenry"
-A98,4274488,"H/m","henry per metre"
-B91,4340017,"µH/m","microhenry per metre"
-C44,4404276,"nH/m","nanohenry per metre"
-A5,16693,"A·m²","ampere square metre"
-B8,16952,"J/m³","joule per cubic metre"
-OHM,5195853,"Ω","ohm"
-A87,4274231,"GΩ","gigaohm"
-B75,4339509,"MΩ","megaohm"
-H44,4731956,"TΩ","teraohm"
-B49,4338745,"kΩ","kiloohm"
-E45,4535349,"mΩ","milliohm"
-B94,4340020,"µΩ","microohm"
-P22,5255730,"nΩ","nanoohm"
-M26,5059126,"GΩ/m","gigaohm per metre"
-SIE,5458245,"S","siemens"
-B53,4338995,"kS","kilosiemens"
-C27,4403767,"mS","millisiemens"
-B99,4340025,"µS","microsiemens"
-G42,4666418,"µS/cm","microsiemens per centimetre"
-G43,4666419,"µS/m","microsiemens per metre"
-N92,5126450,"pS","picosiemens"
-NQ,20049,"mho","mho"
-NR,20050,"micromho","micromho"
-C61,4404785,"Ω·m","ohm metre"
-A88,4274232,"GΩ·m","gigaohm metre"
-B76,4339510,"MΩ·m","megaohm metre"
-H88,4732984,"MΩ·km","megaohm kilometre"
-B50,4338992,"kΩ·m","kiloohm metre"
-C60,4404784,"Ω·cm","ohm centimetre"
-C23,4403763,"mΩ·m","milliohm metre"
-B95,4340021,"µΩ·m","microohm metre"
-C46,4404278,"nΩ·m","nanoohm metre"
-M24,5059124,"Ω·km","ohm kilometre"
-P23,5255731,"Ω·cmil/ft","ohm circular-mil per foot"
-F56,4601142,"Ω/km","ohm per kilometre"
-H26,4731446,"Ω/m","ohm per metre"
-H37,4731703,"MΩ/m","megaohm per metre"
-F54,4601140,"mΩ/m","milliohm per metre"
-H36,4731702,"MΩ/km","megaohm per kilometre"
-F55,4601141,"Ω/mi","ohm per mile (statute mile)"
-D10,4469040,"S/m","siemens per metre"
-H43,4731955,"S/cm","siemens per centimetre"
-H61,4732465,"mS/cm","millisiemens per centimetre"
-B77,4339511,"MS/m","megasiemens per metre"
-B54,4338996,"kS/m","kilosiemens per metre"
-G45,4666421,"nS/m","nanosiemens per metre"
-G44,4666420,"nS/cm","nanosiemens per centimetre"
-L42,4994098,"pS/m","picosiemens per metre"
-C89,4405305,"H⁻¹","reciprocal henry"
-P14,5255476,"J/s","joule per second"
-D31,4469553,"TW","terawatt"
-P15,5255477,"J/min","joule per minute"
-P16,5255478,"J/h","joule per hour"
-P17,5255479,"J/d","joule per day"
-P18,5255480,"kJ/s","kilojoule per second"
-P19,5255481,"kJ/min","kilojoule per minute"
-P20,5255728,"kJ/h","kilojoule per hour"
-P21,5255729,"kJ/d","kilojoule per day"
-K43,4928563,"electric hp","horsepower (electric)"
-C49,4404281,"nW","nanowatt"
-C75,4405045,"pW","picowatt"
-D46,4469814,"V·A","volt - ampere"
-MVA,5068353,"MV·A","megavolt - ampere"
-KVA,4937281,"kV·A","kilovolt - ampere"
-M35,5059381,"mV·A","millivolt - ampere"
-D44,4469812,"var","var"
-K5,19253,"kvar","kilovolt ampere (reactive)"
-KVR,4937298,"kvar","kilovar"
-MAR,5062994,"kvar","megavar"
-N91,5126449,"1/J","reciprocal joule"
-M30,5059376,"1/(V·A·s)","reciprocal volt - ampere reciprocal second"
-M17,5058871,"kHz·m","kilohertz metre"
-M18,5058872,"GHz·m","gigahertz metre"
-M27,5059127,"MHz·m","megahertz metre"
-M21,5059121,"1/kVAh","reciprocal kilovolt - ampere reciprocal hour"
-H34,4731700,"Hz·m","hertz metre"
-H39,4731705,"MHz·km","megahertz kilometre"
-C84,4405300,"rad/m","radian per metre"
-JM,19021,"MJ/m³","megajoule per cubic metre"
-B14,4337972,"J/m⁴","joule per metre to the fourth power"
-B13,4337971,"J/m²","joule per square metre"
-D1,17457,"s⁻¹/sr","reciprocal second per steradian"
-D2,17458,"s⁻¹/(sr·m²)","reciprocal second per steradian metre squared"
-C99,4405561,"s⁻¹/m²","reciprocal second per metre squared"
-C93,4405555,"m⁻²","reciprocal square metre"
-H47,4731959,"W/m³","watt per cubic metre"
-H74,4732724,"W/m","watt per metre"
-E43,4535347,"J/cm²","joule per square centimetre"
-P37,5255991,"BtuIT/ft²","British thermal unit (international table) per square foot"
-P38,5255992,"Btuth/ft²","British thermal unit (thermochemical) per square foot"
-P39,5255993,"calth/cm²","calorie (thermochemical) per square centimetre"
-P40,5256240,"Ly","langley"
-D57,4470071,"W/sr","watt per steradian"
-D58,4470072,"W/(sr·m²)","watt per steradian square metre"
-D56,4470070,"W/(m²·K⁴)","watt per square metre kelvin to the fourth power"
-D18,4469048,"m·K","metre kelvin"
-CDL,4408396,"cd","candela"
-P33,5255987,"kcd","kilocandela"
-P34,5255988,"mcd","millicandela"
-P35,5255989,"HK","Hefner-Kerze"
-P36,5255990,"IK","international candle"
-LUM,5002573,"lm","lumen"
-B62,4339250,"lm·s","lumen second"
-B59,4339001,"lm·h","lumen hour"
-A24,4272692,"cd/m²","candela per square metre"
-P28,5255736,"cd/in²","candela per square inch"
-P29,5255737,"ftL","footlambert"
-P30,5255984,"Lb","lambert"
-P31,5255985,"sb","stilb"
-P32,5255986,"cd/ft²","candela per square foot"
-B60,4339248,"lm/m²","lumen per square metre"
-LUX,5002584,"lx","lux"
-KLX,4934744,"klx","kilolux"
-P25,5255733,"lm/ft²","lumen per square foot"
-P26,5255734,"ph","phot"
-P27,5255735,"ftc","footcandle"
-B64,4339252,"lx·s","lux second"
-B63,4339251,"lx·h","lux hour"
-B61,4339249,"lm/W","lumen per watt"
-D22,4469298,"m²/mol","square metre per mole"
-C59,4404537,"octave","octave"
-D9,17465,"dyn/cm²","dyne per square centimetre"
-A60,4273712,"erg/cm³","erg per cubic centimetre"
-C32,4404018,"mW/m²","milliwatt per square metre"
-D85,4470837,"µW/m²","microwatt per square metre"
-C76,4405046,"pW/m²","picowatt per square metre"
-A64,4273716,"erg/(s·cm²)","erg per second square centimetre"
-C67,4404791,"Pa· s/m","pascal second per metre"
-A50,4273456,"dyn·s/cm³","dyne second per cubic centimetre"
-C66,4404790,"Pa·s/m³","pascal second per cubic metre"
-A52,4273458,"dyn·s/cm⁵","dyne second per centimetre to the fifth power"
-M32,5059378,"Pa·s/l","pascal second per litre"
-C58,4404536,"N·s/m","newton second per metre"
-A51,4273457,"dyn·s/cm","dyne second per centimetre"
-P43,5256243,"B/m","bel per metre"
-H51,4732209,"dB/km","decibel per kilometre"
-H52,4732210,"dB/m","decibel per metre"
-C69,4404793,"phon","phon"
-D15,4469045,"sone","sone"
-P42,5256242,"Pa²·s","pascal squared second"
-P41,5256241,"dec","decade (logarithmic)"
-C34,4404020,"mol","mole"
-B45,4338741,"kmol","kilomole"
-C18,4403512,"mmol","millimole"
-FH,17992,"µmol","micromole"
-Z9,23097,"nmol","nanomole"
-P44,5256244,"lbmol","pound mole"
-C95,4405557,"mol⁻¹","reciprocal mole"
-D74,4470580,"kg/mol","kilogram per mole"
-A94,4274484,"g/mol","gram per mole"
-A40,4273200,"m³/mol","cubic metre per mole"
-A37,4272951,"dm³/mol","cubic decimetre per mole"
-A36,4272950,"cm³/mol","cubic centimetre per mole"
-B58,4339000,"l/mol","litre per mole"
-B15,4337973,"J/mol","joule per mole"
-B44,4338740,"kJ/mol","kilojoule per mole"
-B16,4337974,"J/(mol·K)","joule per mole kelvin"
-C86,4405302,"m⁻³","reciprocal cubic metre"
-H50,4732208,"cm⁻³","reciprocal cubic centimetre"
-L20,4993584,"1/mm³","reciprocal cubic millimetre"
-K20,4928048,"1/ft³","reciprocal cubic foot"
-K49,4928569,"1/in³","reciprocal cubic inch"
-K63,4929075,"1/l","reciprocal litre"
-M10,5058864,"1/yd³","reciprocal cubic yard"
-C36,4404022,"mol/m³","mole per cubic metre"
-C38,4404024,"mol/l","mole per litre"
-C35,4404021,"mol/dm³","mole per cubic decimetre"
-B46,4338742,"kmol/m³","kilomole per cubic metre"
-E95,4536629,"mol/s","mole per second"
-M33,5059379,"mmol/l","millimole per litre"
-P51,5256497,"(mol/kg)/Pa","mol per kilogram pascal"
-P52,5256498,"(mol/m³)/Pa","mol per cubic metre pascal"
-K59,4928825,"(kmol/m³)/K","kilomole per cubic metre kelvin"
-K60,4929072,"(kmol/m³)/bar","kilomole per cubic metre bar"
-K93,4929843,"1/psi","reciprocal psi"
-L24,4993588,"(mol/kg)/K","mole per kilogram kelvin"
-L25,4993589,"(mol/kg)/bar","mole per kilogram bar"
-L26,4993590,"(mol/l)/K","mole per litre kelvin"
-L27,4993591,"(mol/l)/bar","mole per litre bar"
-L28,4993592,"(mol/m³)/K","mole per cubic metre kelvin"
-L29,4993593,"(mol/m³)/bar","mole per cubic metre bar"
-C19,4403513,"mol/kg","mole per kilogram"
-D93,4471091,"s/m³","second per cubic metre"
-D87,4470839,"mmol/kg","millimole per kilogram"
-H68,4732472,"mmol/g","millimole per gram"
-P47,5256247,"kmol/kg","kilomole per kilogram"
-P48,5256248,"lbmol/lb","pound mole per pound"
-KAT,4931924,"kat","katal"
-E94,4536628,"kmol/s","kilomole per second"
-P45,5256245,"lbmol/s","pound mole per second"
-P46,5256246,"lbmol/h","pound mole per minute"
-D43,4469811,"u","unified atomic mass unit"
-A27,4272695,"C·m²/V","coulomb metre squared per volt"
-A32,4272946,"C/mol","coulomb per mole"
-D12,4469042,"S·m²/mol","siemens square metre per mole"
-K58,4928824,"kmol/h","kilomole per hour"
-K61,4929073,"kmol/min","kilomole per minute"
-L23,4993587,"mol/h","mole per hour"
-L30,4993840,"mol/min","mole per minute"
-C82,4405298,"rad·m²/mol","radian square metre per mole"
-C83,4405299,"rad·m²/kg","radian square metre per kilogram"
-P49,5256249,"N·m²/A","newton square metre per ampere"
-P50,5256496,"Wb·m","weber metre"
-Q30,5321520,"pH","pH (potential of Hydrogen)"
-B18,4337976,"J·s","joule second"
-A10,4272432,"A·m²/(J·s)","ampere square metre per joule second"
-CUR,4412754,"Ci","curie"
-MCU,5063509,"mCi","millicurie"
-M5,19765,"µCi","microcurie"
-2R,12882,"kCi","kilocurie"
-BQL,4346188,"Bq","becquerel"
-GBQ,4670033,"GBq","gigabecquerel"
-2Q,12881,"kBq","kilobecquerel"
-4N,13390,"MBq","megabecquerel"
-H08,4730936,"µBq","microbecquerel"
-A42,4273202,"Ci/kg","curie per kilogram"
-A18,4272440,"Bq/kg","becquerel per kilogram"
-B67,4339255,"MBq/kg","megabecquerel per kilogram"
-B25,4338229,"kBq/kg","kilobecquerel per kilogram"
-A19,4272441,"Bq/m³","becquerel per cubic metre"
-A14,4272436,"b","barn"
-D24,4469300,"m²/sr","square metre per steradian"
-A17,4272439,"b/sr","barn per steradian"
-D20,4469296,"m²/J","square metre per joule"
-A15,4272437,"b/eV","barn per electronvolt"
-D16,4469046,"cm²/erg","square centimetre per erg"
-D25,4469301,"m²/(sr·J)","square metre per steradian joule"
-A16,4272438,"b/(sr·eV)","barn per steradian electronvolt"
-D17,4469047,"cm²/(sr·erg)","square centimetre per steradian erg"
-B81,4339761,"m⁻²/s","reciprocal metre squared reciprocal second"
-A65,4273717,"erg/(cm²·s)","erg per square centimetre second"
-D21,4469297,"m²/kg","square metre per kilogram"
-B12,4337970,"J/m","joule per metre"
-A54,4273460,"eV/m","electronvolt per metre"
-A58,4273464,"erg/cm","erg per centimetre"
-D73,4470579,"J·m²","joule square metre"
-A55,4273461,"eV·m²","electronvolt square metre"
-A66,4273718,"erg·cm²","erg square centimetre"
-B20,4338224,"J·m²/kg","joule square metre per kilogram"
-A56,4273462,"eV·m²/kg","electronvolt square metre per kilogram"
-A67,4273719,"erg·cm²/g","erg square centimetre per gram"
-D26,4469302,"m²/(V·s)","square metre per volt second"
-H58,4732216,"m/(V·s)","metre per volt second"
-C87,4405303,"m⁻³/s","reciprocal cubic metre per second"
-A95,4274485,"Gy","gray"
-C13,4403507,"mGy","milligray"
-C80,4405296,"rad","rad"
-A61,4273713,"erg/g","erg per gram"
-D13,4469043,"Sv","sievert"
-C28,4403768,"mSv","millisievert"
-D91,4471089,"rem","rem"
-L31,4993841,"mrem","milliroentgen aequivalent men"
-A96,4274486,"Gy/s","gray per second"
-A62,4273714,"erg/g·s","erg per gram second"
-CKG,4410183,"C/kg","coulomb per kilogram"
-C8,17208,"mC/kg","millicoulomb per kilogram"
-2C,12867,"R","roentgen"
-2Y,12889,"mR","milliroentgen"
-J53,4863283,"C·m²/kg","coulomb square metre per kilogram"
-KR,19282,"kR","kiloroentgen"
-A31,4272945,"C/(kg·s)","coulomb per kilogram second"
-D6,17462,"R/s","roentgen per second"
-P54,5256500,"mGy/s","milligray per second"
-P55,5256501,"µGy/s","microgray per second"
-P56,5256502,"nGy/s","nanogray per second"
-P57,5256503,"Gy/min","gray per minute"
-P58,5256504,"mGy/min","milligray per minute"
-P59,5256505,"µGy/min","microgray per minute"
-P60,5256752,"nGy/min","nanogray per minute"
-P61,5256753,"Gy/h","gray per hour"
-P62,5256754,"mGy/h","milligray per hour"
-P63,5256755,"µGy/h","microgray per hour"
-P64,5256756,"nGy/h","nanogray per hour"
-P65,5256757,"Sv/s","sievert per second"
-P66,5256758,"mSv/s","millisievert per second"
-P67,5256759,"µSv/s","microsievert per second"
-P68,5256760,"nSv/s","nanosievert per second"
-P69,5256761,"rem/s","rem per second"
-P70,5257008,"Sv/h","sievert per hour"
-P71,5257009,"mSv/h","millisievert per hour"
-P72,5257010,"µSv/h","microsievert per hour"
-P73,5257011,"nSv/h","nanosievert per hour"
-P74,5257012,"Sv/min","sievert per minute"
-P75,5257013,"mSv/min","millisievert per minute"
-P76,5257014,"µSv/min","microsievert per minute"
-P77,5257015,"nSv/min","nanosievert per minute"
-P78,5257016,"1/in²","reciprocal square inch"
-P53,5256499,"unit pole","unit pole"
-C85,4405301,"Å⁻¹","reciprocal angstrom"
-D94,4471092,"s/(rad·m³)","second per cubic metre radian"
-C90,4405552,"J⁻¹/m³","reciprocal joule per cubic metre"
-C88,4405304,"eV⁻¹/m³","reciprocal electron volt per cubic metre"
-A38,4272952,"m³/C","cubic metre per coulomb"
-D48,4469816,"V/K","volt per kelvin"
-D49,4469817,"mV/K","millivolt per kelvin"
-A6,16694,"A/(m²·K²)","ampere per square metre kelvin squared"
-33,13107,"kPa·m²/g","kilopascal square metre per gram"
-P79,5257017,"Pa/(kg/m²)","pascal square metre per kilogram"
-34,13108,"kPa/mm","kilopascal per millimetre"
-H42,4731954,"Pa/m","pascal per metre"
-H69,4732473,"pPa/km","picopascal per kilometre"
-P80,5257264,"mPa/m","millipascal per metre"
-P81,5257265,"kPa/m","kilopascal per metre"
-P82,5257266,"hPa/m","hectopascal per metre"
-P83,5257267,"Atm/m","standard atmosphere per metre"
-P84,5257268,"at/m","technical atmosphere per metre"
-P85,5257269,"Torr/m","torr per metre"
-P86,5257270,"psi/in","psi per inch"
-35,13109,"ml/(cm²·s)","millilitre per square centimetre second"
-P87,5257271,"(m³/s)/m²","cubic metre per second square metre"
-OPM,5197901,"o/min","oscillations per minute"
-KNM,4935245,"KN/m2","kilonewton per square metre"
-Q35,5321525,"MW/min","megawatts per minute"
-10,12592,"group","group"
-11,12593,"outfit","outfit"
-13,12595,"ration","ration"
-14,12596,"shot","shot"
-15,12597,"stick, military","stick, military"
-20,12848,"twenty foot container","twenty foot container"
-21,12849,"forty foot container","forty foot container"
-24,12852,"theoretical pound","theoretical pound"
-27,12855,"theoretical ton","theoretical ton"
-38,13112,"oz/(ft²/cin)","ounce per square foot per 0,01inch"
-56,13622,"sitas","sitas"
-57,13623,"mesh","mesh"
-58,13624,"net kilogram","net kilogram"
-59,13625,"ppm","part per million"
-60,13872,"percent weight","percent weight"
-61,13873,"ppb","part per billion (US)"
-64,13876,"pound per square inch, gauge","pound per square inch, gauge"
-66,13878,"Oe","oersted"
-76,14134,"Gs","gauss"
-78,14136,"kGs","kilogauss"
-1I,12617,"fixed rate","fixed rate"
-2G,12871,"V","volt AC"
-2H,12872,"V","volt DC"
-2P,12880,"kbyte","kilobyte"
-3C,13123,"manmonth","manmonth"
-4L,13388,"Mbyte","megabyte"
-5B,13634,"batch","batch"
-5E,13637,"MMSCF/day","MMSCF/day"
-5J,13642,"hydraulic horse power","hydraulic horse power"
-A43,4273203,"dwt","deadweight tonnage"
-A47,4273207,"dtex (g/10km)","decitex"
-A49,4273209,"den (g/9 km)","denier"
-A59,4273465,"8-part cloud cover","8-part cloud cover"
-A75,4273973,"freight ton","freight ton"
-A77,4273975,"Gaussian CGS (Centimetre-Gram-Second system) unit of displacement","Gaussian CGS (Centimetre-Gram-Second system) unit of displacement"
-A78,4273976,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric current","Gaussian CGS (Centimetre-Gram-Second system) unit of electric current"
-A79,4273977,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric charge","Gaussian CGS (Centimetre-Gram-Second system) unit of electric charge"
-A80,4274224,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric field strength","Gaussian CGS (Centimetre-Gram-Second system) unit of electric field strength"
-A81,4274225,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric polarization","Gaussian CGS (Centimetre-Gram-Second system) unit of electric polarization"
-A82,4274226,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric potential","Gaussian CGS (Centimetre-Gram-Second system) unit of electric potential"
-A83,4274227,"Gaussian CGS (Centimetre-Gram-Second system) unit of magnetization","Gaussian CGS (Centimetre-Gram-Second system) unit of magnetization"
-A9,16697,"rate","rate"
-A99,4274489,"bit","bit"
-AA,16705,"ball","ball"
-AB,16706,"pk","bulk pack"
-ACT,4277076,"activity","activity"
-AD,16708,"byte","byte"
-AH,16712,"additional minute","additional minute"
-AI,16713,"average minute per call","average minute per call"
-AL,16716,"access line","access line"
-AQ,16721,"anti-hemophilic factor (AHF) unit","anti-hemophilic factor (AHF) unit"
-AS,16723,"assortment","assortment"
-ASM,4281165,"alcoholic strength by mass","alcoholic strength by mass"
-ASU,4281173,"alcoholic strength by volume","alcoholic strength by volume"
-AY,16729,"assembly","assembly"
-B1,16945,"barrel (US)/d","barrel (US) per day"
-B10,4337968,"bit/s","bit per second"
-B17,4337975,"credit","credit"
-B19,4337977,"digit","digit"
-B3,16947,"batting pound","batting pound"
-B30,4338480,"Gibit","gibibit"
-B4,16948,"barrel, imperial","barrel, imperial"
-B65,4339253,"Mx","maxwell"
-B68,4339256,"Gbit","gigabit"
-B7,16951,"cycle","cycle"
-B80,4339760,"Gbit/s","gigabit per second"
-B82,4339762,"inch per linear foot","inch per linear foot"
-BB,16962,"base box","base box"
-BFT,4343380,"fbm","board foot"
-BIL,4344140,"billion (EUR)","billion (EUR)"
-BP,16976,"hundred board foot","hundred board foot"
-BPM,4345933,"BPM","beats per minute"
-C0,17200,"call","call"
-C21,4403761,"Kibit","kibibit"
-C37,4404023,"kbit","kilobit"
-C74,4405044,"kbit/s","kilobit per second"
-C79,4405049,"kVAh","kilovolt ampere hour"
-C9,17209,"coil group","coil group"
-CCT,4408148,"carrying capacity in metric ton","carrying capacity in metric ton"
-CEN,4408654,"hundred","hundred"
-CG,17223,"card","card"
-CLF,4410438,"hundred leave","hundred leave"
-CNP,4410960,"hundred pack","hundred pack"
-CNT,4410964,"cental (UK)","cental (UK)"
-CTG,4412487,"content gram","content gram"
-CTM,4412493,"metric carat","metric carat"
-CTN,4412494,"content ton (metric)","content ton (metric)"
-D03,4468787,"kW·h/h","kilowatt hour per hour"
-D04,4468788,"lot [unit of weight]","lot [unit of weight]"
-D11,4469041,"Mibit","mebibit"
-D23,4469299,"pen gram (protein)","pen gram (protein)"
-D34,4469556,"tex (g/km)","tex"
-D36,4469558,"Mbit","megabit"
-D63,4470323,"book","book"
-D65,4470325,"round","round"
-D68,4470328,"number of words","number of words"
-D78,4470584,"MJ/s","megajoule per second"
-DAD,4473156,"ten day","ten day"
-DB,17474,"dry pound","dry pound"
-DEC,4474179,"decade","decade"
-DMO,4476239,"standard kilolitre","standard kilolitre"
-DPC,4476995,"dozen piece","dozen piece"
-DPR,4477010,"dozen pair","dozen pair"
-DPT,4477012,"displacement tonnage","displacement tonnage"
-DRA,4477505,"dram (US)","dram (US)"
-DRI,4477513,"dram (UK)","dram (UK)"
-DRL,4477516,"dozen roll","dozen roll"
-DT,17492,"dry ton","dry ton"
-DWT,4478804,"pennyweight","pennyweight"
-DZN,4479566,"DOZ","dozen"
-DZP,4479568,"dozen pack","dozen pack"
-E07,4534327,"MW·h/h","megawatt hour per hour"
-E08,4534328,"MW/Hz","megawatt per hertz"
-E10,4534576,"deg da","degree day"
-E11,4534577,"gigacalorie","gigacalorie"
-E12,4534578,"mille","mille"
-E16,4534582,"BtuIT/h","million Btu(IT) per hour"
-E17,4534583,"ft³/s","cubic foot per second"
-E19,4534585,"ping","ping"
-E20,4534832,"Mbit/s","megabit per second"
-E21,4534833,"shares","shares"
-E22,4534834,"TEU","TEU"
-E23,4534835,"tyre","tyre"
-E25,4534837,"active unit","active unit"
-E27,4534839,"dose","dose"
-E28,4534840,"air dry ton","air dry ton"
-E30,4535088,"strand","strand"
-E31,4535089,"m²/l","square metre per litre"
-E32,4535090,"l/h","litre per hour"
-E33,4535091,"foot per thousand","foot per thousand"
-E34,4535092,"Gbyte","gigabyte"
-E35,4535093,"Tbyte","terabyte"
-E36,4535094,"Pbyte","petabyte"
-E37,4535095,"pixel","pixel"
-E38,4535096,"megapixel","megapixel"
-E39,4535097,"dpi","dots per inch"
-E4,17716,"gross kilogram","gross kilogram"
-E40,4535344,"ppht","part per hundred thousand"
-E44,4535348,"kgf·m/cm²","kilogram-force metre per square centimetre"
-E46,4535350,"kW·h/m³","kilowatt hour per cubic metre"
-E47,4535351,"kW·h/K","kilowatt hour per kelvin"
-E48,4535352,"service unit","service unit"
-E49,4535353,"working day","working day"
-E50,4535600,"accounting unit","accounting unit"
-E51,4535601,"job","job"
-E52,4535602,"run foot","run foot"
-E53,4535603,"test","test"
-E54,4535604,"trip","trip"
-E55,4535605,"use","use"
-E56,4535606,"well","well"
-E57,4535607,"zone","zone"
-E58,4535608,"Ebit/s","exabit per second"
-E59,4535609,"Eibyte","exbibyte"
-E60,4535856,"Pibyte","pebibyte"
-E61,4535857,"Tibyte","tebibyte"
-E62,4535858,"Gibyte","gibibyte"
-E63,4535859,"Mibyte","mebibyte"
-E64,4535860,"Kibyte","kibibyte"
-E65,4535861,"Eibit/m","exbibit per metre"
-E66,4535862,"Eibit/m²","exbibit per square metre"
-E67,4535863,"Eibit/m³","exbibit per cubic metre"
-E68,4535864,"Gbyte/s","gigabyte per second"
-E69,4535865,"Gibit/m","gibibit per metre"
-E70,4536112,"Gibit/m²","gibibit per square metre"
-E71,4536113,"Gibit/m³","gibibit per cubic metre"
-E72,4536114,"Kibit/m","kibibit per metre"
-E73,4536115,"Kibit/m²","kibibit per square metre"
-E74,4536116,"Kibit/m³","kibibit per cubic metre"
-E75,4536117,"Mibit/m","mebibit per metre"
-E76,4536118,"Mibit/m²","mebibit per square metre"
-E77,4536119,"Mibit/m³","mebibit per cubic metre"
-E78,4536120,"Pbit","petabit"
-E79,4536121,"Pbit/s","petabit per second"
-E80,4536368,"Pibit/m","pebibit per metre"
-E81,4536369,"Pibit/m²","pebibit per square metre"
-E82,4536370,"Pibit/m³","pebibit per cubic metre"
-E83,4536371,"Tbit","terabit"
-E84,4536372,"Tbit/s","terabit per second"
-E85,4536373,"Tibit/m","tebibit per metre"
-E86,4536374,"Tibit/m³","tebibit per cubic metre"
-E87,4536375,"Tibit/m²","tebibit per square metre"
-E88,4536376,"bit/m","bit per metre"
-E89,4536377,"bit/m²","bit per square metre"
-E90,4536624,"cm⁻¹","reciprocal centimetre"
-E91,4536625,"d⁻¹","reciprocal day"
-EA,17729,"each","each"
-EB,17730,"electronic mail box","electronic mail box"
-EQ,17745,"equivalent gallon","equivalent gallon"
-F01,4599857,"bit/m³","bit per cubic metre"
-FBM,4604493,"fibre metre","fibre metre"
-FC,17987,"kft³","thousand cubic foot"
-FF,17990,"hundred cubic metre","hundred cubic metre"
-FIT,4606292,"FIT","failures in time"
-FL,17996,"flake ton","flake ton"
-GB,18242,"gal (US)/d","gallon (US) per day"
-GDW,4670551,"gram, dry weight","gram, dry weight"
-GFI,4671049,"gi F/S","gram of fissile isotope"
-GGR,4671314,"great gross","great gross"
-GIA,4671809,"gi (US)","gill (US)"
-GIC,4671811,"gram, including container","gram, including container"
-GII,4671817,"gi (UK)","gill (UK)"
-GIP,4671824,"gram, including inner packaging","gram, including inner packaging"
-GRO,4674127,"gr","gross"
-GRT,4674132,"gross register ton","gross register ton"
-GT,18260,"gross ton","gross ton"
-H21,4731441,"blank","blank"
-H25,4731445,"%/K","percent per kelvin"
-H71,4732721,"%/mo","percent per month"
-H72,4732722,"%/hbar","percent per hectobar"
-H73,4732723,"%/daK","percent per decakelvin"
-H77,4732727,"MW","module width"
-H80,4732976,"U or RU","rack unit"
-H82,4732978,"bp","big point"
-H87,4732983,"piece","piece"
-H89,4732985,"%/Ω","percent per ohm"
-H90,4733232,"%/°","percent per degree"
-H91,4733233,"%/10000","percent per ten thousand"
-H92,4733234,"%/100000","percent per one hundred thousand"
-H93,4733235,"%/100","percent per hundred"
-H94,4733236,"%/1000","percent per thousand"
-H95,4733237,"%/V","percent per volt"
-H96,4733238,"%/bar","percent per bar"
-H98,4733240,"%/in","percent per inch"
-H99,4733241,"%/m","percent per metre"
-HA,18497,"hank","hank"
-HBX,4735576,"hundred boxes","hundred boxes"
-HC,18499,"hundred count","hundred count"
-HDW,4736087,"hundred kilogram, dry weight","hundred kilogram, dry weight"
-HEA,4736321,"head","head"
-HH,18504,"hundred cubic foot","hundred cubic foot"
-HIU,4737365,"hundred international unit","hundred international unit"
-HKM,4737869,"hundred kilogram, net mass","hundred kilogram, net mass"
-HMQ,4738385,"Mm³","million cubic metre"
-HPA,4739137,"hectolitre of pure alcohol","hectolitre of pure alcohol"
-IE,18757,"person","person"
-ISD,4805444,"international sugar degree","international sugar degree"
-IUG,4805959,"international unit per gram","international unit per gram"
-J10,4862256,"%/mm","percent per millimetre"
-J12,4862258,"‰/psi","per mille per psi"
-J13,4862259,"°API","degree API"
-J14,4862260,"°Bé","degree Baume (origin scale)"
-J15,4862261,"°Bé (US heavy)","degree Baume (US heavy)"
-J16,4862262,"°Bé (US light)","degree Baume (US light)"
-J17,4862263,"°Balling","degree Balling"
-J18,4862264,"°Bx","degree Brix"
-J27,4862519,"°Oechsle","degree Oechsle"
-J31,4862769,"°Tw","degree Twaddell"
-J38,4862776,"Bd","baud"
-J54,4863284,"MBd","megabaud"
-JNT,4869716,"pipeline joint","pipeline joint"
-JPS,4870227,"hundred metre","hundred metre"
-JWL,4872012,"number of jewels","number of jewels"
-K1,19249,"kilowatt demand","kilowatt demand"
-K2,19250,"kilovolt ampere reactive demand","kilovolt ampere reactive demand"
-K3,19251,"kvar·h","kilovolt ampere reactive hour"
-K50,4928816,"kBd","kilobaud"
-KA,19265,"cake","cake"
-KB,19266,"kilocharacter","kilocharacter"
-KCC,4932419,"kg C₅ H₁₄ClNO","kilogram of choline chloride"
-KDW,4932695,"kg/net eda","kilogram drained net weight"
-KHY,4933721,"kg H₂O₂","kilogram of hydrogen peroxide"
-KI,19273,"kilogram per millimetre width","kilogram per millimetre width"
-KIC,4933955,"kilogram, including container","kilogram, including container"
-KIP,4933968,"kilogram, including inner packaging","kilogram, including inner packaging"
-KJ,19274,"kilosegment","kilosegment"
-KLK,4934731,"lactic dry material percentage","lactic dry material percentage"
-KMA,4934977,"kg met.am.","kilogram of methylamine"
-KNI,4935241,"kg N","kilogram of nitrogen"
-KNS,4935251,"kilogram named substance","kilogram named substance"
-KO,19279,"milliequivalence caustic potash per gram of product","milliequivalence caustic potash per gram of product"
-KPH,4935752,"kg KOH","kilogram of potassium hydroxide (caustic potash)"
-KPO,4935759,"kg K₂O","kilogram of potassium oxide"
-KPP,4935760,"kilogram of phosphorus pentoxide (phosphoric anhydride)","kilogram of phosphorus pentoxide (phosphoric anhydride)"
-KSD,4936516,"kg 90 % sdt","kilogram of substance 90 % dry"
-KSH,4936520,"kg NaOH","kilogram of sodium hydroxide (caustic soda)"
-KT,19284,"kit","kit"
-KUR,4937042,"kg U","kilogram of uranium"
-KWY,4937561,"kW/year","kilowatt year"
-KWO,4937551,"kg WO₃","kilogram of tungsten trioxide"
-LAC,4997443,"lactose excess percentage","lactose excess percentage"
-LBT,4997716,"troy pound (US)","troy pound (US)"
-LEF,4998470,"leaf","leaf"
-LF,19526,"linear foot","linear foot"
-LH,19528,"labour hour","labour hour"
-LK,19531,"link","link"
-LM,19533,"linear metre","linear metre"
-LN,19534,"length","length"
-LO,19535,"lot [unit of procurement]","lot [unit of procurement]"
-LP,19536,"liquid pound","liquid pound"
-LPA,5001281,"litre of pure alcohol","litre of pure alcohol"
-LR,19538,"layer","layer"
-LS,19539,"lump sum","lump sum"
-LUB,5002562,"metric ton, lubricating oil","metric ton, lubricating oil"
-LY,19545,"linear yard","linear yard"
-M19,5058873,"Bft","Beaufort"
-M25,5059125,"%/°C","percent per degree Celsius"
-M36,5059382,"mo (30 days)","30-day month"
-M37,5059383,"y (360 days)","actual/360"
-M4,19764,"monetary value","monetary value"
-M9,19769,"MBTU/kft³","million Btu per 1000 cubic foot"
-MAH,5062984,"Mvar·h","megavolt ampere reactive hour"
-MBE,5063237,"thousand standard brick equivalent","thousand standard brick equivalent"
-MBF,5063238,"thousand board foot","thousand board foot"
-MD,19780,"air dry metric ton","air dry metric ton"
-MIL,5065036,"thousand","thousand"
-MIO,5065039,"million","million"
-MIU,5065045,"million international unit","million international unit"
-MLD,5065796,"milliard","milliard"
-MND,5066308,"kilogram, dry weight","kilogram, dry weight"
-N1,20017,"pen calorie","pen calorie"
-N3,20019,"print point","print point"
-NAR,5128530,"number of articles","number of articles"
-NCL,5129036,"number of cells","number of cells"
-NF,20038,"message","message"
-NIL,5130572,"()","nil"
-NIU,5130581,"number of international units","number of international units"
-NL,20044,"load","load"
-NMP,5131600,"number of packs","number of packs"
-NPR,5132370,"number of pairs","number of pairs"
-NPT,5132372,"number of parts","number of parts"
-NT,20052,"net ton","net ton"
-NTT,5133396,"net register ton","net register ton"
-NX,20056,"‰","part per thousand"
-OA,20289,"panel","panel"
-ODE,5194821,"ozone depletion equivalent","ozone depletion equivalent"
-ODG,5194823,"ODS Grams","ODS Grams"
-ODK,5194827,"ODS Kilograms","ODS Kilograms"
-ODM,5194829,"ODS Milligrams","ODS Milligrams"
-OT,20308,"overtime hour","overtime hour"
-OZ,20314,"ounce av","ounce av"
-P1,20529,"% or pct","percent"
-P5,20533,"five pack","five pack"
-P88,5257272,"rhe","rhe"
-P89,5257273,"lbf·ft/in","pound-force foot per inch"
-P90,5257520,"lbf·in/in","pound-force inch per inch"
-P91,5257521,"perm (0 ºC)","perm (0 ºC)"
-P92,5257522,"perm (23 ºC)","perm (23 ºC)"
-P93,5257523,"byte/s","byte per second"
-P94,5257524,"kbyte/s","kilobyte per second"
-P95,5257525,"Mbyte/s","megabyte per second"
-P96,5257526,"1/V","reciprocal volt"
-P97,5257527,"1/rad","reciprocal radian"
-P98,5257528,"PaΣνB","pascal to the power sum of stoichiometric numbers"
-P99,5257529,"(mol/m³)∑νB","mole per cubiv metre to the power sum of stoichiometric numbers"
-PD,20548,"pad","pad"
-PFL,5260876,"proof litre","proof litre"
-PGL,5261132,"proof gallon","proof gallon"
-PI,20553,"pitch","pitch"
-PLA,5262401,"°P","degree Plato"
-PQ,20561,"ppi","page per inch"
-PR,20562,"pair","pair"
-PTN,5264462,"PTN","portion"
-Q10,5321008,"J/T","joule per tesla"
-Q11,5321009,"E","erlang"
-Q12,5321010,"o","octet"
-Q13,5321011,"o/s","octet per second"
-Q14,5321012,"Sh","shannon"
-Q15,5321013,"Hart","hartley"
-Q16,5321014,"nat","natural unit of information"
-Q17,5321015,"Sh/s","shannon per second"
-Q18,5321016,"Hart/s","hartley per second"
-Q19,5321017,"nat/s","natural unit of information per second"
-Q20,5321264,"s/kg","second per kilogramm"
-Q21,5321265,"W·m²","watt square metre"
-Q22,5321266,"1/(Hz·rad·m³)","second per radian cubic metre"
-Q23,5321267,"1/Wb","weber to the power minus one"
-Q24,5321268,"1/in","reciprocal inch"
-Q25,5321269,"dpt","dioptre"
-Q26,5321270,"1/1","one per one"
-Q27,5321271,"N·m/m²","newton metre per metre"
-Q28,5321272,"kg/(m²·Pa·s)","kilogram per square metre pascal second"
-Q36,5321526,"m2/m3","square metre per cubic metre"
-Q3,20787,"meal","meal"
-QA,20801,"page - facsimile","page - facsimile"
-QAN,5325134,"quarter (of a year)","quarter (of a year)"
-QB,20802,"page - hardcopy","page - hardcopy"
-QR,20818,"qr","quire"
-QTR,5330002,"Qr (UK)","quarter (UK)"
-R1,21041,"pica","pica"
-R9,21049,"thousand cubic metre","thousand cubic metre"
-RH,21064,"running or operating hour","running or operating hour"
-RM,21069,"ream","ream"
-ROM,5394253,"room","room"
-RP,21072,"pound per ream","pound per ream"
-RT,21076,"revenue ton mile","revenue ton mile"
-SAN,5456206,"half year (6 months)","half year (6 months)"
-SCO,5456719,"score","score"
-SCR,5456722,"scruple","scruple"
-SET,5457236,"set","set"
-SG,21319,"segment","segment"
-SHT,5458004,"shipping ton","shipping ton"
-SQ,21329,"square","square"
-SQR,5460306,"square, roofing","square, roofing"
-SR,21330,"strip","strip"
-STC,5461059,"stick","stick"
-STK,5461067,"stick, cigarette","stick, cigarette"
-STL,5461068,"standard litre","standard litre"
-STW,5461079,"straw","straw"
-SW,21335,"skein","skein"
-SX,21336,"shipment","shipment"
-SYR,5462354,"syringe","syringe"
-T0,21552,"telecommunication line in service","telecommunication line in service"
-T3,21555,"thousand piece","thousand piece"
-TAN,5521742,"TAN","total acid number"
-TI,21577,"thousand square inch","thousand square inch"
-TIC,5523779,"metric ton, including container","metric ton, including container"
-TIP,5523792,"metric ton, including inner packaging","metric ton, including inner packaging"
-TKM,5524301,"t·km","tonne kilometre"
-TMS,5524819,"kilogram of imported meat, less offal","kilogram of imported meat, less offal"
-TP,21584,"ten pack","ten pack"
-TPI,5525577,"TPI","teeth per inch"
-TPR,5525586,"ten pair","ten pair"
-TQD,5525828,"km³/d","thousand cubic metre per day"
-TRL,5526092,"trillion (EUR)","trillion (EUR)"
-TST,5526356,"ten set","ten set"
-TTS,5526611,"ten thousand sticks","ten thousand sticks"
-U1,21809,"treatment","treatment"
-U2,21810,"tablet","tablet"
-UB,21826,"telecommunication line in service average","telecommunication line in service average"
-UC,21827,"telecommunication port","telecommunication port"
-VA,22081,"V·A / kg","volt - ampere per kilogram"
-VP,22096,"percent volume","percent volume"
-W2,22322,"wet kilo","wet kilo"
-WA,22337,"W/kg","watt per kilogram"
-WB,22338,"wet pound","wet pound"
-WCD,5718852,"cord","cord"
-WE,22341,"wet ton","wet ton"
-WG,22343,"wine gallon","wine gallon"
-WM,22349,"working month","working month"
-WSD,5722948,"std","standard"
-WW,22359,"millilitre of water","millilitre of water"
-Z11,5910833,"hanging container","hanging container"
-ZP,23120,"page","page"
-ZZ,23130,"mutually defined","mutually defined"
-MRW,5067351,"m·wk","Metre Week"
-MKW,5065559,"m²· wk","Square Metre Week"
-MQW,5067095,"m³·wk","Cubic Metre Week"
-HWE,4740933,"piece·k","Piece Week"
-MRD,5067332,"m·day","Metre Day"
-MKD,5065540,"m²·d","Square Metre Day"
-MQD,5067076,"m³·d","Cubic Metre Day"
-HAD,4735300,"piece·d","Piece Day"
-MRM,5067341,"m·mo","Metre Month"
-MKM,5065549,"m²·mo","Square Metre Month"
-MQM,5067085,"m³·mo","Cubic Metre Month"
-HMO,4738383,"piece·mo","Piece Month"
-DBW,4473431,"dBW","Decibel watt"
-DBM,4473421,"dBm","Decibel-milliwatts"
-FNU,4607573,"FNU","Formazin nephelometric unit"
-NTU,5133397,"NTU","Nephelometric turbidity unit"
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeSets/UNECE_to_OPCUA.csv b/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeSets/UNECE_to_OPCUA.csv
deleted file mode 100644
index f1923775..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodeSets/UNECE_to_OPCUA.csv
+++ /dev/null
@@ -1,1828 +0,0 @@
-UNECECode,UnitId,DisplayName,Description
-C81,4405297,"rad","radian"
-C25,4403765,"mrad","milliradian"
-B97,4340023,"µrad","microradian"
-DD,17476,"°","degree [unit of angle]"
-D61,4470321,"'","minute [unit of angle]"
-D62,4470322,"""","second [unit of angle]"
-A91,4274481,"gon","gon"
-M43,5059635,"mil","mil"
-M44,5059636,"rev","revolution"
-D27,4469303,"sr","steradian"
-H57,4732215,"in/revolution","inch per two pi radiant"
-MTR,5067858,"m","metre"
-E96,4536630,"°/s","degree per second"
-H27,4731447,"°/m","degree per metre"
-M55,5059893,"m/rad","metre per radiant"
-DMT,4476244,"dm","decimetre"
-CMT,4410708,"cm","centimetre"
-4H,13384,"µm","micrometre (micron)"
-MMT,5066068,"mm","millimetre"
-HMT,4738388,"hm","hectometre"
-KMT,4934996,"km","kilometre"
-C45,4404277,"nm","nanometre"
-C52,4404530,"pm","picometre"
-A71,4273969,"fm","femtometre"
-A45,4273205,"dam","decametre"
-NMI,5131593,"n mile","nautical mile"
-A11,4272433,"Å","angstrom"
-A12,4272434,"ua","astronomical unit"
-C63,4404787,"pc","parsec"
-F52,4601138,"m/K","metre per kelvin"
-F50,4601136,"µm/K","micrometre per kelvin"
-F51,4601137,"cm/K","centimetre per kelvin"
-G06,4665398,"mm/bar","millimetre per bar"
-H84,4732980,"g·mm","gram millimetre"
-G04,4665396,"cm/bar","centimetre per bar"
-G05,4665397,"m/bar","metre per bar"
-H79,4732729,"Fg","French gauge"
-AK,16715,"fth","fathom"
-X1,22577,"ch (UK)","Gunter's chain"
-INH,4804168,"in","inch"
-M7,19767,"µin","micro-inch"
-FOT,4607828,"ft","foot"
-YRD,5853764,"yd","yard"
-SMI,5459273,"mile","mile (statute mile)"
-77,14135,"mil","milli-inch"
-B57,4338999,"ly","light year"
-F49,4600889,"rd (US)","rod [unit of distance]"
-MAM,5062989,"Mm","megametre"
-K13,4927795,"ft/°F","foot per degree Fahrenheit"
-K17,4927799,"ft/psi","foot per psi"
-K45,4928565,"in/°F","inch per degree Fahrenheit"
-K46,4928566,"in/psi","inch per psi"
-L98,4995384,"yd/°F","yard per degree Fahrenheit"
-L99,4995385,"yd/psi","yard per psi"
-M49,5059641,"ch (US survey)","chain (based on U.S. survey foot)"
-M50,5059888,"fur","furlong"
-M51,5059889,"ft (US survey)","foot (U.S. survey)"
-M52,5059890,"mi (US survey)","mile (based on U.S. survey foot)"
-M53,5059891,"m/Pa","metre per pascal"
-MTK,5067851,"m²","square metre"
-KMK,4934987,"km²","square kilometre"
-H30,4731696,"µm²","square micrometre (square micron)"
-H59,4732217,"m²/N","square metre per newton"
-DAA,4473153,"daa","decare"
-CMK,4410699,"cm²","square centimetre"
-DMK,4476235,"dm²","square decimetre"
-H16,4731190,"dam²","square decametre"
-H18,4731192,"hm²","square hectometre"
-MMK,5066059,"mm²","square millimetre"
-ARE,4280901,"a","are"
-HAR,4735314,"ha","hectare"
-INK,4804171,"in²","square inch"
-FTK,4609099,"ft²","square foot"
-YDK,5850187,"yd²","square yard"
-MIK,5065035,"mi²","square mile (statute mile)"
-M48,5059640,"mi² (US survey)","square mile (based on U.S. survey foot)"
-ACR,4277074,"acre","acre"
-M47,5059639,"cmil","circular mil"
-MTQ,5067857,"m³","cubic metre"
-MAL,5062988,"Ml","megalitre"
-LTR,5002322,"l","litre"
-MMQ,5066065,"mm³","cubic millimetre"
-CMQ,4410705,"cm³","cubic centimetre"
-DMQ,4476241,"dm³","cubic decimetre"
-MLT,5065812,"ml","millilitre"
-HLT,4738132,"hl","hectolitre"
-CLT,4410452,"cl","centilitre"
-DMA,4476225,"dam³","cubic decametre"
-H19,4731193,"hm³","cubic hectometre"
-H20,4731440,"km³","cubic kilometre"
-M71,5060401,"m³/Pa","cubic metre per pascal"
-DLT,4475988,"dl","decilitre"
-4G,13383,"µl","microlitre"
-K6,19254,"kl","kilolitre"
-A44,4273204,"dal","decalitre"
-G94,4667700,"cm³/bar","cubic centimetre per bar"
-G95,4667701,"l/bar","litre per bar"
-G96,4667702,"m³/bar","cubic metre per bar"
-G97,4667703,"ml/bar","millilitre per bar"
-INQ,4804177,"in³","cubic inch"
-FTQ,4609105,"ft³","cubic foot"
-YDQ,5850193,"yd³","cubic yard"
-GLI,4672585,"gal (UK)","gallon (UK)"
-GLL,4672588,"gal (US)","gallon (US)"
-PT,20564,"pt (US)","pint (US)"
-PTI,5264457,"pt (UK)","pint (UK)"
-QTI,5329993,"qt (UK)","quart (UK)"
-PTL,5264460,"liq pt (US)","liquid pint (US)"
-QTL,5329996,"liq qt (US)","liquid quart (US)"
-PTD,5264452,"dry pt (US)","dry pint (US)"
-OZI,5200457,"fl oz (UK)","fluid ounce (UK)"
-QT,20820,"qt (US)","quart (US)"
-J57,4863287,"bbl (UK liq.)","barrel (UK petroleum)"
-K21,4928049,"ft³/°F","cubic foot per degree Fahrenheit"
-K23,4928051,"ft³/psi","cubic foot per psi"
-L43,4994099,"pk (UK)","peck (UK)"
-L84,4995124,"British shipping ton","ton (UK shipping)"
-L86,4995126,"(US) shipping ton","ton (US shipping)"
-M11,5058865,"yd³/°F","cubic yard per degree Fahrenheit"
-M14,5058868,"yd³/psi","cubic yard per psi"
-OZA,5200449,"fl oz (US)","fluid ounce (US)"
-BUI,4347209,"bushel (UK)","bushel (UK)"
-BUA,4347201,"bu (US)","bushel (US)"
-BLL,4344908,"barrel (US)","barrel (US)"
-BLD,4344900,"bbl (US)","dry barrel (US)"
-GLD,4672580,"dry gal (US)","dry gallon (US)"
-QTD,5329988,"dry qt (US)","dry quart (US)"
-G26,4665910,"st","stere"
-G21,4665905,"cup (US)","cup [unit of volume]"
-G24,4665908,"tablespoon (US)","tablespoon (US)"
-G25,4665909,"teaspoon (US)","teaspoon (US)"
-G23,4665907,"pk (US)","peck"
-M67,5060151,"acre-ft (US survey)","acre-foot (based on U.S. survey foot)"
-M68,5060152,"cord","cord (128 ft3)"
-M69,5060153,"mi³","cubic mile (UK statute)"
-M70,5060400,"RT","ton, register"
-G27,4665911,"cm³/K","cubic centimetre per kelvin"
-G29,4665913,"m³/K","cubic metre per kelvin"
-G28,4665912,"l/K","litre per kelvin"
-G30,4666160,"ml/K","millilitre per kelvin"
-J36,4862774,"µl/l","microlitre per litre"
-J87,4864055,"cm³/m³","cubic centimetre per cubic metre"
-J91,4864305,"dm³/m³","cubic decimetre per cubic metre"
-K62,4929074,"l/l","litre per litre"
-L19,4993337,"ml/l","millilitre per litre"
-L21,4993585,"mm³/m³","cubic millimetre per cubic metre"
-SEC,5457219,"s","second [unit of time]"
-MIN,5065038,"min","minute [unit of time]"
-HUR,4740434,"h","hour"
-DAY,4473177,"d","day"
-B52,4338994,"ks","kilosecond"
-C26,4403766,"ms","millisecond"
-H70,4732720,"ps","picosecond"
-B98,4340024,"µs","microsecond"
-C47,4404279,"ns","nanosecond"
-WEE,5719365,"wk","week"
-MON,5066574,"mo","month"
-ANN,4279886,"y","year"
-D42,4469810,"y (tropical)","tropical year"
-L95,4995381,"y (365 days)","common year"
-L96,4995382,"y (sidereal)","sidereal year"
-M56,5059894,"shake","shake"
-2A,12865,"rad/s","radian per second"
-M46,5059638,"r/min","revolution per minute"
-2B,12866,"rad/s²","radian per second squared"
-M45,5059637,"°/s²","degree [unit of angle] per second squared"
-MTS,5067859,"m/s","metre per second"
-KNT,4935252,"kn","knot"
-KMH,4934984,"km/h","kilometre per hour"
-C16,4403510,"mm/s","millimetre per second"
-2M,12877,"cm/s","centimetre per second"
-H49,4731961,"cm/h","centimetre per hour"
-H81,4732977,"mm/min","millimetre per minute"
-2X,12888,"m/min","metre per minute"
-M59,5059897,"(m/s)/Pa","metre per second pascal"
-H66,4732470,"mm/y","millimetre per year"
-H67,4732471,"mm/h","millimetre per hour"
-FR,18002,"ft/min","foot per minute"
-IU,18773,"in/s","inch per second"
-FS,18003,"ft/s","foot per second"
-HM,18509,"mile/h","mile per hour (statute mile)"
-J84,4864052,"(cm/s)/K","centimetre per second kelvin"
-J85,4864053,"(cm/s)/bar","centimetre per second bar"
-K14,4927796,"ft/h","foot per hour"
-K18,4927800,"(ft/s)/°F","foot per second degree Fahrenheit"
-K19,4927801,"(ft/s)/psi","foot per second psi"
-K47,4928567,"(in/s)/°F","inch per second degree Fahrenheit"
-K48,4928568,"(in/s)/psi","inch per second psi"
-L12,4993330,"(m/s)/K","metre per second kelvin"
-L13,4993331,"(m/s)/bar","metre per second bar"
-M22,5059122,"(ml/min)/cm²","millilitre per square centimetre minute"
-M57,5059895,"mi/min","mile per minute"
-M58,5059896,"mi/s","mile per second"
-M60,5060144,"m/h","metre per hour"
-M61,5060145,"in/y","inch per year"
-M62,5060146,"km/s","kilometre per second"
-M63,5060147,"in/min","inch per minute"
-M64,5060148,"yd/s","yard per second"
-M65,5060149,"yd/min","yard per minute"
-M66,5060150,"yd/h","yard per hour"
-MSK,5067595,"m/s²","metre per second squared"
-A76,4273974,"Gal","gal"
-C11,4403505,"mGal","milligal"
-M38,5059384,"km/s²","kilometre per second squared"
-M39,5059385,"cm/s²","centimetre per second squared"
-M41,5059633,"mm/s²","millimetre per second squared"
-A73,4273971,"ft/s²","foot per second squared"
-IV,18774,"in/s²","inch per second squared"
-K40,4928560,"gn","standard acceleration of free fall"
-M40,5059632,"yd/s²","yard per second squared"
-M42,5059634,"mi/s²","mile (statute mile) per second squared"
-C92,4405554,"m⁻¹","reciprocal metre"
-Q32,5321522,"fl","femtolitre"
-Q33,5321523,"pl","picolitre"
-Q34,5321524,"nl","nanolitre"
-AWG,4282183,"AWG","american wire gauge"
-NM3,5131571,"Normalised cubic metre","Normalised cubic metre"
-SM3,5459251,"Standard cubic metre","Standard cubic metre"
-HTZ,4740186,"Hz","hertz"
-KHZ,4933722,"kHz","kilohertz"
-MHZ,5064794,"MHz","megahertz"
-D29,4469305,"THz","terahertz"
-A86,4274230,"GHz","gigahertz"
-MTZ,5067866,"mHz","millihertz"
-H10,4731184,"1/h","reciprocal hour"
-H11,4731185,"1/mo","reciprocal month"
-H09,4730937,"1/y","reciprocal year"
-H85,4732981,"1/wk","reciprocal week"
-C97,4405559,"s⁻¹","reciprocal second"
-RPS,5394515,"r/s","revolutions per second"
-RPM,5394509,"r/min","revolutions per minute"
-C94,4405556,"min⁻¹","reciprocal minute"
-C50,4404528,"Np","neper"
-2N,12878,"dB","decibel"
-M72,5060402,"B","bel"
-C51,4404529,"Np/s","neper per second"
-KGM,4933453,"kg","kilogram"
-MC,19779,"µg","microgram"
-DJ,17482,"dag","decagram"
-DG,17479,"dg","decigram"
-GRM,4674125,"g","gram"
-CGM,4409165,"cg","centigram"
-TNE,5525061,"t","tonne (metric ton)"
-DTN,4478030,"dt or dtn","decitonne"
-MGM,5064525,"mg","milligram"
-HGM,4736845,"hg","hectogram"
-KTN,4936782,"kt","kilotonne"
-2U,12885,"Mg","megagram"
-LBR,4997714,"lb","pound"
-GRN,4674126,"gr","grain"
-ONZ,5197402,"oz","ounce (avoirdupois)"
-CWI,4413257,"cwt (UK)","hundred weight (UK)"
-CWA,4413249,"cwt (US)","hundred pound (cwt) / hundred weight (US)"
-LTN,5002318,"ton (UK)","ton (UK) or long ton (US)"
-STI,5461065,"st","stone (UK)"
-STN,5461070,"ton (US)","ton (US) or short ton (UK/US)"
-APZ,4280410,"tr oz","troy ounce or apothecary ounce"
-F13,4600115,"slug","slug"
-K64,4929076,"lb/°F","pound (avoirdupois) per degree Fahrenheit"
-L69,4994617,"t/K","tonne per kelvin"
-L87,4995127,"ton (US)/°F","ton short per degree Fahrenheit"
-M85,5060661,"ton, assay","ton, assay"
-M86,5060662,"pfd","pfund"
-KMQ,4934993,"kg/m³","kilogram per cubic metre"
-23,12851,"g/cm³","gram per cubic centimetre"
-D41,4469809,"t/m³","tonne per cubic metre"
-GJ,18250,"g/ml","gram per millilitre"
-B35,4338485,"kg/l or kg/L","kilogram per litre"
-GL,18252,"g/l","gram per litre"
-A93,4274483,"g/m³","gram per cubic metre"
-GP,18256,"mg/m³","milligram per cubic metre"
-B72,4339506,"Mg/m³","megagram per cubic metre"
-B34,4338484,"kg/dm³","kilogram per cubic decimetre"
-H64,4732468,"mg/g","milligram per gram"
-H29,4731449,"µg/l","microgram per litre"
-M1,19761,"mg/l","milligram per litre"
-GQ,18257,"µg/m³","microgram per cubic metre"
-G11,4665649,"g/(cm³·bar)","gram per cubic centimetre bar"
-G33,4666163,"g/(cm³·K)","gram per cubic centimetre kelvin"
-F23,4600371,"g/dm³","gram per cubic decimetre"
-G12,4665650,"g/(dm³·bar)","gram per cubic decimetre bar"
-G34,4666164,"g/(dm³·K)","gram per cubic decimetre kelvin"
-G14,4665652,"g/(m³·bar)","gram per cubic metre bar"
-G36,4666166,"g/(m³·K)","gram per cubic metre kelvin"
-G13,4665651,"g/(l·bar)","gram per litre bar"
-G35,4666165,"g/(l·K)","gram per litre kelvin"
-G15,4665653,"g/(ml·bar)","gram per millilitre bar"
-G37,4666167,"g/(ml·K)","gram per millilitre kelvin"
-G31,4666161,"kg/cm³","kilogram per cubic centimetre"
-G16,4665654,"kg/(cm³·bar)","kilogram per cubic centimetre bar"
-G38,4666168,"kg/(cm³·K)","kilogram per cubic centimetre kelvin"
-G18,4665656,"kg/(m³·bar)","kilogram per cubic metre bar"
-G40,4666416,"kg/(m³·K)","kilogram per cubic metre kelvin"
-H54,4732212,"(kg/dm³)/K","kilogram per cubic decimetre kelvin"
-H55,4732213,"(kg/dm³)/bar","kilogram per cubic decimetre bar"
-F14,4600116,"g/K","gram per kelvin"
-F15,4600117,"kg/K","kilogram per kelvin"
-F24,4600372,"kg/kmol","kilogram per kilomole"
-G17,4665655,"kg/(l·bar)","kilogram per litre bar"
-G39,4666169,"kg/(l·K)","kilogram per litre kelvin"
-H53,4732211,"kg/bar","kilogram per bar"
-F18,4600120,"kg·cm²","kilogram square centimetre"
-F19,4600121,"kg·mm²","kilogram square millimetre"
-F74,4601652,"g/bar","gram per bar"
-F75,4601653,"mg/bar","milligram per bar"
-F16,4600118,"mg/K","milligram per kelvin"
-M73,5060403,"(kg/m³)/Pa","kilogram per cubic metre pascal"
-87,14391,"lb/ft³","pound per cubic foot"
-GE,18245,"lb/gal (US)","pound per gallon (US)"
-LA,19521,"lb/in³","pound per cubic inch"
-G32,4666162,"oz/yd³","ounce (avoirdupois) per cubic yard"
-J34,4862772,"(µg/m³)/K","microgram per cubic metre kelvin"
-J35,4862773,"(µg/m³)/bar","microgram per cubic metre bar"
-K41,4928561,"gr/gal (US)","grain per gallon (US)"
-K69,4929081,"(lb/ft³)/°F","pound (avoirdupois) per cubic foot degree Fahrenheit"
-K70,4929328,"(lb/ft³)/psi","pound (avoirdupois) per cubic foot psi"
-K71,4929329,"lb/gal (UK)","pound (avoirdupois) per gallon (UK)"
-K75,4929333,"(lb/in³)/°F","pound (avoirdupois) per cubic inch degree Fahrenheit"
-K76,4929334,"(lb/in³)/psi","pound (avoirdupois) per cubic inch psi"
-K84,4929588,"lb/yd³","pound per cubic yard"
-L17,4993335,"(mg/m³)/K","milligram per cubic metre kelvin"
-L18,4993336,"(mg/m³)/bar","milligram per cubic metre bar"
-L37,4993847,"oz/gal (UK)","ounce (avoirdupois) per gallon (UK)"
-L38,4993848,"oz/gal (US)","ounce (avoirdupois) per gallon (US)"
-L39,4993849,"oz/in³","ounce (avoirdupois) per cubic inch"
-L65,4994613,"slug/ft³","slug per cubic foot"
-L76,4994870,"(t/m³)/K","tonne per cubic metre kelvin"
-L77,4994871,"(t/m³)/bar","tonne per cubic metre bar"
-L92,4995378,"ton.l/yd³ (UK)","ton (UK long) per cubic yard"
-L93,4995379,"ton.s/yd³ (US)","ton (US short) per cubic yard"
-K77,4929335,"lb/psi","pound (avoirdupois) per psi"
-L70,4994864,"t/bar","tonne per bar"
-L91,4995377,"ton (US)/psi","ton short per psi"
-M74,5060404,"kg/Pa","kilogram per pascal"
-C62,4404786,"1","one"
-A39,4272953,"m³/kg","cubic metre per kilogram"
-22,12850,"dl/g","decilitre per gram"
-H65,4732469,"ml/m³","millilitre per cubic metre"
-H83,4732979,"l/kg","litre per kilogram"
-KX,19288,"ml/kg","millilitre per kilogram"
-H15,4731189,"cm²/g","square centimetre per gram"
-N28,5124664,"dm³/kg","cubic decimetre per kilogram"
-N29,5124665,"ft³/lb","cubic foot per pound"
-N30,5124912,"in³/lb","cubic inch per pound"
-KL,19276,"kg/m","kilogram per metre"
-GF,18246,"g/m","gram per metre (gram per 100 centimetres)"
-H76,4732726,"g/mm","gram per millimetre"
-KW,19287,"kg/mm","kilogram per millimetre"
-C12,4403506,"mg/m","milligram per metre"
-M31,5059377,"kg/km","kilogram per kilometre"
-P2,20530,"lb/ft","pound per foot"
-PO,20559,"lb/in","pound per inch of length"
-M83,5060659,"den","denier"
-M84,5060660,"lb/yd","pound per yard"
-GO,18255,"mg/m²","milligram per square metre"
-25,12853,"g/cm²","gram per square centimetre"
-H63,4732467,"mg/cm²","milligram per square centimetre"
-GM,18253,"g/m²","gram per square metre"
-28,12856,"kg/m²","kilogram per square metre"
-D5,17461,"kg/cm²","kilogram per square centimetre"
-ON,20302,"oz/yd²","ounce per square yard"
-37,13111,"oz/ft²","ounce per square foot"
-B31,4338481,"kg·m/s","kilogram metre per second"
-M98,5060920,"kg·(cm/s)","kilogram centimetre per second"
-M99,5060921,"g·(cm/s)","gram centimetre per second"
-N10,5124400,"lb·(ft/s)","pound foot per second"
-N11,5124401,"lb·(in/s)","pound inch per second"
-B33,4338483,"kg·m²/s","kilogram metre squared per second"
-B32,4338482,"kg·m²","kilogram metre squared"
-F20,4600368,"lb·in²","pound inch squared"
-K65,4929077,"lb·ft²","pound (avoirdupois) square foot"
-NEW,5129559,"N","newton"
-B73,4339507,"MN","meganewton"
-B47,4338743,"kN","kilonewton"
-C20,4403760,"mN","millinewton"
-B92,4340018,"µN","micronewton"
-DU,17493,"dyn","dyne"
-C78,4405048,"lbf","pound-force"
-B37,4338487,"kgf","kilogram-force"
-B51,4338993,"kp","kilopond"
-L40,4994096,"ozf","ounce (avoirdupois)-force"
-L94,4995380,"ton.sh-force","ton-force (US short)"
-M75,5060405,"kip","kilopound-force"
-M76,5060406,"pdl","poundal"
-M77,5060407,"kg·m/s²","kilogram metre per second squared"
-M78,5060408,"p","pond"
-F17,4600119,"lbf/ft","pound-force per foot"
-F48,4600888,"lbf/in","pound-force per inch"
-C54,4404532,"N·m²/kg²","newton metre squared per kilogram squared"
-NU,20053,"N·m","newton metre"
-H40,4731952,"N/A","newton per ampere"
-B74,4339508,"MN·m","meganewton metre"
-B48,4338744,"kN·m","kilonewton metre"
-D83,4470835,"mN·m","millinewton metre"
-B93,4340019,"µN·m","micronewton metre"
-DN,17486,"dN·m","decinewton metre"
-J72,4863794,"cN·m","centinewton metre"
-M94,5060916,"kg·m","kilogram metre"
-F88,4601912,"N·cm","newton centimetre"
-F90,4602160,"N·m/A","newton metre per ampere"
-F89,4601913,"Nm/°","newton metre per degree"
-G19,4665657,"N·m/kg","newton metre per kilogram"
-F47,4600887,"N/mm","newton per millimetre"
-M93,5060915,"N·m/rad","newton metre per radian"
-H41,4731953,"N·m·W⁻⁰‧⁵","newton metre watt to the power minus 0,5"
-B38,4338488,"kgf·m","kilogram-force metre"
-IA,18753,"in·lb","inch pound (pound inch)"
-4Q,13393,"oz·in","ounce inch"
-4R,13394,"oz·ft","ounce foot"
-F22,4600370,"lbf·ft/A","pound-force foot per ampere"
-F21,4600369,"lbf·in","pound-force inch"
-G20,4665904,"lbf·ft/lb","pound-force foot per pound"
-J94,4864308,"dyn·cm","dyne centimetre"
-L41,4994097,"ozf·in","ounce (avoirdupois)-force inch"
-M92,5060914,"lbf·ft","pound-force foot"
-M95,5060917,"pdl·ft","poundal foot"
-M96,5060918,"pdl·in","poundal inch"
-M97,5060919,"dyn·m","dyne metre"
-C57,4404535,"N·s","newton second"
-C53,4404531,"N·m·s","newton metre second"
-74,14132,"mPa","millipascal"
-MPA,5066817,"MPa","megapascal"
-PAL,5259596,"Pa","pascal"
-KPA,4935745,"kPa","kilopascal"
-BAR,4342098,"bar","bar [unit of pressure]"
-HBA,4735553,"hbar","hectobar"
-MBR,5063250,"mbar","millibar"
-KBA,4932161,"kbar","kilobar"
-ATM,4281421,"atm","standard atmosphere"
-A89,4274233,"GPa","gigapascal"
-B96,4340022,"µPa","micropascal"
-A97,4274487,"hPa","hectopascal"
-H75,4732725,"daPa","decapascal"
-B85,4339765,"µbar","microbar"
-C55,4404533,"N/m²","newton per square metre"
-C56,4404534,"N/mm²","newton per square millimetre"
-H07,4730935,"Pa·s/bar","pascal second per bar"
-F94,4602164,"hPa·m³/s","hectopascal cubic metre per second"
-F93,4602163,"hPa·l/s","hectopascal litre per second"
-F82,4601906,"hPa/K","hectopascal per kelvin"
-F83,4601907,"kPa/K","kilopascal per kelvin"
-F98,4602168,"MPa·m³/s","megapascal cubic metre per second"
-F97,4602167,"MPa·l/s","megapascal litre per second"
-F85,4601909,"MPa/K","megapascal per kelvin"
-F96,4602166,"mbar·m³/s","millibar cubic metre per second"
-F95,4602165,"mbar·l/s","millibar litre per second"
-F84,4601908,"mbar/K","millibar per kelvin"
-G01,4665393,"Pa·m³/s","pascal cubic metre per second"
-F99,4602169,"Pa·l/s","pascal litre per second"
-F77,4601655,"Pa.s/K","pascal second per kelvin"
-E01,4534321,"N/cm²","newton per square centimetre"
-FP,18000,"lb/ft²","pound per square foot"
-PS,20563,"lbf/in²","pound-force per square inch"
-B40,4338736,"kgf/m²","kilogram-force per square metre"
-UA,21825,"Torr","torr"
-ATT,4281428,"at","technical atmosphere"
-80,14384,"lb/in²","pound per square inch absolute"
-H78,4732728,"cm H₂O","conventional centimetre of water"
-HP,18512,"mm H₂O","conventional millimetre of water"
-HN,18510,"mm Hg","conventional millimetre of mercury"
-F79,4601657,"inHg","inch of mercury"
-F78,4601656,"inH₂O","inch of water"
-J89,4864057,"cm Hg","centimetre of mercury"
-K24,4928052,"ft H₂O","foot of water"
-K25,4928053,"ft Hg","foot of mercury"
-K31,4928305,"gf/cm²","gram-force per square centimetre"
-E42,4535346,"kgf/cm²","kilogram-force per square centimetre"
-E41,4535345,"kgf·m/cm²","kilogram-force per square millimetre"
-K85,4929589,"lbf/ft²","pound-force per square foot"
-K86,4929590,"psi/°F","pound-force per square inch degree Fahrenheit"
-84,14388,"klbf/in²","kilopound-force per square inch"
-N13,5124403,"cmHg (0 ºC)","centimetre of mercury (0 ºC)"
-N14,5124404,"cmH₂O (4 °C)","centimetre of water (4 ºC)"
-N15,5124405,"ftH₂O (39,2 ºF)","foot of water (39.2 ºF)"
-N16,5124406,"inHG (32 ºF)","inch of mercury (32 ºF)"
-N17,5124407,"inHg (60 ºF)","inch of mercury (60 ºF)"
-N18,5124408,"inH₂O (39,2 ºF)","inch of water (39.2 ºF)"
-N19,5124409,"inH₂O (60 ºF)","inch of water (60 ºF)"
-N20,5124656,"ksi","kip per square inch"
-N21,5124657,"pdl/ft²","poundal per square foot"
-N22,5124658,"oz/in²","ounce (avoirdupois) per square inch"
-N23,5124659,"mH₂O","conventional metre of water"
-N24,5124660,"g/mm²","gram per square millimetre"
-N25,5124661,"lb/yd²","pound per square yard"
-N26,5124662,"pdl/in²","poundal per square inch"
-E99,4536633,"hPa/bar","hectopascal per bar"
-F05,4599861,"MPa/bar","megapascal per bar"
-F04,4599860,"mbar/bar","millibar per bar"
-F07,4599863,"Pa/bar","pascal per bar"
-F03,4599859,"kPa/bar","kilopascal per bar"
-L52,4994354,"psi/psi","psi per psi"
-J56,4863286,"bar/bar","bar per bar"
-C96,4405558,"Pa⁻¹","reciprocal pascal or pascal to the power minus one"
-F58,4601144,"1/bar","reciprocal bar"
-B83,4339763,"m⁴","metre to the fourth power"
-G77,4667191,"mm⁴","millimetre to the fourth power"
-D69,4470329,"in⁴","inch to the fourth power"
-N27,5124663,"ft⁴","foot to the fourth power"
-C65,4404789,"Pa·s","pascal second"
-N37,5124919,"kg/(m·s)","kilogram per metre second"
-N38,5124920,"kg/(m·min)","kilogram per metre minute"
-C24,4403764,"mPa·s","millipascal second"
-N36,5124918,"(N/m²)·s","newton second per square metre"
-N39,5124921,"kg/(m·d)","kilogram per metre day"
-N40,5125168,"kg/(m·h)","kilogram per metre hour"
-N41,5125169,"g/(cm·s)","gram per centimetre second"
-89,14393,"P","poise"
-C7,17207,"cP","centipoise"
-F06,4599862,"P/bar","poise per bar"
-F86,4601910,"P/K","poise per kelvin"
-J32,4862770,"µP","micropoise"
-J73,4863795,"cP/K","centipoise per kelvin"
-J74,4863796,"cP/bar","centipoise per bar"
-K67,4929079,"lb/(ft·h)","pound per foot hour"
-K68,4929080,"lb/(ft·s)","pound per foot second"
-K91,4929841,"lbf·s/ft²","pound-force second per square foot"
-K92,4929842,"lbf·s/in²","pound-force second per square inch"
-L15,4993333,"mPa·s/K","millipascal second per kelvin"
-L16,4993334,"mPa·s/bar","millipascal second per bar"
-L64,4994612,"slug/(ft·s)","slug per foot second"
-N34,5124916,"(pdl/ft²)·s","poundal second per square foot"
-N35,5124917,"P/Pa","poise per pascal"
-N42,5125170,"(pdl/in²)·s","poundal second per square inch"
-N43,5125171,"lb/(ft·min)","pound per foot minute"
-N44,5125172,"lb/(ft·d)","pound per foot day"
-S4,21300,"m²/s","square metre per second"
-M82,5060658,"(m²/s)/Pa","square metre per second pascal"
-C17,4403511,"mm²/s","millimetre squared per second"
-G41,4666417,"m²/(s·bar)","square metre per second bar"
-G09,4665401,"m²/(s·K)","square metre per second kelvin"
-91,14641,"St","stokes"
-4C,13379,"cSt","centistokes"
-G46,4666422,"St/bar","stokes per bar"
-G10,4665648,"St/K","stokes per kelvin"
-S3,21299,"ft²/s","square foot per second"
-G08,4665400,"in²/s","square inch per second"
-M79,5060409,"ft²/h","square foot per hour"
-M80,5060656,"St/Pa","stokes per pascal"
-M81,5060657,"cm²/s","square centimetre per second"
-4P,13392,"N/m","newton per metre"
-C22,4403762,"mN/m","millinewton per metre"
-M23,5059123,"N/cm","newton per centimetre"
-N31,5124913,"kN/m","kilonewton per metre"
-DX,17496,"dyn/cm","dyne per centimetre"
-N32,5124914,"pdl/in","poundal per inch"
-N33,5124915,"lbf/yd","pound-force per yard"
-M34,5059380,"N·m/m²","newton metre per square metre"
-JOU,4869973,"J","joule"
-KJO,4934223,"kJ","kilojoule"
-A68,4273720,"EJ","exajoule"
-C68,4404792,"PJ","petajoule"
-D30,4469552,"TJ","terajoule"
-GV,18262,"GJ","gigajoule"
-3B,13122,"MJ","megajoule"
-C15,4403509,"mJ","millijoule"
-A70,4273968,"fJ","femtojoule"
-A13,4272435,"aJ","attojoule"
-WHR,5720146,"W·h","watt hour"
-MWH,5068616,"MW·h","megawatt hour (1000 kW.h)"
-KWH,4937544,"kW·h","kilowatt hour"
-GWH,4675400,"GW·h","gigawatt hour"
-D32,4469554,"TW·h","terawatt hour"
-A53,4273459,"eV","electronvolt"
-B71,4339505,"MeV","megaelectronvolt"
-A85,4274229,"GeV","gigaelectronvolt"
-B29,4338233,"keV","kiloelectronvolt"
-A57,4273463,"erg","erg"
-85,14389,"ft·lbf","foot pound-force"
-N46,5125174,"ft·pdl","foot poundal"
-N47,5125175,"in·pdl","inch poundal"
-WTT,5723220,"W","watt"
-KWT,4937556,"kW","kilowatt"
-MAW,5062999,"MW","megawatt"
-A90,4274480,"GW","gigawatt"
-C31,4404017,"mW","milliwatt"
-D80,4470832,"µW","microwatt"
-F80,4601904,"water horse power","water horse power"
-A63,4273715,"erg/s","erg per second"
-A74,4273972,"ft·lbf/s","foot pound-force per second"
-B39,4338489,"kgf·m/s","kilogram-force metre per second"
-HJ,18506,"metric hp","metric horse power"
-A25,4272693,"CV","cheval vapeur"
-BHP,4343888,"BHP","brake horse power"
-K15,4927797,"ft·lbf/h","foot pound-force per hour"
-K16,4927798,"ft·lbf/min","foot pound-force per minute"
-K42,4928562,"boiler hp","horsepower (boiler)"
-N12,5124402,"PS","Pferdestaerke"
-KGS,4933459,"kg/s","kilogram per second"
-H56,4732214,"kg/(m²·s)","kilogram per square metre second"
-M87,5060663,"(kg/s)/Pa","kilogram per second pascal"
-4M,13389,"mg/h","milligram per hour"
-F26,4600374,"g/d","gram per day"
-F62,4601394,"g/(d·bar)","gram per day bar"
-F35,4600629,"g/(d·K)","gram per day kelvin"
-F27,4600375,"g/h","gram per hour"
-F63,4601395,"g/(h·bar)","gram per hour bar"
-F36,4600630,"g/(h·K)","gram per hour kelvin"
-F28,4600376,"g/min","gram per minute"
-F64,4601396,"g/(min·bar)","gram per minute bar"
-F37,4600631,"g/(min·K)","gram per minute kelvin"
-F29,4600377,"g/s","gram per second"
-F65,4601397,"g/(s·bar)","gram per second bar"
-F38,4600632,"g/(s·K)","gram per second kelvin"
-F30,4600624,"kg/d","kilogram per day"
-F66,4601398,"kg/(d·bar)","kilogram per day bar"
-F39,4600633,"kg/(d·K)","kilogram per day kelvin"
-E93,4536627,"kg/h","kilogram per hour"
-F67,4601399,"kg/(h·bar)","kilogram per hour bar"
-F40,4600880,"kg/(h·K)","kilogram per hour kelvin"
-F31,4600625,"kg/min","kilogram per minute"
-F68,4601400,"kg/(min·bar)","kilogram per minute bar"
-F41,4600881,"kg/(min·K)","kilogram per minute kelvin"
-F69,4601401,"kg/(s·bar)","kilogram per second bar"
-F42,4600882,"kg/(s·K)","kilogram per second kelvin"
-F32,4600626,"mg/d","milligram per day"
-F70,4601648,"mg/(d·bar)","milligram per day bar"
-F43,4600883,"mg/(d·K)","milligram per day kelvin"
-F71,4601649,"mg/(h·bar)","milligram per hour bar"
-F44,4600884,"mg/(h·K)","milligram per hour kelvin"
-F33,4600627,"mg/min","milligram per minute"
-F72,4601650,"mg/(min·bar)","milligram per minute bar"
-F45,4600885,"mg/(min·K)","milligram per minute kelvin"
-F34,4600628,"mg/s","milligram per second"
-F73,4601651,"mg/(s·bar)","milligram per second bar"
-F46,4600886,"mg/(s·K)","milligram per second kelvin"
-F25,4600373,"g/Hz","gram per hertz"
-4W,13399,"ton (US) /h","ton (US) per hour"
-4U,13397,"lb/h","pound per hour"
-K66,4929078,"lb/d","pound (avoirdupois) per day"
-K73,4929331,"(lb/h)/°F","pound (avoirdupois) per hour degree Fahrenheit"
-K74,4929332,"(lb/h)/psi","pound (avoirdupois) per hour psi"
-K78,4929336,"lb/min","pound (avoirdupois) per minute"
-K79,4929337,"lb/(min·°F)","pound (avoirdupois) per minute degree Fahrenheit"
-K80,4929584,"(lb/min)/psi","pound (avoirdupois) per minute psi"
-K81,4929585,"lb/s","pound (avoirdupois) per second"
-K82,4929586,"(lb/s)/°F","pound (avoirdupois) per second degree Fahrenheit"
-K83,4929587,"(lb/s)/psi","pound (avoirdupois) per second psi"
-L33,4993843,"oz/d","ounce (avoirdupois) per day"
-L34,4993844,"oz/h","ounce (avoirdupois) per hour"
-L35,4993845,"oz/min","ounce (avoirdupois) per minute"
-L36,4993846,"oz/s","ounce (avoirdupois) per second"
-L63,4994611,"slug/d","slug per day"
-L66,4994614,"slug/h","slug per hour"
-L67,4994615,"slug/min","slug per minute"
-L68,4994616,"slug/s","slug per second"
-L71,4994865,"t/d","tonne per day"
-L72,4994866,"(t/d)/K","tonne per day kelvin"
-L73,4994867,"(t/d)/bar","tonne per day bar"
-E18,4534584,"t/h","tonne per hour"
-L74,4994868,"(t/h)/K","tonne per hour kelvin"
-L75,4994869,"(t/h)/bar","tonne per hour bar"
-L78,4994872,"t/min","tonne per minute"
-L79,4994873,"(t/min)/K","tonne per minute kelvin"
-L80,4995120,"(t/min)/bar","tonne per minute bar"
-L81,4995121,"t/s","tonne per second"
-L82,4995122,"(t/s)/K","tonne per second kelvin"
-L83,4995123,"(t/s)/bar","tonne per second bar"
-L85,4995125,"ton (UK)/d","ton long per day"
-L88,4995128,"ton (US)/d","ton short per day"
-L89,4995129,"ton (US)/(h·°F)","ton short per hour degree Fahrenheit"
-L90,4995376,"(ton (US)/h)/psi","ton short per hour psi"
-M88,5060664,"t/mo","tonne per month"
-M89,5060665,"t/y","tonne per year"
-M90,5060912,"klb/h","kilopound per hour"
-J33,4862771,"µg/kg","microgram per kilogram"
-L32,4993842,"ng/kg","nanogram per kilogram"
-NA,20033,"mg/kg","milligram per kilogram"
-M29,5059129,"kg/kg","kilogram per kilogram"
-M91,5060913,"lb/lb","pound per pound"
-MQS,5067091,"m³/s","cubic metre per second"
-MQH,5067080,"m³/h","cubic metre per hour"
-40,13360,"ml/s","millilitre per second"
-41,13361,"ml/min","millilitre per minute"
-LD,19524,"l/d","litre per day"
-2J,12874,"cm³/s","cubic centimetre per second"
-4X,13400,"kl/h","kilolitre per hour"
-L2,19506,"l/min","litre per minute"
-G47,4666423,"cm³/d","cubic centimetre per day"
-G78,4667192,"cm³/(d·bar)","cubic centimetre per day bar"
-G61,4666929,"cm³/(d·K)","cubic centimetre per day kelvin"
-G48,4666424,"cm³/h","cubic centimetre per hour"
-G79,4667193,"cm³/(h·bar)","cubic centimetre per hour bar"
-G62,4666930,"cm³/(h·K)","cubic centimetre per hour kelvin"
-G49,4666425,"cm³/min","cubic centimetre per minute"
-G80,4667440,"cm³/(min·bar)","cubic centimetre per minute bar"
-G63,4666931,"cm³/(min·K)","cubic centimetre per minute kelvin"
-G81,4667441,"cm³/(s·bar)","cubic centimetre per second bar"
-G64,4666932,"cm³/(s·K)","cubic centimetre per second kelvin"
-E92,4536626,"dm³/h","cubic decimetre per hour"
-G52,4666674,"m³/d","cubic metre per day"
-G86,4667446,"m³/(d·bar)","cubic metre per day bar"
-G69,4666937,"m³/(d·K)","cubic metre per day kelvin"
-G87,4667447,"m³/(h·bar)","cubic metre per hour bar"
-G70,4667184,"m³/(h·K)","cubic metre per hour kelvin"
-G53,4666675,"m³/min","cubic metre per minute"
-G88,4667448,"m³/(min·bar)","cubic metre per minute bar"
-G71,4667185,"m³/(min·K)","cubic metre per minute kelvin"
-G89,4667449,"m³/(s·bar)","cubic metre per second bar"
-G72,4667186,"m³/(s·K)","cubic metre per second kelvin"
-G82,4667442,"l/(d·bar)","litre per day bar"
-G65,4666933,"l/(d·K)","litre per day kelvin"
-G83,4667443,"l/(h·bar)","litre per hour bar"
-G66,4666934,"l/(h·K)","litre per hour kelvin"
-G84,4667444,"l/(min·bar)","litre per minute bar"
-G67,4666935,"l/(min·K)","litre per minute kelvin"
-G51,4666673,"l/s","litre per second"
-G85,4667445,"l/(s·bar)","litre per second bar"
-G68,4666936,"l/(s·K)","litre per second kelvin"
-G54,4666676,"ml/d","millilitre per day"
-G90,4667696,"ml/(d·bar)","millilitre per day bar"
-G73,4667187,"ml/(d·K)","millilitre per day kelvin"
-G55,4666677,"ml/h","millilitre per hour"
-G91,4667697,"ml/(h·bar)","millilitre per hour bar"
-G74,4667188,"ml/(h·K)","millilitre per hour kelvin"
-G92,4667698,"ml/(min·bar)","millilitre per minute bar"
-G75,4667189,"ml/(min·K)","millilitre per minute kelvin"
-G93,4667699,"ml/(s·bar)","millilitre per second bar"
-G76,4667190,"ml/(s·K)","millilitre per second kelvin"
-2K,12875,"ft³/h","cubic foot per hour"
-2L,12876,"ft³/min","cubic foot per minute"
-5A,13633,"barrel (US)/min","barrel (US) per minute"
-G2,18226,"gal (US) /min","US gallon per minute"
-G3,18227,"gal (UK) /min","Imperial gallon per minute"
-G56,4666678,"in³/h","cubic inch per hour"
-G57,4666679,"in³/min","cubic inch per minute"
-G58,4666680,"in³/s","cubic inch per second"
-G50,4666672,"gal/h","gallon (US) per hour"
-J58,4863288,"bbl (UK liq.)/min","barrel (UK petroleum) per minute"
-J59,4863289,"bbl (UK liq.)/d","barrel (UK petroleum) per day"
-J60,4863536,"bbl (UK liq.)/h","barrel (UK petroleum) per hour"
-J61,4863537,"bbl (UK liq.)/s","barrel (UK petroleum) per second"
-J62,4863538,"bbl (US)/h","barrel (US petroleum) per hour"
-J63,4863539,"bbl (US)/s","barrel (US petroleum) per second"
-J64,4863540,"bu (UK)/d","bushel (UK) per day"
-J65,4863541,"bu (UK)/h","bushel (UK) per hour"
-J66,4863542,"bu (UK)/min","bushel (UK) per minute"
-J67,4863543,"bu (UK)/s","bushel (UK) per second"
-J68,4863544,"bu (US dry)/d","bushel (US dry) per day"
-J69,4863545,"bu (US dry)/h","bushel (US dry) per hour"
-J70,4863792,"bu (US dry)/min","bushel (US dry) per minute"
-J71,4863793,"bu (US dry)/s","bushel (US dry) per second"
-J90,4864304,"dm³/d","cubic decimetre per day"
-J92,4864306,"dm³/min","cubic decimetre per minute"
-J93,4864307,"dm³/s","cubic decimetre per second"
-N45,5125173,"(m³/s)/Pa","cubic metre per second pascal"
-J95,4864309,"fl oz (UK)/d","ounce (UK fluid) per day"
-J96,4864310,"fl oz (UK)/h","ounce (UK fluid) per hour"
-J97,4864311,"fl oz (UK)/min","ounce (UK fluid) per minute"
-J98,4864312,"fl oz (UK)/s","ounce (UK fluid) per second"
-J99,4864313,"fl oz (US)/d","ounce (US fluid) per day"
-K10,4927792,"fl oz (US)/h","ounce (US fluid) per hour"
-K11,4927793,"fl oz (US)/min","ounce (US fluid) per minute"
-K12,4927794,"fl oz (US)/s","ounce (US fluid) per second"
-K22,4928050,"ft³/d","cubic foot per day"
-K26,4928054,"gal (UK)/d","gallon (UK) per day"
-K27,4928055,"gal (UK)/h","gallon (UK) per hour"
-K28,4928056,"gal (UK)/s","gallon (UK) per second"
-K30,4928304,"gal (US liq.)/s","gallon (US liquid) per second"
-K32,4928306,"gi (UK)/d","gill (UK) per day"
-K33,4928307,"gi (UK)/h","gill (UK) per hour"
-K34,4928308,"gi (UK)/min","gill (UK) per minute"
-K35,4928309,"gi (UK)/s","gill (UK) per second"
-K36,4928310,"gi (US)/d","gill (US) per day"
-K37,4928311,"gi (US)/h","gill (US) per hour"
-K38,4928312,"gi (US)/min","gill (US) per minute"
-K39,4928313,"gi (US)/s","gill (US) per second"
-K94,4929844,"qt (UK liq.)/d","quart (UK liquid) per day"
-K95,4929845,"qt (UK liq.)/h","quart (UK liquid) per hour"
-K96,4929846,"qt (UK liq.)/min","quart (UK liquid) per minute"
-K97,4929847,"qt (UK liq.)/s","quart (UK liquid) per second"
-K98,4929848,"qt (US liq.)/d","quart (US liquid) per day"
-K99,4929849,"qt (US liq.)/h","quart (US liquid) per hour"
-L10,4993328,"qt (US liq.)/min","quart (US liquid) per minute"
-L11,4993329,"qt (US liq.)/s","quart (US liquid) per second"
-L44,4994100,"pk (UK)/d","peck (UK) per day"
-L45,4994101,"pk (UK)/h","peck (UK) per hour"
-L46,4994102,"pk (UK)/min","peck (UK) per minute"
-L47,4994103,"pk (UK)/s","peck (UK) per second"
-L48,4994104,"pk (US dry)/d","peck (US dry) per day"
-L49,4994105,"pk (US dry)/h","peck (US dry) per hour"
-L50,4994352,"pk (US dry)/min","peck (US dry) per minute"
-L51,4994353,"pk (US dry)/s","peck (US dry) per second"
-L53,4994355,"pt (UK)/d","pint (UK) per day"
-L54,4994356,"pt (UK)/h","pint (UK) per hour"
-L55,4994357,"pt (UK)/min","pint (UK) per minute"
-L56,4994358,"pt (UK)/s","pint (UK) per second"
-L57,4994359,"pt (US liq.)/d","pint (US liquid) per day"
-L58,4994360,"pt (US liq.)/h","pint (US liquid) per hour"
-L59,4994361,"pt (US liq.)/min","pint (US liquid) per minute"
-L60,4994608,"pt (US liq.)/s","pint (US liquid) per second"
-M12,5058866,"yd³/d","cubic yard per day"
-M13,5058867,"yd³/h","cubic yard per hour"
-M15,5058869,"yd³/min","cubic yard per minute"
-M16,5058870,"yd³/s","cubic yard per second"
-H60,4732464,"m³/m³","cubic metre per cubic metre"
-F92,4602162,"bar·m³/s","bar cubic metre per second"
-F91,4602161,"bar·l/s","bar litre per second"
-K87,4929591,"psi·in³/s","psi cubic inch per second"
-K88,4929592,"psi·l/s","psi litre per second"
-K89,4929593,"psi·m³/s","psi cubic metre per second"
-K90,4929840,"psi·yd³/s","psi cubic yard per second"
-Q29,5321273,"µg/hg","microgram per hectogram"
-Q37,5321527,"Standard cubic metre per day","Standard cubic metre per day"
-Q38,5321528,"Standard cubic metre per hour","Standard cubic metre per hour"
-Q39,5321529,"Normalized cubic metre per day","Normalized cubic metre per day"
-Q40,5321776,"Normalized cubic metre per hour","Normalized cubic metre per hour"
-KWN,4937550,"Kilowatt hour per normalized cubic metre","Kilowatt hour per normalized cubic metre"
-KWS,4937555,"Kilowatt hour per standard cubic metre","Kilowatt hour per standard cubic metre"
-Q41,5321777,"Joule per normalised cubic metre","Joule per normalised cubic metre"
-Q42,5321778,"Joule per standard cubic metre","Joule per standard cubic metre"
-MNJ,5066314,"MJ/m³","Mega Joule per Normalised cubic Metre"
-KEL,4932940,"K","kelvin"
-CEL,4408652,"°C","degree Celsius"
-H12,4731186,"°C/h","degree Celsius per hour"
-F60,4601392,"°C/bar","degree Celsius per bar"
-E98,4536632,"°C/K","degree Celsius per kelvin"
-H13,4731187,"°C/min","degree Celsius per minute"
-H14,4731188,"°C/s","degree Celsius per second"
-F61,4601393,"K/bar","kelvin per bar"
-F10,4600112,"K/h","kelvin per hour"
-F02,4599858,"K/K","kelvin per kelvin"
-F11,4600113,"K/min","kelvin per minute"
-F12,4600114,"K/s","kelvin per second"
-N79,5125945,"K/Pa","kelvin per pascal"
-J20,4862512,"°F/K","degree Fahrenheit per kelvin"
-J21,4862513,"°F/bar","degree Fahrenheit per bar"
-J26,4862518,"1/°F","reciprocal degree Fahrenheit"
-A48,4273208,"°R","degree Rankine"
-FAH,4604232,"°F","degree Fahrenheit"
-J23,4862515,"°F/h","degree Fahrenheit per hour"
-J24,4862516,"°F/min","degree Fahrenheit per minute"
-J25,4862517,"°F/s","degree Fahrenheit per second"
-J28,4862520,"°R/h","degree Rankine per hour"
-J29,4862521,"°R/min","degree Rankine per minute"
-J30,4862768,"°R/s","degree Rankine per second"
-C91,4405553,"K⁻¹","reciprocal kelvin or kelvin to the power minus one"
-M20,5059120,"1/MK","reciprocal megakelvin or megakelvin to the power minus one"
-C64,4404788,"Pa/K","pascal per kelvin"
-F81,4601905,"bar/K","bar per kelvin"
-J55,4863285,"W·s","watt second"
-BTU,4346965,"BtuIT","British thermal unit (international table)"
-A1,16689,"cal₁₅","15 °C calorie"
-D70,4470576,"calIT","calorie (international table)"
-J39,4862777,"Btu","British thermal unit (mean)"
-J75,4863797,"cal","calorie (mean)"
-K51,4928817,"kcal","kilocalorie (mean)"
-E14,4534580,"kcalIT","kilocalorie (international table)"
-K53,4928819,"kcalth","kilocalorie (thermochemical)"
-N66,5125686,"Btu (39 ºF)","British thermal unit (39 ºF)"
-N67,5125687,"Btu (59 ºF)","British thermal unit (59 ºF)"
-N68,5125688,"Btu (60 ºF)","British thermal unit (60 ºF)"
-N69,5125689,"cal₂₀","calorie (20 ºC)"
-N70,5125936,"quad","quad (1015 BtuIT)"
-N71,5125937,"thm (EC)","therm (EC)"
-N72,5125938,"thm (US)","therm (U.S.)"
-D35,4469557,"calth","calorie (thermochemical)"
-2I,12873,"BtuIT/h","British thermal unit (international table) per hour"
-J44,4863028,"BtuIT/min","British thermal unit (international table) per minute"
-J45,4863029,"BtuIT/s","British thermal unit (international table) per second"
-J47,4863031,"Btuth/h","British thermal unit (thermochemical) per hour"
-J51,4863281,"Btuth/min","British thermal unit (thermochemical) per minute"
-J52,4863282,"Btuth/s","British thermal unit (thermochemical) per second"
-J81,4864049,"calth/min","calorie (thermochemical) per minute"
-J82,4864050,"calth/s","calorie (thermochemical) per second"
-E15,4534581,"kcalth/h","kilocalorie (thermochemical) per hour"
-K54,4928820,"kcalth/min","kilocalorie (thermochemical) per minute"
-K55,4928821,"kcalth/s","kilocalorie (thermochemical) per second"
-D54,4470068,"W/m²","watt per square metre"
-N48,5125176,"W/cm²","watt per square centimetre"
-N49,5125177,"W/in²","watt per square inch"
-N50,5125424,"BtuIT/(ft²·h)","British thermal unit (international table) per square foot hour"
-N51,5125425,"Btuth/(ft²·h)","British thermal unit (thermochemical) per square foot hour"
-N52,5125426,"Btuth/(ft²·min)","British thermal unit (thermochemical) per square foot minute"
-N53,5125427,"BtuIT/(ft²·s)","British thermal unit (international table) per square foot second"
-N54,5125428,"Btuth/(ft²·s)","British thermal unit (thermochemical) per square foot second"
-N55,5125429,"BtuIT/(in²·s)","British thermal unit (international table) per square inch second"
-N56,5125430,"calth/(cm²·min)","calorie (thermochemical) per square centimetre minute"
-N57,5125431,"calth/(cm²·s)","calorie (thermochemical) per square centimetre second"
-D53,4470067,"W/(m·K)","watt per metre kelvin"
-N80,5126192,"W/(m·°C)","watt per metre degree Celsius"
-N81,5126193,"kW/(m·K)","kilowatt per metre kelvin"
-N82,5126194,"kW/(m·°C)","kilowatt per metre degree Celsius"
-A22,4272690,"BtuIT/(s·ft·°R)","British thermal unit (international table) per second foot degree Rankine"
-D71,4470577,"calIT/(s·cm·K)","calorie (international table) per second centimetre kelvin"
-D38,4469560,"calth/(s·cm·K)","calorie (thermochemical) per second centimetre kelvin"
-J40,4863024,"BtuIT·ft/(h·ft²·°F)","British thermal unit (international table) foot per hour square foot degree Fahrenheit"
-J41,4863025,"BtuIT·in/(h·ft²·°F)","British thermal unit (international table) inch per hour square foot degree Fahrenheit"
-J42,4863026,"BtuIT·in/(s·ft²·°F)","British thermal unit (international table) inch per second square foot degree Fahrenheit"
-J46,4863030,"Btuth·ft/(h·ft²·°F)","British thermal unit (thermochemical) foot per hour square foot degree Fahrenheit"
-J48,4863032,"Btuth·in/(h·ft²·°F)","British thermal unit (thermochemical) inch per hour square foot degree Fahrenheit"
-J49,4863033,"Btuth·in/(s·ft²·°F)","British thermal unit (thermochemical) inch per second square foot degree Fahrenheit"
-J78,4863800,"calth/(cm·s·°C)","calorie (thermochemical) per centimetre second degree Celsius"
-K52,4928818,"kcal/(m·h·°C)","kilocalorie (international table) per hour metre degree Celsius"
-D55,4470069,"W/(m²·K)","watt per square metre kelvin"
-N78,5125944,"kW/(m²·K)","kilowatt per square metre kelvin"
-D72,4470578,"calIT/(s·cm²·K)","calorie (international table) per second square centimetre kelvin"
-D39,4469561,"calth/(s·cm²·K)","calorie (thermochemical) per second square centimetre kelvin"
-A20,4272688,"BtuIT/(s·ft²·°R)","British thermal unit (international table) per second square foot degree Rankine"
-A23,4272691,"BtuIT/(h·ft²·°R)","British thermal unit (international table) per hour square foot degree Rankine"
-N74,5125940,"BtuIT/(h·ft²·ºF)","British thermal unit (international table) per hour square foot degree Fahrenheit"
-N75,5125941,"Btuth/(h·ft²·ºF)","British thermal unit (thermochemical) per hour square foot degree Fahrenheit"
-N76,5125942,"BtuIT/(s·ft²·ºF)","British thermal unit (international table) per second square foot degree Fahrenheit"
-N77,5125943,"Btuth/(s·ft²·ºF)","British thermal unit (thermochemical) per second square foot degree Fahrenheit"
-D19,4469049,"m²·K/W","square metre kelvin per watt"
-J19,4862265,"°F·h·ft²/Btuth","degree Fahrenheit hour square foot per British thermal unit (thermochemical)"
-J22,4862514,"°F·h·ft²/BtuIT","degree Fahrenheit hour square foot per British thermal unit (international table)"
-J83,4864051,"clo","clo"
-L14,4993332,"m²·h·°C/kcal","square metre hour degree Celsius per kilocalorie (international table)"
-B21,4338225,"K/W","kelvin per watt"
-H35,4731701,"K·m/W","kelvin metre per watt"
-N84,5126196,"ºF/(BtuIT/h)","degree Fahrenheit hour per British thermal unit (international table)"
-N85,5126197,"ºF/(Btuth/h)","degree Fahrenheit hour per British thermal unit (thermochemical)"
-N86,5126198,"ºF/(BtuIT/s)","degree Fahrenheit second per British thermal unit (international table)"
-N87,5126199,"ºF/(Btuth/s)","degree Fahrenheit second per British thermal unit (thermochemical)"
-N88,5126200,"ºF·h·ft²/(BtuIT·in)","degree Fahrenheit hour square foot per British thermal unit (international table) inch"
-N89,5126201,"ºF·h·ft²/(Btuth·in)","degree Fahrenheit hour square foot per British thermal unit (thermochemical) inch"
-D52,4470066,"W/K","watt per kelvin"
-E97,4536631,"mm/(°C·m)","millimetre per degree Celcius metre"
-F53,4601139,"mm/K","millimetre per kelvin"
-N83,5126195,"m/(°C·m)","metre per degree Celcius metre"
-JE,19013,"J/K","joule per kelvin"
-B41,4338737,"kJ/K","kilojoule per kelvin"
-J43,4863027,"BtuIT/(lb·°F)","British thermal unit (international table) per pound degree Fahrenheit"
-J50,4863280,"Btuth/(lb·°F)","British thermal unit (thermochemical) per pound degree Fahrenheit"
-J76,4863798,"calIT/(g·°C)","calorie (international table) per gram degree Celsius"
-J79,4863801,"calth/(g·°C)","calorie (thermochemical) per gram degree Celsius"
-N60,5125680,"BtuIT/ºF","British thermal unit (international table) per degree Fahrenheit"
-N61,5125681,"Btuth/ºF","British thermal unit (thermochemical) per degree Fahrenheit"
-N62,5125682,"BtuIT/ºR","British thermal unit (international table) per degree Rankine"
-N63,5125683,"Btuth/ºR","British thermal unit (thermochemical) per degree Rankine"
-N64,5125684,"(Btuth/°R)/lb","British thermal unit (thermochemical) per pound degree Rankine"
-N65,5125685,"(kcalIT/K)/g","kilocalorie (international table) per gram kelvin"
-B11,4337969,"J/(kg·K)","joule per kilogram kelvin"
-B43,4338739,"kJ/(kg·K)","kilojoule per kilogram kelvin"
-A21,4272689,"Btu/IT(lb·°R)","British thermal unit (international table) per pound degree Rankine"
-D76,4470582,"calIT/(g·K)","calorie (international table) per gram kelvin"
-D37,4469559,"calth/(g·K)","calorie (thermochemical) per gram kelvin"
-J2,18994,"J/kg","joule per kilogram"
-D95,4471093,"J/g","joule per gram"
-JK,19019,"MJ/kg","megajoule per kilogram"
-B42,4338738,"kJ/kg","kilojoule per kilogram"
-AZ,16730,"BtuIT/lb","British thermal unit (international table) per pound"
-D75,4470581,"calIT/g","calorie (international table) per gram"
-N73,5125939,"Btuth/lb","British thermal unit (thermochemical) per pound"
-B36,4338486,"calth/g","calorie (thermochemical) per gram"
-N58,5125432,"BtuIT/ft³","British thermal unit (international table) per cubic foot"
-N59,5125433,"Btuth/ft³","British thermal unit (thermochemical) per cubic foot"
-Q31,5321521,"kJ/g","kilojoule per gram"
-AMP,4279632,"A","ampere"
-B22,4338226,"kA","kiloampere"
-H38,4731704,"MA","megaampere"
-4K,13387,"mA","milliampere"
-B84,4339764,"µA","microampere"
-C39,4404025,"nA","nanoampere"
-C70,4405040,"pA","picoampere"
-N96,5126454,"Bi","biot"
-N97,5126455,"Gi","gilbert"
-COU,4411221,"C","coulomb"
-A8,16696,"A·s","ampere second"
-H32,4731698,"A²·s","ampere squared second"
-AMH,4279624,"A·h","ampere hour"
-TAH,5521736,"kA·h","kiloampere hour (thousand ampere hour)"
-D77,4470583,"MC","megacoulomb"
-D86,4470838,"mC","millicoulomb"
-B26,4338230,"kC","kilocoulomb"
-B86,4339766,"µC","microcoulomb"
-C40,4404272,"nC","nanocoulomb"
-C71,4405041,"pC","picocoulomb"
-E09,4534329,"mA·h","milliampere hour"
-N95,5126453,"A·min","ampere minute"
-N94,5126452,"Fr","franklin"
-A29,4272697,"C/m³","coulomb per cubic metre"
-A84,4274228,"GC/m³","gigacoulomb per cubic metre"
-A30,4272944,"C/mm³","coulomb per cubic millimetre"
-B69,4339257,"MC/m³","megacoulomb per cubic metre"
-A28,4272696,"C/cm³","coulomb per cubic centimetre"
-B27,4338231,"kC/m³","kilocoulomb per cubic metre"
-D88,4470840,"mC/m³","millicoulomb per cubic metre"
-B87,4339767,"µC/m³","microcoulomb per cubic metre"
-A34,4272948,"C/m²","coulomb per square metre"
-B70,4339504,"MC/m²","megacoulomb per square metre"
-A35,4272949,"C/mm²","coulomb per square millimetre"
-A33,4272947,"C/cm²","coulomb per square centimetre"
-B28,4338232,"kC/m²","kilocoulomb per square metre"
-D89,4470841,"mC/m²","millicoulomb per square metre"
-B88,4339768,"µC/m²","microcoulomb per square metre"
-D50,4470064,"V/m","volt per metre"
-H45,4731957,"V·s/m","volt second per metre"
-D45,4469813,"V²/K²","volt squared per kelvin squared"
-D51,4470065,"V/mm","volt per millimetre"
-H24,4731444,"V/µs","volt per microsecond"
-H62,4732466,"mV/min","millivolt per minute"
-H46,4731958,"V/s","volt per second"
-B79,4339513,"MV/m","megavolt per metre"
-B55,4338997,"kV/m","kilovolt per metre"
-D47,4469815,"V/cm","volt per centimetre"
-C30,4404016,"mV/m","millivolt per metre"
-C3,17203,"µV/m","microvolt per metre"
-G60,4666928,"V/bar","volt per bar"
-N98,5126456,"V/Pa","volt per pascal"
-F87,4601911,"V/(l·min)","volt per litre minute"
-H22,4731442,"V/(lbf/in²)","volt square inch per pound-force"
-H23,4731443,"V/in","volt per inch"
-VLT,5655636,"V","volt"
-B78,4339512,"MV","megavolt"
-KVT,4937300,"kV","kilovolt"
-2Z,12890,"mV","millivolt"
-D82,4470834,"µV","microvolt"
-N99,5126457,"pV","picovolt"
-FAR,4604242,"F","farad"
-H48,4731960,"aF","attofarad"
-C10,4403504,"mF","millifarad"
-4O,13391,"µF","microfarad"
-C41,4404273,"nF","nanofarad"
-4T,13396,"pF","picofarad"
-N90,5126448,"kF","kilofarad"
-A69,4273721,"F/m","farad per metre"
-H28,4731448,"µF/km","microfarad per kilometre"
-H33,4731699,"F/km","farad per kilometre"
-B89,4339769,"µF/m","microfarad per metre"
-C42,4404274,"nF/m","nanofarad per metre"
-C72,4405042,"pF/m","picofarad per metre"
-A26,4272694,"C·m","coulomb metre"
-A41,4273201,"A/m²","ampere per square metre"
-H31,4731697,"A/kg","ampere per kilogram"
-B66,4339254,"MA/m²","megaampere per square metre"
-A7,16695,"A/mm²","ampere per square millimetre"
-A4,16692,"A/cm²","ampere per square centimetre"
-B23,4338227,"kA/m²","kiloampere per square metre"
-G59,4666681,"mA/(l·min)","milliampere per litre minute"
-N93,5126451,"A/Pa","ampere per pascal"
-F57,4601143,"mA/(lbf/in²)","milliampere per pound-force per square inch"
-F59,4601145,"mA/bar","milliampere per bar"
-AE,16709,"A/m","ampere per metre"
-B24,4338228,"kA/m","kiloampere per metre"
-A3,16691,"A/mm","ampere per millimetre"
-A2,16690,"A/cm","ampere per centimetre"
-F76,4601654,"mA/mm","milliampere per millimetre"
-F08,4599864,"mA/in","milliampere per inch"
-P10,5255472,"C/m","coulomb per metre"
-D33,4469555,"T","tesla"
-C29,4403769,"mT","millitesla"
-D81,4470833,"µT","microtesla"
-C48,4404280,"nT","nanotesla"
-P13,5255475,"kT","kilotesla"
-P12,5255474,"γ","gamma"
-WEB,5719362,"Wb","weber"
-C33,4404019,"mWb","milliweber"
-P11,5255473,"kWb","kiloweber"
-D59,4470073,"Wb/m","weber per metre"
-B56,4338998,"kWb/m","kiloweber per metre"
-D60,4470320,"Wb/mm","weber per millimetre"
-81,14385,"H","henry"
-C14,4403508,"mH","millihenry"
-B90,4340016,"µH","microhenry"
-C43,4404275,"nH","nanohenry"
-C73,4405043,"pH","picohenry"
-H03,4730931,"H/kΩ","henry per kiloohm"
-H04,4730932,"H/Ω","henry per ohm"
-G98,4667704,"µH/kΩ","microhenry per kiloohm"
-G99,4667705,"µH/Ω","microhenry per ohm"
-H05,4730933,"mH/kΩ","millihenry per kiloohm"
-H06,4730934,"mH/Ω","millihenry per ohm"
-P24,5255732,"kH","kilohenry"
-A98,4274488,"H/m","henry per metre"
-B91,4340017,"µH/m","microhenry per metre"
-C44,4404276,"nH/m","nanohenry per metre"
-A5,16693,"A·m²","ampere square metre"
-B8,16952,"J/m³","joule per cubic metre"
-OHM,5195853,"Ω","ohm"
-A87,4274231,"GΩ","gigaohm"
-B75,4339509,"MΩ","megaohm"
-H44,4731956,"TΩ","teraohm"
-B49,4338745,"kΩ","kiloohm"
-E45,4535349,"mΩ","milliohm"
-B94,4340020,"µΩ","microohm"
-P22,5255730,"nΩ","nanoohm"
-M26,5059126,"GΩ/m","gigaohm per metre"
-SIE,5458245,"S","siemens"
-B53,4338995,"kS","kilosiemens"
-C27,4403767,"mS","millisiemens"
-B99,4340025,"µS","microsiemens"
-G42,4666418,"µS/cm","microsiemens per centimetre"
-G43,4666419,"µS/m","microsiemens per metre"
-N92,5126450,"pS","picosiemens"
-NQ,20049,"mho","mho"
-NR,20050,"micromho","micromho"
-C61,4404785,"Ω·m","ohm metre"
-A88,4274232,"GΩ·m","gigaohm metre"
-B76,4339510,"MΩ·m","megaohm metre"
-H88,4732984,"MΩ·km","megaohm kilometre"
-B50,4338992,"kΩ·m","kiloohm metre"
-C60,4404784,"Ω·cm","ohm centimetre"
-C23,4403763,"mΩ·m","milliohm metre"
-B95,4340021,"µΩ·m","microohm metre"
-C46,4404278,"nΩ·m","nanoohm metre"
-M24,5059124,"Ω·km","ohm kilometre"
-P23,5255731,"Ω·cmil/ft","ohm circular-mil per foot"
-F56,4601142,"Ω/km","ohm per kilometre"
-H26,4731446,"Ω/m","ohm per metre"
-H37,4731703,"MΩ/m","megaohm per metre"
-F54,4601140,"mΩ/m","milliohm per metre"
-H36,4731702,"MΩ/km","megaohm per kilometre"
-F55,4601141,"Ω/mi","ohm per mile (statute mile)"
-D10,4469040,"S/m","siemens per metre"
-H43,4731955,"S/cm","siemens per centimetre"
-H61,4732465,"mS/cm","millisiemens per centimetre"
-B77,4339511,"MS/m","megasiemens per metre"
-B54,4338996,"kS/m","kilosiemens per metre"
-G45,4666421,"nS/m","nanosiemens per metre"
-G44,4666420,"nS/cm","nanosiemens per centimetre"
-L42,4994098,"pS/m","picosiemens per metre"
-C89,4405305,"H⁻¹","reciprocal henry"
-P14,5255476,"J/s","joule per second"
-D31,4469553,"TW","terawatt"
-P15,5255477,"J/min","joule per minute"
-P16,5255478,"J/h","joule per hour"
-P17,5255479,"J/d","joule per day"
-P18,5255480,"kJ/s","kilojoule per second"
-P19,5255481,"kJ/min","kilojoule per minute"
-P20,5255728,"kJ/h","kilojoule per hour"
-P21,5255729,"kJ/d","kilojoule per day"
-K43,4928563,"electric hp","horsepower (electric)"
-C49,4404281,"nW","nanowatt"
-C75,4405045,"pW","picowatt"
-D46,4469814,"V·A","volt - ampere"
-MVA,5068353,"MV·A","megavolt - ampere"
-KVA,4937281,"kV·A","kilovolt - ampere"
-M35,5059381,"mV·A","millivolt - ampere"
-D44,4469812,"var","var"
-K5,19253,"kvar","kilovolt ampere (reactive)"
-KVR,4937298,"kvar","kilovar"
-MAR,5062994,"kvar","megavar"
-N91,5126449,"1/J","reciprocal joule"
-M30,5059376,"1/(V·A·s)","reciprocal volt - ampere reciprocal second"
-M17,5058871,"kHz·m","kilohertz metre"
-M18,5058872,"GHz·m","gigahertz metre"
-M27,5059127,"MHz·m","megahertz metre"
-M21,5059121,"1/kVAh","reciprocal kilovolt - ampere reciprocal hour"
-H34,4731700,"Hz·m","hertz metre"
-H39,4731705,"MHz·km","megahertz kilometre"
-C84,4405300,"rad/m","radian per metre"
-JM,19021,"MJ/m³","megajoule per cubic metre"
-B14,4337972,"J/m⁴","joule per metre to the fourth power"
-B13,4337971,"J/m²","joule per square metre"
-D1,17457,"s⁻¹/sr","reciprocal second per steradian"
-D2,17458,"s⁻¹/(sr·m²)","reciprocal second per steradian metre squared"
-C99,4405561,"s⁻¹/m²","reciprocal second per metre squared"
-C93,4405555,"m⁻²","reciprocal square metre"
-H47,4731959,"W/m³","watt per cubic metre"
-H74,4732724,"W/m","watt per metre"
-E43,4535347,"J/cm²","joule per square centimetre"
-P37,5255991,"BtuIT/ft²","British thermal unit (international table) per square foot"
-P38,5255992,"Btuth/ft²","British thermal unit (thermochemical) per square foot"
-P39,5255993,"calth/cm²","calorie (thermochemical) per square centimetre"
-P40,5256240,"Ly","langley"
-D57,4470071,"W/sr","watt per steradian"
-D58,4470072,"W/(sr·m²)","watt per steradian square metre"
-D56,4470070,"W/(m²·K⁴)","watt per square metre kelvin to the fourth power"
-D18,4469048,"m·K","metre kelvin"
-CDL,4408396,"cd","candela"
-P33,5255987,"kcd","kilocandela"
-P34,5255988,"mcd","millicandela"
-P35,5255989,"HK","Hefner-Kerze"
-P36,5255990,"IK","international candle"
-LUM,5002573,"lm","lumen"
-B62,4339250,"lm·s","lumen second"
-B59,4339001,"lm·h","lumen hour"
-A24,4272692,"cd/m²","candela per square metre"
-P28,5255736,"cd/in²","candela per square inch"
-P29,5255737,"ftL","footlambert"
-P30,5255984,"Lb","lambert"
-P31,5255985,"sb","stilb"
-P32,5255986,"cd/ft²","candela per square foot"
-B60,4339248,"lm/m²","lumen per square metre"
-LUX,5002584,"lx","lux"
-KLX,4934744,"klx","kilolux"
-P25,5255733,"lm/ft²","lumen per square foot"
-P26,5255734,"ph","phot"
-P27,5255735,"ftc","footcandle"
-B64,4339252,"lx·s","lux second"
-B63,4339251,"lx·h","lux hour"
-B61,4339249,"lm/W","lumen per watt"
-D22,4469298,"m²/mol","square metre per mole"
-C59,4404537,"octave","octave"
-D9,17465,"dyn/cm²","dyne per square centimetre"
-A60,4273712,"erg/cm³","erg per cubic centimetre"
-C32,4404018,"mW/m²","milliwatt per square metre"
-D85,4470837,"µW/m²","microwatt per square metre"
-C76,4405046,"pW/m²","picowatt per square metre"
-A64,4273716,"erg/(s·cm²)","erg per second square centimetre"
-C67,4404791,"Pa· s/m","pascal second per metre"
-A50,4273456,"dyn·s/cm³","dyne second per cubic centimetre"
-C66,4404790,"Pa·s/m³","pascal second per cubic metre"
-A52,4273458,"dyn·s/cm⁵","dyne second per centimetre to the fifth power"
-M32,5059378,"Pa·s/l","pascal second per litre"
-C58,4404536,"N·s/m","newton second per metre"
-A51,4273457,"dyn·s/cm","dyne second per centimetre"
-P43,5256243,"B/m","bel per metre"
-H51,4732209,"dB/km","decibel per kilometre"
-H52,4732210,"dB/m","decibel per metre"
-C69,4404793,"phon","phon"
-D15,4469045,"sone","sone"
-P42,5256242,"Pa²·s","pascal squared second"
-P41,5256241,"dec","decade (logarithmic)"
-C34,4404020,"mol","mole"
-B45,4338741,"kmol","kilomole"
-C18,4403512,"mmol","millimole"
-FH,17992,"µmol","micromole"
-Z9,23097,"nmol","nanomole"
-P44,5256244,"lbmol","pound mole"
-C95,4405557,"mol⁻¹","reciprocal mole"
-D74,4470580,"kg/mol","kilogram per mole"
-A94,4274484,"g/mol","gram per mole"
-A40,4273200,"m³/mol","cubic metre per mole"
-A37,4272951,"dm³/mol","cubic decimetre per mole"
-A36,4272950,"cm³/mol","cubic centimetre per mole"
-B58,4339000,"l/mol","litre per mole"
-B15,4337973,"J/mol","joule per mole"
-B44,4338740,"kJ/mol","kilojoule per mole"
-B16,4337974,"J/(mol·K)","joule per mole kelvin"
-C86,4405302,"m⁻³","reciprocal cubic metre"
-H50,4732208,"cm⁻³","reciprocal cubic centimetre"
-L20,4993584,"1/mm³","reciprocal cubic millimetre"
-K20,4928048,"1/ft³","reciprocal cubic foot"
-K49,4928569,"1/in³","reciprocal cubic inch"
-K63,4929075,"1/l","reciprocal litre"
-M10,5058864,"1/yd³","reciprocal cubic yard"
-C36,4404022,"mol/m³","mole per cubic metre"
-C38,4404024,"mol/l","mole per litre"
-C35,4404021,"mol/dm³","mole per cubic decimetre"
-B46,4338742,"kmol/m³","kilomole per cubic metre"
-E95,4536629,"mol/s","mole per second"
-M33,5059379,"mmol/l","millimole per litre"
-P51,5256497,"(mol/kg)/Pa","mol per kilogram pascal"
-P52,5256498,"(mol/m³)/Pa","mol per cubic metre pascal"
-K59,4928825,"(kmol/m³)/K","kilomole per cubic metre kelvin"
-K60,4929072,"(kmol/m³)/bar","kilomole per cubic metre bar"
-K93,4929843,"1/psi","reciprocal psi"
-L24,4993588,"(mol/kg)/K","mole per kilogram kelvin"
-L25,4993589,"(mol/kg)/bar","mole per kilogram bar"
-L26,4993590,"(mol/l)/K","mole per litre kelvin"
-L27,4993591,"(mol/l)/bar","mole per litre bar"
-L28,4993592,"(mol/m³)/K","mole per cubic metre kelvin"
-L29,4993593,"(mol/m³)/bar","mole per cubic metre bar"
-C19,4403513,"mol/kg","mole per kilogram"
-D93,4471091,"s/m³","second per cubic metre"
-D87,4470839,"mmol/kg","millimole per kilogram"
-H68,4732472,"mmol/g","millimole per gram"
-P47,5256247,"kmol/kg","kilomole per kilogram"
-P48,5256248,"lbmol/lb","pound mole per pound"
-KAT,4931924,"kat","katal"
-E94,4536628,"kmol/s","kilomole per second"
-P45,5256245,"lbmol/s","pound mole per second"
-P46,5256246,"lbmol/h","pound mole per minute"
-D43,4469811,"u","unified atomic mass unit"
-A27,4272695,"C·m²/V","coulomb metre squared per volt"
-A32,4272946,"C/mol","coulomb per mole"
-D12,4469042,"S·m²/mol","siemens square metre per mole"
-K58,4928824,"kmol/h","kilomole per hour"
-K61,4929073,"kmol/min","kilomole per minute"
-L23,4993587,"mol/h","mole per hour"
-L30,4993840,"mol/min","mole per minute"
-C82,4405298,"rad·m²/mol","radian square metre per mole"
-C83,4405299,"rad·m²/kg","radian square metre per kilogram"
-P49,5256249,"N·m²/A","newton square metre per ampere"
-P50,5256496,"Wb·m","weber metre"
-Q30,5321520,"pH","pH (potential of Hydrogen)"
-B18,4337976,"J·s","joule second"
-A10,4272432,"A·m²/(J·s)","ampere square metre per joule second"
-CUR,4412754,"Ci","curie"
-MCU,5063509,"mCi","millicurie"
-M5,19765,"µCi","microcurie"
-2R,12882,"kCi","kilocurie"
-BQL,4346188,"Bq","becquerel"
-GBQ,4670033,"GBq","gigabecquerel"
-2Q,12881,"kBq","kilobecquerel"
-4N,13390,"MBq","megabecquerel"
-H08,4730936,"µBq","microbecquerel"
-A42,4273202,"Ci/kg","curie per kilogram"
-A18,4272440,"Bq/kg","becquerel per kilogram"
-B67,4339255,"MBq/kg","megabecquerel per kilogram"
-B25,4338229,"kBq/kg","kilobecquerel per kilogram"
-A19,4272441,"Bq/m³","becquerel per cubic metre"
-A14,4272436,"b","barn"
-D24,4469300,"m²/sr","square metre per steradian"
-A17,4272439,"b/sr","barn per steradian"
-D20,4469296,"m²/J","square metre per joule"
-A15,4272437,"b/eV","barn per electronvolt"
-D16,4469046,"cm²/erg","square centimetre per erg"
-D25,4469301,"m²/(sr·J)","square metre per steradian joule"
-A16,4272438,"b/(sr·eV)","barn per steradian electronvolt"
-D17,4469047,"cm²/(sr·erg)","square centimetre per steradian erg"
-B81,4339761,"m⁻²/s","reciprocal metre squared reciprocal second"
-A65,4273717,"erg/(cm²·s)","erg per square centimetre second"
-D21,4469297,"m²/kg","square metre per kilogram"
-B12,4337970,"J/m","joule per metre"
-A54,4273460,"eV/m","electronvolt per metre"
-A58,4273464,"erg/cm","erg per centimetre"
-D73,4470579,"J·m²","joule square metre"
-A55,4273461,"eV·m²","electronvolt square metre"
-A66,4273718,"erg·cm²","erg square centimetre"
-B20,4338224,"J·m²/kg","joule square metre per kilogram"
-A56,4273462,"eV·m²/kg","electronvolt square metre per kilogram"
-A67,4273719,"erg·cm²/g","erg square centimetre per gram"
-D26,4469302,"m²/(V·s)","square metre per volt second"
-H58,4732216,"m/(V·s)","metre per volt second"
-C87,4405303,"m⁻³/s","reciprocal cubic metre per second"
-A95,4274485,"Gy","gray"
-C13,4403507,"mGy","milligray"
-C80,4405296,"rad","rad"
-A61,4273713,"erg/g","erg per gram"
-D13,4469043,"Sv","sievert"
-C28,4403768,"mSv","millisievert"
-D91,4471089,"rem","rem"
-L31,4993841,"mrem","milliroentgen aequivalent men"
-A96,4274486,"Gy/s","gray per second"
-A62,4273714,"erg/g·s","erg per gram second"
-CKG,4410183,"C/kg","coulomb per kilogram"
-C8,17208,"mC/kg","millicoulomb per kilogram"
-2C,12867,"R","roentgen"
-2Y,12889,"mR","milliroentgen"
-J53,4863283,"C·m²/kg","coulomb square metre per kilogram"
-KR,19282,"kR","kiloroentgen"
-A31,4272945,"C/(kg·s)","coulomb per kilogram second"
-D6,17462,"R/s","roentgen per second"
-P54,5256500,"mGy/s","milligray per second"
-P55,5256501,"µGy/s","microgray per second"
-P56,5256502,"nGy/s","nanogray per second"
-P57,5256503,"Gy/min","gray per minute"
-P58,5256504,"mGy/min","milligray per minute"
-P59,5256505,"µGy/min","microgray per minute"
-P60,5256752,"nGy/min","nanogray per minute"
-P61,5256753,"Gy/h","gray per hour"
-P62,5256754,"mGy/h","milligray per hour"
-P63,5256755,"µGy/h","microgray per hour"
-P64,5256756,"nGy/h","nanogray per hour"
-P65,5256757,"Sv/s","sievert per second"
-P66,5256758,"mSv/s","millisievert per second"
-P67,5256759,"µSv/s","microsievert per second"
-P68,5256760,"nSv/s","nanosievert per second"
-P69,5256761,"rem/s","rem per second"
-P70,5257008,"Sv/h","sievert per hour"
-P71,5257009,"mSv/h","millisievert per hour"
-P72,5257010,"µSv/h","microsievert per hour"
-P73,5257011,"nSv/h","nanosievert per hour"
-P74,5257012,"Sv/min","sievert per minute"
-P75,5257013,"mSv/min","millisievert per minute"
-P76,5257014,"µSv/min","microsievert per minute"
-P77,5257015,"nSv/min","nanosievert per minute"
-P78,5257016,"1/in²","reciprocal square inch"
-P53,5256499,"unit pole","unit pole"
-C85,4405301,"Å⁻¹","reciprocal angstrom"
-D94,4471092,"s/(rad·m³)","second per cubic metre radian"
-C90,4405552,"J⁻¹/m³","reciprocal joule per cubic metre"
-C88,4405304,"eV⁻¹/m³","reciprocal electron volt per cubic metre"
-A38,4272952,"m³/C","cubic metre per coulomb"
-D48,4469816,"V/K","volt per kelvin"
-D49,4469817,"mV/K","millivolt per kelvin"
-A6,16694,"A/(m²·K²)","ampere per square metre kelvin squared"
-33,13107,"kPa·m²/g","kilopascal square metre per gram"
-P79,5257017,"Pa/(kg/m²)","pascal square metre per kilogram"
-34,13108,"kPa/mm","kilopascal per millimetre"
-H42,4731954,"Pa/m","pascal per metre"
-H69,4732473,"pPa/km","picopascal per kilometre"
-P80,5257264,"mPa/m","millipascal per metre"
-P81,5257265,"kPa/m","kilopascal per metre"
-P82,5257266,"hPa/m","hectopascal per metre"
-P83,5257267,"Atm/m","standard atmosphere per metre"
-P84,5257268,"at/m","technical atmosphere per metre"
-P85,5257269,"Torr/m","torr per metre"
-P86,5257270,"psi/in","psi per inch"
-35,13109,"ml/(cm²·s)","millilitre per square centimetre second"
-P87,5257271,"(m³/s)/m²","cubic metre per second square metre"
-OPM,5197901,"o/min","oscillations per minute"
-KNM,4935245,"KN/m2","kilonewton per square metre"
-Q35,5321525,"MW/min","megawatts per minute"
-10,12592,"group","group"
-11,12593,"outfit","outfit"
-13,12595,"ration","ration"
-14,12596,"shot","shot"
-15,12597,"stick, military","stick, military"
-20,12848,"twenty foot container","twenty foot container"
-21,12849,"forty foot container","forty foot container"
-24,12852,"theoretical pound","theoretical pound"
-27,12855,"theoretical ton","theoretical ton"
-38,13112,"oz/(ft²/cin)","ounce per square foot per 0,01inch"
-56,13622,"sitas","sitas"
-57,13623,"mesh","mesh"
-58,13624,"net kilogram","net kilogram"
-59,13625,"ppm","part per million"
-60,13872,"percent weight","percent weight"
-61,13873,"ppb","part per billion (US)"
-64,13876,"pound per square inch, gauge","pound per square inch, gauge"
-66,13878,"Oe","oersted"
-76,14134,"Gs","gauss"
-78,14136,"kGs","kilogauss"
-1I,12617,"fixed rate","fixed rate"
-2G,12871,"V","volt AC"
-2H,12872,"V","volt DC"
-2P,12880,"kbyte","kilobyte"
-3C,13123,"manmonth","manmonth"
-4L,13388,"Mbyte","megabyte"
-5B,13634,"batch","batch"
-5E,13637,"MMSCF/day","MMSCF/day"
-5J,13642,"hydraulic horse power","hydraulic horse power"
-A43,4273203,"dwt","deadweight tonnage"
-A47,4273207,"dtex (g/10km)","decitex"
-A49,4273209,"den (g/9 km)","denier (g/9 km)"
-A59,4273465,"8-part cloud cover","8-part cloud cover"
-A75,4273973,"freight ton","freight ton"
-A77,4273975,"Gaussian CGS (Centimetre-Gram-Second system) unit of displacement","Gaussian CGS (Centimetre-Gram-Second system) unit of displacement"
-A78,4273976,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric current","Gaussian CGS (Centimetre-Gram-Second system) unit of electric current"
-A79,4273977,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric charge","Gaussian CGS (Centimetre-Gram-Second system) unit of electric charge"
-A80,4274224,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric field strength","Gaussian CGS (Centimetre-Gram-Second system) unit of electric field strength"
-A81,4274225,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric polarization","Gaussian CGS (Centimetre-Gram-Second system) unit of electric polarization"
-A82,4274226,"Gaussian CGS (Centimetre-Gram-Second system) unit of electric potential","Gaussian CGS (Centimetre-Gram-Second system) unit of electric potential"
-A83,4274227,"Gaussian CGS (Centimetre-Gram-Second system) unit of magnetization","Gaussian CGS (Centimetre-Gram-Second system) unit of magnetization"
-A9,16697,"rate","rate"
-A99,4274489,"bit","bit"
-AA,16705,"ball","ball"
-AB,16706,"pk","bulk pack"
-ACT,4277076,"activity","activity"
-AD,16708,"byte","byte"
-AH,16712,"additional minute","additional minute"
-AI,16713,"average minute per call","average minute per call"
-AL,16716,"access line","access line"
-AQ,16721,"anti-hemophilic factor (AHF) unit","anti-hemophilic factor (AHF) unit"
-AS,16723,"assortment","assortment"
-ASM,4281165,"alcoholic strength by mass","alcoholic strength by mass"
-ASU,4281173,"alcoholic strength by volume","alcoholic strength by volume"
-AY,16729,"assembly","assembly"
-B1,16945,"barrel (US)/d","barrel (US) per day"
-B10,4337968,"bit/s","bit per second"
-B17,4337975,"credit","credit"
-B19,4337977,"digit","digit"
-B3,16947,"batting pound","batting pound"
-B30,4338480,"Gibit","gibibit"
-B4,16948,"barrel, imperial","barrel, imperial"
-B65,4339253,"Mx","maxwell"
-B68,4339256,"Gbit","gigabit"
-B7,16951,"cycle","cycle"
-B80,4339760,"Gbit/s","gigabit per second"
-B82,4339762,"inch per linear foot","inch per linear foot"
-BB,16962,"base box","base box"
-BFT,4343380,"fbm","board foot"
-BIL,4344140,"billion (EUR)","billion (EUR)"
-BP,16976,"hundred board foot","hundred board foot"
-BPM,4345933,"BPM","beats per minute"
-C0,17200,"call","call"
-C21,4403761,"Kibit","kibibit"
-C37,4404023,"kbit","kilobit"
-C74,4405044,"kbit/s","kilobit per second"
-C79,4405049,"kVAh","kilovolt ampere hour"
-C9,17209,"coil group","coil group"
-CCT,4408148,"carrying capacity in metric ton","carrying capacity in metric ton"
-CEN,4408654,"hundred","hundred"
-CG,17223,"card","card"
-CLF,4410438,"hundred leave","hundred leave"
-CNP,4410960,"hundred pack","hundred pack"
-CNT,4410964,"cental (UK)","cental (UK)"
-CTG,4412487,"content gram","content gram"
-CTM,4412493,"metric carat","metric carat"
-CTN,4412494,"content ton (metric)","content ton (metric)"
-D03,4468787,"kW·h/h","kilowatt hour per hour"
-D04,4468788,"lot [unit of weight]","lot [unit of weight]"
-D11,4469041,"Mibit","mebibit"
-D23,4469299,"pen gram (protein)","pen gram (protein)"
-D34,4469556,"tex (g/km)","tex"
-D36,4469558,"Mbit","megabit"
-D63,4470323,"book","book"
-D65,4470325,"round","round"
-D68,4470328,"number of words","number of words"
-D78,4470584,"MJ/s","megajoule per second"
-DAD,4473156,"ten day","ten day"
-DB,17474,"dry pound","dry pound"
-DEC,4474179,"decade","decade"
-DMO,4476239,"standard kilolitre","standard kilolitre"
-DPC,4476995,"dozen piece","dozen piece"
-DPR,4477010,"dozen pair","dozen pair"
-DPT,4477012,"displacement tonnage","displacement tonnage"
-DRA,4477505,"dram (US)","dram (US)"
-DRI,4477513,"dram (UK)","dram (UK)"
-DRL,4477516,"dozen roll","dozen roll"
-DT,17492,"dry ton","dry ton"
-DWT,4478804,"pennyweight","pennyweight"
-DZN,4479566,"DOZ","dozen"
-DZP,4479568,"dozen pack","dozen pack"
-E07,4534327,"MW·h/h","megawatt hour per hour"
-E08,4534328,"MW/Hz","megawatt per hertz"
-E10,4534576,"deg da","degree day"
-E11,4534577,"gigacalorie","gigacalorie"
-E12,4534578,"mille","mille"
-E16,4534582,"BtuIT/h","million Btu(IT) per hour"
-E17,4534583,"ft³/s","cubic foot per second"
-E19,4534585,"ping","ping"
-E20,4534832,"Mbit/s","megabit per second"
-E21,4534833,"shares","shares"
-E22,4534834,"TEU","TEU"
-E23,4534835,"tyre","tyre"
-E25,4534837,"active unit","active unit"
-E27,4534839,"dose","dose"
-E28,4534840,"air dry ton","air dry ton"
-E30,4535088,"strand","strand"
-E31,4535089,"m²/l","square metre per litre"
-E32,4535090,"l/h","litre per hour"
-E33,4535091,"foot per thousand","foot per thousand"
-E34,4535092,"Gbyte","gigabyte"
-E35,4535093,"Tbyte","terabyte"
-E36,4535094,"Pbyte","petabyte"
-E37,4535095,"pixel","pixel"
-E38,4535096,"megapixel","megapixel"
-E39,4535097,"dpi","dots per inch"
-E4,17716,"gross kilogram","gross kilogram"
-E40,4535344,"ppht","part per hundred thousand"
-E44,4535348,"kgf·m/cm²","kilogram-force metre per square centimetre"
-E46,4535350,"kW·h/m³","kilowatt hour per cubic metre"
-E47,4535351,"kW·h/K","kilowatt hour per kelvin"
-E48,4535352,"service unit","service unit"
-E49,4535353,"working day","working day"
-E50,4535600,"accounting unit","accounting unit"
-E51,4535601,"job","job"
-E52,4535602,"run foot","run foot"
-E53,4535603,"test","test"
-E54,4535604,"trip","trip"
-E55,4535605,"use","use"
-E56,4535606,"well","well"
-E57,4535607,"zone","zone"
-E58,4535608,"Ebit/s","exabit per second"
-E59,4535609,"Eibyte","exbibyte"
-E60,4535856,"Pibyte","pebibyte"
-E61,4535857,"Tibyte","tebibyte"
-E62,4535858,"Gibyte","gibibyte"
-E63,4535859,"Mibyte","mebibyte"
-E64,4535860,"Kibyte","kibibyte"
-E65,4535861,"Eibit/m","exbibit per metre"
-E66,4535862,"Eibit/m²","exbibit per square metre"
-E67,4535863,"Eibit/m³","exbibit per cubic metre"
-E68,4535864,"Gbyte/s","gigabyte per second"
-E69,4535865,"Gibit/m","gibibit per metre"
-E70,4536112,"Gibit/m²","gibibit per square metre"
-E71,4536113,"Gibit/m³","gibibit per cubic metre"
-E72,4536114,"Kibit/m","kibibit per metre"
-E73,4536115,"Kibit/m²","kibibit per square metre"
-E74,4536116,"Kibit/m³","kibibit per cubic metre"
-E75,4536117,"Mibit/m","mebibit per metre"
-E76,4536118,"Mibit/m²","mebibit per square metre"
-E77,4536119,"Mibit/m³","mebibit per cubic metre"
-E78,4536120,"Pbit","petabit"
-E79,4536121,"Pbit/s","petabit per second"
-E80,4536368,"Pibit/m","pebibit per metre"
-E81,4536369,"Pibit/m²","pebibit per square metre"
-E82,4536370,"Pibit/m³","pebibit per cubic metre"
-E83,4536371,"Tbit","terabit"
-E84,4536372,"Tbit/s","terabit per second"
-E85,4536373,"Tibit/m","tebibit per metre"
-E86,4536374,"Tibit/m³","tebibit per cubic metre"
-E87,4536375,"Tibit/m²","tebibit per square metre"
-E88,4536376,"bit/m","bit per metre"
-E89,4536377,"bit/m²","bit per square metre"
-E90,4536624,"cm⁻¹","reciprocal centimetre"
-E91,4536625,"d⁻¹","reciprocal day"
-EA,17729,"each","each"
-EB,17730,"electronic mail box","electronic mail box"
-EQ,17745,"equivalent gallon","equivalent gallon"
-F01,4599857,"bit/m³","bit per cubic metre"
-FBM,4604493,"fibre metre","fibre metre"
-FC,17987,"kft³","thousand cubic foot"
-FF,17990,"hundred cubic metre","hundred cubic metre"
-FIT,4606292,"FIT","failures in time"
-FL,17996,"flake ton","flake ton"
-GB,18242,"gal (US)/d","gallon (US) per day"
-GDW,4670551,"gram, dry weight","gram, dry weight"
-GFI,4671049,"gi F/S","gram of fissile isotope"
-GGR,4671314,"great gross","great gross"
-GIA,4671809,"gi (US)","gill (US)"
-GIC,4671811,"gram, including container","gram, including container"
-GII,4671817,"gi (UK)","gill (UK)"
-GIP,4671824,"gram, including inner packaging","gram, including inner packaging"
-GRO,4674127,"gr","gross"
-GRT,4674132,"gross register ton","gross register ton"
-GT,18260,"gross ton","gross ton"
-H21,4731441,"blank","blank"
-H25,4731445,"%/K","percent per kelvin"
-H71,4732721,"%/mo","percent per month"
-H72,4732722,"%/hbar","percent per hectobar"
-H73,4732723,"%/daK","percent per decakelvin"
-H77,4732727,"MW","module width"
-H80,4732976,"U or RU","rack unit"
-H82,4732978,"bp","big point"
-H87,4732983,"piece","piece"
-H89,4732985,"%/Ω","percent per ohm"
-H90,4733232,"%/°","percent per degree"
-H91,4733233,"%/10000","percent per ten thousand"
-H92,4733234,"%/100000","percent per one hundred thousand"
-H93,4733235,"%/100","percent per hundred"
-H94,4733236,"%/1000","percent per thousand"
-H95,4733237,"%/V","percent per volt"
-H96,4733238,"%/bar","percent per bar"
-H98,4733240,"%/in","percent per inch"
-H99,4733241,"%/m","percent per metre"
-HA,18497,"hank","hank"
-HBX,4735576,"hundred boxes","hundred boxes"
-HC,18499,"hundred count","hundred count"
-HDW,4736087,"hundred kilogram, dry weight","hundred kilogram, dry weight"
-HEA,4736321,"head","head"
-HH,18504,"hundred cubic foot","hundred cubic foot"
-HIU,4737365,"hundred international unit","hundred international unit"
-HKM,4737869,"hundred kilogram, net mass","hundred kilogram, net mass"
-HMQ,4738385,"Mm³","million cubic metre"
-HPA,4739137,"hectolitre of pure alcohol","hectolitre of pure alcohol"
-IE,18757,"person","person"
-ISD,4805444,"international sugar degree","international sugar degree"
-IUG,4805959,"international unit per gram","international unit per gram"
-J10,4862256,"%/mm","percent per millimetre"
-J12,4862258,"‰/psi","per mille per psi"
-J13,4862259,"°API","degree API"
-J14,4862260,"°Bé","degree Baume (origin scale)"
-J15,4862261,"°Bé (US heavy)","degree Baume (US heavy)"
-J16,4862262,"°Bé (US light)","degree Baume (US light)"
-J17,4862263,"°Balling","degree Balling"
-J18,4862264,"°Bx","degree Brix"
-J27,4862519,"°Oechsle","degree Oechsle"
-J31,4862769,"°Tw","degree Twaddell"
-J38,4862776,"Bd","baud"
-J54,4863284,"MBd","megabaud"
-JNT,4869716,"pipeline joint","pipeline joint"
-JPS,4870227,"hundred metre","hundred metre"
-JWL,4872012,"number of jewels","number of jewels"
-K1,19249,"kilowatt demand","kilowatt demand"
-K2,19250,"kilovolt ampere reactive demand","kilovolt ampere reactive demand"
-K3,19251,"kvar·h","kilovolt ampere reactive hour"
-K50,4928816,"kBd","kilobaud"
-KA,19265,"cake","cake"
-KB,19266,"kilocharacter","kilocharacter"
-KCC,4932419,"kg C₅ H₁₄ClNO","kilogram of choline chloride"
-KDW,4932695,"kg/net eda","kilogram drained net weight"
-KHY,4933721,"kg H₂O₂","kilogram of hydrogen peroxide"
-KI,19273,"kilogram per millimetre width","kilogram per millimetre width"
-KIC,4933955,"kilogram, including container","kilogram, including container"
-KIP,4933968,"kilogram, including inner packaging","kilogram, including inner packaging"
-KJ,19274,"kilosegment","kilosegment"
-KLK,4934731,"lactic dry material percentage","lactic dry material percentage"
-KMA,4934977,"kg met.am.","kilogram of methylamine"
-KNI,4935241,"kg N","kilogram of nitrogen"
-KNS,4935251,"kilogram named substance","kilogram named substance"
-KO,19279,"milliequivalence caustic potash per gram of product","milliequivalence caustic potash per gram of product"
-KPH,4935752,"kg KOH","kilogram of potassium hydroxide (caustic potash)"
-KPO,4935759,"kg K₂O","kilogram of potassium oxide"
-KPP,4935760,"kilogram of phosphorus pentoxide (phosphoric anhydride)","kilogram of phosphorus pentoxide (phosphoric anhydride)"
-KSD,4936516,"kg 90 % sdt","kilogram of substance 90 % dry"
-KSH,4936520,"kg NaOH","kilogram of sodium hydroxide (caustic soda)"
-KT,19284,"kit","kit"
-KUR,4937042,"kg U","kilogram of uranium"
-KWY,4937561,"kW/year","kilowatt year"
-KWO,4937551,"kg WO₃","kilogram of tungsten trioxide"
-LAC,4997443,"lactose excess percentage","lactose excess percentage"
-LBT,4997716,"troy pound (US)","troy pound (US)"
-LEF,4998470,"leaf","leaf"
-LF,19526,"linear foot","linear foot"
-LH,19528,"labour hour","labour hour"
-LK,19531,"link","link"
-LM,19533,"linear metre","linear metre"
-LN,19534,"length","length"
-LO,19535,"lot [unit of procurement]","lot [unit of procurement]"
-LP,19536,"liquid pound","liquid pound"
-LPA,5001281,"litre of pure alcohol","litre of pure alcohol"
-LR,19538,"layer","layer"
-LS,19539,"lump sum","lump sum"
-LUB,5002562,"metric ton, lubricating oil","metric ton, lubricating oil"
-LY,19545,"linear yard","linear yard"
-M19,5058873,"Bft","Beaufort"
-M25,5059125,"%/°C","percent per degree Celsius"
-M36,5059382,"mo (30 days)","30-day month"
-M37,5059383,"y (360 days)","actual/360"
-M4,19764,"monetary value","monetary value"
-M9,19769,"MBTU/kft³","million Btu per 1000 cubic foot"
-MAH,5062984,"Mvar·h","megavolt ampere reactive hour"
-MBE,5063237,"thousand standard brick equivalent","thousand standard brick equivalent"
-MBF,5063238,"thousand board foot","thousand board foot"
-MD,19780,"air dry metric ton","air dry metric ton"
-MIL,5065036,"thousand","thousand"
-MIO,5065039,"million","million"
-MIU,5065045,"million international unit","million international unit"
-MLD,5065796,"milliard","milliard"
-MND,5066308,"kilogram, dry weight","kilogram, dry weight"
-N1,20017,"pen calorie","pen calorie"
-N3,20019,"print point","print point"
-NAR,5128530,"number of articles","number of articles"
-NCL,5129036,"number of cells","number of cells"
-NF,20038,"message","message"
-NIL,5130572,"()","nil"
-NIU,5130581,"number of international units","number of international units"
-NL,20044,"load","load"
-NMP,5131600,"number of packs","number of packs"
-NPR,5132370,"number of pairs","number of pairs"
-NPT,5132372,"number of parts","number of parts"
-NT,20052,"net ton","net ton"
-NTT,5133396,"net register ton","net register ton"
-NX,20056,"‰","part per thousand"
-OA,20289,"panel","panel"
-ODE,5194821,"ozone depletion equivalent","ozone depletion equivalent"
-ODG,5194823,"ODS Grams","ODS Grams"
-ODK,5194827,"ODS Kilograms","ODS Kilograms"
-ODM,5194829,"ODS Milligrams","ODS Milligrams"
-OT,20308,"overtime hour","overtime hour"
-OZ,20314,"ounce av","ounce av"
-P1,20529,"%","percent"
-P5,20533,"five pack","five pack"
-P88,5257272,"rhe","rhe"
-P89,5257273,"lbf·ft/in","pound-force foot per inch"
-P90,5257520,"lbf·in/in","pound-force inch per inch"
-P91,5257521,"perm (0 ºC)","perm (0 ºC)"
-P92,5257522,"perm (23 ºC)","perm (23 ºC)"
-P93,5257523,"byte/s","byte per second"
-P94,5257524,"kbyte/s","kilobyte per second"
-P95,5257525,"Mbyte/s","megabyte per second"
-P96,5257526,"1/V","reciprocal volt"
-P97,5257527,"1/rad","reciprocal radian"
-P98,5257528,"PaΣνB","pascal to the power sum of stoichiometric numbers"
-P99,5257529,"(mol/m³)∑νB","mole per cubiv metre to the power sum of stoichiometric numbers"
-PD,20548,"pad","pad"
-PFL,5260876,"proof litre","proof litre"
-PGL,5261132,"proof gallon","proof gallon"
-PI,20553,"pitch","pitch"
-PLA,5262401,"°P","degree Plato"
-PQ,20561,"ppi","page per inch"
-PR,20562,"pair","pair"
-PTN,5264462,"PTN","portion"
-Q10,5321008,"J/T","joule per tesla"
-Q11,5321009,"E","erlang"
-Q12,5321010,"o","octet"
-Q13,5321011,"o/s","octet per second"
-Q14,5321012,"Sh","shannon"
-Q15,5321013,"Hart","hartley"
-Q16,5321014,"nat","natural unit of information"
-Q17,5321015,"Sh/s","shannon per second"
-Q18,5321016,"Hart/s","hartley per second"
-Q19,5321017,"nat/s","natural unit of information per second"
-Q20,5321264,"s/kg","second per kilogramm"
-Q21,5321265,"W·m²","watt square metre"
-Q22,5321266,"1/(Hz·rad·m³)","second per radian cubic metre"
-Q23,5321267,"1/Wb","weber to the power minus one"
-Q24,5321268,"1/in","reciprocal inch"
-Q25,5321269,"dpt","dioptre"
-Q26,5321270,"1/1","one per one"
-Q27,5321271,"N·m/m²","newton metre per metre"
-Q28,5321272,"kg/(m²·Pa·s)","kilogram per square metre pascal second"
-Q36,5321526,"m2/m3","square metre per cubic metre"
-Q3,20787,"meal","meal"
-QA,20801,"page - facsimile","page - facsimile"
-QAN,5325134,"quarter (of a year)","quarter (of a year)"
-QB,20802,"page - hardcopy","page - hardcopy"
-QR,20818,"qr","quire"
-QTR,5330002,"Qr (UK)","quarter (UK)"
-R1,21041,"pica","pica"
-R9,21049,"thousand cubic metre","thousand cubic metre"
-RH,21064,"running or operating hour","running or operating hour"
-RM,21069,"ream","ream"
-ROM,5394253,"room","room"
-RP,21072,"pound per ream","pound per ream"
-RT,21076,"revenue ton mile","revenue ton mile"
-SAN,5456206,"half year (6 months)","half year (6 months)"
-SCO,5456719,"score","score"
-SCR,5456722,"scruple","scruple"
-SET,5457236,"set","set"
-SG,21319,"segment","segment"
-SHT,5458004,"shipping ton","shipping ton"
-SQ,21329,"square","square"
-SQR,5460306,"square, roofing","square, roofing"
-SR,21330,"strip","strip"
-STC,5461059,"stick","stick"
-STK,5461067,"stick, cigarette","stick, cigarette"
-STL,5461068,"standard litre","standard litre"
-STW,5461079,"straw","straw"
-SW,21335,"skein","skein"
-SX,21336,"shipment","shipment"
-SYR,5462354,"syringe","syringe"
-T0,21552,"telecommunication line in service","telecommunication line in service"
-T3,21555,"thousand piece","thousand piece"
-TAN,5521742,"TAN","total acid number"
-TI,21577,"thousand square inch","thousand square inch"
-TIC,5523779,"metric ton, including container","metric ton, including container"
-TIP,5523792,"metric ton, including inner packaging","metric ton, including inner packaging"
-TKM,5524301,"t·km","tonne kilometre"
-TMS,5524819,"kilogram of imported meat, less offal","kilogram of imported meat, less offal"
-TP,21584,"ten pack","ten pack"
-TPI,5525577,"TPI","teeth per inch"
-TPR,5525586,"ten pair","ten pair"
-TQD,5525828,"km³/d","thousand cubic metre per day"
-TRL,5526092,"trillion (EUR)","trillion (EUR)"
-TST,5526356,"ten set","ten set"
-TTS,5526611,"ten thousand sticks","ten thousand sticks"
-U1,21809,"treatment","treatment"
-U2,21810,"tablet","tablet"
-UB,21826,"telecommunication line in service average","telecommunication line in service average"
-UC,21827,"telecommunication port","telecommunication port"
-VA,22081,"V·A / kg","volt - ampere per kilogram"
-VP,22096,"percent volume","percent volume"
-W2,22322,"wet kilo","wet kilo"
-WA,22337,"W/kg","watt per kilogram"
-WB,22338,"wet pound","wet pound"
-WCD,5718852,"cord","cord"
-WE,22341,"wet ton","wet ton"
-WG,22343,"wine gallon","wine gallon"
-WM,22349,"working month","working month"
-WSD,5722948,"std","standard"
-WW,22359,"millilitre of water","millilitre of water"
-Z11,5910833,"hanging container","hanging container"
-ZP,23120,"page","page"
-ZZ,23130,"mutually defined","mutually defined"
-MRW,5067351,"m·wk","Metre Week"
-MKW,5065559,"m²· wk","Square Metre Week"
-MQW,5067095,"m³·wk","Cubic Metre Week"
-HWE,4740933,"piece·k","Piece Week"
-MRD,5067332,"m·day","Metre Day"
-MKD,5065540,"m²·d","Square Metre Day"
-MQD,5067076,"m³·d","Cubic Metre Day"
-HAD,4735300,"piece·d","Piece Day"
-MRM,5067341,"m·mo","Metre Month"
-MKM,5065549,"m²·mo","Square Metre Month"
-MQM,5067085,"m³·mo","Cubic Metre Month"
-HMO,4738383,"piece·mo","Piece Month"
-DBW,4473431,"dBW","Decibel watt"
-DBM,4473421,"dBm","Decibel-milliwatts"
-FNU,4607573,"FNU","Formazin nephelometric unit"
-NTU,5133397,"NTU","Nephelometric turbidity unit"
diff --git a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodesetModelExportOpc.cs b/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodesetModelExportOpc.cs
deleted file mode 100644
index 8da32895..00000000
--- a/CESMII.OpcUa.NodeSetModel.Factory.Opc/NodesetModelExportOpc.cs
+++ /dev/null
@@ -1,1086 +0,0 @@
-using Opc.Ua;
-using ua = Opc.Ua;
-using uaExport = Opc.Ua.Export;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using CESMII.OpcUa.NodeSetModel.Opc.Extensions;
-using Opc.Ua.Export;
-using CESMII.OpcUa.NodeSetModel.Factory.Opc;
-using System.Xml;
-using System.Globalization;
-using Newtonsoft.Json;
-
-namespace CESMII.OpcUa.NodeSetModel.Export.Opc
-{
-
- public class NodeModelExportOpc : NodeModelExportOpc
- {
-
- }
- public class NodeModelExportOpc where T : NodeModel, new()
- {
- protected T _model;
-
- public static (UANode ExportedNode, List AdditionalNodes, bool Created) GetUANode(NodeModel model, ExportContext context)
- {
- if (model is InterfaceModel uaInterface)
- {
- return new InterfaceModelExportOpc { _model = uaInterface }.GetUANode(context);
- }
- else if (model is ObjectTypeModel objectType)
- {
- return new ObjectTypeModelExportOpc { _model = objectType, }.GetUANode(context);
- }
- else if (model is VariableTypeModel variableType)
- {
- return new VariableTypeModelExportOpc { _model = variableType, }.GetUANode(context);
- }
- else if (model is DataTypeModel dataType)
- {
- return new DataTypeModelExportOpc { _model = dataType, }.GetUANode(context);
- }
- else if (model is DataVariableModel dataVariable)
- {
- return new DataVariableModelExportOpc { _model = dataVariable, }.GetUANode(context);
- }
- else if (model is PropertyModel property)
- {
- return new PropertyModelExportOpc { _model = property, }.GetUANode(context);
- }
- else if (model is ObjectModel uaObject)
- {
- return new ObjectModelExportOpc { _model = uaObject, }.GetUANode(context);
- }
- else if (model is MethodModel uaMethod)
- {
- return new MethodModelExportOpc { _model = uaMethod, }.GetUANode(context);
- }
- else if (model is ReferenceTypeModel referenceType)
- {
- return new ReferenceTypeModelExportOpc { _model = referenceType, }.GetUANode(context);
- }
- throw new Exception($"Unexpected node model {model.GetType()}");
- }
-
- public virtual (TUANode ExportedNode, List AdditionalNodes, bool Created) GetUANode(ExportContext context) where TUANode : UANode, new()
- {
- var nodeIdForExport = GetNodeIdForExport(_model.NodeId, context);
- if (context._exportedSoFar.TryGetValue(nodeIdForExport, out var existingNode))
- {
- return ((TUANode)existingNode, null, false);
- }
- var node = new TUANode
- {
- Description = _model.Description?.ToExport()?.ToArray(),
- BrowseName = GetBrowseNameForExport(context.NamespaceUris),
- SymbolicName = _model.SymbolicName,
- DisplayName = _model.DisplayName?.ToExport()?.ToArray(),
- NodeId = nodeIdForExport,
- Documentation = _model.Documentation,
- Category = _model.Categories?.ToArray(),
- };
- context._exportedSoFar.Add(nodeIdForExport, node);
- if (!string.IsNullOrEmpty(_model.ReleaseStatus))
- {
- if (Enum.TryParse(_model.ReleaseStatus, out var releaseStatus))
- {
- node.ReleaseStatus = releaseStatus;
- }
- else
- {
- throw new Exception($"Invalid release status '{_model.ReleaseStatus}' on {_model}");
- }
- }
-
- var references = new List();
- foreach (var property in _model.Properties)
- {
- if (_model is DataTypeModel &&
- (property.BrowseName.EndsWith(BrowseNames.EnumValues)
- || property.BrowseName.EndsWith(BrowseNames.EnumStrings)
- || property.BrowseName.EndsWith(BrowseNames.OptionSetValues)))
- {
- // Property will get generated during data type export
- continue;
- }
- context.NamespaceUris.GetIndexOrAppend(property.Namespace);
- var referenceTypeId = context.GetModelNodeId(ReferenceTypeIds.HasProperty);
- if (GetOtherReferenceWithDerivedReferenceType(property, referenceTypeId) == null)
- {
- references.Add(new Reference
- {
- ReferenceType = GetNodeIdForExport(ReferenceTypeIds.HasProperty, context),
- Value = GetNodeIdForExport(property.NodeId, context),
- });
- }
- }
- foreach (var uaObject in this._model.Objects)
- {
- context.NamespaceUris.GetIndexOrAppend(uaObject.Namespace);
- var referenceTypeId = context.GetModelNodeId(ReferenceTypeIds.HasComponent);
- if (GetOtherReferenceWithDerivedReferenceType(uaObject, referenceTypeId) == null)
- {
- // Only add if not also covered in OtherReferencedNodes (will be added later)
- references.Add(new Reference
- {
- ReferenceType = GetNodeIdForExport(referenceTypeId, context),
- Value = GetNodeIdForExport(uaObject.NodeId, context),
- });
- }
- }
- foreach (var nodeRef in this._model.OtherReferencedNodes)
- {
- context.NamespaceUris.GetIndexOrAppend(nodeRef.Node.Namespace);
- context.NamespaceUris.GetIndexOrAppend(NodeModelUtils.GetNamespaceFromNodeId(nodeRef.ReferenceType?.NodeId));
-
- references.Add(new Reference
- {
- ReferenceType = GetNodeIdForExport(nodeRef.ReferenceType?.NodeId, context),
- Value = GetNodeIdForExport(nodeRef.Node.NodeId, context),
- });
- }
- foreach (var inverseNodeRef in this._model.OtherReferencingNodes)
- {
- context.NamespaceUris.GetIndexOrAppend(inverseNodeRef.Node.Namespace);
- context.NamespaceUris.GetIndexOrAppend(NodeModelUtils.GetNamespaceFromNodeId(inverseNodeRef.ReferenceType?.NodeId));
-
- var inverseRef = new Reference
- {
- ReferenceType = GetNodeIdForExport(inverseNodeRef.ReferenceType?.NodeId, context),
- Value = GetNodeIdForExport(inverseNodeRef.Node.NodeId, context),
- IsForward = false,
- };
- if (!references.Any(r => r.IsForward == false && r.ReferenceType == inverseRef.ReferenceType && r.Value == inverseRef.Value))
- {
- // TODO ensure we pick the most derived reference type
- references.Add(inverseRef);
- }
- }
- foreach (var uaInterface in this._model.Interfaces)
- {
- context.NamespaceUris.GetIndexOrAppend(uaInterface.Namespace);
- var referenceTypeId = context.GetModelNodeId(ReferenceTypeIds.HasInterface);
- if (GetOtherReferenceWithDerivedReferenceType(uaInterface, referenceTypeId) == null)
- {
- references.Add(new Reference
- {
- ReferenceType = GetNodeIdForExport(referenceTypeId, context),
- Value = GetNodeIdForExport(uaInterface.NodeId, context),
- });
- }
- }
- foreach (var method in this._model.Methods)
- {
- context.NamespaceUris.GetIndexOrAppend(method.Namespace);
-
- var referenceTypeId = context.GetModelNodeId(ReferenceTypeIds.HasComponent);
- if (GetOtherReferenceWithDerivedReferenceType(method, referenceTypeId) == null)
- {
- references.Add(new Reference
- {
- ReferenceType = GetNodeIdForExport(referenceTypeId, context),
- Value = GetNodeIdForExport(method.NodeId, context),
- });
- }
- }
- foreach (var uaEvent in this._model.Events)
- {
- context.NamespaceUris.GetIndexOrAppend(uaEvent.Namespace);
- var referenceTypeId = context.GetModelNodeId(ReferenceTypeIds.GeneratesEvent);
- if (GetOtherReferenceWithDerivedReferenceType(uaEvent, referenceTypeId) == null)
- {
- references.Add(new Reference
- {
- ReferenceType = GetNodeIdForExport(referenceTypeId, context),
- Value = GetNodeIdForExport(uaEvent.NodeId, context),
- });
- }
- }
- foreach (var variable in this._model.DataVariables)
- {
- context.NamespaceUris.GetIndexOrAppend(variable.Namespace);
- var referenceTypeId = context.GetModelNodeId(ReferenceTypeIds.HasComponent);
- if (GetOtherReferenceWithDerivedReferenceType(variable, referenceTypeId) == null)
- {
- references.Add(new Reference
- {
- ReferenceType = GetNodeIdForExport(referenceTypeId, context),
- Value = GetNodeIdForExport(variable.NodeId, context),
- });
- }
- }
- if (references.Any())
- {
- node.References = references.ToArray();
- }
- return (node, null, true);
- }
-
- protected string GetOtherReferenceWithDerivedReferenceType(NodeModel uaNode, string referenceTypeModelId)
- {
- return GetOtherReferenceWithDerivedReferenceType(_model, uaNode, referenceTypeModelId);
- }
-
- static protected string GetOtherReferenceWithDerivedReferenceType(NodeModel parentModel, NodeModel uaNode, string referenceTypeModelId)
- {
- var otherReferences = parentModel.OtherReferencedNodes.Where(nr => nr.Node == uaNode).ToList();
- var otherMatchingReference = otherReferences.FirstOrDefault(r => (r.ReferenceType as ReferenceTypeModel).SuperType == null || (r.ReferenceType as ReferenceTypeModel)?.HasBaseType(referenceTypeModelId) == true);
- if (otherMatchingReference != null && otherMatchingReference.ReferenceType.NodeId != referenceTypeModelId)
- {
- return otherMatchingReference.ReferenceType.NodeId;
- }
- return null;
- }
-
- protected string GetNodeIdForExport(NodeId nodeId, ExportContext context, bool applyAlias = true)
- {
- if (nodeId == null) return null;
- var nodeIdStr = nodeId.ToString();
-
- context._nodeIdsUsed?.Add(nodeIdStr);
-
- if (applyAlias && context.Aliases?.TryGetValue(nodeIdStr, out var alias) == true)
- {
- return alias;
- }
- return ExpandedNodeId.ToNodeId(nodeId, context.NamespaceUris).ToString();
- }
- protected string GetNodeIdForExport(string nodeId, ExportContext context, bool applyAlias = true)
- {
- if (nodeId == null) { return null; }
- NodeId parsedNodeId = GetNodeIdFromString(nodeId, context);
- return GetNodeIdForExport(parsedNodeId, context);
- }
-
- private NodeId GetNodeIdFromString(string nodeId, ExportContext context)
- {
- if (nodeId == null) return null;
- NodeId parsedNodeId;
- try
- {
- parsedNodeId = ExpandedNodeId.Parse(nodeId, context.NamespaceUris);
- }
- catch (ServiceResultException)
- {
- // try again after adding namespace to the namespace table
- var nameSpace = NodeModelUtils.GetNamespaceFromNodeId(nodeId);
- context.NamespaceUris.GetIndexOrAppend(nameSpace);
- parsedNodeId = ExpandedNodeId.Parse(nodeId, context.NamespaceUris);
- }
- if (string.IsNullOrEmpty(context.NamespaceUris.GetString(parsedNodeId.NamespaceIndex)))
- {
- throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "Namespace Uri for Node id ({0}) not specified or not found in the namespace table. Node Ids should be specified in nsu= format.", nodeId);
- }
- return parsedNodeId;
- }
-
- protected string GetBrowseNameForExport(NamespaceTable namespaces)
- {
- return GetQualifiedNameForExport(_model.BrowseName, _model.Namespace, _model.DisplayName, namespaces);
- }
-
- protected static string GetQualifiedNameForExport(string qualifiedName, string fallbackNamespace, List displayName, NamespaceTable namespaces)
- {
- string qualifiedNameForExport;
- if (qualifiedName != null)
- {
- var parts = qualifiedName.Split(new[] { ';' }, 2);
- if (parts.Length >= 2)
- {
- qualifiedNameForExport = new QualifiedName(parts[1], namespaces.GetIndexOrAppend(parts[0])).ToString();
- }
- else if (parts.Length == 1)
- {
- qualifiedNameForExport = parts[0];
- }
- else
- {
- qualifiedNameForExport = "";
- }
- }
- else
- {
- qualifiedNameForExport = new QualifiedName(displayName?.FirstOrDefault()?.Text, namespaces.GetIndexOrAppend(fallbackNamespace)).ToString();
- }
-
- return qualifiedNameForExport;
- }
-
- public override string ToString()
- {
- return _model?.ToString();
- }
- }
-
- public abstract class InstanceModelExportOpc : NodeModelExportOpc
- where TInstanceModel : InstanceModel, new()
- where TBaseTypeModel : NodeModel, new()
- {
-
- protected abstract (bool IsChild, NodeId ReferenceTypeId) ReferenceFromParent(NodeModel parent);
-
- public override (T ExportedNode, List AdditionalNodes, bool Created) GetUANode(ExportContext context)
- {
- var result = base.GetUANode(context);
- if (!result.Created)
- {
- return result;
- }
- var instance = result.ExportedNode as UAInstance;
- if (instance == null)
- {
- throw new Exception("Internal error: wrong generic type requested");
- }
- var references = instance.References?.ToList() ?? new List();
-
- if (!string.IsNullOrEmpty(_model.Parent?.NodeId))
- {
- instance.ParentNodeId = GetNodeIdForExport(_model.Parent.NodeId, context);
- }
-
- string typeDefinitionNodeIdForExport;
- if (_model.TypeDefinition != null)
- {
- context.NamespaceUris.GetIndexOrAppend(_model.TypeDefinition.Namespace);
- typeDefinitionNodeIdForExport = GetNodeIdForExport(_model.TypeDefinition.NodeId, context);
- }
- else
- {
- NodeId typeDefinitionNodeId = null;
- if (_model is PropertyModel)
- {
- typeDefinitionNodeId = VariableTypeIds.PropertyType;
- }
- else if (_model is DataVariableModel)
- {
- typeDefinitionNodeId = VariableTypeIds.BaseDataVariableType;
- }
- else if (_model is VariableModel)
- {
- typeDefinitionNodeId = VariableTypeIds.BaseVariableType;
- }
- else if (_model is ObjectModel)
- {
- typeDefinitionNodeId = ObjectTypeIds.BaseObjectType;
- }
-
- typeDefinitionNodeIdForExport = GetNodeIdForExport(typeDefinitionNodeId, context);
- }
- if (typeDefinitionNodeIdForExport != null && !(_model.TypeDefinition is MethodModel))
- {
- var reference = new Reference
- {
- ReferenceType = GetNodeIdForExport(ReferenceTypeIds.HasTypeDefinition, context),
- Value = typeDefinitionNodeIdForExport,
- };
- references.Add(reference);
- }
-
- AddModellingRuleReference(_model.ModellingRule, references, context);
-
- if (references.Any())
- {
- instance.References = references.Distinct(new ReferenceComparer()).ToArray();
- }
-
- return (instance as T, result.AdditionalNodes, result.Created);
- }
-
- protected List AddModellingRuleReference(string modellingRule, List references, ExportContext context)
- {
- if (modellingRule != null)
- {
- var modellingRuleId = modellingRule switch
- {
- "Optional" => ObjectIds.ModellingRule_Optional,
- "Mandatory" => ObjectIds.ModellingRule_Mandatory,
- "MandatoryPlaceholder" => ObjectIds.ModellingRule_MandatoryPlaceholder,
- "OptionalPlaceholder" => ObjectIds.ModellingRule_OptionalPlaceholder,
- "ExposesItsArray" => ObjectIds.ModellingRule_ExposesItsArray,
- _ => null,
- };
- if (modellingRuleId != null)
- {
- references.Add(new Reference
- {
- ReferenceType = GetNodeIdForExport(ReferenceTypeIds.HasModellingRule, context),
- Value = GetNodeIdForExport(modellingRuleId, context),
- });
- }
- }
- return references;
- }
-
- protected void AddOtherReferences(List references, string parentNodeId, NodeId referenceTypeId, bool bIsChild, ExportContext context)
- {
- if (!string.IsNullOrEmpty(_model.Parent?.NodeId))
- {
- bool bAdded = false;
- foreach (var referencingNode in _model.Parent.OtherReferencedNodes.Where(cr => cr.Node == _model))
- {
- var referenceType = GetNodeIdForExport(referencingNode.ReferenceType?.NodeId, context);
- if (!references.Any(r => r.IsForward == false && r.Value == parentNodeId && r.ReferenceType != referenceType))
- {
- references.Add(new Reference { IsForward = false, ReferenceType = referenceType, Value = parentNodeId });
- }
- else
- {
- // TODO ensure we pick the most derived reference type
- }
- bAdded = true;
- }
- if (bIsChild || !bAdded)//_model.Parent.Objects.Contains(_model))
- {
- var referenceType = GetNodeIdForExport(referenceTypeId, context);
- if (!references.Any(r => r.IsForward == false && r.Value == parentNodeId && r.ReferenceType != referenceType))
- {
- references.Add(new Reference { IsForward = false, ReferenceType = referenceType, Value = parentNodeId });
- }
- else
- {
- // TODO ensure we pick the most derived reference type
- }
- }
- }
- }
-
-
-
- }
-
- public class ObjectModelExportOpc : InstanceModelExportOpc
- {
- public override (T ExportedNode, List AdditionalNodes, bool Created) GetUANode(ExportContext context)
- {
- var result = base.GetUANode(context);
- if (!result.Created)
- {
- return (result.ExportedNode as T, result.AdditionalNodes, result.Created);
- }
- var uaObject = result.ExportedNode;
- if (_model.EventNotifier != null)
- {
- uaObject.EventNotifier = _model.EventNotifier.Value;
- }
- var references = uaObject.References?.ToList() ?? new List();
-
- if (uaObject.ParentNodeId != null)
- {
- AddOtherReferences(references, uaObject.ParentNodeId, ReferenceTypeIds.HasComponent, _model.Parent.Objects.Contains(_model), context);
- }
- if (references.Any())
- {
- uaObject.References = references.Distinct(new ReferenceComparer()).ToArray();
- }
-
- return (uaObject as T, result.AdditionalNodes, result.Created);
- }
-
- protected override (bool IsChild, NodeId ReferenceTypeId) ReferenceFromParent(NodeModel parent)
- {
- return (parent.Objects.Contains(_model), ReferenceTypeIds.HasComponent);
- }
- }
-
- public class BaseTypeModelExportOpc : NodeModelExportOpc where TBaseTypeModel : BaseTypeModel, new()
- //public class BaseTypeModelExportOpc : NodeModelExportOpc where TBaseTypeModel : BaseTypeModel, new()
- {
- public override (T ExportedNode, List AdditionalNodes, bool Created) GetUANode(ExportContext context)
- {
- var result = base.GetUANode(context);
- if (!result.Created)
- {
- return result;
- }
- var objectType = result.ExportedNode;
- foreach (var subType in this._model.SubTypes)
- {
- context.NamespaceUris.GetIndexOrAppend(subType.Namespace);
- }
-
- var superType = _model.SuperType;
- if (superType == null && _model.NodeId == context.GetModelNodeId(ObjectTypeIds.BaseInterfaceType))
- {
- superType = context.GetModelForNode(_model.NodeId);
- }
- if (superType != null)
- {
- context.NamespaceUris.GetIndexOrAppend(superType.Namespace);
- var superTypeReference = new Reference
- {
- ReferenceType = GetNodeIdForExport(ReferenceTypeIds.HasSubtype, context),
- IsForward = false,
- Value = GetNodeIdForExport(superType.NodeId, context),
- };
- if (objectType.References == null)
- {
- objectType.References = new Reference[] { superTypeReference };
- }
- else
- {
- var referenceList = new List(objectType.References);
- referenceList.Add(superTypeReference);
- objectType.References = referenceList.ToArray();
- }
- }
- if (objectType is UAType uaType)
- {
- uaType.IsAbstract = _model.IsAbstract;
- }
- else
- {
- throw new Exception("Must be UAType or derived");
- }
- return (objectType, result.AdditionalNodes, result.Created);
- }
- }
-
- public class ObjectTypeModelExportOpc : BaseTypeModelExportOpc where TTypeModel : BaseTypeModel, new()
- //public class ObjectTypeModelExportOpc : BaseTypeModelExportOpc where TTypeModel : BaseTypeModel, new()
- {
- public override (T ExportedNode, List AdditionalNodes, bool Created) GetUANode(ExportContext context)
- {
- var result = base.GetUANode