7cf7442420
- fix comportamento reload - test reset variabili SIMULA
551 lines
23 KiB
C#
551 lines
23 KiB
C#
using EgwProxy.Gomba.GombaServ;
|
|
using IOB_UT_NEXT;
|
|
using MapoSDK;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Net.NetworkInformation;
|
|
|
|
namespace IOB_WIN_NEXT.IobSoap
|
|
{
|
|
/// <summary>
|
|
/// Adapter specializzato per GOMA e le chiamate tramite WS Soap alla bilancia, libreria EgwProxy.Gomba
|
|
/// </summary>
|
|
public class Gomba : Iob.Generic
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Costruttore dell'IOB SOAP della bilancia GOMBA
|
|
/// </summary>
|
|
/// <param name="caller">AdapterForm chiamante</param>
|
|
/// <param name="IOBConf">Configurazione IOB per avvio</param>
|
|
public Gomba(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
|
|
{
|
|
lgInfo($"Richiesto Adapter IobSoap.Gomba con i parametri seguenti | ADDR: {IOBConf.cncIpAddr} | PORT: {IOBConf.cncPort}");
|
|
redKeyPesate = redisMan.redHash($"IOB:Status:{cIobConf.codIOB}:ListPesate");
|
|
lastPING = DateTime.Now.AddHours(-1);
|
|
}
|
|
|
|
#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 (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!");
|
|
}
|
|
}
|
|
|
|
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>();
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
// test lettura elenco pesate... se NON nullo --> OK!
|
|
var weightArray = gombaConn.reqWeightList("ALL", dataFrom, dataTo);
|
|
// riordino DESC
|
|
listPesateCurr = weightArray.OrderByDescending(x => x.dateIn).ToList();
|
|
sw.Stop();
|
|
lgInfo($"getDynData | SOAP: effettuata chiamata reqWeightList in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo} | {listPesateCurr.Count} rec");
|
|
|
|
// verifico se ci siano pesate nuove o meno...
|
|
if (listPesateCurr.Count != listPesateArch.Count)
|
|
{
|
|
// elenco indici
|
|
List<string> listRmCurr = listPesateCurr.OrderBy(x => x.dateIn).Select(x => x.rm).ToList();
|
|
List<string> listRmArch = listPesateArch.OrderBy(x => x.dateIn).Select(x => x.rm).ToList();
|
|
// cerco nuove pesate confrontando rn archivio e curr...
|
|
List<string> listPresent = listRmCurr.Intersect(listRmArch).ToList();
|
|
foreach (var item in listPresent)
|
|
{
|
|
listRmCurr.Remove(item);
|
|
}
|
|
|
|
// aggiungo solo 1 pesata, la + vecchia...
|
|
if (listRmCurr.Count > 0)
|
|
{
|
|
// prendo la prima
|
|
var firstRec = listPesateCurr.Find(x => x.rm == listRmCurr[0]);
|
|
if (firstRec != null)
|
|
{
|
|
outVal.Add("RM", firstRec.rm);
|
|
}
|
|
// accodo x invio pesata valide IN se presenti...
|
|
if (firstRec.dateInSpecified)
|
|
{
|
|
// invio record SOLO PESO
|
|
outVal.Add("lastWeightIn", $"{firstRec.weightIn}");
|
|
// registro record completo ultima pesata
|
|
outVal.Add("lastRecIn", formatPesata(firstRec, true));
|
|
}
|
|
// accodo x invio pesata valide OUT se presenti...
|
|
if (firstRec.dateOutSpecified)
|
|
{
|
|
// invio record SOLO PESO
|
|
outVal.Add("lastWeightOut", $"{firstRec.weightIn}");
|
|
// registro record completo ultima pesata
|
|
outVal.Add("lastRecOut", formatPesata(firstRec, false));
|
|
}
|
|
// la aggiungo alle pesate archiviate...
|
|
var tmpPesate = listPesateArch;
|
|
tmpPesate.Add(firstRec);
|
|
listPesateArch = tmpPesate;
|
|
}
|
|
}
|
|
|
|
// processo comunque le aree memoria READ...
|
|
if (memMap.mMapRead.Count > 0)
|
|
{
|
|
foreach (var item in memMap.mMapRead)
|
|
{
|
|
var currVal = getCurrProdData(item.Key, "");
|
|
outVal.Add(item.Key, $"{currVal}");
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <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("Gomba: 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;
|
|
|
|
// init del proxy!!!
|
|
string endpointAddr = $"https://{cIobConf.cncIpAddr}:{cIobConf.cncPort}/ws";
|
|
lgInfo($"Tentativo avvio SOAP su endpoint {endpointAddr}");
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
|
|
// salto verifica certificato
|
|
System.Net.ServicePointManager.ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => { return true; };
|
|
|
|
// avvio!
|
|
gombaConn = new EgwProxy.Gomba.GombaServ.lwpServiceClient("lwpServicePort", new System.ServiceModel.EndpointAddress(endpointAddr));
|
|
|
|
// test lettura elenco pesate... se NON nullo --> OK!
|
|
var weightArray = gombaConn.reqWeightList("ALL", dataFrom, dataTo);
|
|
|
|
// riordino DESC
|
|
listPesateCurr = weightArray.OrderByDescending(x => x.dateIn).ToList();
|
|
sw.Stop();
|
|
lgInfo($"SOAP: effettuata chiamata reqWeightList in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo}");
|
|
if (listPesateCurr != null && listPesateCurr.Count >= 0)
|
|
{
|
|
lgInfo($"szStatusConnection Gomba, recuperato elenco di {listPesateCurr.Count} pesate");
|
|
parentForm.commPlcActive = false;
|
|
connectionOk = true;
|
|
// sistemo data per recuperi successivi se ho + di 10 record...
|
|
if (listPesateCurr.Count > 10)
|
|
{
|
|
var lastRec = listPesateCurr.Skip(9).FirstOrDefault();
|
|
dtStartLive = lastRec.dateIn;
|
|
}
|
|
}
|
|
// refresh stato connessione!!!
|
|
if (connectionOk)
|
|
{
|
|
queueInEnabCurr = true;
|
|
// carico pesate da redis...
|
|
listPesatePrev = listPesateArch;
|
|
if (adpRunning)
|
|
{
|
|
lgInfo("Connessione OK");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lgError("Impossibile procedere, connessione mancante...");
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgFatal($"Errore nella connessione all'adapter Gomba: {szStatusConnection}{Environment.NewLine}{exc}");
|
|
connectionOk = false;
|
|
lgInfo($"Eccezione in TryConnect, Adapter Gomba 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: Gomba 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>
|
|
/// Proxy per connessione al SOAP webservice GOMBA
|
|
/// </summary>
|
|
protected EgwProxy.Gomba.GombaServ.lwpServiceClient gombaConn;
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Methods
|
|
|
|
/// <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);
|
|
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.value.ToUpper() == "IN";
|
|
answ = reqWeight(isIN);
|
|
}
|
|
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")
|
|
{
|
|
string recPesata = formatPesata(answ, item.uid == "reqIN");
|
|
lgInfo($"reqWeight | OK effettuato pesata | {recPesata}");
|
|
// aggiorno dati pesate IN/OUT...
|
|
if(isIN)
|
|
{
|
|
upsertKey("lastWeightIn", answ.weightIn);
|
|
upsertKey("lastRecIn", recPesata);
|
|
}
|
|
else
|
|
{
|
|
upsertKey("lastWeightOut", answ.weightOut);
|
|
upsertKey("lastRecOut", recPesata);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lgError($"reqWeight | Errore in richiesta peso GOMBA | {answ.feedback} | {answ.notes}");
|
|
}
|
|
item.value = "";
|
|
//item.value = $"{answ.feedback} | {answ.notes}";
|
|
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;
|
|
}
|
|
else
|
|
{
|
|
// se fatto --> aggiorno!
|
|
if (fatto)
|
|
{
|
|
//item.value = item.reqValue;
|
|
item.reqValue = "";
|
|
item.lastRead = DateTime.Now;
|
|
item.UM = "";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue richiesta PESO
|
|
/// </summary>
|
|
/// <param name="reqIN">Tipo richiesta: IN (true) / OUT (false)</param>
|
|
/// <returns></returns>
|
|
protected gestWeightOut reqWeight(bool reqIN)
|
|
{
|
|
lgInfo($"reqWeight | IN: {reqIN}");
|
|
gestWeightOut answ = null;
|
|
try
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
// preparo parametri
|
|
string tipoRic = reqIN ? "IN" : "OUT";
|
|
string rm = getCurrProdData("RM", $"{DateTime.Now:yyyyMMdd-HHmmss}");// string.IsNullOrEmpty(currProdData["RM"]) ? $"{DateTime.Now:yyyyMMdd-HHmmss}" : currProdData["RM"];
|
|
string Cod1 = getCurrProdData("Cod1", ""); //string.IsNullOrEmpty(currProdData["Cod1"]) ? "" : currProdData["Cod1"];
|
|
string Cod2 = getCurrProdData("Cod2", ""); //string.IsNullOrEmpty(currProdData["Cod2"]) ? "" : currProdData["Cod2"];
|
|
string Cod3 = getCurrProdData("Cod3", ""); //string.IsNullOrEmpty(currProdData["Cod3"]) ? "" : currProdData["Cod3"];
|
|
string Cod4 = getCurrProdData("Cod4", ""); //string.IsNullOrEmpty(currProdData["Cod4"]) ? "" : currProdData["Cod4"];
|
|
string Cod5 = getCurrProdData("Cod5", ""); //string.IsNullOrEmpty(currProdData["Cod5"]) ? "" : currProdData["Cod5"];
|
|
string Cod6 = getCurrProdData("Cod6", ""); //string.IsNullOrEmpty(currProdData["Cod6"]) ? "" : currProdData["Cod6"];
|
|
// faccio chiamata
|
|
answ = gombaConn.memWeight(tipoRic, rm, Cod1, Cod2, Cod3, Cod4, Cod5, Cod6);
|
|
sw.Stop();
|
|
lgInfo($"reqWeight: effettuata chiamata SOAP in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo}");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgError($"reqWeight | errore richiesta pesatura{Environment.NewLine}{exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Properties
|
|
|
|
/// <summary>
|
|
/// Data inizio periodo dati Bilancia:
|
|
/// - al boot impostato a -6 mesi
|
|
/// - dopo lettura impostato a data ultimi 5 record
|
|
/// </summary>
|
|
private string dataFrom
|
|
{
|
|
get => dtStartLive.ToString("dd/MM/yyyy");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Data fine periodo dati Bilancia: oggi + 1gg
|
|
/// </summary>
|
|
private string dataTo
|
|
{
|
|
get => DateTime.Today.AddDays(1).ToString("dd/MM/yyyy");
|
|
}
|
|
|
|
private DateTime dtStartLive { get; set; } = DateTime.Today.AddMonths(-6);
|
|
|
|
/// <summary>
|
|
/// Gestione archivio serializzato delle pesate già processate
|
|
/// </summary>
|
|
private List<EgwProxy.Gomba.GombaServ.gestWeightOut> listPesateArch
|
|
{
|
|
get
|
|
{
|
|
List<EgwProxy.Gomba.GombaServ.gestWeightOut> answ = new List<EgwProxy.Gomba.GombaServ.gestWeightOut>();
|
|
string rawData = redisMan.getRSV(redKeyPesate);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
try
|
|
{
|
|
answ = JsonConvert.DeserializeObject<List<EgwProxy.Gomba.GombaServ.gestWeightOut>>(rawData);
|
|
lgInfo($"Rilettura status listPesateArch: trovati {answ.Count} record");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgError($"Errore in deserializzazione listPesateArch{Environment.NewLine}{exc}");
|
|
answ = new List<EgwProxy.Gomba.GombaServ.gestWeightOut>();
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
set
|
|
{
|
|
string rawVal = JsonConvert.SerializeObject(value);
|
|
redisMan.setRSV(redKeyPesate, rawVal);
|
|
lgInfo($"Salvataggio status listPesateArch | {value.Count} record");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco pesate attuali
|
|
/// </summary>
|
|
private List<EgwProxy.Gomba.GombaServ.gestWeightOut> listPesateCurr { get; set; } = new List<EgwProxy.Gomba.GombaServ.gestWeightOut>();
|
|
|
|
/// <summary>
|
|
/// Elenco lettura pesate precedenti
|
|
/// </summary>
|
|
private List<EgwProxy.Gomba.GombaServ.gestWeightOut> listPesatePrev { get; set; } = new List<EgwProxy.Gomba.GombaServ.gestWeightOut>();
|
|
|
|
private string redKeyPesate { get; set; } = "";
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Methods
|
|
|
|
private static string formatCode(string currCode)
|
|
{
|
|
string code = string.IsNullOrEmpty(currCode) ? "-" : currCode;
|
|
return $" | {code}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Formatta record completo pesata
|
|
/// </summary>
|
|
/// <param name="rec">record completo pesate Gomba</param>
|
|
/// <param name="isIN">Indica se deve formattare i dati tipo IN (true) o OUT (false)</param>
|
|
/// <returns></returns>
|
|
private static string formatPesata(gestWeightOut rec, bool isIN)
|
|
{
|
|
string currVal = "";
|
|
if (isIN)
|
|
{
|
|
currVal = $"{rec.dateIn:yyyy-MM-dd HH:mm:ss} | {rec.weightIn} kg";
|
|
}
|
|
else
|
|
{
|
|
currVal = $"{rec.dateOut:yyyy-MM-dd HH:mm:ss} | {rec.weightOut} kg";
|
|
}
|
|
currVal += formatCode(rec.cod1);
|
|
currVal += formatCode(rec.cod2);
|
|
currVal += formatCode(rec.cod3);
|
|
currVal += formatCode(rec.cod4);
|
|
currVal += formatCode(rec.cod5);
|
|
currVal += formatCode(rec.cod6);
|
|
return currVal;
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |