Files
Mapo-IOB-WIN/IOB-WIN-NEXT/IobSiemens/SiemensIngenia.cs
T
Samuele Locatelli 8bb0f158b5 SPLIT PROGETTO!!!
- 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
2024-12-20 10:16:32 +01:00

306 lines
12 KiB
C#

using IOB_UT_NEXT;
using MapoSDK;
using System;
using System.Collections.Generic;
namespace IOB_WIN_NEXT.IobSiemens
{
/// <summary>
/// Controllo Siemens specifico x impianti Ingenia (Automazione Valvital)
/// </summary>
public class SiemensIngenia : Siemens
{
/* --------------------------------------------------------------------------------
* Controlli SIEMENS INGENIA (system integrator gestione robot impianto PRESSA in VALVITAL)
* - basasto su SIEMENS
* - S7 vers 1500
*
* STRUTTURA MEMORIA DB700
*
* Le informazioni di cui abbiamo bisogno (lettura) sono le seguenti :
* Macchina Lavora (DB700.DBX0.0)
* Macchina in ciclo (DB700.DBX0.1)
* Macchina in manuale (DB700.DBX0.2)
* Macchina in allarme (DB700.DBX0.3)
* Macchina in emergenza (DB700.DBX0.4)
* Macchina in timeout -> NON GESTIBILE in quanto attualmente gestito come ALLARME o SCARTO.
* Contapezzi
* Gestione scarti
*
* Sul tema del contapezzi ovviamente ci adattiamo a come gestite la cosa e quindi vanno bene sia 2 (o più) contapezzi (contapezzi_buono, contapezzi_scarto_forno, contapezzi_scarto_pressa, contapezzi_scarto_bilancere) -> VITA ISOLA (DB700.DBD24), BUONI (DB700.DBD28), SCARTO SAET (DB700.DBD32), SCARTO PEZZI FREDDI (DB700.DBD36).
*
* in scrittura vorremmo indicare al PLC
* - codice articolo(DB701.DBD20)
* - codice commessa(DB701.DBD24)
* - quantità produzione(DB701.DBD28)
*
* Questi 3 dati devono essere visualizzati in una qualche schermata per poter asseverare il requisito della 4.0, non è necessario ci siano vincoli per cui se ad esempio la richiesta fosse superata il robot continua a lavorare comunque.
*
*
* NB: Si intende tutto con DB700.DBxx
*
* - BIT di stato
* - DBX0.0: Macchina in LAVORAZIONE
* - DBX0.1: Macchina in CICLO
* - DBX0.2: Macchina in MANUALE
* - DBX0.3: Macchina in ALLARME
* - DBX0.4: Macchina in EMERGENZA
*
* - DBD24: Vita isola (!!!???) Contapezzi TOTALISSIMO?
* - DBD28: BUONI
* - DBD32: pezzi prelevati per controllo qualità (era SCARTO SAET)
* - DBD36: SCARTO pezzi freddi
*
*
* SCRITTURA
* - DBD701.DBD20: codice articolo
* - DBD701.DBD24: codice commessa
* - DBD701.DBD28: qta produzione
*
* -------------------------------------------------------------------------------- */
#region Public Constructors
/// <summary>
/// Classe base con i metodi x Siemens
/// </summary>
/// <param name="caller"></param>
/// <param name="adpConf"></param>
public SiemensIngenia(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
lgInfo("NEW IOB SIEMENS versione VIPA INGENIA");
lastPLCWatchDog = DateTime.Now.AddMinutes(-1);
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Processo i task richiesti e li elimino dalla coda 1:1
/// </summary>
/// <param name="task2exe"></param>
public override 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>();
bool taskOk = false;
string taskVal = "";
// inizio con 1 byte VUOTO
byte[] MemBlock = new byte[1];
string memAddrWrite = "";
if (task2exe != null)
{
// cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4
foreach (var item in task2exe)
{
taskOk = false;
taskVal = "";
memAddrWrite = "";
// converto richiesta in enum...
taskType tName = taskType.nihil;
Enum.TryParse(item.Key, out tName);
// controllo sulla KEY
switch (tName)
{
case taskType.nihil:
case taskType.fixStopSetup:
case taskType.forceResetPzCount:
case taskType.forceSetPzCount:
case taskType.setProg:
case taskType.startSetup:
case taskType.stopSetup:
taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
break;
case taskType.sendWatchDogMes2Plc:
memAddrWrite = "DB701.DBB12";
upsertKey(item.Key, item.Value);
MemBlock = dwordToByte(counterMes2Plc.ToString());
taskVal = $"VALUE DB701.DBB12 --> {counterMes2Plc} ({MemBlock})";
if (verboseLog)
{
lgInfo(taskVal);
}
break;
case taskType.setArt:
case taskType.setComm:
case taskType.setPzComm:
case taskType.setParameter:
upsertKey(item.Key, item.Value);
// verifico se posso aggiornare valori in memoria...
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}";
}
// richiedo da URL i parametri WRITE da popolare
lgInfo("Chiamata 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";
}
}
taskOk = true;
break;
default:
taskVal = "SKIPPED | NO EXEC";
break;
}
// aggiungo task!
taskDone.Add(item.Key, taskVal);
if (!string.IsNullOrEmpty(memAddrWrite))
{
// scrivo!
taskOk = S7WriteBB(ref MemBlock, memAddrWrite);
}
if (!taskOk)
{
lgError($"Ingenia: errore in S7WriteBB durante executeTasks: {item.Key} | {item.Value} | memAddrWrite: {memAddrWrite} | {taskVal}");
}
}
}
return taskDone;
}
/// <summary>
/// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid)
/// </summary>
public override void processOverride()
{
}
public override void processWhatchDog()
{
// scrivo 1 volta al secondo il contatore incrementale su area apposita
DateTime adesso = DateTime.Now;
if (adesso.Subtract(lastPLCWatchDog).TotalSeconds > watchDogPeriod)
{
// incremento
counterMes2Plc++;
// se > 999'999'999 --> 0
if (counterMes2Plc > 999999999) counterMes2Plc = 0;
// salvo su DB
Dictionary<string, string> task2exe = new Dictionary<string, string>();
Dictionary<string, string> taskDone = new Dictionary<string, string>();
task2exe.Add("sendWatchDogMes2Plc", counterMes2Plc.ToString());
taskDone = executeTasks(task2exe);
lgInfo($"Scritto watchdog: {counterMes2Plc}");
// salvo watchdog PLC
lastPLCWatchDog = adesso;
}
}
#endregion Public Methods
#region Protected Fields
protected int counterMes2Plc = 0;
protected int counterPlc2Mes = 0;
protected DateTime lastPLCWatchDog;
#endregion Protected Fields
#region Protected Methods
/// <summary>
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
/// </summary>
protected override void decodeToBaseBitmap()
{
// init a zero...
B_input = 0;
/* -----------------------------------------------------
* bitmap MAPO STANDARD
* B0: POWER_ON
* B1: RUN
* B2: pzCount
* B3: allarme
* B4: manuale
* B5: emergenza
*
*
* - BIT di stato
* - DBX0.0: Macchina in LAVORAZIONE
* - DBX0.1: Macchina in CICLO
* - DBX0.2: Macchina in MANUALE
* - DBX0.3: Macchina in ALLARME
* - DBX0.4: Macchina in EMERGENZA
----------------------------------------------------- */
// bit 0 (poweron) imposto a 1 SE connected...
B_input = currPLC.IsConnected ? 1 : 0;
// recupero byte segnali...
byte mainData = RawInput[0];
int byteSignals = 0;
// bit 0 (poweron) imposto a 1 SE connected...
if (currPLC.IsConnected)
{
byteSignals += (1 << 0);
}
// RUN se lavora ed in ciclo
if ((mainData & (1 << 0)) != 0 && (mainData & (1 << 1)) != 0)
{
byteSignals += (1 << 1);
}
// manuale
if ((mainData & (1 << 2)) != 0)
{
byteSignals += (1 << 4);
}
// allarme
if ((mainData & (1 << 3)) != 0)
{
byteSignals += (1 << 3);
}
// emergenza
if ((mainData & (1 << 4)) != 0)
{
byteSignals += (1 << 5);
}
// salvo!
B_input = byteSignals;
// log opzionale!
if (verboseLog)
{
lgInfo(string.Format($"Trasformazione dati: RawInput:{RawInput[3]} --> B_input: {B_input}"));
}
}
#endregion Protected Methods
}
}