561 lines
22 KiB
C#
561 lines
22 KiB
C#
using IOB_UT_NEXT;
|
|
using MapoSDK;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net.NetworkInformation;
|
|
using static IOB_WIN_NEXT.IobRest.Citizen.Responses;
|
|
|
|
namespace IOB_WIN_NEXT.IobRest
|
|
{
|
|
/// <summary>
|
|
/// Adapter specializzato per Citizen (Colcom, MT70)
|
|
/// </summary>
|
|
public class Citizen : Base
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Costruttore dell'IOB SOAP della bilancia RestCitizen
|
|
/// </summary>
|
|
/// <param name="caller">AdapterForm chiamante</param>
|
|
/// <param name="IOBConf">Configurazione IOB per avvio</param>
|
|
public Citizen(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
|
|
{
|
|
lgInfo($"Richiesto Adapter IobRest.RestCitizen con i parametri seguenti | ADDR: {IOBConf.cncIpAddr} | PORT: {IOBConf.cncPort}");
|
|
lastPING = DateTime.Now.AddHours(-1);
|
|
redKeyAlarm = redisMan.redHash($"IOB:Status:{cIobConf.codIOB}:Alarm:LastRead");
|
|
lastPING = DateTime.Now.AddHours(-1);
|
|
// predispongo configurazione specifica Rest...
|
|
lgInfo("Rest - 01");
|
|
if (!string.IsNullOrEmpty(getOptPar("REST_CONF")))
|
|
{
|
|
setupRestConf(getOptPar("REST_CONF"));
|
|
}
|
|
lgInfo("Rest - 02");
|
|
// fixme todo levare forzatura test iniziale...
|
|
if (EnableTest)
|
|
{
|
|
lgInfo("Rest - 03");
|
|
// test folder salvataggio log
|
|
var appPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
|
var fPath = Directory.GetParent(appPath).FullName;
|
|
basePath = Path.Combine(fPath, "Test");
|
|
if (!Directory.Exists(basePath))
|
|
{
|
|
Directory.CreateDirectory(basePath);
|
|
}
|
|
lgInfo("Rest - 04");
|
|
|
|
string token = TestCitizenCall("gettoken/mecmaticames/mecmatica@mes");
|
|
token = token.Replace("\"", "");
|
|
string gLamp = TestCitizenCall($"getsingleladderio/{token}/Y/8E");
|
|
string yLamp = TestCitizenCall($"getsingleladderio/{token}/Y/21");
|
|
string rLamp = TestCitizenCall($"getsingleladderio/{token}/Y/22");
|
|
string qtyTot = TestCitizenCall($"gettotalquantity/{token}");
|
|
string qtyReq = TestCitizenCall($"getneededquantity/{token}");
|
|
string qtyWrk = TestCitizenCall($"getworkedquantity/{token}");
|
|
string cTime = TestCitizenCall($"getcycletime/{token}");
|
|
string pName = TestCitizenCall($"getmainprogram/{token}");
|
|
|
|
string cAlarm = ExecuteCallGet($"getalarm/{token}");
|
|
var sAlarm = JsonConvert.DeserializeObject<WarnInfo>(cAlarm);
|
|
cAlarm = JsonConvert.SerializeObject(sAlarm, Formatting.Indented);
|
|
lgInfo($"Call: getalarm/{token} | resp: {cAlarm}");
|
|
|
|
string allAlarm = ExecuteCallGet($"getallalarmlog/{token}");
|
|
var alarmList = JsonConvert.DeserializeObject<List<AlarmInfo>>(allAlarm);
|
|
allAlarm = JsonConvert.SerializeObject(alarmList, Formatting.Indented);
|
|
lgInfo($"Call: getallalarmlog/{token} | resp: {allAlarm}");
|
|
|
|
string err = TestCitizenCall($"getsingleladderio/ABC/Y/22");
|
|
|
|
// salvo i valori
|
|
File.WriteAllText(Path.Combine(basePath, "token.txt"), token);
|
|
File.WriteAllText(Path.Combine(basePath, "gLamp.txt"), gLamp);
|
|
File.WriteAllText(Path.Combine(basePath, "yLamp.txt"), yLamp);
|
|
File.WriteAllText(Path.Combine(basePath, "rLamp.txt"), rLamp);
|
|
File.WriteAllText(Path.Combine(basePath, "qtyTot.txt"), qtyTot);
|
|
File.WriteAllText(Path.Combine(basePath, "qtyReq.txt"), qtyReq);
|
|
File.WriteAllText(Path.Combine(basePath, "qtyWrk.txt"), qtyWrk);
|
|
File.WriteAllText(Path.Combine(basePath, "cTime.txt"), cTime);
|
|
File.WriteAllText(Path.Combine(basePath, "pName.txt"), pName);
|
|
File.WriteAllText(Path.Combine(basePath, "cAlarm.txt"), cAlarm);
|
|
File.WriteAllText(Path.Combine(basePath, "allAlarm.txt"), allAlarm);
|
|
File.WriteAllText(Path.Combine(basePath, "err.txt"), err);
|
|
}
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Methods
|
|
|
|
/// <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;
|
|
bool checkMachine = false;
|
|
// 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"));
|
|
lgInfo($"GetConnection | {checkResp}");
|
|
bool.TryParse(checkResp, out checkMachine);
|
|
// forse va eliminato...
|
|
if (checkMachine)
|
|
{
|
|
connectionOk = true;
|
|
queueInEnabCurr = true;
|
|
if (adpRunning)
|
|
{
|
|
lgInfo("Connessione OK");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lgError($"Errore check connessione | checkResp: {checkResp}");
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Internal Classes
|
|
|
|
/// <summary>
|
|
/// Struttura delle risposte alle chiamare REST specifiche
|
|
/// </summary>
|
|
internal class Responses
|
|
{
|
|
#region Internal Classes
|
|
|
|
/// <summary>
|
|
/// Struttura info restituiti da AlarmList
|
|
/// </summary>
|
|
internal class AlarmInfo
|
|
{
|
|
#region Public Properties
|
|
|
|
public DateTime date { get; set; } = DateTime.Today.AddYears(-10);
|
|
public string ErrorMessage { get; set; } = "";
|
|
public int id { get; set; } = 0;
|
|
public string message { get; set; } = "";
|
|
public string type { get; set; } = "";
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Struttura info restituiti x lettura Ladder
|
|
/// </summary>
|
|
internal class LadderIO
|
|
{
|
|
#region Public Properties
|
|
|
|
public string Address { get; set; } = "";
|
|
public string Description { get; set; } = "";
|
|
public string ErrorMessage { get; set; } = "";
|
|
public string IOType { get; set; } = "";
|
|
public string VarValue { get; set; } = "";
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Struttura dato AlarmState (singolo, corrente)
|
|
/// </summary>
|
|
internal class WarnInfo
|
|
{
|
|
#region Public Properties
|
|
|
|
public string ErrorMessage { get; set; } = "";
|
|
public bool IsAlarm { get; set; } = false;
|
|
public bool IsCaution { get; set; } = false;
|
|
public string message { get; set; } = "";
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
#endregion Internal Classes
|
|
}
|
|
|
|
#endregion Internal Classes
|
|
|
|
#region Private Fields
|
|
|
|
private string basePath = "";
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
/// <summary>
|
|
/// Elenco pesate attuali
|
|
/// </summary>
|
|
private List<AlarmInfo> listAllarmiCurr { get; set; } = new List<AlarmInfo>();
|
|
|
|
/// <summary>
|
|
/// CHiave redis di salvataggio ultimo set di allarmi scaricato
|
|
/// </summary>
|
|
private string redKeyAlarm { get; set; } = "";
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
|
|
/// </summary>
|
|
protected override 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 (connectionOk)
|
|
{
|
|
B_input = 1;
|
|
currDispData.semIn = Semaforo.SV;
|
|
|
|
// controllo lampade... da rosso a verde...
|
|
if(RestLutGet("rLamp")=="1")
|
|
{
|
|
B_input += (1 << 3);
|
|
}
|
|
else if (RestLutGet("yLamp") == "1")
|
|
{
|
|
B_input += (1 << 4);
|
|
}
|
|
else if (RestLutGet("gLamp") == "1")
|
|
{
|
|
B_input += (1 << 1);
|
|
}
|
|
|
|
// accodo NON emergenza ... poi da cercare meglio...
|
|
B_input += (1 << 7);
|
|
}
|
|
else
|
|
{
|
|
B_input = 0;
|
|
currDispData.semIn = Semaforo.SR;
|
|
}
|
|
|
|
|
|
#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 queueInEnabCurr] | veto attivo alle {DateTime.Now:yyyy.MM.dd HH:mm:ss}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue lettura dati + salvataggio in LUT
|
|
/// </summary>
|
|
protected override void refreshData()
|
|
{
|
|
bool checkMachine = false;
|
|
LadderIO ladderResp = new LadderIO();
|
|
// in primis testo che sia connessa...
|
|
var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"));
|
|
lgInfo($"GetConnection | {checkResp}");
|
|
bool.TryParse(checkResp, out checkMachine);
|
|
|
|
// proseguo SOLO SE macchina OK, altrimenti disconnetto...
|
|
if (checkMachine)
|
|
{
|
|
// faccio refresh token comunque...
|
|
string token = ExecuteCallGet(GetUrlResource("GetToken"));
|
|
RestLutUpsert("token", token);
|
|
|
|
// ora controllo valori lampada SE scaduti
|
|
// FixMe ToDo !!! gestione con scadenza info x evitare troppe letture...
|
|
if (true)
|
|
{
|
|
// resetto 3 valori lamp
|
|
RestLutUpsert("gLamp", "0");
|
|
RestLutUpsert("yLamp", "0");
|
|
RestLutUpsert("rLamp", "0");
|
|
|
|
int signVal = 0;
|
|
string gLamp = ExecuteCallGet(GetUrlResource("GetLampGreen"));
|
|
ladderResp = JsonConvert.DeserializeObject<LadderIO>(gLamp);
|
|
if (string.IsNullOrEmpty(ladderResp.ErrorMessage))
|
|
{
|
|
int.TryParse(gLamp, out signVal);
|
|
RestLutUpsert("gLamp", gLamp);
|
|
}
|
|
|
|
// se il valore è zero --> proseguo con yellow!
|
|
if (signVal == 0)
|
|
{
|
|
string yLamp = ExecuteCallGet(GetUrlResource("GetLampYellow"));
|
|
ladderResp = JsonConvert.DeserializeObject<LadderIO>(yLamp);
|
|
if (string.IsNullOrEmpty(ladderResp.ErrorMessage))
|
|
{
|
|
int.TryParse(yLamp, out signVal);
|
|
RestLutUpsert("yLamp", yLamp);
|
|
}
|
|
}
|
|
|
|
// se il valore è zero --> proseguo con red!
|
|
if (signVal == 0)
|
|
{
|
|
string rLamp = ExecuteCallGet(GetUrlResource("GetLampRed"));
|
|
ladderResp = JsonConvert.DeserializeObject<LadderIO>(rLamp);
|
|
if (string.IsNullOrEmpty(ladderResp.ErrorMessage))
|
|
{
|
|
int.TryParse(rLamp, out signVal);
|
|
RestLutUpsert("rLamp", rLamp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tryDisconnect();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue gestioen contapezzi...
|
|
/// </summary>
|
|
public override void processContapezzi()
|
|
{
|
|
bool checkMachine = false;
|
|
LadderIO ladderResp = new LadderIO();
|
|
// in primis testo che sia connessa...
|
|
var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"));
|
|
lgInfo($"GetConnection | {checkResp}");
|
|
bool.TryParse(checkResp, out checkMachine);
|
|
|
|
// proseguo SOLO SE macchina OK, altrimenti disconnetto...
|
|
if (checkMachine)
|
|
{
|
|
// faccio refresh token comunque...
|
|
string token = ExecuteCallGet(GetUrlResource("GetToken"));
|
|
RestLutUpsert("token", token);
|
|
|
|
// contapezzi corrente
|
|
int intVal = 0;
|
|
string qtyWrk = ExecuteCallGet(GetUrlResource("GetQtyProd"));
|
|
int.TryParse(qtyWrk, out intVal);
|
|
contapezziPLC = intVal;
|
|
RestLutUpsert("qtyWrk", qtyWrk);
|
|
|
|
// gestione altri contapezzi x
|
|
string qtyTot = ExecuteCallGet(GetUrlResource("GetQtyTot"));
|
|
string qtyReq = ExecuteCallGet(GetUrlResource("GetQtyReq"));
|
|
RestLutUpsert("qtyTot", qtyTot);
|
|
RestLutUpsert("qtyReq", qtyReq);
|
|
// gestione tempociclo e nome programma...
|
|
string cTime = ExecuteCallGet(GetUrlResource("GetCycleTime"));
|
|
string pName = ExecuteCallGet(GetUrlResource("GetProgName"));
|
|
RestLutUpsert("cTime", cTime);
|
|
RestLutUpsert("pName", pName);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero dati DYN, impiegando i valori della LUT...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override Dictionary<string, string> getDynData()
|
|
{
|
|
return RestDataLUT;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera il progName in modalità custom...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override string getPrgName()
|
|
{
|
|
return RestLutGet("pName");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test Chiamata Citizen
|
|
/// </summary>
|
|
/// <param name="urlReq"></param>
|
|
/// <returns></returns>
|
|
private string TestCitizenCall(string urlReq)
|
|
{
|
|
lgInfo($"TestCitizenCall: {urlReq}");
|
|
string answ = ExecuteCallGet(urlReq);
|
|
lgInfo($"TestCitizenCall resp: {answ}");
|
|
return answ;
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |