392 lines
12 KiB
C#
392 lines
12 KiB
C#
// See https://aka.ms/new-console-template for more information
|
|
using MachineSim;
|
|
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<string>("AlarmSimMode");
|
|
Logger Log = LogManager.GetCurrentClassLogger();
|
|
Random rand = new Random();
|
|
List<MachineStatus>? statusList = new List<MachineStatus>();
|
|
List<MachineMode>? modeList = new List<MachineMode>();
|
|
|
|
// fix numero minimo dei thread pool x evitare collasso chiamate redis
|
|
ThreadPool.SetMinThreads(10, 10);
|
|
|
|
Dictionary<string, int> LogSimulator = new Dictionary<string, int>();
|
|
Dictionary<string, DateTime> LastSend = new Dictionary<string, DateTime>();
|
|
DateTime lastLog = DateTime.Now.AddMinutes(-1);
|
|
bool verboseLog = false;
|
|
bool logWriting = false;
|
|
|
|
logInfo(lineSep, true, true);
|
|
logInfo($"Starting Machine SIM", 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();
|
|
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();
|
|
|
|
/// <summary>
|
|
/// verifica esistenza file oppure lo crea...
|
|
/// </summary>
|
|
void checkFilePresent(string filePath)
|
|
{
|
|
// verific presenza file log...
|
|
if (!File.Exists(filePath))
|
|
{
|
|
File.WriteAllText(filePath, $"{filePath} created!");
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Setup e salvataggio redis delle conf (es modi/stati)
|
|
/// </summary>
|
|
void setupConf()
|
|
{
|
|
// leggo e salvo conf stati
|
|
string fullPath = Path.Combine(confPath, "ConfStatus.json");
|
|
if (File.Exists(fullPath))
|
|
{
|
|
var rawData = File.ReadAllText(fullPath);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
List<MachineStatus>? statusList = JsonConvert.DeserializeObject<List<MachineStatus>>(rawData);
|
|
// salvo in redis!
|
|
redisDb.StringSetAsync(Constants.STATUS_CONF_KEY, JsonConvert.SerializeObject(statusList));
|
|
}
|
|
}
|
|
// leggo e salvo conf modi
|
|
fullPath = Path.Combine(confPath, "ConfMode.json");
|
|
if (File.Exists(fullPath))
|
|
{
|
|
var rawData = File.ReadAllText(fullPath);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
var localObj = JsonConvert.DeserializeObject<List<MachineMode>>(rawData);
|
|
// salvo in redis!
|
|
redisDb.StringSetAsync(Constants.MODE_CONF_KEY, JsonConvert.SerializeObject(localObj));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua log INFO su file e se richiesto su console
|
|
/// </summary>
|
|
void logInfo(string msg, bool log2file = true, bool log2console = false)
|
|
{
|
|
if (log2console)
|
|
{
|
|
Console.WriteLine(msg);
|
|
}
|
|
if (log2file)
|
|
{
|
|
Log.Info(msg);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Effettua log ERROR su file e se richiesto su console
|
|
/// </summary>
|
|
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<string, int>(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}");
|
|
}
|
|
}
|
|
}
|
|
|
|
void simAlarms()
|
|
{
|
|
int minPeriod = 5000;
|
|
int maxPeriod = 10000;
|
|
|
|
do
|
|
{
|
|
List<int> currAlarmsVal = new List<int>();
|
|
List<string> activeAlarms = new List<string>();
|
|
//int alarmCode = rand.Next(0, 255);
|
|
int alarmCode = rand.Next(0, 160);
|
|
// se >= 128 --> 0 (no alarm)
|
|
alarmCode = alarmCode <= 127 ? alarmCode : 0;
|
|
currAlarmsVal.Add(alarmCode);
|
|
string rawDataVal = JsonConvert.SerializeObject(currAlarmsVal);
|
|
saveAndSendMessage(Constants.ALARM_ACT_KEY, rawDataVal, Constants.ALARM_ACT_VAL, rawDataVal);
|
|
if (alarmSimMode == "all")
|
|
{
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if ((alarmCode & (1 << i)) != 0)
|
|
{
|
|
activeAlarms.Add($"Alarm {i:000}");
|
|
}
|
|
}
|
|
string rawData = JsonConvert.SerializeObject(activeAlarms);
|
|
// decodifico allarme e lo trasformo in List<String> + List<int> di allarmi attivi...
|
|
saveAndSendMessage(Constants.ALARM_CURR_KEY, rawData, Constants.ALARM_M_QUEUE, rawData);
|
|
}
|
|
// attesa random
|
|
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
|
|
} while (true);
|
|
}
|
|
|
|
void simParameters()
|
|
{
|
|
int minPeriod = 150;
|
|
int maxPeriod = 500;
|
|
|
|
do
|
|
{
|
|
var newParams = currSimGen.getParameters();
|
|
string rawData = JsonConvert.SerializeObject(newParams);
|
|
saveAndSendMessage(Constants.PARAMS_CURR_KEY, rawData, Constants.PARAMS_M_QUEUE, rawData);
|
|
// attesa random
|
|
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
|
|
} while (true);
|
|
}
|
|
|
|
void simStatus()
|
|
{
|
|
int minPeriod = 1000;
|
|
int maxPeriod = 5000;
|
|
|
|
do
|
|
{
|
|
// recupero uno stato simulato
|
|
var newStatus = currSimGen.getStatus();
|
|
string rawData = JsonConvert.SerializeObject(newStatus);
|
|
saveAndSendMessage(Constants.STATUS_CURR_KEY, rawData, Constants.STATUS_M_QUEUE, rawData);
|
|
|
|
// attesa random
|
|
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
|
|
} while (true);
|
|
}
|
|
|
|
void simProd()
|
|
{
|
|
int minPeriod = 3000;
|
|
int maxPeriod = 10000;
|
|
|
|
do
|
|
{
|
|
// recupero uno stato simulato
|
|
var newStatus = currSimGen.getProd();
|
|
string rawData = JsonConvert.SerializeObject(newStatus);
|
|
saveAndSendMessage(Constants.PROD_CURR_KEY, rawData, Constants.PROD_M_QUEUE, rawData);
|
|
|
|
// attesa random
|
|
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
|
|
} while (true);
|
|
}
|
|
|
|
void simMachStat()
|
|
{
|
|
int minPeriod = 5000;
|
|
int maxPeriod = 15000;
|
|
|
|
do
|
|
{
|
|
// recupero uno stato simulato
|
|
var newVal = currSimGen.getProdStats();
|
|
string rawData = JsonConvert.SerializeObject(newVal);
|
|
saveAndSendMessage(Constants.MACH_STATS_CURR_KEY, rawData, Constants.MACH_STATS_M_QUEUE, rawData);
|
|
|
|
// attesa random
|
|
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
|
|
} while (true);
|
|
}
|
|
|
|
void simMaint()
|
|
{
|
|
int minPeriod = 10000;
|
|
int maxPeriod = 20000;
|
|
|
|
do
|
|
{
|
|
// recupero uno stato simulato
|
|
var newVal = currSimGen.getMaint();
|
|
string rawData = JsonConvert.SerializeObject(newVal);
|
|
saveAndSendMessage(Constants.MAINT_STATS_CURR_KEY, rawData, Constants.MAINT_STATS_M_QUEUE, rawData);
|
|
|
|
// attesa random
|
|
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
|
|
} while (true);
|
|
}
|
|
|
|
void simTools()
|
|
{
|
|
int minPeriod = 3000;
|
|
int maxPeriod = 10000;
|
|
|
|
do
|
|
{
|
|
// recupero uno stato simulato
|
|
var newVal = currSimGen.getTools();
|
|
string rawData = JsonConvert.SerializeObject(newVal);
|
|
saveAndSendMessage(Constants.TOOLS_CURR_KEY, rawData, Constants.TOOLS_M_QUEUE, rawData);
|
|
|
|
// attesa random
|
|
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
|
|
} while (true);
|
|
}
|
|
|
|
void simEvents()
|
|
{
|
|
int minPeriod = 200;
|
|
int maxPeriod = 800;
|
|
|
|
do
|
|
{
|
|
// recupero uno stato simulato
|
|
var newVal = currSimGen.getEvents();
|
|
string rawData = JsonConvert.SerializeObject(newVal);
|
|
saveAndSendMessage(Constants.EVENT_LOG_CURR_KEY, rawData, Constants.EVENT_LOG_M_QUEUE, rawData);
|
|
|
|
// attesa random
|
|
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
|
|
} while (true);
|
|
}
|
|
|
|
void simActivityLog()
|
|
{
|
|
int minPeriod = 15000;
|
|
int maxPeriod = 30000;
|
|
|
|
do
|
|
{
|
|
// recupero uno stato simulato
|
|
var newVal = currSimGen.getActLog();
|
|
string rawData = JsonConvert.SerializeObject(newVal);
|
|
saveAndSendMessage(Constants.ACT_LOG_CURR_KEY, rawData, Constants.ACT_LOG_M_QUEUE, rawData);
|
|
|
|
// attesa random
|
|
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
|
|
} while (true);
|
|
} |