8bb0f158b5
- proj di base con le 2 form da ereditare - progetto globale che contiene TUTTI gli adapter (pronto a venire spezzettato - gettate le basi x "portare fuori" i vari componenti oppure fare compilazione condizonale
298 lines
12 KiB
C#
298 lines
12 KiB
C#
using IOB_UT_NEXT;
|
|
using MapoSDK;
|
|
using Newtonsoft.Json;
|
|
using Opc.Ua;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.NetworkInformation;
|
|
using System.Threading.Tasks;
|
|
using static IOB_UT_NEXT.CustomObj;
|
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
|
|
|
namespace IOB_WIN_NEXT.IobOpc
|
|
{
|
|
public class OpcUaSiemensRama : OpcUaSiemens
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Estende l'init della classe base, impiegando il pacchetto Nuget OPC-UA foundation con la
|
|
/// gestione specifica per adapter Siemens integrato OPC-UA (es RAMA RED by Unitech x TFT)
|
|
/// https://github.com/OPCFoundation/UA-.NETStandard
|
|
/// </summary>
|
|
/// <param name="caller"></param>
|
|
/// <param name="IOBConf"></param>
|
|
public OpcUaSiemensRama(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf)
|
|
{
|
|
lgInfo("Init OpcUa Siemens x RAMA");
|
|
doByteRead = true;
|
|
|
|
/*-------------------------------------------
|
|
* Gestione custom
|
|
*
|
|
* Creare array vettori di BIN/bool x decodificare info specifiche
|
|
* configurare CABLATO in oggetti custom RAMA
|
|
* decodifica dataitem custom rama dagli oggetti binari
|
|
*
|
|
* QUANDO FUNZIONA verificare se e come rendere parametrica la gestione oggetti/byte configurabili
|
|
*
|
|
*-------------------------------------------*/
|
|
sendKeyRichiesta = true;
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// Esegue step a valle dell'auto ODL:
|
|
/// - reset contapezzi
|
|
/// - richiesta setup (uguale al precedente)
|
|
/// </summary>
|
|
protected override void processAutoOdlExtraStep()
|
|
{
|
|
// inizio con reset ricetta caricata
|
|
ListaCalcParams = new List<objItem>();
|
|
// aggiungo reset caricamento
|
|
objItem resRecipeData = new objItem()
|
|
{
|
|
uid = "ResetAccepted",
|
|
reqValue = "false",
|
|
name = "ResetAccepted"
|
|
};
|
|
ListaCalcParams.Add(resRecipeData);
|
|
// effettua chiamata scrittura verso impianto x il solo reset......
|
|
plcWriteParams(ref ListaCalcParams);
|
|
|
|
// aspetta 1 sec procede
|
|
Task.Delay(1 * 1000);
|
|
|
|
// aggiungo ultimo parametro di resetCounter... come 0/1... boh!
|
|
objItem resetCnt = new objItem()
|
|
{
|
|
uid = "ResetCounter",
|
|
reqValue = "1",
|
|
name = "ResetCounter"
|
|
};
|
|
ListaCalcParams.Add(resetCnt);
|
|
|
|
// effettua chiamata scrittura verso impianto...
|
|
plcWriteParams(ref ListaCalcParams);
|
|
|
|
// aspetta 1 sec e indica ricetta richiesta
|
|
Task.Delay(1 * 1000);
|
|
ListaCalcParams = new List<objItem>();
|
|
// aggiungo ultimo parametro di newRecipe...
|
|
objItem newRecipeData = new objItem()
|
|
{
|
|
uid = "NewRecipe",
|
|
reqValue = "true",
|
|
name = "NewRecipe"
|
|
};
|
|
ListaCalcParams.Add(newRecipeData);
|
|
// effettua chiamata scrittura verso impianto...
|
|
plcWriteParams(ref ListaCalcParams);
|
|
|
|
// aggiungo 1 altro step di attesa alla lettura pezzi x sicurezza...
|
|
dtVetoReadPzCount = DateTime.Now.AddMinutes(delayMinReadPzCount);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua sync dati inviando RICETTA
|
|
/// </summary>
|
|
protected override void processDataSync()
|
|
{
|
|
lgInfo("--------------------------------------------");
|
|
lgInfo($"executeTasks --> syncDbData --> processDataSync");
|
|
lgInfo("--------------------------------------------");
|
|
// effettua sync recuperando dati ed effettuando scrittura su kepware
|
|
var taskGet = iobGetSendDossier();
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Recupero dati da server x invio dati ricetta a OPC-UA Siemens (RAMA x Tenditalia)
|
|
/// NB: modificato rispetto a TFT: invia PODL correntemente in esecuzione (SE DISPONIBILE) oppure il PRIMO di quelli attivabili...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private bool iobGetSendDossier()
|
|
{
|
|
bool answ;
|
|
|
|
lgInfo("iobGetSendDossier: Inizio scrittura dati a server OPC-UA");
|
|
/*-----------------------------------------
|
|
* STEPS processo:
|
|
* - recupero ARTICOLI (solo quelli dei PODL attivi)
|
|
* - recupero PODL (tutti)
|
|
* - recupero elenco DOSSIER last x macchina (legato ai PODL attivi)
|
|
* - prendo SOLO PODL attivi, e prendo il + vecchio
|
|
* - se trovo dossier x articolo del PODL + vecchio (e dovrebbe...) procedo
|
|
* - uso Dictionary dei memWrite x tradurre l'elenco fluxLog in nuovi valori
|
|
* - preparo il set di valori da scrivere con traduzione
|
|
* - invio scritture
|
|
* - aggiungo info articolo (+ ODL...)
|
|
* - aggiungo i valori BIT di "reset contapezzi " + "nuova ricetta"
|
|
*----------------------------------------- */
|
|
|
|
bool okArt = false;
|
|
bool okDoss = false;
|
|
bool okPodl = false;
|
|
List<AnagArticoli> listaArt = new List<AnagArticoli>();
|
|
List<PODLModel> listaPODL = new List<PODLModel>();
|
|
List<DossiersModel> listaDoss = new List<DossiersModel>();
|
|
// recupera dati da server tramite chiamate REST a MP/IO/IOB...
|
|
var rawListArt = callUrl(urlGetCurrArt, false);
|
|
var rawListDOSS = callUrl(urlGetCurrDOSS, false);
|
|
var rawListPODL = callUrl(urlGetActPODL, false);
|
|
if (!string.IsNullOrEmpty(rawListArt))
|
|
{
|
|
try
|
|
{
|
|
listaArt = JsonConvert.DeserializeObject<List<AnagArticoli>>(rawListArt);
|
|
okArt = listaArt.Count > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"Errore: chiamata elenco ART ha restituito errore{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lg.Error($"Errore: chiamata elenco ART ({urlGetCurrArt}) ha restituito valore vuoto");
|
|
}
|
|
if (!string.IsNullOrEmpty(rawListDOSS))
|
|
{
|
|
try
|
|
{
|
|
listaDoss = JsonConvert.DeserializeObject<List<DossiersModel>>(rawListDOSS);
|
|
okDoss = listaDoss.Count > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"Errore: chiamata elenco DOSSIER ha restituito errore{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lg.Error($"Errore: chiamata elenco DOSSIER ({urlGetCurrDOSS}) ha restituito valore vuoto");
|
|
}
|
|
if (!string.IsNullOrEmpty(rawListPODL))
|
|
{
|
|
try
|
|
{
|
|
listaPODL = JsonConvert.DeserializeObject<List<PODLModel>>(rawListPODL);
|
|
okPodl = listaPODL.Count > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"Errore: chiamata elenco DOSSIER ha restituito errore{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lg.Error($"Errore: chiamata elenco PODL ({urlGetActPODL}) ha restituito valore vuoto");
|
|
}
|
|
|
|
answ = okArt && okPodl && okDoss;
|
|
if (answ)
|
|
{
|
|
// verifico i PODL attivi...
|
|
var listPodlAct = listaPODL.Where(x => x.Attivabile).OrderBy(x => x.InsertDate).ToList();
|
|
if (listPodlAct.Count > 0)
|
|
{
|
|
string codArt = listPodlAct.FirstOrDefault().CodArticolo;
|
|
// verifico di avere il dossier e l'articolo x questo PODL
|
|
var selArt = listaArt.Where(x => x.CodArticolo == codArt).FirstOrDefault();
|
|
var selDoss = listaDoss.Where(x => x.CodArticolo == codArt).FirstOrDefault();
|
|
// prendo il primo e recupero...
|
|
if (selArt != null && selDoss != null)
|
|
{
|
|
// recupero il resultset dei valori FluxLog da caricare
|
|
DossierFluxLogDTO resultSet = JsonConvert.DeserializeObject<DossierFluxLogDTO>(selDoss.Valore);
|
|
List<FluxLog> listFluxLog = resultSet.ODL;
|
|
|
|
// inizio con reset ricetta caricata
|
|
ListaCalcParams = new List<objItem>();
|
|
// aggiungo reset caricamento
|
|
objItem resRecipeData = new objItem()
|
|
{
|
|
uid = "ResetAccepted",
|
|
reqValue = "false",
|
|
name = "ResetAccepted"
|
|
};
|
|
ListaCalcParams.Add(resRecipeData);
|
|
// effettua chiamata scrittura verso impianto x il solo reset......
|
|
plcWriteParams(ref ListaCalcParams);
|
|
|
|
// preparo elenco parametri da inviare...
|
|
|
|
// aspetta 1 sec procede
|
|
Task.Delay(1 * 1000);
|
|
ListaCalcParams = new List<objItem>();
|
|
// per ogni valore ricevuto nel dossier --> calcolo parametro da inviare
|
|
foreach (var item in listFluxLog)
|
|
{
|
|
objItem currData = new objItem()
|
|
{
|
|
uid = item.CodFlux,
|
|
reqValue = item.Valore,
|
|
name = item.CodFlux
|
|
};
|
|
// aggiungo!
|
|
ListaCalcParams.Add(currData);
|
|
lgInfo($"Add param: {currData.uid} | reqVal: {currData.reqValue}");
|
|
}
|
|
// aggiungo parametro ARTICOLO...
|
|
objItem setArt = new objItem()
|
|
{
|
|
uid = "setArt",
|
|
reqValue = getMemMapWriteVal("setArt"),
|
|
name = "setArt"
|
|
};
|
|
ListaCalcParams.Add(setArt);
|
|
// aggiungo parametro COMMESSA...
|
|
objItem setComm = new objItem()
|
|
{
|
|
uid = "setComm",
|
|
reqValue = getMemMapWriteVal("setComm"),
|
|
name = "setComm"
|
|
};
|
|
ListaCalcParams.Add(setComm);
|
|
// aggiungo ultimo parametro di resetCounter... come 0/1... boh!
|
|
objItem resetCnt = new objItem()
|
|
{
|
|
uid = "ResetCounter",
|
|
reqValue = "1",
|
|
name = "ResetCounter"
|
|
};
|
|
ListaCalcParams.Add(resetCnt);
|
|
|
|
// effettua chiamata scrittura verso impianto...
|
|
plcWriteParams(ref ListaCalcParams);
|
|
|
|
// aspetta 1 sec e indica ricetta richiesta
|
|
Task.Delay(1 * 1000);
|
|
ListaCalcParams = new List<objItem>();
|
|
// aggiungo ultimo parametro di newRecipe...
|
|
objItem newRecipeData = new objItem()
|
|
{
|
|
uid = "NewRecipe",
|
|
reqValue = "true",
|
|
name = "NewRecipe"
|
|
};
|
|
ListaCalcParams.Add(newRecipeData);
|
|
// effettua chiamata scrittura verso impianto...
|
|
plcWriteParams(ref ListaCalcParams);
|
|
}
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |