765 lines
29 KiB
C#
765 lines
29 KiB
C#
using RestSharp;
|
|
using IOB_UT_NEXT;
|
|
using MapoSDK;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Net.NetworkInformation;
|
|
using System.IO;
|
|
using System.Windows.Forms;
|
|
using System.Threading;
|
|
using S7.Net.Types;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace IOB_WIN_NEXT.IobRest
|
|
{
|
|
/// <summary>
|
|
/// Adapter base per sviluppo chiamate con servizi REST
|
|
/// </summary>
|
|
public class Base : Iob.Generic
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Costruttore dell'IOB Rest generico
|
|
/// </summary>
|
|
/// <param name="caller">AdapterForm chiamante</param>
|
|
/// <param name="IOBConf">Configurazione IOB per avvio</param>
|
|
public Base(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
|
|
{
|
|
lgInfo($"Richiesto Adapter IobRest.Base con i parametri seguenti | ADDR: {IOBConf.cncIpAddr} | PORT: {IOBConf.cncPort}");
|
|
lastPING = DateTime.Now.AddHours(-1);
|
|
// predispongo configurazione specifica Rest...
|
|
if (!string.IsNullOrEmpty(getOptPar("REST_CONF")))
|
|
{
|
|
setupRestConf(getOptPar("REST_CONF"));
|
|
}
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Implementazione custom esecuzione task specifici
|
|
/// </summary>
|
|
/// <param name="task2exe"></param>
|
|
/// <returns></returns>
|
|
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
|
|
{
|
|
/*---------------------------------------
|
|
* gestione execute task SPECIFICI x pesa:
|
|
* - salva i parametri richiesta (RM, cod1..cod6)
|
|
* - esegue metodo richiesta (IN/OUT)
|
|
*---------------------------------------*/
|
|
|
|
// Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti...
|
|
Dictionary<string, string> taskDone = new Dictionary<string, string>();
|
|
#if false
|
|
if (task2exe != null)
|
|
{
|
|
lgTrace($"executeTasks: richiesta esecuzione {task2exe.Count} task");
|
|
// controllo se memMap != null...
|
|
if (memMap != null)
|
|
{
|
|
bool taskOk = false;
|
|
string taskVal = "";
|
|
// cerco task specifici: qui sono NON standard...
|
|
foreach (var item in task2exe)
|
|
{
|
|
lgInfo($"TASK | {item.Key} --> {item.Value}");
|
|
taskOk = false;
|
|
taskVal = "";
|
|
// converto richiesta in enum...
|
|
taskType tName = taskType.nihil;
|
|
Enum.TryParse(item.Key, out tName);
|
|
// controllo sulla KEY...
|
|
switch (tName)
|
|
{
|
|
case taskType.setParameter:
|
|
// richiedo da URL i parametri WRITE da popolare
|
|
lgInfo("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";
|
|
lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
|
|
break;
|
|
}
|
|
// aggiungo task!
|
|
taskDone.Add(item.Key, taskVal);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return taskDone;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero dati dinamici...
|
|
/// </summary>
|
|
public override Dictionary<string, string> getDynData()
|
|
{
|
|
// valore non presente in vers default... se gestito fare override
|
|
Dictionary<string, string> outVal = new Dictionary<string, string>();
|
|
#if false
|
|
// controllo se ho indicato ancora che ci siano pesate già lette da inviare...
|
|
if (num2send() > 0)
|
|
{
|
|
// preparo oggetti x confronto ...
|
|
List<WeightRec> listaArch = listPesateArchivio;
|
|
|
|
// se non ho nulla in archivio prendo ultima pesata (essendo DESC è la prima cronologicamente)
|
|
if (listaArch.Count == 0)
|
|
{
|
|
WeightRec lastRec = listPesateCurr.LastOrDefault();
|
|
// aggiungo...
|
|
SavePesata(ref outVal, lastRec);
|
|
}
|
|
// ora il confronto è cronologico sulle pesate + recenti...
|
|
else
|
|
{
|
|
// prendo prima della lista pesate archiviate = più recente come dt da cui partire...
|
|
DateTime dtRif = listaArch.FirstOrDefault().DtEvent;
|
|
var firstRec = listPesateCurr
|
|
.Where(x => x.DtEvent > dtRif)
|
|
.OrderBy(x => x.DtEvent)
|
|
.FirstOrDefault();
|
|
if (firstRec != null)
|
|
{
|
|
SavePesata(ref outVal, firstRec);
|
|
}
|
|
}
|
|
|
|
// processo comunque le aree memoria READ...
|
|
if (memMap.mMapRead.Count > 0)
|
|
{
|
|
foreach (var item in memMap.mMapRead)
|
|
{
|
|
var currVal = getCurrProdData(item.Key, "");
|
|
if (!outVal.ContainsKey(item.Key))
|
|
{
|
|
outVal.Add(item.Key, $"{currVal}");
|
|
}
|
|
// se fosse logReq --> resetto...
|
|
if (item.Key == "logReq" && !string.IsNullOrEmpty(currVal))
|
|
{
|
|
upsertKey(item.Key, "");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// altrimenti rileggo e cerco se ci siano
|
|
else
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
try
|
|
{
|
|
// test lettura elenco pesate... se NON nullo --> OK!
|
|
var weightArray = RestConn.reqWeightList("ALL", dataFrom, dataTo);
|
|
// riordino DESC
|
|
listPesateCurr = WeightRec.ConvertPesate(weightArray.OrderByDescending(x => x.dateIn).ToList());
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgError($"Eccezione in RestConn.reqWeightList{Environment.NewLine}{exc}");
|
|
}
|
|
sw.Stop();
|
|
lgInfo($"getDynData | SOAP: effettuata chiamata reqWeightList in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo} | {listPesateCurr.Count} rec");
|
|
}
|
|
#endif
|
|
// indico esecuzione e proseguo
|
|
lastReadPLC = DateTime.Now;
|
|
return outVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua lettura semafori principale
|
|
/// <paramref name="currDispData">Parametri da aggiornare x display in form</paramref>
|
|
/// </summary>
|
|
public override void readSemafori(ref newDisplayData currDispData)
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
lastReadPLC = adesso;
|
|
// verifico non sia in veto invio iniziale...
|
|
if (queueInEnabCurr)
|
|
{
|
|
try
|
|
{
|
|
if (verboseLog)
|
|
{
|
|
lgInfo("inizio read semafori");
|
|
}
|
|
|
|
currDispData.semIn = Semaforo.SV;
|
|
// effettua refresh dati da leggere SPECIFICi x citizen...
|
|
refreshData();
|
|
// decodifica e gestione
|
|
decodeToBaseBitmap(ref currDispData);
|
|
// display
|
|
reportRawInput(ref currDispData);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
currDispData.semIn = Semaforo.SR;
|
|
lgError($"Eccezione in readSemafori:{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lgDebug($"[VETO readSemafori] | veto attivo alle {adesso:yyyy.MM.dd HH:mm:ss}");
|
|
checkVetoQueueIn();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override connessione
|
|
/// </summary>
|
|
public override void tryConnect()
|
|
{
|
|
if (!connectionOk)
|
|
{
|
|
// controllo che il ping sia stato tentato almeno pingTestSec fa...
|
|
if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec"))
|
|
{
|
|
if (verboseLog || periodicLog)
|
|
{
|
|
lgInfo("Rest: ConnKO - tryConnect");
|
|
}
|
|
// in primis salvo data ping...
|
|
lastPING = DateTime.Now;
|
|
// se passa il ping faccio il resto...
|
|
if (testPingMachine == IPStatus.Success)
|
|
{
|
|
string szStatusConnection = "";
|
|
try
|
|
{
|
|
// ora provo connessione...
|
|
parentForm.commPlcActive = true;
|
|
|
|
// chiamo metodo connect
|
|
var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"));
|
|
// forse va eliminato...
|
|
lgInfo($"GetConnection | {checkResp}");
|
|
if (checkResp != null && checkResp.ToLower().Contains("true"))
|
|
{
|
|
connectionOk = true;
|
|
}
|
|
else
|
|
{
|
|
lgError($"Errore check connessione | checkResp: {checkResp}");
|
|
}
|
|
// refresh stato connessione!!!
|
|
if (connectionOk)
|
|
{
|
|
queueInEnabCurr = true;
|
|
if (adpRunning)
|
|
{
|
|
lgInfo("Connessione OK");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lgError("Impossibile procedere, connessione mancante...");
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgFatal($"Errore nella connessione all'Adapter IobRest.Base: {szStatusConnection}{Environment.NewLine}{exc}");
|
|
connectionOk = false;
|
|
lgInfo($"Eccezione in TryConnect, Adapter IobRest.Base NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// loggo no risposta ping ...
|
|
connectionOk = false;
|
|
if (verboseLog || periodicLog)
|
|
{
|
|
lgInfo($"Attenzione: Rest controllo PING fallito per IP {cIobConf.cncPingAddr}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
needRefresh = true;
|
|
}
|
|
}
|
|
|
|
public override void tryDisconnect()
|
|
{
|
|
// registro solo che è disconnesso
|
|
connectionOk = false;
|
|
queueInEnabCurr = false;
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// Api Url di base x chiamate REST
|
|
/// </summary>
|
|
protected string apiUrl = "http://localhost:8733";
|
|
|
|
/// <summary>
|
|
/// Timeout chiamate REST
|
|
/// </summary>
|
|
protected int tOutSec = 60;
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Properties
|
|
|
|
/// <summary>
|
|
/// Parametri specifici Client Rest
|
|
/// </summary>
|
|
protected RestParamConf restParams { get; set; } = new RestParamConf();
|
|
|
|
#endregion Protected Properties
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// verifica stato ok ovvero connected oppure open
|
|
/// </summary>
|
|
/// <param name="currState"></param>
|
|
/// <returns></returns>
|
|
protected bool checkStateOk(System.ServiceModel.CommunicationState currState)
|
|
{
|
|
bool answ = false;
|
|
#if false
|
|
answ == System.ServiceModel.CommunicationState.Opened || currState == System.ServiceModel.CommunicationState.Created;
|
|
#endif
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esecuzione chiamata Rest tipo GET
|
|
/// </summary>
|
|
/// <param name="resource"></param>
|
|
/// <returns></returns>
|
|
protected string ExecuteCallGet(string resource)
|
|
{
|
|
string answ = "";
|
|
if (!string.IsNullOrEmpty(resource))
|
|
{
|
|
try
|
|
{
|
|
// client chiamate rest
|
|
using (var client = new RestClient(restOptStd))
|
|
{
|
|
var currReq = new RestRequest(resource, Method.Get);
|
|
currReq.AddHeader("Content-type", "application/json");
|
|
// effettuo vera chiamata
|
|
var currResp = client.Get(currReq);
|
|
if (currResp.StatusCode == System.Net.HttpStatusCode.OK && currResp.Content != null)
|
|
{
|
|
answ = currResp.Content ?? "";
|
|
}
|
|
}
|
|
}
|
|
catch(Exception exc)
|
|
{
|
|
lgError($"Eccezione in ExecuteCallGet{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// restituisce URL della risorsa eventualmente completato con token o altro
|
|
/// </summary>
|
|
/// <param name="resName"></param>
|
|
/// <returns></returns>
|
|
protected string GetUrlResource(string resName)
|
|
{
|
|
string answ = "";
|
|
if (restParams != null && restParams.CallList != null && restParams.CallList.Count > 0)
|
|
{
|
|
if (restParams.CallList.ContainsKey(resName))
|
|
{
|
|
answ = restParams.CallList[resName].Url;
|
|
// eseguo eventuale sostituzione (se trovo "[[")
|
|
if (answ.Contains("[["))
|
|
{
|
|
string pattern = @"\[\[.*\]\]";
|
|
Regex regex = new Regex(pattern);
|
|
Match match = regex.Match(resName);
|
|
if (match.Success)
|
|
{
|
|
string key = match.Value.Replace("[[", "").Replace("]]", "");
|
|
// cerco nella LUT...
|
|
if (RestDataLUT.ContainsKey(key))
|
|
{
|
|
// sostituisco!
|
|
answ = answ.Replace($"[[{key}]]", RestDataLUT[key]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
/// <summary>
|
|
/// Upsert in cache LUT del parametro
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="value"></param>
|
|
protected void RestLutUpsert(string key, string value)
|
|
{
|
|
if (RestDataLUT.ContainsKey(key))
|
|
{
|
|
RestDataLUT[key] = value;
|
|
}
|
|
else
|
|
{
|
|
RestDataLUT.Add(key, value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero valore da cache LUT
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="value"></param>
|
|
protected string RestLutGet(string key)
|
|
{
|
|
string value = "";
|
|
if (RestDataLUT.ContainsKey(key))
|
|
{
|
|
value = RestDataLUT[key];
|
|
}
|
|
return value;
|
|
}
|
|
/// <summary>
|
|
/// Metodo da overridare x scrivere DAVVERO i parametri sul PLC
|
|
/// </summary>
|
|
/// <param name="updatedPar"></param>
|
|
protected override void plcWriteParams(ref List<objItem> updatedPar)
|
|
{
|
|
lgTrace($"plcWriteParams: richiesta per {updatedPar.Count} params");
|
|
foreach (var item in updatedPar)
|
|
{
|
|
lgInfo($"ITEM | {item.uid} | {item.value}");
|
|
// salvo i valori di setup x prox pesata...
|
|
upsertKey(item.uid, item.value);
|
|
#if false
|
|
bool fatto = false;
|
|
bool isPesata = false;
|
|
bool isIN = false;
|
|
gestWeightOut answ = new gestWeightOut();
|
|
// se è richiesta pesata IN/OUT --> mando chiamata
|
|
if (item.uid == "reqPesata")
|
|
{
|
|
isPesata = true;
|
|
isIN = item.reqValue.ToUpper() == "IN";
|
|
//isIN = item.value.ToUpper() == "IN";
|
|
try
|
|
{
|
|
answ = reqWeight(isIN);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgError($"Eccezione in plcWriteParams.reqWeight | isIn: {isIN}{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
else if (item.uid == "RM" || item.uid.StartsWith("Cod"))
|
|
{
|
|
// comunque segno fatto x altri casi
|
|
fatto = true;
|
|
}
|
|
|
|
// se è pesata...
|
|
if (isPesata)
|
|
{
|
|
// se è OK
|
|
if (answ.feedback == "C")
|
|
{
|
|
lgInfo($"reqWeight | Effettuato richiesta | {answ.feedback} | {answ.notes}");
|
|
// resetto pesata
|
|
upsertKey(item.uid, "");
|
|
}
|
|
else
|
|
{
|
|
lgError($"reqWeight | Errore in richiesta peso Rest | {answ.feedback} | {answ.notes}");
|
|
}
|
|
item.value = "";
|
|
item.reqValue = "";
|
|
item.lastRead = DateTime.Now;
|
|
item.UM = "";
|
|
// salvo esito richiesta comunque
|
|
upsertKey("logReq", $"{answ.feedback} | {answ.notes}");
|
|
// faccio in modo di eseguire subito getDynData
|
|
demFactDynData = 1;
|
|
processDynData();
|
|
}
|
|
else
|
|
{
|
|
// se fatto --> aggiorno!
|
|
if (fatto)
|
|
{
|
|
//item.value = item.reqValue;
|
|
item.reqValue = "";
|
|
item.lastRead = DateTime.Now;
|
|
item.UM = "";
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
protected void setupRestConf(string restConfFile)
|
|
{
|
|
// se ho file specifico
|
|
if (!string.IsNullOrEmpty(getOptPar("REST_CONF")))
|
|
{
|
|
string rawData = "";
|
|
// leggo file e decodifico...
|
|
string confPath = $"{Application.StartupPath}/DATA/CONF/{restConfFile}";
|
|
lgInfo($"Apertura file {confPath}");
|
|
using (StreamReader sr = new StreamReader(confPath))
|
|
{
|
|
rawData = sr.ReadToEnd().Replace("\n", "").Replace("\r", "");
|
|
}
|
|
// continuo decodifica
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
restParams = JsonConvert.DeserializeObject<RestParamConf>(rawData);
|
|
if (restParams != null)
|
|
{
|
|
// inizializzo dal file di conf le variabili necessarie...
|
|
tOutSec = restParams.timeOutSec;
|
|
apiUrl = restParams.apiUrl ?? "http://localhost:8733";
|
|
}
|
|
}
|
|
}
|
|
|
|
// sistemo conf standard x call REST
|
|
restOptStd = new RestClientOptions
|
|
{
|
|
Timeout = TimeSpan.FromSeconds(tOutSec),
|
|
BaseUrl = new Uri(apiUrl)
|
|
};
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
/// <summary>
|
|
/// LookUpTable informazioni raccolte
|
|
/// </summary>
|
|
protected Dictionary<string, string> RestDataLUT = new Dictionary<string, string>();
|
|
|
|
/// <summary>
|
|
/// Conf client RestSharp standard:
|
|
/// - timeout 1 min
|
|
/// </summary>
|
|
private RestClientOptions restOptStd = new RestClientOptions { Timeout = TimeSpan.FromSeconds(60) };
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
|
|
/// </summary>
|
|
protected virtual void decodeToBaseBitmap(ref newDisplayData currDispData)
|
|
{
|
|
// init a zero...
|
|
B_input = 0;
|
|
if (queueInEnabCurr)
|
|
{
|
|
/* -----------------------------------------------------
|
|
* bitmap MAPO STD 60
|
|
* B0: POWER_ON
|
|
* B1: RUN
|
|
* B2: pzCount
|
|
* B3: allarme
|
|
* B4: manuale
|
|
* B5: allarme TCiclo (SLOW)
|
|
* B6: WarmUp_CoolDown
|
|
* B7: EmergArmed (1 = NON emergenza, 0 = emergenza)
|
|
----------------------------------------------------- */
|
|
|
|
// per prima cosa controllo ping e se sia connesso...
|
|
|
|
#if false
|
|
if (connectionOk)
|
|
{
|
|
B_input = 1;
|
|
currDispData.semIn = Semaforo.SV;
|
|
|
|
// se ho pesate in memoria nel periodo richiesto --> RUN
|
|
if (listPesateCurr != null && listPesateCurr.Count > 0)
|
|
{
|
|
B_input += (1 << 1);
|
|
}
|
|
// metto manuale
|
|
else
|
|
{
|
|
B_input += (1 << 4);
|
|
}
|
|
|
|
// accodo NON emergenza
|
|
B_input += (1 << 7);
|
|
}
|
|
else
|
|
{
|
|
B_input = 0;
|
|
currDispData.semIn = Semaforo.SR;
|
|
}
|
|
#endif
|
|
|
|
#if false
|
|
// Controllo booleano PING e POWERON...
|
|
string currPowerOn = getDataItemValue(mtcParams.condPowerOn.keyName);
|
|
// se valido il check ping lo eseguo... altrimenti lo do x buono
|
|
bool isPingOk = mtcParams.pingAsPowerOn && (testPingMachine == IPStatus.Success);
|
|
|
|
// verifico da target value richiesto...
|
|
bool checkPowerOn = (currPowerOn == mtcParams.condPowerOn.targetValue);
|
|
|
|
// bit 0 (poweron) imposto a 1 SE pingo o PowerOn=="ON"...
|
|
B_input = (isPingOk || checkPowerOn) ? 1 : 0;
|
|
|
|
// variabili RUN...
|
|
string currRun = getDataItemValue(mtcParams.keyRunMode);
|
|
|
|
// controllo RUN MODE preliminare... CABLATO - è GENERALE x MTC
|
|
if (currRun == "AUTOMATIC" || currRun == "SEMI_AUTO" || currRun == "SEMI_AUTOMATIC")
|
|
{
|
|
int numCond = mtcParams.condWork.Count;
|
|
int numCondOk = 0;
|
|
// cerco nell'elenco delle condizioni che indicano lavora se sono ok faccio +1 conteggio......
|
|
foreach (var item in mtcParams.condWork)
|
|
{
|
|
if (getDataItemValue(item.keyName) == item.targetValue)
|
|
{
|
|
numCondOk++;
|
|
}
|
|
}
|
|
// se tutte condizioni rispettate --> lavora!
|
|
if (numCond == numCondOk)
|
|
{
|
|
// RUN = LAVORA!
|
|
B_input += (1 << 1);
|
|
}
|
|
}
|
|
// se ho almeno 1 allarme E NON SONO IN AUTO --> ALARM!
|
|
else if (hasError)
|
|
{
|
|
B_input += (1 << 3);
|
|
}
|
|
// 2024.01.90: gestione dati UNAVAILABLE che indicano poweroff...
|
|
else if (hasUnavailableData && unavailPoweroff)
|
|
{
|
|
B_input = 0;
|
|
}
|
|
else
|
|
{
|
|
// se ho run mode != auto --> manual
|
|
B_input += (1 << 4);
|
|
}
|
|
|
|
// emergenza armata da riportare con bit True/ 1
|
|
if (mtcParams.emergencyArmedTrue)
|
|
{
|
|
//se NON premuta lazo il bit
|
|
if (!hasEStopTriggered)
|
|
{
|
|
B_input += (1 << 5);
|
|
}
|
|
}
|
|
// emergenza armata da riportare come False/0 (!mtcParams.emergencyArmedTrue)
|
|
else
|
|
{
|
|
// se premuta alzo il bit...
|
|
if (hasEStopTriggered)
|
|
{
|
|
B_input += (1 << 5);
|
|
}
|
|
}
|
|
|
|
DateTime adesso = DateTime.Now;
|
|
int vFactor = 1;
|
|
// controllo SE HO dati per fare verifiche...
|
|
if (string.IsNullOrEmpty(currRun))
|
|
{
|
|
// se ho parametro x gestione reset...
|
|
if (enableMtcRestart)
|
|
{
|
|
// controllo se ho ricevuto il current da OLTRE 1 minuto...
|
|
if (lastCurrent.AddMinutes(3) < adesso)
|
|
{
|
|
lastCurrent = adesso;
|
|
// stop...
|
|
lgInfo("Fermato MTC_ref per mancanza dati current");
|
|
MTC_ref.Stop();
|
|
Thread.Sleep(1000);
|
|
// restart
|
|
lgInfo("Riavviato MTC_ref per mancanza dati current");
|
|
MTC_ref.Start();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vFactor = 6;
|
|
}
|
|
|
|
// solo se non ho veto check
|
|
if (vetoCheckStatus < adesso)
|
|
{
|
|
lgInfo($"Stato variabili: currRun: {currRun}");
|
|
// imposto veto per vetoSeconds...
|
|
vetoCheckStatus = adesso.AddSeconds(vetoSeconds * vFactor);
|
|
}
|
|
// log opzionale!
|
|
if (verboseLog)
|
|
{
|
|
lgInfo($"Trasformazione B_input: {B_input} | currRun = {currRun}");
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
lgDebug($"[VETO getDataItemValue] | veto attivo alle {DateTime.Now:yyyy.MM.dd HH:mm:ss}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue lettura dati + salvataggio in LUT
|
|
/// </summary>
|
|
protected virtual void refreshData()
|
|
{ }
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |