Inserito prototipo gestione password calcolabile + master

This commit is contained in:
Samuele E. Locatelli
2020-11-02 20:06:56 +01:00
parent bd49fbb743
commit 962c19e134
8 changed files with 472 additions and 236 deletions
+1
View File
@@ -77,6 +77,7 @@
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\ConsolePrinter.cs" />
<Compile Include="Services\CryptoUtils.cs" />
<Compile Include="Services\DataRecorder.cs" />
<Compile Include="Services\IPrinter.cs" />
<Compile Include="Services\LogPrinter.cs" />
+224
View File
@@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace OpcUaCommon.Services
{
/// <summary>
/// utils x cifrature passeword e Crypto functionality in genere
/// </summary>
public static class CryptoUtils
{
#region Public Methods
/// <summary>
/// Decifra un messaggio AES
/// </summary>
/// <param name="Message"></param>
/// <param name="Passphrase"></param>
/// <returns></returns>
public static string DecryptString(string Message, string Passphrase)
{
string answ = Message;
byte[] Results = null;
UTF8Encoding UTF8 = new UTF8Encoding();
// Step 1. faccio hash per ottenere la Key a 128 bit + l'InitVector a 256 bit
// - MD5 hash generator --> 128 bit byte array
// - Sha256 hash generator --> 256 bit byte array
MD5CryptoServiceProvider MD5HashProv = new MD5CryptoServiceProvider();
SHA256CryptoServiceProvider Sha256HashProv = new SHA256CryptoServiceProvider();
byte[] AESKey = Sha256HashProv.ComputeHash(UTF8.GetBytes(Passphrase));
byte[] AESIV = MD5HashProv.ComputeHash(UTF8.GetBytes(Passphrase));
// Step 2. Crea oggett AESCryptoServiceProvider
AesCryptoServiceProvider AESAlgorithm = new AesCryptoServiceProvider();
// Step 3. Setup del dencoder
AESAlgorithm.Key = AESKey;
AESAlgorithm.IV = AESIV;
// Step 4. Conversione della stringa in ingresso in un byte[]
byte[] DataToDecrypt = null;
try
{
DataToDecrypt = Convert.FromBase64String(Message);
}
catch
{ }
if (DataToDecrypt != null)
{
// Step 5. Attempt to decrypt the string
try
{
ICryptoTransform Decryptor = AESAlgorithm.CreateDecryptor();
Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
}
finally
{
// Clear the TripleDes and Hashprovider services of any sensitive information
AESAlgorithm.Clear();
MD5HashProv.Clear();
Sha256HashProv.Clear();
}
// Step 6. Return the decrypted string in UTF8 format
answ = UTF8.GetString(Results);
}
return answ;
}
/// <summary>
/// Cifra un messaggio con AES
/// </summary>
/// <param name="Message">Messaggio da cifrare (la password)</param>
/// <param name="Passphrase">Stringa usate per generare le key/IV da 128/256bit</param>
/// <returns></returns>
public static string EncryptString(string Message, string Passphrase)
{
byte[] Results;
UTF8Encoding UTF8 = new UTF8Encoding();
// Step 1. faccio hash per ottenere la Key a 128 bit + l'InitVector a 256 bit
// - MD5 hash generator --> 128 bit byte array
// - Sha256 hash generator --> 256 bit byte array
MD5CryptoServiceProvider MD5HashProv = new MD5CryptoServiceProvider();
SHA256CryptoServiceProvider Sha256HashProv = new SHA256CryptoServiceProvider();
byte[] AESKey = Sha256HashProv.ComputeHash(UTF8.GetBytes(Passphrase));
byte[] AESIV = MD5HashProv.ComputeHash(UTF8.GetBytes(Passphrase));
// Step 2. Crea oggett AESCryptoServiceProvider
AesCryptoServiceProvider AESAlgorithm = new AesCryptoServiceProvider();
// Step 3. Setup dell'encoder
AESAlgorithm.Key = AESKey;
AESAlgorithm.IV = AESIV;
// Step 4. Conversione della stringa in ingresso in un byte[]
byte[] DataToEncrypt = UTF8.GetBytes(Message);
// Step 5. Attempt to encrypt the string
try
{
ICryptoTransform Encryptor = AESAlgorithm.CreateEncryptor();
Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
}
finally
{
// ripulisce il provider di ogni informazione sensibile
AESAlgorithm.Clear();
MD5HashProv.Clear();
Sha256HashProv.Clear();
}
// Step 6. Restitusice stringa cifrata come una "base64 encoded string"
return Convert.ToBase64String(Results);
}
/// <summary>
/// Genera una password valida
/// </summary>
/// <param name="userName"></param>
/// <param name="passphrase"></param>
/// <returns></returns>
public static string generatePwd(string userName, string passphrase)
{
// Check preliminare della "master password"
return EncryptString(userName, passphrase);
}
/// <summary>
/// genera hash di una stringa in MD5 (es x hash gravatar)
/// </summary>
/// <param name="Message"></param>
/// <returns></returns>
public static string getHashStringMD5(string Message)
{
string hash = "";
using (MD5 md5Hash = MD5.Create())
{
hash = GetMd5Hash(md5Hash, Message);
}
return hash;
}
/// <summary>
/// Crea un hash MD5
/// </summary>
/// <param name="md5Hash"></param>
/// <param name="input"></param>
/// <returns></returns>
public static string GetMd5Hash(MD5 md5Hash, string input)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
/// <summary>
/// Effettua validazione password
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <param name="passphrase"></param>
/// <returns></returns>
public static bool validateUserPwd(string userName, string password, string passphrase)
{
#if false
// helper calcolo pwd..
//string correctPwd = generatePwd(userName, passphrase);
#endif
// Check preliminare della "master password"
bool answ = (userName == "scmAdmin" && password == "1PasswordDavveroDifficil3!");
// verifico password avanzata
if (!answ)
{
string plainText = DecryptString(password, passphrase);
answ = (userName == plainText);
}
return answ;
}
/// <summary>
/// Verify a hash against a string.
/// </summary>
/// <param name="md5Hash"></param>
/// <param name="input"></param>
/// <param name="hash"></param>
/// <returns></returns>
public static bool VerifyMd5Hash(MD5 md5Hash, string input, string hash)
{
// Hash the input.
string hashOfInput = GetMd5Hash(md5Hash, input);
// Create a StringComparer an compare the hashes.
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
if (0 == comparer.Compare(hashOfInput, hash))
{
return true;
}
else
{
return false;
}
}
#endregion Public Methods
}
}
+15 -15
View File
@@ -114,13 +114,7 @@ namespace OpcUaServer.Server
#region Public Methods
public override ResponseHeader Browse(
RequestHeader requestHeader,
ViewDescription view,
uint requestedMaxReferencesPerNode,
BrowseDescriptionCollection nodesToBrowse,
out BrowseResultCollection results,
out DiagnosticInfoCollection diagnosticInfos)
public override ResponseHeader Browse(RequestHeader requestHeader, ViewDescription view, uint requestedMaxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos)
{
results = null;
diagnosticInfos = null;
@@ -141,18 +135,24 @@ namespace OpcUaServer.Server
if (context.UserIdentity.TokenType == UserTokenType.Anonymous)
filter = true;
ServerInternal.NodeManager.Browse(
context,
view,
requestedMaxReferencesPerNode,
nodesToBrowse,
out results,
out diagnosticInfos);
// legge gli oggetti contenuti nell'elemento richeisto
ServerInternal.NodeManager.Browse(context, view, requestedMaxReferencesPerNode, nodesToBrowse, out results, out diagnosticInfos);
if (filter) foreach (var res in results)
// se attivato il filtro == utente anonimo
if (filter)
{
foreach (var res in results)
{
var filtrati = res.References.FindAll(x => x.NodeClass == NodeClass.Variable && (x.BrowseName.Name.StartsWith("Machine/") && x.BrowseName.Name != "Machine/Status"));
// rimuove tutto tranne status...
//res.References.RemoveAll(x => x.NodeClass == NodeClass.Variable && (x.BrowseName.Name.StartsWith("Machine/") && x.BrowseName.Name != "Machine/Status"));
res.References.RemoveAll(x => x.BrowseName.Name.StartsWith("Machine/") && x.BrowseName.Name != "Machine/Status");
//// includo SOLO SE VGroup = "A" (All)
//res.References.RemoveAll(x => x.BrowseName.Name.StartsWith("Machine/") && x.BrowseName.Name != "Machine/Status");
}
}
return CreateResponse(requestHeader, context.StringTable);
}
@@ -1,6 +1,8 @@
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using Opc.Ua;
using OpcUaCommon.Services;
namespace OpcUaServer.Server.Services
{
@@ -23,6 +25,13 @@ namespace OpcUaServer.Server.Services
#region Public Methods
public static string ReverseString(string s)
{
char[] array = s.ToCharArray();
Array.Reverse(array);
return new string(array);
}
public IUserIdentity VerifyPassword(UserNameIdentityToken userNameToken, string productUri)
{
var userName = userNameToken.UserName;
@@ -48,7 +57,10 @@ namespace OpcUaServer.Server.Services
//}
// standard users for CTT verification
if ((userName == "scmAdmin" && password == "password123"))
string passphrase = $"{userName}_{ReverseString(userName)}";
//bool hashUser = CryptoUtils.validateUserPwd(userName, password, passphrase);
//if ((userName == "scmAdmin" && password == "passwordDifficile"))
if (CryptoUtils.validateUserPwd(userName, password, passphrase))
return new UserIdentity(userNameToken);
// construct translation object with default text.
@@ -69,13 +69,6 @@ namespace OpcUaServer.Server.Services
AddProperty(folder, xmlElement, stringFolderName, nameSpaceIndex, folderInstanceState);
break;
#if false
case "Events":
// aggiungo "Events:"
AddVariable(folderInstanceState, nameSpaceIndex, xmlElement, $"{stringFolderName}/Events", folder);
break;
#endif
case "Condition":
AddCondition(folderInstanceState, nameSpaceIndex, xmlElement, stringFolderName, folder);
break;
+4 -1
View File
@@ -8,7 +8,10 @@ namespace SOUR.Core
private readonly List<TreeNodeInstance> _children;
public string BrowseName { get; set; }
public string DisplayName { get; set; }
/// <summary>
/// Visibilità dell'oggetto nodo d'albero
/// </summary>
public string Visibility { get; set; } = "A";
public TreeNodeInstance[] Children
+214 -211
View File
@@ -6,236 +6,239 @@ using System.Xml;
namespace SOUR.Core
{
public class XmlParser
{
private readonly IEventMessageRepository _eventMessageRepository;
public XmlParser(IEventMessageRepository eventMessageRepository)
public class XmlParser
{
_eventMessageRepository = eventMessageRepository;
}
#region Private Fields
private readonly IEventMessageRepository _eventMessageRepository;
public IDictionary<string, NodeProperties> CreateDictionaryFromXmlToGenerateValues(string tracciatoXml)
{
IDictionary<string, NodeProperties> nodeNameAndBuiltInTypes = new Dictionary<string, NodeProperties>();
var xmlDocument = new XmlDocument();
// carico XML appena salvato
xmlDocument.Load(tracciatoXml);
ParseXml(xmlDocument, nodeNameAndBuiltInTypes, new TreeNodeInstance());
#endregion Private Fields
return nodeNameAndBuiltInTypes;
#region Public Constructors
}
public TreeNodeInstance CreateTree(string tracciatoXml)
{
IDictionary<string, NodeProperties> nodeNameAndBuiltInTypes = new Dictionary<string, NodeProperties>();
var treeNodeInstance = new TreeNodeInstance();
var xmlDocument = new XmlDocument();
xmlDocument.Load(tracciatoXml);
ParseXml(xmlDocument, nodeNameAndBuiltInTypes, treeNodeInstance);
return treeNodeInstance;
}
private void CreateSubDictionary(string path, XmlNode component, IDictionary<string, NodeProperties> nodeNameAndBuiltInTypes, TreeNodeInstance treeNodeInstance)
{
string redisPath = path.Replace("/", ":");
foreach (XmlElement xmlElement in component)
{
if (xmlElement.Name != "Component" && xmlElement.Name != "Conditions" && xmlElement.Name != "Property")
public XmlParser(IEventMessageRepository eventMessageRepository)
{
var nodeName = xmlElement.Attributes["BrowseName"].Value;
var symbolicName = xmlElement.Attributes["SymbolicName"].Value;
var nodeDataType = xmlElement.Attributes["DataType"].Value;
// range NON lo richiediamo x cui controllo NULL "a monte"...
var nodeRange = component.Attributes["Range"] != null ? (component.Attributes["Range"].Value ?? "null") : "null";
//// vecchio modo che genera eccezioni se manca attributo...
//var nodeRange = xmlElement.Attributes["Range"].Value ?? "null";
var nodeUnits = xmlElement.Attributes["Units"]?.Value ?? "null";
var severity = xmlElement.Attributes["Severity"]?.Value ?? "null";
// 2019.01.29 aggiunta decodifica nuove conf XML, con valori default
var nodeSGroup = xmlElement.Attributes["SGroup"]?.Value ?? "3";
var nodeDBand = xmlElement.Attributes["DBand"]?.Value ?? "";
var nodeVGroup = xmlElement.Attributes["VGroup"]?.Value ?? "A"; // default: ALL
//var parentName = component.Attributes["Name"].Value ?? "";
if (!Enum.TryParse(xmlElement.Name, out NodePropertiesType nodePropertyType))
{
nodePropertyType = NodePropertiesType.Variable;
}
NodeProperties nodeProperties;
if (xmlElement.Name == "Condition")
{
// allarmi SEMPRE alla massima priorità...
nodeSGroup = "1";
// HARD CODED traduzione messaggi a lingua corrente... in area AdpConf...
string redAlarmPath = string.Format("{0}:{1}", redisPath, symbolicName);
var eventMessages = _eventMessageRepository.getAlarmList(redAlarmPath);
var vetoCodes = _eventMessageRepository.getVetoCodes(redAlarmPath);
nodeProperties = new ConditionNodeProperties(nodeName, nodeDataType, nodeRange, nodeUnits, severity, nodeSGroup, nodeDBand, nodeVGroup, nodePropertyType, eventMessages, vetoCodes);
}
else
{
nodeProperties = new NodeProperties(nodeName, nodeDataType, nodeRange, nodeUnits, severity, nodeSGroup, nodeDBand, nodeVGroup, nodePropertyType);
}
nodeNameAndBuiltInTypes.Add(path + "/" + symbolicName, nodeProperties);
treeNodeInstance.AddChild(new TreeNodeInstance()
{
BrowseName = path + "/" + symbolicName,
DisplayName = symbolicName,
NodePropertyType = nodeProperties.NodePropertiesType,
NodeDataType = nodeProperties.NodeDataType
});
_eventMessageRepository = eventMessageRepository;
}
else if (xmlElement.Name == "Property")
#endregion Public Constructors
#region Private Methods
private void CreateSubDictionary(string path, XmlNode component, IDictionary<string, NodeProperties> nodeNameAndBuiltInTypes, TreeNodeInstance treeNodeInstance)
{
var propName = xmlElement.Attributes["BrowseName"].Value;
var propSymbolicName = xmlElement.Attributes["SymbolicName"].Value;
var propNodeDataType = xmlElement.Attributes["DataType"].Value ?? null;
string nodeSGroup = "5"; // fix a 5
var propNodeVGroup = xmlElement.Attributes["VGroup"]?.Value ?? "A"; // default: ALL
var nodeProperties = new NodeProperties(propName, propNodeDataType, "", null, null, nodeSGroup, null, propNodeVGroup, NodePropertiesType.Property);
var key = path.EndsWith("/") ? path + propSymbolicName : path + "/" + propSymbolicName;
nodeNameAndBuiltInTypes.Add(key, nodeProperties);
treeNodeInstance.AddChild(new TreeNodeInstance()
{
BrowseName = key,
DisplayName = propSymbolicName,
NodePropertyType = nodeProperties.NodePropertiesType,
NodeDataType = nodeProperties.NodeDataType
});
}
else
{
if (xmlElement.Name != "Property")
{
var name = xmlElement.Attributes["Name"].Value;
var treeNodeChild = new TreeNodeInstance()
string redisPath = path.Replace("/", ":");
foreach (XmlElement xmlElement in component)
{
BrowseName = path + "/" + name,
DisplayName = name,
NodePropertyType = NodePropertiesType.Folder,
NodeDataType = null
};
var nodeVGroup = xmlElement.Attributes["VGroup"]?.Value ?? "A"; // default: ALL
if (xmlElement.Name != "Component" && xmlElement.Name != "Conditions" && xmlElement.Name != "Property")
{
var nodeName = xmlElement.Attributes["BrowseName"].Value;
var symbolicName = xmlElement.Attributes["SymbolicName"].Value;
var nodeDataType = xmlElement.Attributes["DataType"].Value;
// range NON lo richiediamo x cui controllo NULL "a monte"...
var nodeRange = component.Attributes["Range"] != null ? (component.Attributes["Range"].Value ?? "null") : "null";
//// vecchio modo che genera eccezioni se manca attributo...
//var nodeRange = xmlElement.Attributes["Range"].Value ?? "null";
var nodeUnits = xmlElement.Attributes["Units"]?.Value ?? "null";
var severity = xmlElement.Attributes["Severity"]?.Value ?? "null";
treeNodeInstance.AddChild(treeNodeChild);
// 2019.01.29 aggiunta decodifica nuove conf XML, con valori default
var nodeSGroup = xmlElement.Attributes["SGroup"]?.Value ?? "3";
var nodeDBand = xmlElement.Attributes["DBand"]?.Value ?? "";
CreateSubDictionary(path + "/" + name, xmlElement, nodeNameAndBuiltInTypes, treeNodeChild);
//var parentName = component.Attributes["Name"].Value ?? "";
}
if (!Enum.TryParse(xmlElement.Name, out NodePropertiesType nodePropertyType))
{
nodePropertyType = NodePropertiesType.Variable;
}
NodeProperties nodeProperties;
if (xmlElement.Name == "Condition")
{
// allarmi SEMPRE alla massima priorità...
nodeSGroup = "1";
// HARD CODED traduzione messaggi a lingua corrente... in area AdpConf...
string redAlarmPath = string.Format("{0}:{1}", redisPath, symbolicName);
var eventMessages = _eventMessageRepository.getAlarmList(redAlarmPath);
var vetoCodes = _eventMessageRepository.getVetoCodes(redAlarmPath);
nodeProperties = new ConditionNodeProperties(nodeName, nodeDataType, nodeRange, nodeUnits, severity, nodeSGroup, nodeDBand, nodeVGroup, nodePropertyType, eventMessages, vetoCodes);
}
else
{
nodeProperties = new NodeProperties(nodeName, nodeDataType, nodeRange, nodeUnits, severity, nodeSGroup, nodeDBand, nodeVGroup, nodePropertyType);
}
nodeNameAndBuiltInTypes.Add(path + "/" + symbolicName, nodeProperties);
treeNodeInstance.AddChild(new TreeNodeInstance()
{
BrowseName = path + "/" + symbolicName,
DisplayName = symbolicName,
NodePropertyType = nodeProperties.NodePropertiesType,
NodeDataType = nodeProperties.NodeDataType,
Visibility = nodeVGroup
});
}
else if (xmlElement.Name == "Property")
{
var propName = xmlElement.Attributes["BrowseName"].Value;
var propSymbolicName = xmlElement.Attributes["SymbolicName"].Value;
var propNodeDataType = xmlElement.Attributes["DataType"].Value ?? null;
string nodeSGroup = "5"; // fix a 5
var nodeProperties = new NodeProperties(propName, propNodeDataType, "", null, null, nodeSGroup, null, nodeVGroup, NodePropertiesType.Property);
var key = path.EndsWith("/") ? path + propSymbolicName : path + "/" + propSymbolicName;
nodeNameAndBuiltInTypes.Add(key, nodeProperties);
treeNodeInstance.AddChild(new TreeNodeInstance()
{
BrowseName = key,
DisplayName = propSymbolicName,
NodePropertyType = nodeProperties.NodePropertiesType,
NodeDataType = nodeProperties.NodeDataType,
Visibility = nodeVGroup
});
}
else
{
if (xmlElement.Name != "Property")
{
var name = xmlElement.Attributes["Name"].Value;
var treeNodeChild = new TreeNodeInstance()
{
BrowseName = path + "/" + name,
DisplayName = name,
NodePropertyType = NodePropertiesType.Folder,
NodeDataType = null,
Visibility = nodeVGroup
};
treeNodeInstance.AddChild(treeNodeChild);
CreateSubDictionary(path + "/" + name, xmlElement, nodeNameAndBuiltInTypes, treeNodeChild);
}
}
}
}
}
}
private void ParseXml(XmlDocument xmlDocument, IDictionary<string, NodeProperties> nodeNameAndBuiltInTypes,
TreeNodeInstance treeNodeInstance)
{
var itemRef = xmlDocument.GetElementsByTagName("Machine");
string rootName = "Machine"; //itemRef[0]?.Attributes?["Name"].Value + "_" + itemRef[0]?.Attributes?["Serial"].Value;
treeNodeInstance.BrowseName = rootName;
treeNodeInstance.DisplayName = rootName;
treeNodeInstance.NodePropertyType = NodePropertiesType.Folder;
treeNodeInstance.NodeDataType = null;
var xmlNodeList = itemRef[0]?.ChildNodes;
if (xmlNodeList == null)
{
nodeNameAndBuiltInTypes = null;
return;
}
foreach (XmlNode component in xmlNodeList)
{
var stringFolderName = rootName + "/";
if (component.Name != "Component" && component.Name != "Components" && component.Name != "Property")
private void ParseXml(XmlDocument xmlDocument, IDictionary<string, NodeProperties> nodeNameAndBuiltInTypes,
TreeNodeInstance treeNodeInstance)
{
var nodeName = component.Attributes["BrowseName"].Value;
var symbolicName = component.Attributes["SymbolicName"].Value;
var nodeDataType = component.Attributes["DataType"].Value ?? null;
// range NON lo richiediamo x cui controllo NULL "a monte"...
var nodeRange = component.Attributes["Range"] != null ? (component.Attributes["Range"].Value ?? "null") : "null";
//// vecchio modo che genera eccezioni se manca attributo...
//var nodeRange = component.Attributes["Range"].Value ?? "null";
var nodeUnits = component.Attributes["Units"]?.Value ?? "null";
var severity = component.Attributes["Severity"]?.Value ?? "null";
var nodeSGroup = component.Attributes["SGroup"]?.Value ?? "3";
var nodeDBand = component.Attributes["DBand"]?.Value ?? "";
var nodeVGroup = component.Attributes["VGroup"]?.Value ?? "A"; // default: ALL
var itemRef = xmlDocument.GetElementsByTagName("Machine");
string rootName = "Machine"; //itemRef[0]?.Attributes?["Name"].Value + "_" + itemRef[0]?.Attributes?["Serial"].Value;
if (!Enum.TryParse(component.Name, out NodePropertiesType nodePropertyType))
{
nodePropertyType = NodePropertiesType.Variable;
}
treeNodeInstance.BrowseName = rootName;
treeNodeInstance.DisplayName = rootName;
treeNodeInstance.NodePropertyType = NodePropertiesType.Folder;
treeNodeInstance.NodeDataType = null;
NodeProperties nodeProperties;
if (component.Name == "Condition")
{
// HARD CODED traduzione messaggi a lingua corrente... in area AdpConf...
string redAlarmPath = string.Format("{0}:{1}", rootName, symbolicName);
var eventMessages = _eventMessageRepository.getAlarmList(redAlarmPath);
var vetoCodes = _eventMessageRepository.getVetoCodes(redAlarmPath);
nodeProperties = new ConditionNodeProperties(nodeName, nodeDataType, nodeRange, nodeUnits, severity, nodeSGroup, nodeDBand, nodeVGroup, nodePropertyType, eventMessages, vetoCodes);
}
else
{
nodeProperties = new NodeProperties(nodeName, nodeDataType, nodeRange, nodeUnits, severity, nodeSGroup, nodeDBand, nodeVGroup, nodePropertyType);
}
treeNodeInstance.AddChild(new TreeNodeInstance() { BrowseName = stringFolderName + symbolicName, DisplayName = symbolicName, NodePropertyType = nodeProperties.NodePropertiesType, NodeDataType = nodeProperties.NodeDataType });
nodeNameAndBuiltInTypes.Add(stringFolderName + symbolicName, nodeProperties);
}
else
{
if (component.Name == "Property")
{
var propName = component.Attributes["BrowseName"].Value;
var propSymbolicName = component.Attributes["SymbolicName"].Value;
var propNodeDataType = component.Attributes["DataType"].Value ?? null;
var propNodeVGroup = component.Attributes["VGroup"]?.Value ?? "A"; // default: ALL
var nodeProperties = new NodeProperties(propName, propNodeDataType, "", null, null, null, null, propNodeVGroup, NodePropertiesType.Property);
nodeNameAndBuiltInTypes.Add(stringFolderName + propSymbolicName, nodeProperties);
treeNodeInstance.AddChild(new TreeNodeInstance() { BrowseName = stringFolderName + propSymbolicName, DisplayName = propSymbolicName, NodePropertyType = nodeProperties.NodePropertiesType, NodeDataType = nodeProperties.NodeDataType });
}
if (component.Name != "Property" && component.Attributes != null)
{
var treeNodeChild = new TreeNodeInstance()
var xmlNodeList = itemRef[0]?.ChildNodes;
if (xmlNodeList == null)
{
BrowseName = stringFolderName + component.Attributes["Name"].Value,
DisplayName = component.Attributes["Name"].Value,
NodePropertyType = NodePropertiesType.Folder,
NodeDataType = null
};
treeNodeInstance.AddChild(treeNodeChild);
nodeNameAndBuiltInTypes = null;
return;
}
foreach (XmlNode component in xmlNodeList)
{
var stringFolderName = rootName + "/";
if (component.Name != "Component" && component.Name != "Components" && component.Name != "Property")
{
var nodeName = component.Attributes["BrowseName"].Value;
var symbolicName = component.Attributes["SymbolicName"].Value;
var nodeDataType = component.Attributes["DataType"].Value ?? null;
// range NON lo richiediamo x cui controllo NULL "a monte"...
var nodeRange = component.Attributes["Range"] != null ? (component.Attributes["Range"].Value ?? "null") : "null";
//// vecchio modo che genera eccezioni se manca attributo...
//var nodeRange = component.Attributes["Range"].Value ?? "null";
var nodeUnits = component.Attributes["Units"]?.Value ?? "null";
var severity = component.Attributes["Severity"]?.Value ?? "null";
var nodeSGroup = component.Attributes["SGroup"]?.Value ?? "3";
var nodeDBand = component.Attributes["DBand"]?.Value ?? "";
var nodeVGroup = component.Attributes["VGroup"]?.Value ?? "A"; // default: ALL
CreateSubDictionary(stringFolderName + component.Attributes["Name"].Value, component, nodeNameAndBuiltInTypes, treeNodeChild);
}
if (!Enum.TryParse(component.Name, out NodePropertiesType nodePropertyType))
{
nodePropertyType = NodePropertiesType.Variable;
}
NodeProperties nodeProperties;
if (component.Name == "Condition")
{
// HARD CODED traduzione messaggi a lingua corrente... in area AdpConf...
string redAlarmPath = string.Format("{0}:{1}", rootName, symbolicName);
var eventMessages = _eventMessageRepository.getAlarmList(redAlarmPath);
var vetoCodes = _eventMessageRepository.getVetoCodes(redAlarmPath);
nodeProperties = new ConditionNodeProperties(nodeName, nodeDataType, nodeRange, nodeUnits, severity, nodeSGroup, nodeDBand, nodeVGroup, nodePropertyType, eventMessages, vetoCodes);
}
else
{
nodeProperties = new NodeProperties(nodeName, nodeDataType, nodeRange, nodeUnits, severity, nodeSGroup, nodeDBand, nodeVGroup, nodePropertyType);
}
treeNodeInstance.AddChild(new TreeNodeInstance() { BrowseName = stringFolderName + symbolicName, DisplayName = symbolicName, NodePropertyType = nodeProperties.NodePropertiesType, NodeDataType = nodeProperties.NodeDataType });
nodeNameAndBuiltInTypes.Add(stringFolderName + symbolicName, nodeProperties);
}
else
{
if (component.Name == "Property")
{
var propName = component.Attributes["BrowseName"].Value;
var propSymbolicName = component.Attributes["SymbolicName"].Value;
var propNodeDataType = component.Attributes["DataType"].Value ?? null;
var propNodeVGroup = component.Attributes["VGroup"]?.Value ?? "A"; // default: ALL
var nodeProperties = new NodeProperties(propName, propNodeDataType, "", null, null, null, null, propNodeVGroup, NodePropertiesType.Property);
nodeNameAndBuiltInTypes.Add(stringFolderName + propSymbolicName, nodeProperties);
treeNodeInstance.AddChild(new TreeNodeInstance() { BrowseName = stringFolderName + propSymbolicName, DisplayName = propSymbolicName, NodePropertyType = nodeProperties.NodePropertiesType, NodeDataType = nodeProperties.NodeDataType });
}
if (component.Name != "Property" && component.Attributes != null)
{
var treeNodeChild = new TreeNodeInstance()
{
BrowseName = stringFolderName + component.Attributes["Name"].Value,
DisplayName = component.Attributes["Name"].Value,
NodePropertyType = NodePropertiesType.Folder,
NodeDataType = null
};
treeNodeInstance.AddChild(treeNodeChild);
CreateSubDictionary(stringFolderName + component.Attributes["Name"].Value, component, nodeNameAndBuiltInTypes, treeNodeChild);
}
}
}
}
}
#endregion Private Methods
#region Public Methods
public IDictionary<string, NodeProperties> CreateDictionaryFromXmlToGenerateValues(string tracciatoXml)
{
IDictionary<string, NodeProperties> nodeNameAndBuiltInTypes = new Dictionary<string, NodeProperties>();
var xmlDocument = new XmlDocument();
// carico XML appena salvato
xmlDocument.Load(tracciatoXml);
ParseXml(xmlDocument, nodeNameAndBuiltInTypes, new TreeNodeInstance());
return nodeNameAndBuiltInTypes;
}
public TreeNodeInstance CreateTree(string tracciatoXml)
{
IDictionary<string, NodeProperties> nodeNameAndBuiltInTypes = new Dictionary<string, NodeProperties>();
var treeNodeInstance = new TreeNodeInstance();
var xmlDocument = new XmlDocument();
xmlDocument.Load(tracciatoXml);
ParseXml(xmlDocument, nodeNameAndBuiltInTypes, treeNodeInstance);
return treeNodeInstance;
}
#endregion Public Methods
}
}
}
}
+1 -1
View File
@@ -11,7 +11,7 @@
<Variable SymbolicName="Power" BrowseName="Power" DataType="ua:Boolean" ValueRank="Scalar" Units="Bool" />
<Variable SymbolicName="ActiveTime" BrowseName="ActiveTime" DataType="ua:Float" ValueRank="Scalar" Units="h" CmsDataType="CounterList" CmsDataIndex="001" CmsDataOpt="HOURS" />
<Variable SymbolicName="ActiveWorkingTime" BrowseName="ActiveTime" DataType="ua:Float" ValueRank="Scalar" Units="h" CmsDataType="CounterList" CmsDataIndex="002" CmsDataOpt="HOURS" />
<Component Name="Events">
<Component Name="Events" VGroup="P">
<Variable SymbolicName="Production" BrowseName="Production" DataType="ua:String" ValueRank="Scalar" Units="" SGroup="1" VGroup="P" />
<Variable SymbolicName="Kpis" BrowseName="Kpis" DataType="ua:String" ValueRank="Scalar" Units="" SGroup="1" VGroup="P" />
<Variable SymbolicName="Tools" BrowseName="Tools" DataType="ua:String" ValueRank="Scalar" Units="" SGroup="1" VGroup="P" />