From 998afbbd7e04cffee5c54d39d1c33e89c85d092c Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Fri, 18 Mar 2022 17:22:24 +0100 Subject: [PATCH] Abbozzato adapter con gestione lettura conf completa --- MP.MONO.ADAPTER/MP.MONO.ADAPTER.csproj | 49 +++++ MP.MONO.ADAPTER/Program.cs | 257 +++++++++++++++++++++++++ MP.MONO.ADAPTER/appsettings.json | 35 ++++ MP.MONO.ADAPTER/conf/AlarmList.json | 52 +++++ MP.MONO.ADAPTER/conf/ModeList.json | 58 ++++++ MP.MONO.ADAPTER/conf/StatusList.json | 58 ++++++ 6 files changed, 509 insertions(+) create mode 100644 MP.MONO.ADAPTER/MP.MONO.ADAPTER.csproj create mode 100644 MP.MONO.ADAPTER/Program.cs create mode 100644 MP.MONO.ADAPTER/appsettings.json create mode 100644 MP.MONO.ADAPTER/conf/AlarmList.json create mode 100644 MP.MONO.ADAPTER/conf/ModeList.json create mode 100644 MP.MONO.ADAPTER/conf/StatusList.json diff --git a/MP.MONO.ADAPTER/MP.MONO.ADAPTER.csproj b/MP.MONO.ADAPTER/MP.MONO.ADAPTER.csproj new file mode 100644 index 0000000..249ce4c --- /dev/null +++ b/MP.MONO.ADAPTER/MP.MONO.ADAPTER.csproj @@ -0,0 +1,49 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + + PreserveNewest + true + PreserveNewest + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + + diff --git a/MP.MONO.ADAPTER/Program.cs b/MP.MONO.ADAPTER/Program.cs new file mode 100644 index 0000000..1346475 --- /dev/null +++ b/MP.MONO.ADAPTER/Program.cs @@ -0,0 +1,257 @@ +using Microsoft.Extensions.Configuration; +using MP.MONO.Core; +using MP.MONO.Core.CONF; +using Newtonsoft.Json; +using NLog; +using StackExchange.Redis; + +// init parte config, vedere https://blog.hildenco.com/2020/05/configuration-in-net-core-console.html +var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); +var builder = new ConfigurationBuilder() + .AddJsonFile($"appsettings.json", true, true) + .AddJsonFile($"appsettings.{env}.json", true, true) + .AddEnvironmentVariables(); +var config = builder.Build(); + +// imposto variabili di base +string lineSep = "---------------------------------------------"; +string redisConf = config.GetConnectionString("Redis"); +string confPath = Path.Combine(Directory.GetCurrentDirectory(), "conf"); +string alarmSimMode = config.GetValue("AlarmSimMode"); +Logger Log = LogManager.GetCurrentClassLogger(); +Random rand = new Random(); +List? statusList = new List(); +List? modeList = new List(); + +// fix numero minimo dei thread pool x evitare collasso chiamate redis +ThreadPool.SetMinThreads(10, 10); + +Dictionary LogSimulator = new Dictionary(); +Dictionary LastSend = new Dictionary(); +DateTime lastLog = DateTime.Now.AddMinutes(-1); +bool verboseLog = false; +bool logWriting = false; + +logInfo(lineSep, true, true); +logInfo($"Starting Machine ADAPTER", true, true); +logInfo($"Redis server param: {redisConf.Substring(0, 20)}...", false, true); +logInfo(lineSep, true, true); +logInfo("", true, true); +logInfo("Running - press CTRL-C to stop SIM", false, true); +logInfo("", false, true); + +//Create a connection +ConnectionMultiplexer.SetFeatureFlag("preventthreadtheft", true); +ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(redisConf); +ISubscriber sub = redis.GetSubscriber(); +IDatabase? redisDb = redis.GetDatabase(); + +// salvo configurazioni in redis +setupConf(); + +#if false +var currSimGen = new Simulator(confPath, modeList.Count, statusList.Count); + +// preparo la lista dei contatori invio... +LogSimulator.Add(Constants.ACT_LOG_M_QUEUE, 0); +LogSimulator.Add(Constants.ALARM_M_QUEUE, 0); +LogSimulator.Add(Constants.EVENT_LOG_M_QUEUE, 0); +LogSimulator.Add(Constants.PARAMS_M_QUEUE, 0); +LogSimulator.Add(Constants.PROD_M_QUEUE, 0); +LogSimulator.Add(Constants.MACH_STATS_M_QUEUE, 0); +LogSimulator.Add(Constants.MAINT_STATS_M_QUEUE, 0); +LogSimulator.Add(Constants.TOOLS_M_QUEUE, 0); + +// avvio tutti i thread... +Thread threadStatus = new Thread(simStatus); +Thread threadAlarms = new Thread(simAlarms); +Thread threadParams = new Thread(simParameters); +Thread threadProd = new Thread(simProd); +Thread threadMachStat = new Thread(simMachStat); +Thread threadMaint = new Thread(simMaint); +Thread threadTools = new Thread(simTools); +Thread threadEvHistory = new Thread(simEvents); +Thread threadActLog = new Thread(simActivityLog); + +threadStatus.Start(); +threadAlarms.Start(); +threadParams.Start(); +threadProd.Start(); +threadMachStat.Start(); +threadMaint.Start(); +threadTools.Start(); +threadEvHistory.Start(); +threadActLog.Start(); +#endif + +// Ciclo infinito x attesa chiusura con CTRL-C +do +{ + Thread.Sleep(100); +} while (true); + + +/// +/// verifica esistenza file oppure lo crea... +/// +void checkFilePresent(string filePath) +{ + // verific presenza file log... + if (!File.Exists(filePath)) + { + File.WriteAllText(filePath, $"{filePath} created!"); + } +} + +/// +/// Setup e salvataggio redis delle conf (es modi/stati) +/// +void setupConf() +{ + // leggo e salvo conf stati + string fullPath = Path.Combine(confPath, "StatusList.json"); + if (File.Exists(fullPath)) + { + var rawData = File.ReadAllText(fullPath); + if (!string.IsNullOrEmpty(rawData)) + { + List? statusList = JsonConvert.DeserializeObject>(rawData); + // salvo in redis! + redisDb.StringSetAsync(Constants.STATUS_CONF_KEY, JsonConvert.SerializeObject(statusList)); + } + } + + // leggo e salvo conf modi + fullPath = Path.Combine(confPath, "ModeList.json"); + if (File.Exists(fullPath)) + { + var rawData = File.ReadAllText(fullPath); + if (!string.IsNullOrEmpty(rawData)) + { + var localObj = JsonConvert.DeserializeObject>(rawData); + // salvo in redis! + redisDb.StringSetAsync(Constants.MODE_CONF_KEY, JsonConvert.SerializeObject(localObj)); + } + } + + // leggo e salvo conf allarmi + fullPath = Path.Combine(confPath, "AlarmList.json"); + if (File.Exists(fullPath)) + { + var rawData = File.ReadAllText(fullPath); + if (!string.IsNullOrEmpty(rawData)) + { + var localObj = JsonConvert.DeserializeObject>(rawData); + if (localObj != null) + { + // sistemo allarmi + foreach (var item in localObj) + { + item.setupData(); + // loggo + logInfo($"Decodifica aree alarmMap: {item.description} | {item.memAddr} x {item.size} byte | {item.messages.Count} messaggi allarme", true, true); + } + } + // salvo in redis! + redisDb.StringSetAsync(Constants.ALARMS_CONF_KEY, JsonConvert.SerializeObject(localObj)); + } + } +} + +/// +/// Effettua log INFO su file e se richiesto su console +/// +void logInfo(string msg, bool log2file = true, bool log2console = false) +{ + if (log2console) + { + Console.WriteLine(msg); + } + if (log2file) + { + Log.Info(msg); + } +} +/// +/// Effettua log ERROR su file e se richiesto su console +/// +void logError(string msg, bool log2file = true, bool log2console = false) +{ + if (log2console) + { + Console.WriteLine(msg); + } + if (log2file) + { + Log.Error(msg); + } +} + +void saveAndSendMessage(string memKey, string value, string notifyChannel, string message) +{ + // effettuo la scrittura nell'area di memoria indicata SE passato intervallo minimo + bool doSend = true; + if (LastSend.ContainsKey(memKey)) + { + if (DateTime.Now.Subtract(LastSend[memKey]).TotalSeconds < 60) + { + doSend = false; + } + } + else + { + LastSend.Add(memKey, DateTime.Now); + } + if (doSend) + { + redisDb.StringSetAsync(memKey, value); + LastSend[memKey] = DateTime.Now; + logInfo($"Redis Cache Key: {memKey}"); + } + //redisDb.SetAdd(memKey, value); + + // invio notifica tramite il canale richiesto + sub.Publish(notifyChannel, message); + if (verboseLog) + { + logInfo($"[{notifyChannel}] key: {memKey} | val: {value} | message: {message}"); + } + else + { + try + { + if (!logWriting) + { + if (LogSimulator.ContainsKey(notifyChannel)) + { + LogSimulator[notifyChannel]++; + } + else + { + LogSimulator.Add(notifyChannel, 1); + } + logWriting = true; + // vedo se loggare... + DateTime adesso = DateTime.Now; + if (adesso.Subtract(lastLog).TotalSeconds > 15) + { + lastLog = adesso; + logInfo(lineSep); + + // lavoro su copia... + var LogSimulatorCopy = new Dictionary(LogSimulator); + foreach (var item in LogSimulatorCopy) + { + logInfo($"Redis mQueue {item.Key,-20}{item.Value,12}"); + } + logInfo(lineSep); + } + logWriting = false; + } + } + catch (Exception ex) + { + logError($"ERROR{Environment.NewLine}{ex}"); + } + } +} \ No newline at end of file diff --git a/MP.MONO.ADAPTER/appsettings.json b/MP.MONO.ADAPTER/appsettings.json new file mode 100644 index 0000000..12d7629 --- /dev/null +++ b/MP.MONO.ADAPTER/appsettings.json @@ -0,0 +1,35 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "Redis": "nkcredis.steamware.net:6379,DefaultDatabase=7,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,password=nkc.password", + "AuthConnection": "Server=localhost;port=3306;database=GWMS;user=GWMS;pwd=GWMS_secret_pwd;sslmode=None;", + "DefaultConnection": "Server=localhost;port=3306;database=MAPO.MONO;user=GWMS;pwd=GWMS_secret_pwd;sslmode=None;", + "AdminConnection": "Server=localhost;port=3306;database=MAPO.MONO;user=root;pwd=Egalware_24068!;sslmode=None;", + "MP.MONO.Data": "Server=localhost;port=3306;database=MAPO.MONO;user=GWMS;pwd=GWMS_secret_pwd;sslmode=None;" + }, + "DbConfig": { + "Server": "10.74.82.230", + "nKey": "MONO", + "sKey": "Calcium0xide-CaO" + }, + "MachineId": 1, + "maxRecord": 15, + "ExternalProviders": { + "MailKit": { + "SMTP": { + "Address": "smtp.gmail.com", + "Port": "465", + "Account": "steamwarebot@gmail.com", + "Password": "drmfsls16", + "SenderEmail": "steamwarebot@gmail.com", + "SenderName": "Steamware Email BOT" + } + } + } +} diff --git a/MP.MONO.ADAPTER/conf/AlarmList.json b/MP.MONO.ADAPTER/conf/AlarmList.json new file mode 100644 index 0000000..66b658b --- /dev/null +++ b/MP.MONO.ADAPTER/conf/AlarmList.json @@ -0,0 +1,52 @@ +[ + { + "description": "General Alarm", + "tipoMem": "DInt", + "memAddr": "40901", + "index": 901, + "size": 2, + "messages": [ + "Alarm 001", + "Alarm 002", + "Alarm 003", + "Alarm 004", + "Alarm 005", + "Alarm 006", + "Alarm 007", + "Alarm 008", + "##Alarm 009", + "##Alarm 010", + "##Alarm 011", + "##Alarm 012", + "##Alarm 013", + "##Alarm 014", + "##Alarm 015", + "##Alarm 016" + ] + }, + { + "description": "Secondary Alarm", + "tipoMem": "DInt", + "memAddr": "40907", + "index": 907, + "size": 2, + "messages": [ + "Warning 001", + "Warning 002", + "Warning 003", + "Warning 004", + "Warning 005", + "Warning 006", + "##Warning 007", + "##Warning 008", + "##Warning 009", + "Warning 010", + "Warning 011", + "Warning 012", + "Warning 013", + "Warning 014", + "Warning 015", + "Warning 016" + ] + } +] \ No newline at end of file diff --git a/MP.MONO.ADAPTER/conf/ModeList.json b/MP.MONO.ADAPTER/conf/ModeList.json new file mode 100644 index 0000000..c71df53 --- /dev/null +++ b/MP.MONO.ADAPTER/conf/ModeList.json @@ -0,0 +1,58 @@ +[ + { + "MModeID": 0, + "Description": "UNDEFINED", + "Css": "bg-dark text-light", + "Priority": 1, + "Group": "POWEROFF" + }, + { + "MModeID": 1, + "Description": "EXE", + "Css": "bg-success text-light", + "Priority": 2, + "Group": "RUN" + }, + { + "MModeID": 2, + "Description": "READY", + "Css": "bg-primary text-light", + "Priority": 3, + "Group": "MANUAL" + }, + { + "MModeID": 3, + "Description": "HOLD", + "Css": "bg-warning text-light", + "Priority": 3, + "Group": "MANUAL" + }, + { + "MModeID": 4, + "Description": "FEED_HOLD", + "Css": "bg-warning text-light", + "Priority": 3, + "Group": "MANUAL" + }, + { + "MModeID": 5, + "Description": "OPTIONAL_STOP", + "Css": "bg-danger text-warning", + "Priority": 3, + "Group": "ERROR" + }, + { + "MModeID": 6, + "Description": "PROGRAM_STOPPED", + "Css": "bg-warning text-light", + "Priority": 3, + "Group": "MANUAL" + }, + { + "MModeID": 7, + "Description": "DONE", + "Css": "bg-primary text-light", + "Priority": 3, + "Group": "MANUAL" + } +] \ No newline at end of file diff --git a/MP.MONO.ADAPTER/conf/StatusList.json b/MP.MONO.ADAPTER/conf/StatusList.json new file mode 100644 index 0000000..e374c71 --- /dev/null +++ b/MP.MONO.ADAPTER/conf/StatusList.json @@ -0,0 +1,58 @@ +[ + { + "MStatusID": 0, + "Description": "UNDEFINED", + "Css": "bg-dark text-light", + "Priority": 1, + "Group": "POWEROFF" + }, + { + "MStatusID": 1, + "Description": "POWEROFF", + "Css": "bg-secondary text-light", + "Priority": 1, + "Group": "POWEROFF" + }, + { + "MStatusID": 2, + "Description": "AUTOMATIC", + "Css": "bg-success text-light", + "Priority": 2, + "Group": "RUN" + }, + { + "MStatusID": 3, + "Description": "EDIT", + "Css": "bg-warning text-light", + "Priority": 3, + "Group": "MANUAL" + }, + { + "MStatusID": 4, + "Description": "SEMIAUTOMATIC", + "Css": "bg-warning text-light", + "Priority": 3, + "Group": "MANUAL" + }, + { + "MStatusID": 5, + "Description": "MANUAL_JOG", + "Css": "bg-warning text-light", + "Priority": 3, + "Group": "MANUAL" + }, + { + "MStatusID": 6, + "Description": "ALARM", + "Css": "bg-danger text-warning", + "Priority": 3, + "Group": "ERROR" + }, + { + "MStatusID": 7, + "Description": "ESTOP", + "Css": "bg-danger text-light", + "Priority": 3, + "Group": "ERROR" + } +] \ No newline at end of file