b86a6021bf
- Adapter - Decoder - UI
759 lines
26 KiB
C#
759 lines
26 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using MP.MONO.Core;
|
|
using MP.MONO.Core.CONF;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Net;
|
|
using System.Net.NetworkInformation;
|
|
using System.Text.RegularExpressions;
|
|
using static MP.MONO.Core.CONF.OpcUaParamConf;
|
|
using static MP.MONO.Core.Enums;
|
|
|
|
namespace MP.MONO.ADAPTER.OPC
|
|
{
|
|
public class IobGeneric
|
|
{
|
|
#region Public Fields
|
|
|
|
/// <summary>
|
|
/// Struttura memoria PLC x lettura/scrittura da JSON file
|
|
/// </summary>
|
|
public plcMemMap memMap;
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Avvia generico IOB
|
|
/// </summary>
|
|
/// <param name="confPath"></param>
|
|
/// <param name="config"></param>
|
|
public IobGeneric(string confPath, IConfigurationRoot? config)
|
|
{
|
|
lg = LogManager.GetCurrentClassLogger();
|
|
connectionOk = false;
|
|
configPath = confPath;
|
|
confMan = config;
|
|
if (confMan != null)
|
|
{
|
|
// carico dati endpoint
|
|
var selection = confMan.GetSection("Endpoint");
|
|
if (selection.Exists())
|
|
{
|
|
// recupero dati endpoint
|
|
cIobConf = selection.Get<EndpointData>();
|
|
}
|
|
// carico dati OptPar
|
|
var optPar = confMan.GetSection("OptPar");
|
|
if (optPar.Exists())
|
|
{
|
|
// configurazione gestione log
|
|
Log2Console = optPar.GetValue<bool>("Log2Console");
|
|
Log2File = optPar.GetValue<bool>("Log2File");
|
|
|
|
// configurazione gestione split/regexp dati
|
|
ForceSplit = optPar.GetValue<bool>("ForceSplit");
|
|
CleanupRegexpPre = optPar.GetValue<string>("CleanupRegexpPre");
|
|
if (optPar.GetValue<bool>("FiltCrLf"))
|
|
{
|
|
FiltSplitChar = new char[] { '\n', '\r', '\0' };
|
|
}
|
|
else
|
|
{
|
|
FiltSplitChar = optPar.GetValue<char[]>("FiltSplitChar");
|
|
}
|
|
CleanupRegexpPost = optPar.GetValue<string>("CleanupRegexpPost");
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// indica se ping disabilitato da optPar
|
|
/// </summary>
|
|
public bool pingDisabled
|
|
{
|
|
get => getCRB("NO_PING");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica SE si debba fare log verboso (verboso + ogni tot letture IN)
|
|
/// </summary>
|
|
public bool verboseLog
|
|
{
|
|
get
|
|
{
|
|
bool answ = false;
|
|
int logEvery = getCRI("logEvery");
|
|
if (logEvery < 1)
|
|
{
|
|
logEvery = 10;
|
|
}
|
|
|
|
answ = getCRB("verbose") && (nReadIN % logEvery == 0);
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Esecuzione dei task richiesti e pulizia coda richieste eseguite
|
|
/// </summary>
|
|
/// <param name="task2exe"></param>
|
|
public virtual Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
|
|
{
|
|
// Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti...
|
|
Dictionary<string, string> taskDone = new Dictionary<string, string>();
|
|
if (task2exe != null)
|
|
{
|
|
// controllo se memMap != null...
|
|
if (memMap != null)
|
|
{
|
|
bool taskOk = false;
|
|
string taskVal = "";
|
|
// cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4
|
|
foreach (var item in task2exe)
|
|
{
|
|
taskOk = false;
|
|
taskVal = "";
|
|
// converto richiesta in enum...
|
|
taskType tName = taskType.nihil;
|
|
Enum.TryParse(item.Key, out tName);
|
|
// controllo sulla KEY...
|
|
switch (tName)
|
|
{
|
|
case taskType.setArt:
|
|
case taskType.setComm:
|
|
case taskType.setProg:
|
|
case taskType.setPzComm:
|
|
// recupero dati da memMap...
|
|
if (memMap != null && memMap.mMapWrite != null)
|
|
{
|
|
if (memMap.mMapWrite.ContainsKey(item.Key))
|
|
{
|
|
dataConf currMem = memMap.mMapWrite[item.Key];
|
|
string addr = currMem.memAddr;
|
|
taskVal = $"SET task: {item.Key} --> {item.Value} | mem: {currMem.memAddr} - {currMem.size} byte";
|
|
// salvo il nuovo valore nella memoria... così prox invio lo trasmetterà
|
|
memMap.mMapWrite[item.Key].value = item.Value;
|
|
}
|
|
else
|
|
{
|
|
taskVal = $"NO DATA MEM, SET task: {item.Key} --> {item.Value}";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
taskVal = $"NO MemMap found, SET task: {item.Key} --> {item.Value}";
|
|
}
|
|
// salvo in currProd..
|
|
saveProdData(new KeyValuePair<string, string>(item.Key, item.Value));
|
|
|
|
break;
|
|
|
|
case taskType.forceResetPzCount:
|
|
// reset contapezzi inizio setup
|
|
taskOk = resetcontapezziPLC();
|
|
taskVal = taskOk ? "RESET PZ COUNT OK" : "PZ RESET DISABLED | NO EXEC";
|
|
logInfo($"Chiamata forceResetPzCount: taskOk: {taskOk} | taskVal: {taskVal}");
|
|
break;
|
|
|
|
case taskType.startSetup:
|
|
// reset contapezzi inizio setup
|
|
taskOk = resetcontapezziPLC();
|
|
taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC";
|
|
logInfo($"Chiamata startSetup: taskOk: {taskOk} | taskVal: {taskVal}");
|
|
break;
|
|
|
|
case taskType.stopSetup:
|
|
// reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO
|
|
if (getCRB("ENABLE_PZ_RESET_stopSetup"))
|
|
{
|
|
taskOk = resetcontapezziPLC();
|
|
}
|
|
taskVal = taskOk ? "RESET: SETUP END" : "PZ RESET DISABLED | NO EXEC";
|
|
logInfo($"Chiamata stopSetup: taskOk: {taskOk} | taskVal: {taskVal}");
|
|
break;
|
|
|
|
case taskType.setParameter:
|
|
// richiedo da URL i parametri WRITE da popolare
|
|
logInfo("Chiamata setParameter --> processMemWriteRequests");
|
|
taskVal = processMemWriteRequests();
|
|
// se restituiscce "" faccio altra prova...
|
|
if (string.IsNullOrEmpty(taskVal))
|
|
{
|
|
// i parametri me li aspetto come stringa composta paramName|paramvalue
|
|
if (item.Value.Contains("|"))
|
|
{
|
|
string[] paramsJob = item.Value.Split('|');
|
|
taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}";
|
|
}
|
|
else
|
|
{
|
|
taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value";
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
|
|
logInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
|
|
break;
|
|
}
|
|
// aggiungo task!
|
|
taskDone.Add(item.Key, taskVal);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
logError($"Attenzione! memMap è nullo, non posso eseguire task2exe!");
|
|
}
|
|
}
|
|
|
|
return taskDone;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fornisce il valore di flusso e valore in formato valido x messa in coda nel formato
|
|
/// dtEve#flusso#valore#cont <paramref name="flusso">Flusso dati</paramref><paramref
|
|
/// name="valore">Valore da salvare</paramref>
|
|
/// </summary>
|
|
public string qEncodeFLog(string flusso, string valore)
|
|
{
|
|
string answ = "";
|
|
// fixme todo !!! fare tenere? cambiare? modificare? si dovrebbe cambiare con invio su
|
|
// channel REDIS dei dati ricevuti, eventualmente divisi x canale secondo setup
|
|
#if false
|
|
try
|
|
{
|
|
answ = $"{DateTime.Now:yyyyMMddHHmmssfff}#{flusso}#{valore}#{counterULog}";
|
|
}
|
|
catch
|
|
{ }
|
|
#endif
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Metodo generico di reset contapezzi...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public virtual bool resetcontapezziPLC()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salva valori indicati in prod data
|
|
/// </summary>
|
|
/// <param name="item">Item KVP di cui salvare i dati in currProdData come chiave/valore</param>
|
|
/// <returns></returns>
|
|
public void saveProdData(KeyValuePair<string, string> item)
|
|
{
|
|
// imposto i valori...
|
|
if (currProdData.ContainsKey(item.Key))
|
|
{
|
|
currProdData[item.Key] = item.Value;
|
|
}
|
|
else
|
|
{
|
|
currProdData.Add(item.Key, item.Value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Metodo base connessione...
|
|
/// </summary>
|
|
public virtual void tryConnect()
|
|
{
|
|
dtAvvioAdp = DateTime.Now;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Metodo base disconnessione...
|
|
/// </summary>
|
|
public virtual void tryDisconnect()
|
|
{
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Internal Fields
|
|
|
|
/// <summary>
|
|
/// valore booleano di check se sia stato AVVIATO l'adapter (Running)
|
|
/// </summary>
|
|
internal bool adpRunning = false;
|
|
|
|
/// <summary>
|
|
/// Data/ora ultimo avvio adapter
|
|
/// </summary>
|
|
internal DateTime dtAvvioAdp = DateTime.Now;
|
|
|
|
/// <summary>
|
|
/// Data/ora ultimo spegnimento adapter
|
|
/// </summary>
|
|
internal DateTime dtStopAdp = DateTime.Now;
|
|
|
|
/// <summary>
|
|
/// dataOra ultimo log periodico...
|
|
/// </summary>
|
|
internal DateTime lastPeriodicLog;
|
|
|
|
/// <summary>
|
|
/// dataOra ultimo PING inviato verso il PLC...
|
|
/// </summary>
|
|
internal DateTime lastPING = DateTime.Now.AddHours(-1);
|
|
|
|
/// <summary>
|
|
/// indica se serva refresh parametri e quindi PLC...
|
|
/// </summary>
|
|
internal bool needRefresh = true;
|
|
|
|
#endregion Internal Fields
|
|
|
|
#region Internal Properties
|
|
|
|
/// <summary>
|
|
/// COnfiguraizone Endpoint corrente
|
|
/// </summary>
|
|
internal EndpointData cIobConf { get; set; } = new EndpointData();
|
|
|
|
/// <summary>
|
|
/// Stringa regexp da usare x bonifica caratteri, POST split
|
|
/// </summary>
|
|
internal string CleanupRegexpPost { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Stringa regexp da usare x bonifica caratteri, PRE split
|
|
/// </summary>
|
|
internal string CleanupRegexpPre { get; set; } = "";
|
|
|
|
internal string configPath { get; set; } = "";
|
|
|
|
internal IConfigurationRoot? confMan { get; set; } = null!;
|
|
|
|
/// <summary>
|
|
/// Salva verifica stato connessione OK
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal virtual bool connectionOk
|
|
{
|
|
get
|
|
{
|
|
return _connOk;
|
|
}
|
|
set
|
|
{
|
|
_connOk = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Carattere x eventuale split/filt valori notificati
|
|
/// </summary>
|
|
internal char[] FiltSplitChar { get; set; } = new char[1];
|
|
|
|
/// <summary>
|
|
/// Indica se forzare split caratteri letti
|
|
/// </summary>
|
|
internal bool ForceSplit { get; set; } = false;
|
|
|
|
/// <summary>
|
|
/// Abilitazione al log su console
|
|
/// </summary>
|
|
internal bool Log2Console { get; set; } = false;
|
|
|
|
/// <summary>
|
|
/// Abilitazione al log su file
|
|
/// </summary>
|
|
internal bool Log2File { get; set; } = false;
|
|
|
|
#endregion Internal Properties
|
|
|
|
#region Internal Methods
|
|
|
|
/// <summary>
|
|
/// Effettua log INFO su file e se richiesto su console
|
|
/// </summary>
|
|
internal static void logInfo(string msg, bool log2file = true, bool log2console = true)
|
|
{
|
|
if (log2console)
|
|
{
|
|
Console.WriteLine("INFO | " + msg);
|
|
}
|
|
if (log2file)
|
|
{
|
|
lg.Info(msg);
|
|
}
|
|
}
|
|
|
|
internal bool getCRB(string keyName)
|
|
{
|
|
bool answ = false;
|
|
answ = confMan.GetValue<bool>(keyName);
|
|
return answ;
|
|
}
|
|
|
|
internal int getCRI(string keyName)
|
|
{
|
|
int answ = -1;
|
|
answ = confMan.GetValue<int>(keyName);
|
|
return answ;
|
|
}
|
|
|
|
internal string getCRS(string keyName)
|
|
{
|
|
string answ = "";
|
|
answ = confMan.GetValue<string>(keyName);
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua log DEBUG su file e se richiesto su console
|
|
/// </summary>
|
|
internal void logDebug(string msg)
|
|
{
|
|
if (Log2Console)
|
|
{
|
|
Console.WriteLine("DEBUG | " + msg);
|
|
}
|
|
if (Log2File)
|
|
{
|
|
lg.Debug(msg);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua log ERROR su file e se richiesto su console
|
|
/// </summary>
|
|
internal void logError(string msg)
|
|
{
|
|
if (Log2Console)
|
|
{
|
|
Console.WriteLine("ERROR | " + msg);
|
|
}
|
|
if (Log2File)
|
|
{
|
|
lg.Error(msg);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua log FATAL su file e se richiesto su console
|
|
/// </summary>
|
|
internal void logFatal(string msg)
|
|
{
|
|
if (Log2Console)
|
|
{
|
|
Console.WriteLine("FATAL | " + msg);
|
|
}
|
|
if (Log2File)
|
|
{
|
|
lg.Fatal(msg);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua log TRACE su file e se richiesto su console
|
|
/// </summary>
|
|
internal void logTrace(string msg)
|
|
{
|
|
if (Log2Console)
|
|
{
|
|
Console.WriteLine("TRACE | " + msg);
|
|
}
|
|
if (Log2File)
|
|
{
|
|
lg.Trace(msg);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua pulizia caratteri da valori non ammessi...
|
|
/// </summary>
|
|
/// <param name="rawData"></param>
|
|
/// <returns></returns>
|
|
internal string stringCleanup(string rawData)
|
|
{
|
|
string currVal = "";
|
|
string temp = "";
|
|
|
|
// Step 01: pulizia dati preliminare (SE impostato cleanup...)
|
|
if (!string.IsNullOrEmpty(CleanupRegexpPre))
|
|
{
|
|
Regex rgxPre = new Regex(CleanupRegexpPre);
|
|
temp = rgxPre.Replace(rawData, "");
|
|
}
|
|
else
|
|
{
|
|
temp = rawData;
|
|
}
|
|
// Step 02: se è abilitato filt/split...
|
|
if (ForceSplit)
|
|
{
|
|
var dataArray = temp.Split(FiltSplitChar);
|
|
if (dataArray.Length > 0)
|
|
{
|
|
currVal = dataArray[0];
|
|
}
|
|
}
|
|
// Step 03: se non ok copio x intero
|
|
if (string.IsNullOrEmpty(currVal))
|
|
{
|
|
currVal = temp;
|
|
}
|
|
|
|
// Step 04: pulizia dati finale (SE impostato cleanup...)
|
|
if (!string.IsNullOrEmpty(CleanupRegexpPost))
|
|
{
|
|
Regex rgxPost = new Regex(CleanupRegexpPost);
|
|
currVal = rgxPost.Replace(currVal, "");
|
|
}
|
|
|
|
return currVal;
|
|
}
|
|
|
|
#endregion Internal Methods
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// wrapper di log
|
|
/// </summary>
|
|
protected static Logger lg;
|
|
|
|
protected bool _connOk = false;
|
|
|
|
/// <summary>
|
|
/// Dizionario valori impostati x produzione
|
|
/// </summary>
|
|
protected Dictionary<string, string> currProdData = new Dictionary<string, string>();
|
|
|
|
/// <summary>
|
|
/// Dizionario ultimi valori (double) delle TSVC
|
|
/// </summary>
|
|
protected Dictionary<string, double> LastTSVC = new Dictionary<string, double>();
|
|
|
|
/// <summary>
|
|
/// Dizionario di VC da trattare come TimeSeries (con conf decodificata + processing successivo...)
|
|
/// </summary>
|
|
protected Dictionary<string, VCData> TSVC_Data = new Dictionary<string, VCData>();
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Properties
|
|
|
|
/// <summary>
|
|
/// Numero letture IN da avvio
|
|
/// </summary>
|
|
protected int nReadIN { get; set; }
|
|
|
|
/// <summary>
|
|
/// test ping all'indirizzo PLC/CNC impostato nei parametri
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected IPStatus testPingMachine
|
|
{
|
|
get
|
|
{
|
|
IPStatus answ = IPStatus.Unknown;
|
|
// se disabilitato salto...
|
|
if (pingDisabled)
|
|
{
|
|
answ = IPStatus.Success;
|
|
}
|
|
else
|
|
{
|
|
IPAddress address;
|
|
PingReply reply;
|
|
using (Ping pingSender = new Ping())
|
|
{
|
|
address = IPAddress.Loopback;
|
|
int pingMsTimeout = cIobConf.PingMsTimeout;
|
|
IPAddress.TryParse(cIobConf.IpAddress, out address);
|
|
try
|
|
{
|
|
// se != null --> uso address...
|
|
if (address != null)
|
|
{
|
|
reply = pingSender.Send(address, pingMsTimeout);
|
|
}
|
|
else
|
|
{
|
|
reply = pingSender.Send(cIobConf.IpAddress, pingMsTimeout);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
reply = pingSender.Send(IPAddress.Loopback, pingMsTimeout);
|
|
}
|
|
answ = reply.Status;
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
#endregion Protected Properties
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// Stringa raw dei parametri da scrivere...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected string getParams2write()
|
|
{
|
|
string answ = "";
|
|
// recuperare da una apposita area REDIS...
|
|
#if false
|
|
string url2call = $"{urlGetParams2Write}";
|
|
if (verboseLog)
|
|
{
|
|
lgInfo("chiamata URL " + url2call);
|
|
}
|
|
answ = utils.callUrlNow(url2call);
|
|
// se vuoto faccio seconda prova...
|
|
if (string.IsNullOrEmpty(answ))
|
|
{
|
|
answ = utils.callUrlNow(url2call);
|
|
}
|
|
#endif
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Metodo da overridare x scrivere DAVVERO i parametri sul PLC
|
|
/// </summary>
|
|
/// <param name="updatedPar"></param>
|
|
protected virtual void plcWriteParams(ref List<objItem> updatedPar)
|
|
{
|
|
// non faccio nulla di base...
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processa le richieste di scrittura memoria
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected string processMemWriteRequests()
|
|
{
|
|
string answ = "";
|
|
// li salvo nei parametri in memoria locale (ogni adapter DOVREBBE salvare POI sul VERO PLC)
|
|
List<objItem> writeList = new List<objItem>();
|
|
List<objItem> updatedPar = new List<objItem>();
|
|
// recupero elenco delle cose da fare
|
|
string resp = getParams2write();
|
|
if (!string.IsNullOrEmpty(resp))
|
|
{
|
|
try
|
|
{
|
|
writeList = JsonConvert.DeserializeObject<List<objItem>>(resp);
|
|
// se ho da fare chiamo esecuzione..
|
|
if (writeList.Count > 0)
|
|
{
|
|
foreach (var item in writeList)
|
|
{
|
|
// scrivo in memoria
|
|
if (memMap.mMapWrite.ContainsKey(item.uid))
|
|
{
|
|
memMap.mMapWrite[item.uid].value = item.reqValue;
|
|
// accodo in stringa taskVal...
|
|
answ += $" | Parameter {item.uid} --> {item.reqValue}";
|
|
// sistemo valori
|
|
item.value = item.reqValue;
|
|
logInfo($"Richiesta update parametro {item.uid} | actVal = {item.value} | reqVal = {item.reqValue}");
|
|
item.reqValue = "";
|
|
// salvo in lista da ritrasmettere
|
|
updatedPar.Add(item);
|
|
}
|
|
else
|
|
{
|
|
answ += $" | Error: parameter {item.uid} not found";
|
|
}
|
|
}
|
|
// richiamo scrittura parametri su PLC
|
|
plcWriteParams(ref updatedPar);
|
|
// invio su cloud parametri!
|
|
string rawData = JsonConvert.SerializeObject(updatedPar);
|
|
logInfo("Notifica a server scrittura parametri");
|
|
#if false
|
|
utils.callUrl($"{urlUpdateWriteParams}", rawData);
|
|
#endif
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
logError($"Eccezione in processMemWriteRequests:{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
logError("Non è stata ricevuta risposta x task da eseguire");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// setup parametri da file di conf
|
|
/// </summary>
|
|
protected void setupMemMap()
|
|
{
|
|
logInfo($"setupMemMap | trovati {memMap.mMapRead.Count} parametri Read (TSVC)");
|
|
logInfo($"setupMemMap | trovati {memMap.mMapWrite.Count} parametri Write");
|
|
if (getCRB("verbose"))
|
|
{
|
|
string rawMemConf = JsonConvert.SerializeObject(memMap, Formatting.Indented);
|
|
logDebug($"setupMemMap | configurazione memoria R/W:{Environment.NewLine}{rawMemConf}");
|
|
}
|
|
// se ho variabili read --> genero dati TSVC...
|
|
if (memMap.mMapRead.Count > 0)
|
|
{
|
|
TSVC_Data.Clear();
|
|
LastTSVC.Clear();
|
|
VCData currConf;
|
|
int periodo = 0;
|
|
VC_func funz = VC_func.POINT;
|
|
// accodo nella conf...
|
|
foreach (var item in memMap.mMapRead)
|
|
{
|
|
funz = item.Value.func;
|
|
periodo = item.Value.period;
|
|
currConf = new VCData()
|
|
{
|
|
Funzione = funz,
|
|
Period = periodo,
|
|
DTStart = DateTime.Now.AddHours(-1),
|
|
dataArray = new List<double>()
|
|
};
|
|
TSVC_Data.Add(item.Key, currConf);
|
|
}
|
|
// documento...
|
|
foreach (var item in TSVC_Data)
|
|
{
|
|
logTrace($"TSVC: {item.Key} | periodo: {item.Value.Period} | funz: {item.Value.Funzione}");
|
|
// salvo i valori PREC...
|
|
LastTSVC.Add(item.Key, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
private IConfigurationRoot config;
|
|
private string confPath;
|
|
|
|
#endregion Private Fields
|
|
}
|
|
} |