26 Commits

Author SHA1 Message Date
marco.salvi 85552ba0aa fix librerie e aggiunta cicd 2022-04-15 13:03:38 +02:00
Samuele E. Locatelli c17d2c0a16 Merge branch 'master' into develop 2021-03-03 14:38:26 +01:00
Samuele E. Locatelli 3e297579e3 refresh x compilazione msi package 2021-03-03 14:38:18 +01:00
Samuele E. Locatelli ee9957ae3c Merge branch 'master' into develop 2021-03-03 13:11:45 +01:00
Samuele E. Locatelli 28e7f19eeb fix gestione DB 2021-03-03 13:11:37 +01:00
Samuele E. Locatelli 7f776d0e2a Merge remote-tracking branch 'gitlab.scm/master' into develop 2020-11-11 10:14:37 +01:00
Samuele E. Locatelli b386f99ecf Merge branch 'develop' 2020-11-11 10:09:18 +01:00
Samuele E. Locatelli a817d8758a fix debug vers senza "rimbalzo" dati 2020-11-11 10:09:12 +01:00
Samuele E. Locatelli 8f635ca7e1 fix eccezione x area Redis che scompare con SOUR attivo 2020-11-11 09:53:36 +01:00
Samuele E. Locatelli 1e91fee62e update datamodel 2020-11-03 19:35:51 +01:00
Ferdinando Sodano 969840acb4 Merge branch 'develop' 2020-11-03 16:45:46 +01:00
Ferdinando Sodano 28c1de8c14 erase all 2020-11-03 16:45:17 +01:00
Samuele E. Locatelli 89be5893d3 Merge branch 'develop' 2020-11-03 14:14:18 +01:00
Samuele E. Locatelli 5a78d159c9 new rel 2020-11-03 14:14:11 +01:00
Samuele E. Locatelli f8b08a34d7 FIx modalità filtro su VGroup="P" 2020-11-03 14:14:00 +01:00
Samuele E. Locatelli 9dcad07d13 Altre modifiche x filtro ma NON lo assegna ancora sugli oggetti component... 2020-11-03 14:08:20 +01:00
Samuele E. Locatelli 8f0a5913d5 vers 287 2020-11-03 09:39:52 +01:00
Samuele E. Locatelli 9be98a6818 Fix filtraggio e pulizia crypto utils 2020-11-03 09:39:41 +01:00
Samuele E. Locatelli 19a28711a4 Merge branch 'develop' 2020-11-02 20:07:22 +01:00
Samuele E. Locatelli 35477d0daa new release! (manca filtraggio + avanzato) 2020-11-02 20:07:14 +01:00
Samuele E. Locatelli 962c19e134 Inserito prototipo gestione password calcolabile + master 2020-11-02 20:06:56 +01:00
Samuele E. Locatelli bd49fbb743 merge preliminare modificehe F.Sodano 2020-11-02 15:36:05 +01:00
Samuele E. Locatelli aa8f776659 fix config x debug 2020-11-02 15:35:54 +01:00
Ferdinando 46eae821f8 start-up 2020-05-15 16:12:37 +02:00
Ferdinando b94b0a8d33 Update README.md 2020-05-15 14:09:01 +00:00
Ferdinando 172d68c1ec Initial commit 2020-05-15 14:08:35 +00:00
19 changed files with 869 additions and 340 deletions
+153
View File
@@ -0,0 +1,153 @@
variables:
NUGET_PATH: 'C:\Tools\nuget.exe'
MSBUILD_PATH: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe'
ASPNET_MERGE_PATH: 'C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools'
NEXUS_PATH: 'OPC-UA-REDIS/SOUR'
APP_NAME: 'SOUR'
SOL_NAME: 'SOUR'
VERS_MAIN: '1.2'
NEW_REL: ''
OUTPUT_DIR: ''
# helper x fix pacchetti nuget da repo locale nexus.steamware.net
.nuget-fix: &nuget-fix
- |
$hasSource = C:\Tools\nuget.exe sources list | find "`"Steamware Nexus`"" /C
if ($hasSource -eq 0) {
C:\Tools\nuget.exe sources Add -Name "`"Steamware Nexus`"" -Source https://nexus.steamware.net/repository/nuget-group -username "`"nugetUser`"" -password "`"$NEXUS_PASSWD`""
} else {
C:\Tools\nuget.exe sources Update -Name "`"Steamware Nexus`"" -Source https://nexus.steamware.net/repository/nuget-group -username "`"nugetUser`"" -password "`"$NEXUS_PASSWD`""
}
echo $hasSource
# helper x fix version number
.version-fix: &version-fix
- |
$env:NEW_REL = $env:VERS_MAIN+"."+(get-date format yyMM)+"."+$CI_PIPELINE_IID
$contenuto = Get-Content -path 'VersGen\VersGen.cs' -Raw
$newContenuto = $contenuto -replace '0.0.0.0', $env:NEW_REL
$newContenuto | Set-Content -Path 'VersGen\VersGen.cs'
echo "Set vers: $env:NEW_REL"
# helper pulizia files zip
.cleanup-zip: &cleanup-zip
- |
$env:OUTPUT_DIR = "Releases\" + $CI_COMMIT_BRANCH + "\*"
if ((Test-Path $env:OUTPUT_DIR))
{
Remove-Item $env:OUTPUT_DIR -Force -Recurse -ErrorAction Ignore
}
echo "Clening ZIP dir: $env:OUTPUT_DIR"
# helper creazione files zip
.zipper: &zipper
- |
$7zipPath = $env:ProgramFiles+"\7-Zip\7z.exe"
if (-not (Test-Path -Path $7zipPath -PathType Leaf)) {
throw "7 zip file '$7zipPath' not found"
}
Set-Alias 7zip $7zipPath
$Target = "Releases\" + $CI_COMMIT_BRANCH + "\" + $env:APP_NAME + ".zip"
$Source = "$env:APP_NAME\bin\*"
7zip a -tzip $Target $Source
echo "called ZIP $Source --> $Target"
# helper creazione hash files
.hashBuild: &hashBuild
- |
$Target = "Releases\" + $CI_COMMIT_BRANCH + "\" + $env:APP_NAME + ".zip"
$MD5 = Get-FileHash $Target -Algorithm MD5
$SHA1 = Get-FileHash $Target -Algorithm SHA1
New-Item $Target".md5"
New-Item $Target".sha1"
$MD5.Hash | Set-Content -Path $Target".md5"
$SHA1.Hash | Set-Content -Path $Target".sha1"
echo "Created HASH files for $Target"
# helper x send su NEXUS
.nexusUpload: &nexusUpload
- |
Set-Alias mCurl C:\Windows\system32\curl.exe
$currentDate = get-date -format yyMM;
$currentTime = get-date -format ddHH;
$VersNumb = $env:NEW_REL
echo "Curr Version: $VersNumb"
$FileManIn="VersGen\manifest.xml"
$FileManOut=$env:APP_NAME +"\Resources\manifest.xml"
$FileCLogIn="VersGen\ChangeLog.html"
$FileCLogOut=$env:APP_NAME +"\Resources\ChangeLog.html"
echo "Manifest path: $FileManOut"
echo "ChangeLog path: $FileCLogOut"
if($CI_COMMIT_BRANCH -eq "master")
{
$version = "stable"
}
else
{
$version = "unstable"
}
$manData = Get-Content $FileManIn
$manData = $manData -replace "1.0.0.0", $VersNumb
$manData = $manData -replace "{{DIRNAME}}", $env:NEXUS_PATH
$manData = $manData -replace "{{BRANCHNAME}}", "$version/LAST"
$manData = $manData -replace "{{PACKNAME}}", $env:APP_NAME
Set-Content -Path $FileManOut -Value $manData
$clogData = Get-Content $FileCLogIn
$clogData = $clogData -replace "{{CURRENT-REL}}", $VersNumb
Set-Content -Path $FileCLogOut -Value $clogData
$File2Send = Get-ChildItem("Releases\$CI_COMMIT_BRANCH\*")
ForEach ($File in $File2Send) {
$FileName = Split-Path $File -leaf
echo "mCurl -s -u GitLab:$NEXUS_PASSWD --upload-file $File https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/$FileName"
mCurl -s -u GitLab:$NEXUS_PASSWD --upload-file $File https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/$FileName
echo "mCurl -s -u GitLab:$NEXUS_PASSWD --upload-file $File https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/ARCHIVE/$VersNumb/$FileName"
mCurl -s -u GitLab:$NEXUS_PASSWD --upload-file $File https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/ARCHIVE/$VersNumb/$FileName
}
echo "mCurl -s -u GitLab:$NEXUS_PASSWD --upload-file $FileManOut https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/manifest.xml"
mCurl -s -u GitLab:$NEXUS_PASSWD --upload-file $FileManOut https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/manifest.xml
echo "mCurl -s -u GitLab:$NEXUS_PASSWD --upload-file $FileCLogOut https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/ChangeLog.html"
mCurl -s -u GitLab:$NEXUS_PASSWD --upload-file $FileCLogOut https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/ChangeLog.html
# $File2Send = "Releases\" + $CI_COMMIT_BRANCH + "\" + $env:APP_NAME + ".zip"
# mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file $File2Send https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$CI_COMMIT_BRANCH/LAST/$env:APP_NAME-$version.zip
# mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file $File2Send https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$CI_COMMIT_BRANCH/ARCHIVE/$VersNumb/$env:APP_NAME-$version.zip
# mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file $File2Send".md5" https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/$env:APP_NAME-$version.zip".md5
# mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file $File2Send".sha1" https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/$env:APP_NAME-$version.zip".sha1"
# mCurl -v -u $env:NEXUS_USER:$env:NEXUS_PASSWD --upload-file bin/release/$env:APP_NAME.zip $env:NEXUS_SERVER/utility/$env:NEXUS_PATH/$version/$env:APP_NAME-$version.zip
stages:
- build
- deploy
PUB:Build:
stage: build
tags:
- win
#variables:
# - APP_NAME: 'PUB'
before_script:
- *nuget-fix
- '& "$env:NUGET_PATH" restore $env:SOL_NAME.sln' # path alla solution corrente
- *version-fix
script:
- '& "$env:MSBUILD_PATH" src\$env:APP_NAME\$env:APP_NAME.csproj -target:Build /p:Configuration=Release /p:Platform="Any CPU" /p:OutputPath=bin/ /verbosity:minimal /m'
PUB:Deploy:
stage: deploy
tags:
- win
before_script:
- *nuget-fix
- '& "$env:NUGET_PATH" restore $env:SOL_NAME.sln' # path alla solution corrente
- *version-fix
- *cleanup-zip
script:
- '& "$env:MSBUILD_PATH" src\$env:APP_NAME\$env:APP_NAME.csproj -target:Build /p:Configuration=Release /p:Platform="Any CPU" /p:OutputPath=bin/ /verbosity:minimal /m'
- *zipper
- *hashBuild
- *nexusUpload
needs: ["PUB:Build"]
Vendored
+1 -1
View File
@@ -10,7 +10,7 @@ pipeline {
/* calcolo numero versione... diverso x branch MASTER/DEVELOP */
script {
withEnv(['NEXT_BUILD_NUMBER=285']) {
withEnv(['NEXT_BUILD_NUMBER=291']) {
// env.versionNumber = VersionNumber(versionNumberString : '2.3.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true)
env.versionNumber = VersionNumber(versionNumberString : '2.3.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true, overrideBuildsAllTime: '${NEXT_BUILD_NUMBER}')
env.APP_NAME = 'SOUR'
+2 -1
View File
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpcUaCommon</RootNamespace>
<AssemblyName>OpcUaCommon</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
@@ -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" />
+154
View File
@@ -0,0 +1,154 @@
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>
/// 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)
{
// 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;
}
#endregion Public Methods
}
}
@@ -8,7 +8,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>OpcUaServer.Server</RootNamespace>
<AssemblyName>OpcUaServer.Server</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<NuGetPackageImportStamp>
+185 -92
View File
@@ -7,105 +7,198 @@ using System.Collections.Generic;
namespace OpcUaServer.Server
{
public class Server : StandardServer
{
private ServerNodeManager _serverNodeManager;
private readonly IPrinter _printer;
private readonly string _pathXml;
private readonly ServerAuthenticationService _serverAuthenticationService;
/// <summary>
/// Evento richiesta refresh invio dellos tato attuale delel conditions
/// </summary>
public event EventHandler eh_reqRefreshCondition;
public Server(IPrinter printer, string pathXml)
public class Server : StandardServer
{
_printer = printer;
_pathXml = pathXml;
_serverAuthenticationService = new ServerAuthenticationService(this);
}
#region Private Fields
public void SetNodeValue(string nodeName, object value)
{
_serverNodeManager.SetNodeValue(nodeName, value);
}
private readonly string _pathXml;
private readonly IPrinter _printer;
private readonly ServerAuthenticationService _serverAuthenticationService;
private ServerNodeManager _serverNodeManager;
public void ReportEvent(string nodeName, string eventMessage, string severity, string value, bool active)
{
_serverNodeManager.ReportEvent(nodeName, eventMessage, severity, value, active);
}
#endregion Private Fields
protected override MasterNodeManager CreateMasterNodeManager(IServerInternal server, ApplicationConfiguration configuration)
{
_printer.Print(">>>>> Server: Creating node manager");
#region Public Fields
_serverNodeManager = new ServerNodeManager(server, configuration, _printer, new XmlNodeParser(), _pathXml);
var nodeManagers = new List<INodeManager>
/// <summary>
/// Elenco dei nodi vietati ("P") per user non autenticati
/// </summary>
public static List<string> NodeVetoList = new List<string>();
#endregion Public Fields
#region Public Constructors
public Server(IPrinter printer, string pathXml)
{
_printer = printer;
_pathXml = pathXml;
_serverAuthenticationService = new ServerAuthenticationService(this);
}
#endregion Public Constructors
#region Public Events
/// <summary>
/// Evento richiesta refresh invio dellos tato attuale delel conditions
/// </summary>
public event EventHandler eh_reqRefreshCondition;
#endregion Public Events
#region Private Methods
private void SessionManager_ImpersonateUser(Session session, ImpersonateEventArgs args)
{
// check for a user name token.
_printer.Print(">>>>> Server: Authentication for session starting");
switch (args.NewIdentity)
{
case UserNameIdentityToken userNameToken:
args.Identity =
_serverAuthenticationService.VerifyPassword(userNameToken,
LoadServerProperties().ProductUri);
_printer.Print(">>>>> Server: Authentication for session userNameToken Accepted: " + args.Identity.DisplayName);
break;
case X509IdentityToken x509Token:
_serverAuthenticationService.VerifyUserTokenCertificate(x509Token.Certificate,
LoadServerProperties().ProductUri);
args.Identity = new UserIdentity(x509Token);
_printer.Print(">>>>> Server: Authentication for session X509 Token Accepted: " +
args.Identity.DisplayName);
break;
default:
_printer.Print(">>>>> Server: Authentication for session Anonymous: ");
break;
}
// 2019.04.08: aggiunta task x forzare il refresh/reinvio di TUTTE le conditions attive al momento in cui si è connesso il NUOVO client...
sendCurrCond();
}
#endregion Private Methods
#region Protected Methods
protected override MasterNodeManager CreateMasterNodeManager(IServerInternal server, ApplicationConfiguration configuration)
{
_printer.Print(">>>>> Server: Creating node manager");
_serverNodeManager = new ServerNodeManager(server, configuration, _printer, new XmlNodeParser(), _pathXml);
var nodeManagers = new List<INodeManager>
{
_serverNodeManager
};
return new MasterNodeManager(server, configuration, null, nodeManagers.ToArray());
return new MasterNodeManager(server, configuration, null, nodeManagers.ToArray());
}
protected override ServerProperties LoadServerProperties()
{
var properties = new ServerProperties
{
ManufacturerName = "Steamware",
ProductName = "Server",
ProductUri = "http://opcfoundation.org/Quickstart/ReferenceServer/v1.03",
SoftwareVersion = Utils.GetAssemblySoftwareVersion(),
BuildNumber = Utils.GetAssemblyBuildNumber(),
BuildDate = Utils.GetAssemblyTimestamp()
};
return properties;
}
protected override void OnServerStarted(IServerInternal server)
{
base.OnServerStarted(server);
server.SessionManager.ImpersonateUser += SessionManager_ImpersonateUser;
}
#endregion Protected Methods
#region Public Methods
public override ResponseHeader Browse(RequestHeader requestHeader, ViewDescription view, uint requestedMaxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos)
{
results = null;
diagnosticInfos = null;
OperationContext context = ValidateRequest(requestHeader, RequestType.Browse);
try
{
if (nodesToBrowse == null || nodesToBrowse.Count == 0)
{
throw new ServiceResultException(StatusCodes.BadNothingToDo);
}
bool filter = false;
// return empty browse results for Anonymous users
// This logic should be further extended....
if (context.UserIdentity.TokenType == UserTokenType.Anonymous)
filter = true;
// legge gli oggetti contenuti nell'elemento richeisto
ServerInternal.NodeManager.Browse(context, view, requestedMaxReferencesPerNode, nodesToBrowse, out results, out diagnosticInfos);
// se attivato il filtro == utente anonimo
if (filter)
{
foreach (var res in results)
{
// rimuove tutto tranne status...
//res.References.RemoveAll(x => x.BrowseName.Name.StartsWith("Machine/") && x.BrowseName.Name != "Machine/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/") && NodeVetoList.Contains(x.BrowseName.Name));
}
}
return CreateResponse(requestHeader, context.StringTable);
}
catch (ServiceResultException e)
{
lock (ServerInternal.DiagnosticsWriteLock)
{
ServerInternal.ServerDiagnostics.RejectedRequestsCount++;
if (IsSecurityError(e.StatusCode))
{
ServerInternal.ServerDiagnostics.SecurityRejectedRequestsCount++;
}
}
throw TranslateException(context, e);
}
finally
{
OnRequestComplete(context);
}
}
public void ReportEvent(string nodeName, string eventMessage, string severity, string value, bool active)
{
_serverNodeManager.ReportEvent(nodeName, eventMessage, severity, value, active);
}
public void sendCurrCond()
{
if (eh_reqRefreshCondition != null)
{
eh_reqRefreshCondition(this, new EventArgs());
}
}
public void SetNodeValue(string nodeName, object value)
{
_serverNodeManager.SetNodeValue(nodeName, value);
}
#endregion Public Methods
}
protected override ServerProperties LoadServerProperties()
{
var properties = new ServerProperties
{
ManufacturerName = "Steamware",
ProductName = "Server",
ProductUri = "http://opcfoundation.org/Quickstart/ReferenceServer/v1.03",
SoftwareVersion = Utils.GetAssemblySoftwareVersion(),
BuildNumber = Utils.GetAssemblyBuildNumber(),
BuildDate = Utils.GetAssemblyTimestamp()
};
return properties;
}
protected override void OnServerStarted(IServerInternal server)
{
base.OnServerStarted(server);
server.SessionManager.ImpersonateUser += SessionManager_ImpersonateUser;
}
private void SessionManager_ImpersonateUser(Session session, ImpersonateEventArgs args)
{
// check for a user name token.
_printer.Print(">>>>> Server: Authentication for session starting");
switch (args.NewIdentity)
{
case UserNameIdentityToken userNameToken:
args.Identity =
_serverAuthenticationService.VerifyPassword(userNameToken,
LoadServerProperties().ProductUri);
_printer.Print(">>>>> Server: Authentication for session userNameToken Accepted: " + args.Identity.DisplayName);
break;
case X509IdentityToken x509Token:
_serverAuthenticationService.VerifyUserTokenCertificate(x509Token.Certificate,
LoadServerProperties().ProductUri);
args.Identity = new UserIdentity(x509Token);
_printer.Print(">>>>> Server: Authentication for session X509 Token Accepted: " +
args.Identity.DisplayName);
break;
default:
_printer.Print(">>>>> Server: Authentication for session Anonymous: ");
break;
}
// 2019.04.08: aggiunta task x forzare il refresh/reinvio di TUTTE le conditions attive al momento in cui si è connesso il NUOVO client...
sendCurrCond();
}
public void sendCurrCond()
{
if(eh_reqRefreshCondition!=null)
{
eh_reqRefreshCondition(this, new EventArgs());
}
}
}
}
}
@@ -1,18 +1,37 @@
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using Opc.Ua;
using OpcUaCommon.Services;
namespace OpcUaServer.Server.Services
{
public class ServerAuthenticationService
{
#region Private Fields
private readonly Server _server;
#endregion Private Fields
#region Public Constructors
public ServerAuthenticationService(Server server)
{
_server = server;
}
#endregion Public Constructors
#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;
@@ -37,9 +56,16 @@ namespace OpcUaServer.Server.Services
// return new SystemConfigurationIdentity(new UserIdentity(userNameToken));
//}
// user / passphrase / pwd
// 9206 / 9206_6029 / lH01JCwOzgPG5zjl26p1qA==
// standard users for CTT verification
if ((userName == "user1" && password == "password") ||
(userName == "user2" && password == "password1")) return new UserIdentity(userNameToken);
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.
var info = new TranslationInfo(
"InvalidPassword",
@@ -53,7 +79,6 @@ namespace OpcUaServer.Server.Services
"InvalidPassword",
productUri,
new LocalizedText(info)));
}
public void VerifyUserTokenCertificate(X509Certificate2 certificate, string productUri)
@@ -104,5 +129,6 @@ namespace OpcUaServer.Server.Services
}
}
#endregion Public Methods
}
}
@@ -10,6 +10,12 @@ namespace OpcUaServer.Server.Services
{
public class XmlNodeParser : INodeParser
{
#region Public Properties
public Server Server { get; }
#endregion Public Properties
#region Private Methods
private static int GetValueRankFromString(string valueRank)
@@ -38,11 +44,15 @@ namespace OpcUaServer.Server.Services
var varName = component.Attributes["BrowseName"].Value;
var symbolicName = component.Attributes["SymbolicName"].Value;
var baseObjectState = CreateCondition(root, rootName + "/" + symbolicName, symbolicName, varName, component.Attributes["Type"].Value,
var bName = rootName + "/" + symbolicName;
var baseObjectState = CreateCondition(root, bName, symbolicName, varName, component.Attributes["Type"].Value,
nameSpaceIndex);
treeInstance.Variables.Add(rootName + "/" + symbolicName,
treeInstance.Variables.Add(bName,
baseObjectState);
// verifico se l'elemento sia di quelli permessi --> metto in lista...
string VGroup = component.Attributes["VGroup"]?.Value ?? "A";
checkVisibGroup(VGroup, bName);
}
private void AddEvent(FolderInstanceState treeInstance, ushort nameSpaceIndex, XmlNode component, string rootName, FolderState root)
@@ -69,13 +79,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;
@@ -96,6 +99,11 @@ namespace OpcUaServer.Server.Services
{
CreateFolder(folder, stringFolderName + "/" + varName, varName, xmlElement, stringFolderName, folderInstanceState, nameSpaceIndex);
}
// verifico se l'elemento sia di quelli permessi --> metto in lista...
string VGroup = xmlElement.Attributes["VGroup"]?.Value ?? "A";
string bName = stringFolderName + "/" + varName;
checkVisibGroup(VGroup, bName);
}
}
@@ -159,6 +167,10 @@ namespace OpcUaServer.Server.Services
treeInstance.Variables.Add(bName,
CreateVariable(parent, bName, bName, bName, type, rank,
nameSpaceIndex));
// verifico se l'elemento sia di quelli permessi --> metto in lista...
string VGroup = component.Attributes["VGroup"]?.Value ?? "A";
checkVisibGroup(VGroup, bName);
}
private void AddVariable(FolderInstanceState treeInstance, ushort nameSpaceIndex, XmlNode component,
@@ -177,11 +189,24 @@ namespace OpcUaServer.Server.Services
var valueRank = component.Attributes["ValueRank"].Value;
var builtInType = (uint)GetBuiltInTypeFromString(dataType);
var valueRankFromString = GetValueRankFromString(valueRank);
var baseDataVariableState = CreateVariable(root, rootName + "/" + symbolicName, symbolicName, varName, builtInType, valueRankFromString,
var bName = rootName + "/" + symbolicName;
var baseDataVariableState = CreateVariable(root, bName, symbolicName, varName, builtInType, valueRankFromString,
nameSpaceIndex);
treeInstance.Variables.Add(rootName + "/" + symbolicName,
treeInstance.Variables.Add(bName,
baseDataVariableState);
// verifico se l'elemento sia di quelli permessi --> metto in lista...
string VGroup = component.Attributes["VGroup"]?.Value ?? "A";
checkVisibGroup(VGroup, bName);
}
private void checkVisibGroup(string VGroup, string BrowseName)
{
if (VGroup != "A")
{
Server.NodeVetoList.Add(BrowseName);
}
}
private BaseObjectState CreateCondition(NodeState parent, string path, string symbolicName, string name, string conditiontype, ushort nameSpaceIndex)
+1 -1
View File
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SOUR.Core</RootNamespace>
<AssemblyName>SOUR.Core</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+28 -7
View File
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
namespace SOUR.Core.Services
{
@@ -498,7 +499,7 @@ namespace SOUR.Core.Services
/// <returns></returns>
public long ListLen(string queueName)
{
return connRedis.GetDatabase().ListLength((RedisKey)queueName);
return currDB.ListLength((RedisKey)queueName);
}
/// <summary>
@@ -508,7 +509,7 @@ namespace SOUR.Core.Services
/// <returns></returns>
public string ListPop(string queueName)
{
return connRedis.GetDatabase().ListLeftPop((RedisKey)queueName).ToString();
return currDB.ListLeftPop((RedisKey)queueName).ToString();
}
/// <summary>
@@ -518,7 +519,7 @@ namespace SOUR.Core.Services
/// <returns></returns>
public void ListPush(string queueName, string value)
{
connRedis.GetDatabase().ListRightPush((RedisKey)queueName, (RedisValue)value);
currDB.ListRightPush((RedisKey)queueName, (RedisValue)value);
}
/// <summary>
@@ -1076,9 +1077,29 @@ namespace SOUR.Core.Services
public bool setRKeys(KeyValuePair<RedisKey, RedisValue>[] valori)
{
bool answ = false;
// calcolo i valori "buoni" per evitare eccezione dei nulli in caso di area redis che scompaia
List<KeyValuePair<RedisKey, RedisValue>> valList = new List<KeyValuePair<RedisKey, RedisValue>>();
foreach (var item in valori)
{
if (!item.Value.IsNull)
{
valList.Add(item);
}
else
{ }
}
try
{
currDB.StringSet(valori);
// se le numerosità non corrispondono --> scrivo solo i "buoni"
if (valori.Count() != valList.Count)
{
currDB.StringSet(valList.ToArray());
}
else
{
currDB.StringSet(valori);
}
answ = true;
}
catch (Exception exc)
@@ -1163,7 +1184,7 @@ namespace SOUR.Core.Services
/// <returns></returns>
public long StackLen(string stackName)
{
return connRedis.GetDatabase().ListLength((RedisKey)stackName);
return currDB.ListLength((RedisKey)stackName);
}
/// <summary>
@@ -1173,7 +1194,7 @@ namespace SOUR.Core.Services
/// <returns></returns>
public string StackPop(string stackName)
{
return connRedis.GetDatabase().ListRightPop((RedisKey)stackName).ToString();
return currDB.ListRightPop((RedisKey)stackName).ToString();
}
/// <summary>
@@ -1183,7 +1204,7 @@ namespace SOUR.Core.Services
/// <param name="value"></param>
public void StackPush(string stackName, string value)
{
connRedis.GetDatabase().ListRightPush((RedisKey)stackName, (RedisValue)value);
currDB.ListRightPush((RedisKey)stackName, (RedisValue)value);
}
#endregion Public Methods
+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
View File
@@ -17,7 +17,6 @@
<add key="waitResendCondition" value="1500" />
<add key="waitEventDequeue" value="1000" />
<add key="simRequeue" value="true" />
<!--Gestione allarmi: modo tra TEXT / LIST-->
<add key="AlarmListMode" value="LIST" />
<!--Indica se allarmi statici (=true) oppure da rileggere SEMPRE da REDIS (=false) -->
+7 -7
View File
@@ -12,7 +12,7 @@
<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">
<Variable SymbolicName="Production" BrowseName="Production" DataType="ua:String" ValueRank="Scalar" Units="" SGroup="1" VGroup="P" />
<Variable SymbolicName="Production" BrowseName="Production" DataType="ua:String" ValueRank="Scalar" Units="" SGroup="1" />
<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" />
<Variable SymbolicName="Downtimes" BrowseName="Downtimes" DataType="ua:String" ValueRank="Scalar" Units="" SGroup="1" VGroup="P" />
@@ -22,7 +22,7 @@
<Property SymbolicName="Name" BrowseName="Name" DataType="ua:String" ValueRank="Scalar" Value="OSAI" />
<Property SymbolicName="Version" BrowseName="Version" DataType="ua:String" ValueRank="Scalar" Value="2019" />
<Condition SymbolicName="Condition" BrowseName="Condition" DataType="ua:String" ValueRank="Scalar" Type="OffNormalAlarmState" Units="" />
<Component Name="CncProcesses">
<Component Name="CncProcesses" VGroup="P">
<Component Name="01">
<Variable SymbolicName="Type" BrowseName="Type" DataType="ua:String" ValueRank="Scalar" Units="Enum" />
<Variable SymbolicName="CodG" BrowseName="CodG" DataType="ua:String" ValueRank="Scalar" Units="" SGroup="2" VGroup="P" />
@@ -41,12 +41,12 @@
</Component>
</Component>
</Component>
<Component Name="Plc">
<Component Name="Plc" VGroup="P">
<Property SymbolicName="Name" BrowseName="Name" DataType="ua:String" ValueRank="Scalar" Value="SIEMENS" />
<Property SymbolicName="Version" BrowseName="Version" DataType="ua:String" ValueRank="Scalar" Value="2019" />
<Condition SymbolicName="Condition" BrowseName="Condition" DataType="ua:String" ValueRank="Scalar" Type="OffNormalAlarmState" Units="" />
</Component>
<Component Name="Hmi">
<Component Name="Hmi" VGroup="P">
<Property SymbolicName="Name" BrowseName="Name" DataType="ua:String" ValueRank="Scalar" Value="CMS Active" />
<Property SymbolicName="Version" BrowseName="Version" DataType="ua:String" ValueRank="Scalar" Value="1.00.02" />
<Condition SymbolicName="Condition" BrowseName="Condition" DataType="ua:String" ValueRank="Scalar" Type="OffNormalAlarmState" Units="" />
@@ -55,7 +55,7 @@
<Variable SymbolicName="ActiveSection" BrowseName="ActiveSection" DataType="ua:String" ValueRank="Scalar" Units="h" />
<Variable SymbolicName="ActiveTimeSession" BrowseName="ActiveTimeSession" DataType="ua:String" ValueRank="Scalar" Units="" />
</Component>
<Component Name="Axes">
<Component Name="Axes" VGroup="P">
<Component Name="01">
<Property SymbolicName="Type" BrowseName="Type" DataType="ua:String" ValueRank="Scalar" Value="LINEAR" />
<Variable SymbolicName="Name" BrowseName="Name" DataType="ua:String" ValueRank="Scalar" Units="Enum" />
@@ -159,7 +159,7 @@
<Variable SymbolicName="ParentProc" BrowseName="ParentProc" DataType="ua:UInt32" ValueRank="Scalar" Units="" />
</Component>
</Component>
<Component Name="OperatingGroups">
<Component Name="OperatingGroups" VGroup="P">
<Component Name="01">
<Property SymbolicName="Type" BrowseName="Type" DataType="ua:String" ValueRank="Scalar" Value="SPINDLE" />
<Property SymbolicName="Model" BrowseName="Model" DataType="ua:String" ValueRank="Scalar" Value="CMS-SPINDLE-01" />
@@ -174,7 +174,7 @@
<Variable SymbolicName="ParentProc" BrowseName="ParentProc" DataType="ua:UInt32" ValueRank="Scalar" Units="" />
</Component>
</Component>
<Component Name="AuxiliaryGroups">
<Component Name="AuxiliaryGroups" VGroup="P">
<Component Name="01">
<Property SymbolicName="Type" BrowseName="Type" DataType="ua:String" ValueRank="Scalar" Value="LUBRO" />
<Variable SymbolicName="Repetitions" BrowseName="Repetitions" DataType="ua:Float" ValueRank="Scalar" Units="Count" CmsDataType="CounterList" CmsDataIndex="021" CmsDataOpt="NUM" />
+44
View File
@@ -0,0 +1,44 @@
<body>
<i>Server gestione Scehde di Collaudo</i>
<h4>Versione: {{CURRENT-REL}}</h4>
<br />
Note di rilascio:
<ul>
<li>
<b>Ultime modifiche:</b>
<ul>{{LAST-CHANGES}}</ul>
</li>
<li>
<b>v.3.1.* &rarr;</b>
<ul>
<li>Revisione ruoli</li>
<li>Gestione fasi con revisione e congelamento fasi</li>
<li>Nuovi elementi schede di collaudo</li>
<li>Implementazione sistema traduzione in campi schede/misure/parametri</li>
<li>Sistemi supporto traduzione/visualizzazione in lingua</li>
<li>Nuovi reports</li>
</ul>
</li>
<li>
<b>v.2.* &rarr;</b>
<ul>
<li>Implementazione modifiche per gestione in CMS</li>
</ul>
</li>
<li>
<b>v.1.* &rarr;</b>
<ul>
<li>Implementazione iniziale con gestione standard Ms AX + ISO9000 e succ</li>
</ul>
</li>
</ul>
<div>
<div style="float: left;">
<img src="logoSteamware.png" />
</div>
<div style="float: right;">
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2018</a>
</div>
</div>
</body>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>1.0.0.0</version>
<url>http://seriate.steamware.net:8083/SWS/CMS_SC/{{PACKNAME}}/{{BRANCHNAME}}/{{PACKNAME}}.zip</url>
<changelog>http://seriate.steamware.net:8083/SWS/CMS_SC/{{PACKNAME}}/{{BRANCHNAME}}/ChangeLog.html</changelog>
<mandatory>false</mandatory>
</item>
+1 -1
View File
@@ -9,7 +9,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>SOUR</RootNamespace>
<AssemblyName>SOUR</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<NuGetPackageImportStamp>
+1 -1
View File
@@ -8,7 +8,7 @@
<OutputType>WinExe</OutputType>
<RootNamespace>TestApp</RootNamespace>
<AssemblyName>TestApp</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>