diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a743d5b1..e4b8b668 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -93,7 +93,7 @@ variables: $Target = "Releases\" + $CI_COMMIT_BRANCH + "\" + $env:APP_NAME + ".zip" cd "$env:APP_NAME\bin\" $Source = "*" - 7zip a -tzip $Target $Source -xr!DATA + 7zip a -tzip $Target $Source -xr!DATA\CONF echo "called ZIP $Source --> $Target" # helper creazione hash files diff --git a/IOB-UT-NEXT/IniFile.cs b/IOB-UT-NEXT/IniFile.cs index a23f2453..66114c6a 100644 --- a/IOB-UT-NEXT/IniFile.cs +++ b/IOB-UT-NEXT/IniFile.cs @@ -16,7 +16,6 @@ namespace IOB_UT_NEXT #endregion Public Fields - #region Public Constructors /// @@ -253,9 +252,6 @@ namespace IOB_UT_NEXT #region Private Methods - - // INI filename - /// /// GetPrivateProfileInt: import windows dll functions /// diff --git a/IOB-UT-NEXT/IobWinStatus.cs b/IOB-UT-NEXT/IobWinStatus.cs index c0dd09e4..a5fdfe10 100644 --- a/IOB-UT-NEXT/IobWinStatus.cs +++ b/IOB-UT-NEXT/IobWinStatus.cs @@ -55,6 +55,11 @@ namespace IOB_UT_NEXT /// public DateTime lastUpdate { get; set; } = DateTime.Now.AddDays(-1); + /// + /// Valore minimo da considerare come delta secondi x indicare variazione sui dati temporali + /// + public int minDeltaSec { get; set; } = 5; + /// /// Status del SINGOLO IOB /// @@ -105,11 +110,6 @@ namespace IOB_UT_NEXT /// public Dictionary setupParams { get; set; } = new Dictionary(); - /// - /// Valore minimo da considerare come delta secondi x indicare variazione sui dati temporali - /// - public int minDeltaSec { get; set; } = 5; - #endregion Public Properties #region Public Methods diff --git a/IOB-UT-NEXT/Objects.cs b/IOB-UT-NEXT/Objects.cs index a9a63508..d7cd69eb 100644 --- a/IOB-UT-NEXT/Objects.cs +++ b/IOB-UT-NEXT/Objects.cs @@ -65,8 +65,6 @@ namespace IOB_UT_NEXT /// public class BaseRawTransf { - #region Public Properties - /// /// Data-Ora riferimento (x ordinamento fifo) /// @@ -104,9 +102,7 @@ namespace IOB_UT_NEXT this.mesContent = mesContent; this.mesType = mesType; } - - #endregion Public Properties - } + } #endif /// @@ -813,7 +809,7 @@ namespace IOB_UT_NEXT public int Period { get; set; } = 60; /// - /// UM parametro, impiegato anche x conversione (es epoch --> datetime) + /// UM parametro, impiegato anche x conversione (es epoch --> datetime) /// public string UM { get; set; } = ""; diff --git a/IOB-UT-NEXT/RedisMan.cs b/IOB-UT-NEXT/RedisMan.cs index abfa8ba2..d689f27f 100644 --- a/IOB-UT-NEXT/RedisMan.cs +++ b/IOB-UT-NEXT/RedisMan.cs @@ -26,7 +26,9 @@ namespace IOB_UT_NEXT /// IP/nome server /// Cod IOB /// Tipo di IOB - /// Minima differenza in secondi x considerare variazione dati DataOra + /// + /// Minima differenza in secondi x considerare variazione dati DataOra + /// public RedisIobCache(string codServer, string codIob, string tipoIob, int minDeltaS) { // init dati di base... @@ -1105,16 +1107,16 @@ namespace IOB_UT_NEXT /// protected string currIobType = "ND"; - /// - /// Hash REDIS x dati IOB - /// - protected string redIobKey = ""; - /// /// Nome del channel REDIS x dati IOB /// protected string redIobChannel = "IobChannel"; + /// + /// Hash REDIS x dati IOB + /// + protected string redIobKey = ""; + /// /// Hash REDIS x dati server /// diff --git a/IOB-UT-NEXT/TimeUtils.cs b/IOB-UT-NEXT/TimeUtils.cs index 9d4dae2d..c46e0744 100644 --- a/IOB-UT-NEXT/TimeUtils.cs +++ b/IOB-UT-NEXT/TimeUtils.cs @@ -1,18 +1,18 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace IOB_UT_NEXT { public class TimeUtils { + #region Public Methods + public static DateTime epochConvert(double epoch) { - DateTime date = new DateTime(1970, 1, 1, 0, 0, 0, 0); //from start epoch time + DateTime date = new DateTime(1970, 1, 1, 0, 0, 0, 0); //from start epoch time date = date.AddSeconds(epoch); return date; } + + #endregion Public Methods } -} +} \ No newline at end of file diff --git a/IOB-UT-NEXT/ToMapo.cs b/IOB-UT-NEXT/ToMapo.cs index e396030c..ca1dbb79 100644 --- a/IOB-UT-NEXT/ToMapo.cs +++ b/IOB-UT-NEXT/ToMapo.cs @@ -234,6 +234,11 @@ namespace IOB_UT_NEXT /// public List fluxLogVeto { get; set; } = new List(); + /// + /// Indica se il controllo di ping sia OK (x controllo prima della connessione) + /// + public bool forcePingOk { get; set; } = false; + /// /// Array degli elementi di traduzione item /// @@ -280,10 +285,14 @@ namespace IOB_UT_NEXT public bool pingAsPowerOn { get; set; } = true; /// - /// Indica se il controllo di ping sia OK (x controllo prima della connessione) + /// Indica se venga richiesta invio del run mode /// - public bool forcePingOk { get; set; } = false; - + public bool runModeSend { get; set; } = false; + + /// + /// Indica se venga richiesta traduzione del run mode + /// + public bool runModeTrad { get; set; } = false; #endregion Public Properties } diff --git a/IOB-UT-NEXT/baseUtils.cs b/IOB-UT-NEXT/baseUtils.cs index 553ee0ea..ccf8e57b 100644 --- a/IOB-UT-NEXT/baseUtils.cs +++ b/IOB-UT-NEXT/baseUtils.cs @@ -41,15 +41,15 @@ namespace IOB_UT_NEXT /// public static bool MPIO_Online = false; + #endregion Public Fields + #if false /// /// Oggetto connessione REDIS /// - public static RedisIobCache redisMan = new RedisIobCache(); + public static RedisIobCache redisMan = new RedisIobCache(); #endif - #endregion Public Fields - #region Public Properties /// diff --git a/IOB-UT-NEXT/fileMover.cs b/IOB-UT-NEXT/fileMover.cs index 8d7583d7..4c02a6cc 100644 --- a/IOB-UT-NEXT/fileMover.cs +++ b/IOB-UT-NEXT/fileMover.cs @@ -13,15 +13,6 @@ namespace IOB_UT_NEXT /// public class fileMover { - #region Protected Fields - - /// - /// path di lavoro dei metodi leggi/scrivi - /// - protected string _workPath; - - #endregion Protected Fields - #region Public Fields /// @@ -42,7 +33,7 @@ namespace IOB_UT_NEXT /// inizializza il metodo alla cartella indicata /// /// - /// non serve +... x retrocompatibilità... + /// non serve +... x retrocompatibilit�... public fileMover(string _path, string _log) { setDirs(_path); @@ -59,111 +50,6 @@ namespace IOB_UT_NEXT #endregion Public Constructors - #region Private Methods - - /// - /// cerca di caricare la directoryInfo o da httpcontext-application re-position o direttamente come workpath - /// - /// - private DirectoryInfo getDirectoryInfo() - { - DirectoryInfo _di; - _di = new DirectoryInfo(_workPath); - return _di; - } - - /// - /// Recupera oggetto DirInfo da path - /// - /// - /// - private DirectoryInfo getDirectoryInfo(string path) - { - DirectoryInfo _di = new DirectoryInfo(path); - return _di; - } - - /// - /// cerca di caricare il fileinfo o da httpcontext-application re-position o direttamente come workpath + nomefile - /// - /// path completo file - /// - private FileInfo getFileInfoByName(string _fullPath) - { - FileInfo _fi; - _fi = new FileInfo(_fullPath); - return _fi; - } - - /// - /// cerca di caricare il fileinfo o da httpcontext-application re-position o direttamente come workpath + nomefile - /// - /// cartella file - /// nome file - /// - private FileInfo getFileInfoByName(string _path, string _nomeFile) - { - FileInfo _fi; - _fi = new FileInfo(_path + "\\" + _nomeFile); - return _fi; - } - - /// - /// setta le directory - /// - /// - private void setDirs(string _path) - { - _workPath = _path; - } - - #endregion Private Methods - - #region Protected Methods - - /// - /// converte un byte[] in una string - /// - /// - /// - protected string byteToStr(byte[] _array) - { - System.Text.ASCIIEncoding encod = new System.Text.ASCIIEncoding(); - return encod.GetString(_array); - } - - /// - /// converte una string in un byte[] - /// - /// - /// - protected byte[] strToByte(string _val) - { - System.Text.ASCIIEncoding encod = new System.Text.ASCIIEncoding(); - return encod.GetBytes(_val); - } - - /// - /// verifica esistenza directory ed eventualmente crea restituendo nome completo di "/" finale - /// - /// - /// - protected string verDir(string _path) - { - DirectoryInfo di = getDirectoryInfo(_path); - if (!di.Exists) - { - di.Create(); - } - if (!_path.EndsWith("/") && !_path.EndsWith(@"\")) - { - _path += "/"; - } - return _path; - } - - #endregion Protected Methods - #region Public Methods /// @@ -253,16 +139,15 @@ namespace IOB_UT_NEXT } /// - /// Legge i dati da uno stream fino a quando arriva alla fine. - /// I dati sono restituiti come un byte[] array. un eccezione IOException è - /// sollevata se una delle chiamate IO sottostanti fallisce. + /// Legge i dati da uno stream fino a quando arriva alla fine. I dati sono restituiti come + /// un byte[] array. Un eccezione IOException viene sollevata se una delle chiamate IO + /// sottostanti fallisce. /// /// Lo stream da cui leggere /// Lunghezza buffer iniziale (-1 = default 32k) public static byte[] ReadFully(Stream stream, int initialLength) { - // If we've been passed an unhelpful initial length, just - // use 32K. + // If we've been passed an unhelpful initial length, just use 32K. if (initialLength < 1) { initialLength = 32768; @@ -276,8 +161,7 @@ namespace IOB_UT_NEXT { read += chunk; - // If we've reached the end of our buffer, check to see if there's - // any more information + // If we've reached the end of our buffer, check to see if there's any more information if (read == buffer.Length) { int nextByte = stream.ReadByte(); @@ -288,8 +172,7 @@ namespace IOB_UT_NEXT return buffer; } - // Nope. Resize the buffer, put in the byte we've just - // read, and continue + // Nope. Resize the buffer, put in the byte we've just read, and continue byte[] newBuffer = new byte[buffer.Length * 2]; Array.Copy(buffer, newBuffer, buffer.Length); newBuffer[read] = (byte)nextByte; @@ -513,6 +396,25 @@ namespace IOB_UT_NEXT return fatto; } + /// + /// Elimina i file + vecchi di maxNumDays giorni + /// + /// + public void deleteOlderThan(int maxNumDays) + { + DirectoryInfo _di = checkDir(); + FileInfo[] _fis = _di.GetFiles(); + DateTime dateLimit = DateTime.Now.AddDays(-maxNumDays); + try + { + _fis.Where(x => x.LastWriteTime < dateLimit).ToList().ForEach(x => x.Delete()); + } + catch (Exception exc) + { + Logging.Instance.Error($"Eccezione in deleteOlderThan{Environment.NewLine}{exc}"); + } + } + /// /// elimina il file + vecchio /// @@ -541,24 +443,6 @@ namespace IOB_UT_NEXT catch { } } - /// - /// Elimina i file + vecchi di maxNumDays giorni - /// - /// - public void deleteOlderThan(int maxNumDays) - { - DirectoryInfo _di = checkDir(); - FileInfo[] _fis = _di.GetFiles(); - DateTime dateLimit = DateTime.Now.AddDays(-maxNumDays); - try - { - _fis.Where(x => x.LastWriteTime x.Delete()); - } - catch(Exception exc) - { - Logging.Instance.Error($"Eccezione in deleteOlderThan{Environment.NewLine}{exc}"); - } - } /// /// elenco dei files come array di oggetti FileInfo @@ -582,7 +466,7 @@ namespace IOB_UT_NEXT } /// - /// elimina la directory di lavoro se è dir virtuale mappata + /// elimina la directory di lavoro se � dir virtuale mappata /// /// public bool eliminaDir() @@ -852,7 +736,7 @@ namespace IOB_UT_NEXT /// imposta la dir di lavoro /// /// - /// non serve +... x retrocompatibilità... + /// non serve +... x retrocompatibilit�... public void setDirectory(string _path, string _log) { setDirs(_path); @@ -911,7 +795,8 @@ namespace IOB_UT_NEXT { s.SetLevel(5); byte[] buffer = new byte[4096]; - // effettuo una ricerca dei files corrispondenti al criterio regexp, e per ognuno effettuo inserimento in zipfile... + // effettuo una ricerca dei files corrispondenti al criterio regexp, e per + // ognuno effettuo inserimento in zipfile... FileInfo[] filesTrovati = elencoFiles_FI(regExp); ZipEntry entry; foreach (FileInfo _fi in filesTrovati) @@ -923,7 +808,8 @@ namespace IOB_UT_NEXT s.PutNextEntry(entry); using (FileStream fs = File.OpenRead(_fi.FullName)) { - // Using a fixed size buffer here makes no noticeable difference for output but keeps a lid on memory usage. + // Using a fixed size buffer here makes no noticeable difference for + // output but keeps a lid on memory usage. int sourceBytes; do { @@ -1026,5 +912,122 @@ namespace IOB_UT_NEXT } #endregion Public Methods + + #region Protected Fields + + /// + /// path di lavoro dei metodi leggi/scrivi + /// + protected string _workPath; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// converte un byte[] in una string + /// + /// + /// + protected string byteToStr(byte[] _array) + { + System.Text.ASCIIEncoding encod = new System.Text.ASCIIEncoding(); + return encod.GetString(_array); + } + + /// + /// converte una string in un byte[] + /// + /// + /// + protected byte[] strToByte(string _val) + { + System.Text.ASCIIEncoding encod = new System.Text.ASCIIEncoding(); + return encod.GetBytes(_val); + } + + /// + /// verifica esistenza directory ed eventualmente crea restituendo nome completo di "/" finale + /// + /// + /// + protected string verDir(string _path) + { + DirectoryInfo di = getDirectoryInfo(_path); + if (!di.Exists) + { + di.Create(); + } + if (!_path.EndsWith("/") && !_path.EndsWith(@"\")) + { + _path += "/"; + } + return _path; + } + + #endregion Protected Methods + + #region Private Methods + + /// + /// cerca di caricare la directoryInfo o da httpcontext-application re-position o + /// direttamente come workpath + /// + /// + private DirectoryInfo getDirectoryInfo() + { + DirectoryInfo _di; + _di = new DirectoryInfo(_workPath); + return _di; + } + + /// + /// Recupera oggetto DirInfo da path + /// + /// + /// + private DirectoryInfo getDirectoryInfo(string path) + { + DirectoryInfo _di = new DirectoryInfo(path); + return _di; + } + + /// + /// cerca di caricare il fileinfo o da httpcontext-application re-position o direttamente + /// come workpath + nomefile + /// + /// path completo file + /// + private FileInfo getFileInfoByName(string _fullPath) + { + FileInfo _fi; + _fi = new FileInfo(_fullPath); + return _fi; + } + + /// + /// cerca di caricare il fileinfo o da httpcontext-application re-position o direttamente + /// come workpath + nomefile + /// + /// cartella file + /// nome file + /// + private FileInfo getFileInfoByName(string _path, string _nomeFile) + { + FileInfo _fi; + _fi = new FileInfo(_path + "\\" + _nomeFile); + return _fi; + } + + /// + /// setta le directory + /// + /// + private void setDirs(string _path) + { + _workPath = _path; + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/AdapterForm.cs b/IOB-WIN-NEXT/AdapterForm.cs index c87880ba..954f45cc 100644 --- a/IOB-WIN-NEXT/AdapterForm.cs +++ b/IOB-WIN-NEXT/AdapterForm.cs @@ -2,14 +2,11 @@ using MapoSDK; using Newtonsoft.Json; using NLog; -using NLog.Config; -using NLog.Targets; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; -using System.Text; using System.Threading; using System.Windows.Forms; @@ -17,60 +14,6 @@ namespace IOB_WIN_NEXT { public partial class AdapterForm : Form { - #region Protected Fields - - /// - /// contatore veloce - /// - protected int fastCount; - - /// - /// Data-Ora prima apertura FORM... - /// - protected DateTime firstStart; - - /// - /// Oggetto ultimo inviato stato IOB x REDIS - /// - protected IobWinStatus lastIobStatus = new IobWinStatus() { lastUpdate = DateTime.Now.AddHours(-1), lastDataOut = DateTime.Now.AddHours(-1) }; - - /// - /// Oggetto ultimo inviato stato MP-IO x REDIS - /// - protected ServerMpStatus lastSrvStatus = new ServerMpStatus(); - - /// - /// ultimo tentativo riavvio... - /// - protected DateTime lastStartTry; - - /// - /// contatore normale - /// - protected int normCount; - - /// - /// Contatore campionamento memoria - /// - protected int sampleMemCount; - - /// - /// contatore lento - /// - protected int slowCount; - - /// - /// contatore sync allarmi - /// - protected int verySlowCount; - - /// - /// Temnpo attesa std in MS - /// - protected int waitRecMSec = 30000; - - #endregion Protected Fields - #region Public Fields /// @@ -207,100 +150,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Delegates - - private delegate void SafeCallDelegate(string text); - - #endregion Private Delegates - - #region Protected Properties - - /// - /// Valore protected comunicazione PLC - /// - protected bool _commPlcActive { get; set; } = false; - - /// - /// Valore protetto stato comunicazione - /// - protected int _commSrvActive { get; set; } = 0; - - /// - /// Valore protected semaforo IN - /// - protected Semaforo _sIN { get; set; } = Semaforo.ND; - - /// - /// Valore protected semaforo OUT - /// - protected Semaforo _sOUT { get; set; } = Semaforo.ND; - - /// - /// Codice IOB della macchina cui connettersi (x scegliere corretto file di conf...) - /// - protected string CurrIOB { get; set; } - - protected int delayShowLogMs { get; set; } = utils.CRI("delayShowLogMs"); - - /// - /// Dictionary dei divieti del datamonitor - /// - protected Dictionary dMonDisplVetoVeto { get; set; } = new Dictionary(); - - /// - /// array degli oggetti datamonitor da mostrare - /// - protected Dictionary dMonValues { get; set; } = new Dictionary(); - - /// - /// Veto a NUOVE scritture in COUNTER... - /// - protected DateTime logCounterVeto { get; set; } = DateTime.Now; - - /// - /// Stringa corrente di log... - /// - protected string logWatchString { get; set; } = ""; - - /// - /// Veto a NUOVE scritture in logWatch... - /// - protected DateTime logWatchWriteVeto { get; set; } = DateTime.Now; - - protected int maxAlQueue { get; set; } - - protected int maxEvQueue { get; set; } - - protected int maxFlQueue { get; set; } - - protected int maxMsQueue { get; set; } - - protected int maxRwTrQueue { get; set; } - - protected int maxUlQueue { get; set; } - - protected int qAlLen { get; set; } - - protected int qEvLen { get; set; } - - protected int qFlLen { get; set; } - - protected int qMsLen { get; set; } - - protected int qRTrLen { get; set; } - - protected int qUlLen { get; set; } - - protected int totQueue - { - get - { - return qEvLen + qFlLen + qAlLen + qMsLen + qUlLen; - } - } - - #endregion Protected Properties - #region Public Properties public int alQueueLen @@ -347,10 +196,7 @@ namespace IOB_WIN_NEXT } /// - /// Visualizzazione stato di comunicazione attiva con PLC: - /// 0 = NO PING - /// 1 = PING OK - /// 2 = IOB enabled + /// Visualizzazione stato di comunicazione attiva con PLC: 0 = NO PING 1 = PING OK 2 = IOB enabled /// public int commSrvActive { @@ -647,6 +493,28 @@ namespace IOB_WIN_NEXT } } + /// + /// Numero max linee da mostrare (da controllo)... + /// + public int nLine2show + { + get + { + int answ = 5; + try + { + Int32.TryParse(nLines.Text, out answ); + } + catch + { } + return answ; + } + set + { + nLines.Text = value.ToString(); + } + } + public int rtrQueueLen { set @@ -672,52 +540,6 @@ namespace IOB_WIN_NEXT } } - public int ulQueueLen - { - set - { - qUlLen = value; - lblQueueULog.Text = qUlLen.ToString(); - showQueueData(); - // se supero max precedente, ed è > 10... loggo! - if (qUlLen > maxUlQueue && qUlLen > 10) - { - maxUlQueue = qUlLen; - lgInfo($"[WARN] Coda UL di {value} record"); - } - else - { - maxUlQueue--; - maxUlQueue = maxUlQueue < qUlLen ? qUlLen : maxUlQueue; - } - } - get - { - return qUlLen; - } - } - /// - /// Numero max linee da mostrare (da controllo)... - /// - public int nLine2show - { - get - { - int answ = 5; - try - { - Int32.TryParse(nLines.Text, out answ); - } - catch - { } - return answ; - } - set - { - nLines.Text = value.ToString(); - } - } - /// /// Imposta COLORE SFONDO x Semaforo IN /// @@ -787,8 +609,510 @@ namespace IOB_WIN_NEXT } } + public int ulQueueLen + { + set + { + qUlLen = value; + lblQueueULog.Text = qUlLen.ToString(); + showQueueData(); + // se supero max precedente, ed è > 10... loggo! + if (qUlLen > maxUlQueue && qUlLen > 10) + { + maxUlQueue = qUlLen; + lgInfo($"[WARN] Coda UL di {value} record"); + } + else + { + maxUlQueue--; + maxUlQueue = maxUlQueue < qUlLen ? qUlLen : maxUlQueue; + } + } + get + { + return qUlLen; + } + } + #endregion Public Properties + #region Public Methods + + /// + /// Decodifica colore da valore semaforico + /// + /// + /// + public static Color decSemaforo(Semaforo valore) + { + Color colore = Color.LightGray; + switch (valore) + { + case Semaforo.SV: + colore = Color.LightGreen; + break; + + case Semaforo.SG: + colore = Color.LightGoldenrodYellow; + break; + + case Semaforo.SR: + colore = Color.Red; + break; + + case Semaforo.SS: + colore = Color.DarkGray; + break; + + default: + colore = Color.LightGray; + break; + } + return colore; + } + + /// + /// Avvio l'adapter + /// + /// indica se sia richeisto di SVUOTARE le code delel info + public void avviaAdapter(bool resetQueue) + { + displayTaskAndLog("Adapter starting"); + // se NON sta girando... + if (!iobObj.adpRunning) + { + iobObj.startAdapter(resetQueue); + displayTaskAndLog("Adapter started!"); + + // fix buttons start/stop/dump + start.Enabled = false; + stop.Enabled = true; + restart.Enabled = true; + + displayTaskAndLog("Start Timers"); + // inizializzo contatori fast/mid/slow + fastCount = utils.CRI("fastCount"); + normCount = utils.CRI("normCount"); + slowCount = utils.CRI("slowCount"); + verySlowCount = utils.CRI("verySlowCount"); + displayTaskAndLog("Adapter Running..."); + // init max queue + maxEvQueue = 1; + maxFlQueue = 1; + + try + { + // segnalo reboot (programma)... + iobObj.QueueFLog.Enqueue(iobObj.qEncodeFLog("IOB-STATUS", "IOB Adapter Started")); + } + catch (Exception exc) + { + lgError(string.Format("EXCEPTION in fase di chiamata URL di segnalazione AVVIO IOB:{0}{1}", Environment.NewLine, exc)); + } + } + else + { + displayTaskAndLog("Adapter STILL Running..."); + } + } + + /// + /// mostra un testo sulla status bar + LOG + /// + /// + public void displayTaskAndLog(string txt2show) + { + lblStatus.Text = txt2show; + lblStatus.Invalidate(); + lgInfo(txt2show); + } + + /// + /// Ferma l'adapter + /// + /// + /// determina se si debba tentare riavvio automatico (per caduta connessione) + /// + /// indica se sia richeisto di SVUOTARE le code delel info + /// indica se aggiornare la form prima di fermare + public void fermaAdapter(bool tryRestart, bool forceDequeue, bool updateForm) + { + fermaTutto(false, tryRestart, forceDequeue, updateForm); + } + + /// + /// Effettua un trim della stringa al numero max di linee da mostrare a video + /// + /// + /// + public string limitLine2show(string newString) + { + if (!string.IsNullOrEmpty(newString)) + { + // se num righe superiore a limite trimmo... + if (newString.Split('\n').Length > nLine2show) + { + //int idx = newString.LastIndexOf('\r'); + int idx = newString.LastIndexOf(Environment.NewLine); + newString = newString.Substring(0, idx); + } + } + return newString; + } + + /// + /// Salva su file l'oggetto di persistenza dati + /// + /// + public void savePersistLayer(string filePath) + { + // in primis check semaforo salvataggio... + if (!iobObj.adpSaving) + { + // alzo semaforo salvataggio + iobObj.adpSaving = true; + // se HO dei dati... + if (iobObj.persistenceLayer != null) + { + try + { + utils.WritePlain(iobObj.persistenceLayer, filePath); + } + catch (Exception exc) + { + lgError(string.Format("Errore salvataggio file{0}{1}", Environment.NewLine, exc)); + } + } + else + { + lgInfo("persistenceLayer null, non salvato..."); + } + // abbasso semaforo salvataggio + iobObj.adpSaving = false; + } + } + + /// + /// Mostra update delle statistiche di comunicazione (numero chiamate, tempo medio...) + /// + /// + public void updateComStats(string txt2show) + { + lblComStats.Text = string.Format("{0} | ", txt2show); + } + + /// + /// Effettua update form una volta ricevuto OBJ che contiene le varie innovazioni... + /// + /// + public void updateFormDisplay(newDisplayData currDispData) + { + // ciclo x ogni oggetto x caricare le innovazioni... + if (currDispData != null && currDispData.hasData) + { + DateTime adesso = DateTime.Now; + // RealTime display + if (!string.IsNullOrWhiteSpace(currDispData.newInData)) + { + dataMonitor_0 = limitLine2show($"{currDispData.newInData}{Environment.NewLine}{dataMonitor_0}"); + } + if (!string.IsNullOrWhiteSpace(currDispData.newSignalData)) + { + dataMonitor_1 = limitLine2show($"{currDispData.newSignalData}{Environment.NewLine}{dataMonitor_1}"); + } + if (!string.IsNullOrWhiteSpace(currDispData.newFLogData)) + { + dataMonitor_3 = limitLine2show($"{currDispData.newFLogData}{Environment.NewLine}{dataMonitor_3}"); + } + if (!string.IsNullOrWhiteSpace(currDispData.newUrlCallData)) + { + dataMonitor_2 = limitLine2show($"{currDispData.newUrlCallData}{Environment.NewLine}{dataMonitor_2}"); + } + + // Bitmap lettura attuale + if (currDispData.counter >= 0) + { + if (logCounterVeto < adesso || lblCounter.Text != $"{currDispData.counter}") + { + lblCounter.Text = $"{currDispData.counter}"; + lblCounter.Refresh(); + logCounterVeto = adesso.AddMilliseconds(delayShowLogMs); + } + } + // Bitmap lettura attuale + if (!string.IsNullOrWhiteSpace(currDispData.currBitmap)) + { + lblBitmap.Text = currDispData.currBitmap; + lblBitmap.Refresh(); + } + // LiveLog + if (!string.IsNullOrWhiteSpace(currDispData.newLiveLogData)) + { + logWatcher = currDispData.newLiveLogData; + } + // semafori + if (currDispData.semOut != Semaforo.ND) + { + // aggiorno SE diverso + if (sOUT != currDispData.semOut) + { + sOUT = currDispData.semOut; + } + } + if (currDispData.semIn != Semaforo.ND) + { + //aggiorno SE diverso + if (sIN != currDispData.semIn) + { + sIN = currDispData.semIn; + } + } + } + } + + public void WriteTextSafe(string text) + { + this.UIThread(delegate + { + lblOutMessage3.Text = text; + }); + + //if (lblOutMessage3.InvokeRequired) + //{ + // var d = new SafeCallDelegate(WriteTextSafe); + // lblOutMessage3.Invoke(d, new object[] { text }); + //} + //else + //{ + //} + } + + #endregion Public Methods + + #region Protected Fields + + /// + /// contatore veloce + /// + protected int fastCount; + + /// + /// Data-Ora prima apertura FORM... + /// + protected DateTime firstStart; + + /// + /// Oggetto ultimo inviato stato IOB x REDIS + /// + protected IobWinStatus lastIobStatus = new IobWinStatus() { lastUpdate = DateTime.Now.AddHours(-1), lastDataOut = DateTime.Now.AddHours(-1) }; + + /// + /// Oggetto ultimo inviato stato MP-IO x REDIS + /// + protected ServerMpStatus lastSrvStatus = new ServerMpStatus(); + + /// + /// ultimo tentativo riavvio... + /// + protected DateTime lastStartTry; + + /// + /// contatore normale + /// + protected int normCount; + + /// + /// Contatore campionamento memoria + /// + protected int sampleMemCount; + + /// + /// contatore lento + /// + protected int slowCount; + + /// + /// contatore sync allarmi + /// + protected int verySlowCount; + + /// + /// Temnpo attesa std in MS + /// + protected int waitRecMSec = 30000; + + #endregion Protected Fields + + #region Protected Properties + + /// + /// Valore protected comunicazione PLC + /// + protected bool _commPlcActive { get; set; } = false; + + /// + /// Valore protetto stato comunicazione + /// + protected int _commSrvActive { get; set; } = 0; + + /// + /// Valore protected semaforo IN + /// + protected Semaforo _sIN { get; set; } = Semaforo.ND; + + /// + /// Valore protected semaforo OUT + /// + protected Semaforo _sOUT { get; set; } = Semaforo.ND; + + /// + /// Codice IOB della macchina cui connettersi (x scegliere corretto file di conf...) + /// + protected string CurrIOB { get; set; } + + protected int delayShowLogMs { get; set; } = utils.CRI("delayShowLogMs"); + + /// + /// Dictionary dei divieti del datamonitor + /// + protected Dictionary dMonDisplVetoVeto { get; set; } = new Dictionary(); + + /// + /// array degli oggetti datamonitor da mostrare + /// + protected Dictionary dMonValues { get; set; } = new Dictionary(); + + /// + /// Veto a NUOVE scritture in COUNTER... + /// + protected DateTime logCounterVeto { get; set; } = DateTime.Now; + + /// + /// Stringa corrente di log... + /// + protected string logWatchString { get; set; } = ""; + + /// + /// Veto a NUOVE scritture in logWatch... + /// + protected DateTime logWatchWriteVeto { get; set; } = DateTime.Now; + + protected int maxAlQueue { get; set; } + + protected int maxEvQueue { get; set; } + + protected int maxFlQueue { get; set; } + + protected int maxMsQueue { get; set; } + + protected int maxRwTrQueue { get; set; } + + protected int maxUlQueue { get; set; } + + protected int qAlLen { get; set; } + + protected int qEvLen { get; set; } + + protected int qFlLen { get; set; } + + protected int qMsLen { get; set; } + + protected int qRTrLen { get; set; } + + protected int qUlLen { get; set; } + + protected int totQueue + { + get + { + return qEvLen + qFlLen + qAlLen + qMsLen + qUlLen; + } + } + + #endregion Protected Properties + + #region Protected Methods + + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + /// + /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere... + /// + /// + protected void lgError(string txt2log) + { + if (!string.IsNullOrEmpty(txt2log)) + { + lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; + lg.Error(txt2log); + // salvo anche in logwatcher... SE non si dimostra ricorsivo... + if (!txt2log.Contains("logWatcher")) + { + newDisplayData currDispData = new newDisplayData(); + currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | ERROR | {txt2log}"; + updateFormDisplay(currDispData); + } + } + } + + /// + /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere... + /// + /// + protected void lgInfo(string txt2log) + { + lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; + lg.Info(txt2log); + // salvo anche in logwatcher... + newDisplayData currDispData = new newDisplayData(); + currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | INFO | {txt2log}"; + updateFormDisplay(currDispData); + } + + /// + /// Init form (grafica) con helper x testi e varie + /// + protected void myGraphInitForm() + { + lblStatus.Text = "Loading"; + + // aggiunta tooltip x send forzato + ToolTip ttForceSend = new ToolTip(); + + // imposto delay. + ttForceSend.AutoPopDelay = 3000; + ttForceSend.InitialDelay = 500; + ttForceSend.ReshowDelay = 500; + // sempre visibile (che sia o meno attiva la form). + ttForceSend.ShowAlways = true; + + // imposto tooltip + ttForceSend.SetToolTip(this.chkForceDequeue, "Forza invio eventi allo stop"); + } + + /// + /// MOstra info su coda complessiva + /// + protected void showQueueData() + { + lblQueueLenTop.Text = totQueue == 0 ? "realtime" : $"ev: {qEvLen} | flog: {qFlLen} | tot: {totQueue}"; + } + + #endregion Protected Methods + + #region Private Delegates + + private delegate void SafeCallDelegate(string text); + + #endregion Private Delegates + #region Private Methods private void btnForceAutoOdl_Click(object sender, EventArgs e) @@ -946,7 +1270,9 @@ namespace IOB_WIN_NEXT /// /// Ferma tutti i componenti adapter + update buttons /// - /// indica se fermare il timer (gather) principale (solo se non si chiude) + /// + /// indica se fermare il timer (gather) principale (solo se non si chiude) + /// /// indica se tentare di riconnettersi /// indica se sia richeisto di SVUOTARE le code delel info /// indica se si debba aggiornare la form (no se si sta chiudendo...) @@ -1069,7 +1395,8 @@ namespace IOB_WIN_NEXT { lgInfo("Adapter stopped"); } - // verifico SE debba tentare il riavvio, ovvero NON running ma adpTryRestart e non ho riprovato x oltre waitRecMSec + // verifico SE debba tentare il riavvio, ovvero NON running ma adpTryRestart + // e non ho riprovato x oltre waitRecMSec DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec); if (iobObj.adpTryRestart && (DateTime.Now > dtVeto)) { @@ -1671,332 +1998,5 @@ namespace IOB_WIN_NEXT } #endregion Private Methods - - #region Protected Methods - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - /// - /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere... - /// - /// - protected void lgError(string txt2log) - { - if (!string.IsNullOrEmpty(txt2log)) - { - lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; - lg.Error(txt2log); - // salvo anche in logwatcher... SE non si dimostra ricorsivo... - if (!txt2log.Contains("logWatcher")) - { - newDisplayData currDispData = new newDisplayData(); - currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | ERROR | {txt2log}"; - updateFormDisplay(currDispData); - } - } - } - - /// - /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere... - /// - /// - protected void lgInfo(string txt2log) - { - lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; - lg.Info(txt2log); - // salvo anche in logwatcher... - newDisplayData currDispData = new newDisplayData(); - currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | INFO | {txt2log}"; - updateFormDisplay(currDispData); - } - - /// - /// Init form (grafica) con helper x testi e varie - /// - protected void myGraphInitForm() - { - lblStatus.Text = "Loading"; - - // aggiunta tooltip x send forzato - ToolTip ttForceSend = new ToolTip(); - - // imposto delay. - ttForceSend.AutoPopDelay = 3000; - ttForceSend.InitialDelay = 500; - ttForceSend.ReshowDelay = 500; - // sempre visibile (che sia o meno attiva la form). - ttForceSend.ShowAlways = true; - - // imposto tooltip - ttForceSend.SetToolTip(this.chkForceDequeue, "Forza invio eventi allo stop"); - } - - /// - /// MOstra info su coda complessiva - /// - protected void showQueueData() - { - lblQueueLenTop.Text = totQueue == 0 ? "realtime" : $"ev: {qEvLen} | flog: {qFlLen} | tot: {totQueue}"; - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Decodifica colore da valore semaforico - /// - /// - /// - public static Color decSemaforo(Semaforo valore) - { - Color colore = Color.LightGray; - switch (valore) - { - case Semaforo.SV: - colore = Color.LightGreen; - break; - - case Semaforo.SG: - colore = Color.LightGoldenrodYellow; - break; - - case Semaforo.SR: - colore = Color.Red; - break; - - case Semaforo.SS: - colore = Color.DarkGray; - break; - - default: - colore = Color.LightGray; - break; - } - return colore; - } - - /// - /// Avvio l'adapter - /// - /// indica se sia richeisto di SVUOTARE le code delel info - public void avviaAdapter(bool resetQueue) - { - displayTaskAndLog("Adapter starting"); - // se NON sta girando... - if (!iobObj.adpRunning) - { - iobObj.startAdapter(resetQueue); - displayTaskAndLog("Adapter started!"); - - // fix buttons start/stop/dump - start.Enabled = false; - stop.Enabled = true; - restart.Enabled = true; - - displayTaskAndLog("Start Timers"); - // inizializzo contatori fast/mid/slow - fastCount = utils.CRI("fastCount"); - normCount = utils.CRI("normCount"); - slowCount = utils.CRI("slowCount"); - verySlowCount = utils.CRI("verySlowCount"); - displayTaskAndLog("Adapter Running..."); - // init max queue - maxEvQueue = 1; - maxFlQueue = 1; - - try - { - // segnalo reboot (programma)... - iobObj.QueueFLog.Enqueue(iobObj.qEncodeFLog("IOB-STATUS", "IOB Adapter Started")); - } - catch (Exception exc) - { - lgError(string.Format("EXCEPTION in fase di chiamata URL di segnalazione AVVIO IOB:{0}{1}", Environment.NewLine, exc)); - } - } - else - { - displayTaskAndLog("Adapter STILL Running..."); - } - } - - /// - /// mostra un testo sulla status bar + LOG - /// - /// - public void displayTaskAndLog(string txt2show) - { - lblStatus.Text = txt2show; - lblStatus.Invalidate(); - lgInfo(txt2show); - } - - /// - /// Ferma l'adapter - /// - /// determina se si debba tentare riavvio automatico (per caduta connessione) - /// indica se sia richeisto di SVUOTARE le code delel info - /// indica se aggiornare la form prima di fermare - public void fermaAdapter(bool tryRestart, bool forceDequeue, bool updateForm) - { - fermaTutto(false, tryRestart, forceDequeue, updateForm); - } - - /// - /// Effettua un trim della stringa al numero max di linee da mostrare a video - /// - /// - /// - public string limitLine2show(string newString) - { - if (!string.IsNullOrEmpty(newString)) - { - // se num righe superiore a limite trimmo... - if (newString.Split('\n').Length > nLine2show) - { - //int idx = newString.LastIndexOf('\r'); - int idx = newString.LastIndexOf(Environment.NewLine); - newString = newString.Substring(0, idx); - } - } - return newString; - } - - /// - /// Salva su file l'oggetto di persistenza dati - /// - /// - public void savePersistLayer(string filePath) - { - // in primis check semaforo salvataggio... - if (!iobObj.adpSaving) - { - // alzo semaforo salvataggio - iobObj.adpSaving = true; - // se HO dei dati... - if (iobObj.persistenceLayer != null) - { - try - { - utils.WritePlain(iobObj.persistenceLayer, filePath); - } - catch (Exception exc) - { - lgError(string.Format("Errore salvataggio file{0}{1}", Environment.NewLine, exc)); - } - } - else - { - lgInfo("persistenceLayer null, non salvato..."); - } - // abbasso semaforo salvataggio - iobObj.adpSaving = false; - } - } - - /// - /// Mostra update delle statistiche di comunicazione (numero chiamate, tempo medio...) - /// - /// - public void updateComStats(string txt2show) - { - lblComStats.Text = string.Format("{0} | ", txt2show); - } - - /// - /// Effettua update form una volta ricevuto OBJ che contiene le varie innovazioni... - /// - /// - public void updateFormDisplay(newDisplayData currDispData) - { - // ciclo x ogni oggetto x caricare le innovazioni... - if (currDispData != null && currDispData.hasData) - { - DateTime adesso = DateTime.Now; - // RealTime display - if (!string.IsNullOrWhiteSpace(currDispData.newInData)) - { - dataMonitor_0 = limitLine2show($"{currDispData.newInData}{Environment.NewLine}{dataMonitor_0}"); - } - if (!string.IsNullOrWhiteSpace(currDispData.newSignalData)) - { - dataMonitor_1 = limitLine2show($"{currDispData.newSignalData}{Environment.NewLine}{dataMonitor_1}"); - } - if (!string.IsNullOrWhiteSpace(currDispData.newFLogData)) - { - dataMonitor_3 = limitLine2show($"{currDispData.newFLogData}{Environment.NewLine}{dataMonitor_3}"); - } - if (!string.IsNullOrWhiteSpace(currDispData.newUrlCallData)) - { - dataMonitor_2 = limitLine2show($"{currDispData.newUrlCallData}{Environment.NewLine}{dataMonitor_2}"); - } - - // Bitmap lettura attuale - if (currDispData.counter >= 0) - { - if (logCounterVeto < adesso || lblCounter.Text != $"{currDispData.counter}") - { - lblCounter.Text = $"{currDispData.counter}"; - lblCounter.Refresh(); - logCounterVeto = adesso.AddMilliseconds(delayShowLogMs); - } - } - // Bitmap lettura attuale - if (!string.IsNullOrWhiteSpace(currDispData.currBitmap)) - { - lblBitmap.Text = currDispData.currBitmap; - lblBitmap.Refresh(); - } - // LiveLog - if (!string.IsNullOrWhiteSpace(currDispData.newLiveLogData)) - { - logWatcher = currDispData.newLiveLogData; - } - // semafori - if (currDispData.semOut != Semaforo.ND) - { - // aggiorno SE diverso - if (sOUT != currDispData.semOut) - { - sOUT = currDispData.semOut; - } - } - if (currDispData.semIn != Semaforo.ND) - { - //aggiorno SE diverso - if (sIN != currDispData.semIn) - { - sIN = currDispData.semIn; - } - } - } - } - - public void WriteTextSafe(string text) - { - this.UIThread(delegate - { - lblOutMessage3.Text = text; - }); - - //if (lblOutMessage3.InvokeRequired) - //{ - // var d = new SafeCallDelegate(WriteTextSafe); - // lblOutMessage3.Invoke(d, new object[] { text }); - //} - //else - //{ - //} - } - - #endregion Public Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/ControlExtensions.cs b/IOB-WIN-NEXT/ControlExtensions.cs index 8d58683a..45dd3490 100644 --- a/IOB-WIN-NEXT/ControlExtensions.cs +++ b/IOB-WIN-NEXT/ControlExtensions.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; namespace IOB_WIN_NEXT @@ -15,7 +11,7 @@ namespace IOB_WIN_NEXT { #region Public Methods - static public void UIThread(this Control control, Action code) + public static void UIThread(this Control control, Action code) { if (control.InvokeRequired) { @@ -25,7 +21,7 @@ namespace IOB_WIN_NEXT code.Invoke(); } - static public void UIThreadInvoke(this Control control, Action code) + public static void UIThreadInvoke(this Control control, Action code) { if (control.InvokeRequired) { diff --git a/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.ini b/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.ini index d24dd833..432f354f 100644 --- a/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.ini +++ b/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.ini @@ -58,6 +58,7 @@ ENABLE_DYN_DATA=FALSE FORCE_DYN_DATA=TRUE ENABLE_DATA_FILTER=TRUE ENABLE_CLI_RESTART=TRUE +MAX_TRY_PING=3 ;NO_PING=FALSE diff --git a/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.json b/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.json index 77cea455..642d8910 100644 --- a/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.json +++ b/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.json @@ -6,9 +6,10 @@ "keyPartReq": "", "keyPartId": "", "keyProgName": "", - "keyRunMode": "", + "keyRunMode": "PLC/DB231/Attivita", "pingAsPowerOn": true, "forcePingOk": false, + "translRunMode": true, "condWork": [ { "keyName": "PLC/DB13/Gen/Marcia_AUX", @@ -42,11 +43,26 @@ }, "condError": { "checkMode": "OR", - "negateValue": true, "checkList": [ { "keyName": "PLC/DB13/Gen/ComProfibusMessage", - "targetValue": "0" + "targetValue": "1" + }, + { + "keyName": "PLC/DB13/Gen/ComProfibusMessage", + "targetValue": "3" + }, + { + "keyName": "PLC/DB13/Gen/Hydraulic_Unit", + "targetValue": "3" + }, + { + "keyName": "PLC/DB13/Gen/Marcia_AUX", + "targetValue": "1" + }, + { + "keyName": "PLC/DB13/Gen/Wheel_Fault", + "targetValue": "3" } ] }, @@ -56,7 +72,8 @@ }, "condWarmUpCoolDown": { "checkMode": "OR", - "checkList": [] + "checkList": [], + "negateValue": true }, "condWarning": { "checkMode": "AND", @@ -71,7 +88,16 @@ ], "itemTranslation": { "fdovrd": "PATH FEED OVERRIDE", - "rovrd": "PATH RAPID OVERRIDE" + "rovrd": "PATH RAPID OVERRIDE", + "RunMode_1": "Avvio Registrazione Ricetta", + "RunMode_2": "Inizio Comando Traslazione", + "RunMode_3": "Termine Comando Traslazione", + "RunMode_4": "Inizio Comando Sterzatura", + "RunMode_5": "Termine Comando Sterzatura", + "RunMode_6": "Inizio Comando Movimento Carrelli", + "RunMode_7": "Termine Comando Movimento Carrelli", + "RunMode_8": "Inizio Comando Sollevamento", + "RunMode_9": "Termine Comando Sollevamento" }, "paramsEndThresh": { "InvDDone": 50 diff --git a/IOB-WIN-NEXT/DATA/CONF/FINASSI_OMP_01.ini b/IOB-WIN-NEXT/DATA/CONF/FINASSI_OMP_01.ini index 4989bcc7..7dea2c94 100644 --- a/IOB-WIN-NEXT/DATA/CONF/FINASSI_OMP_01.ini +++ b/IOB-WIN-NEXT/DATA/CONF/FINASSI_OMP_01.ini @@ -58,6 +58,7 @@ ENABLE_DYN_DATA=FALSE FORCE_DYN_DATA=TRUE ENABLE_DATA_FILTER=TRUE ENABLE_CLI_RESTART=TRUE +MAX_TRY_PING=3 ; conf parametri memoria READ/WRITE OPC_PARAM_CONF=FINASSI_OMP_01.json diff --git a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini index 61da321e..5e4d363b 100644 --- a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini +++ b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini @@ -40,7 +40,7 @@ CLI_INST=SteamWareSim ;STARTLIST=GIACO_NWSE ;STARTLIST=SIM_DP_01 ;STARTLIST=FINASSI_HELPI_01 -STARTLIST=FINASSI_OMP_01 -;STARTLIST=BAGLIETTO_CIMOLAI_01 +;STARTLIST=FINASSI_OMP_01 +STARTLIST=BAGLIETTO_CIMOLAI_01 MAXCNC=10 \ No newline at end of file diff --git a/IOB-WIN-NEXT/DATA/CONF/IobOpcUaClient.Config.xml b/IOB-WIN-NEXT/DATA/IobOpcUaClient.Config.xml similarity index 100% rename from IOB-WIN-NEXT/DATA/CONF/IobOpcUaClient.Config.xml rename to IOB-WIN-NEXT/DATA/IobOpcUaClient.Config.xml diff --git a/IOB-WIN-NEXT/Enums.cs b/IOB-WIN-NEXT/Enums.cs index cf164466..5d83a707 100644 --- a/IOB-WIN-NEXT/Enums.cs +++ b/IOB-WIN-NEXT/Enums.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace IOB_WIN_NEXT +namespace IOB_WIN_NEXT { public enum StartMode { diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index 821b1d30..5c9a6a10 100644 --- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj +++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj @@ -427,7 +427,7 @@ Always - + Always diff --git a/IOB-WIN-NEXT/IobBeckhoff.cs b/IOB-WIN-NEXT/IobBeckhoff.cs index 16b5d3ee..2d8790f2 100644 --- a/IOB-WIN-NEXT/IobBeckhoff.cs +++ b/IOB-WIN-NEXT/IobBeckhoff.cs @@ -1,30 +1,10 @@ -using IOB_UT_NEXT; -using MapoSDK; -using Newtonsoft.Json; -using System; +using System; using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; namespace IOB_WIN_NEXT { public class IobBeckhoff : IobGeneric { - #region Protected Fields - - protected TcAdsClient AdsCli; - - /// - /// Veto controllo status x log... - /// - protected DateTime vetoCheckStatus = DateTime.Now; - - #endregion Protected Fields - #region Public Fields public List dataVal = new List(); @@ -54,15 +34,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - protected void AdsCli_ValueChanged(TcAdsClient sender, string key, string value) - { - lg.Info($"Monitored Value changed | sender: {sender} | key: {key} | value: {value}"); - } - - #endregion Protected Methods - #region Public Methods /// @@ -125,6 +96,8 @@ namespace IOB_WIN_NEXT } } + + /// /// Override connessione /// public override void tryConnect() @@ -168,5 +141,25 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected TcAdsClient AdsCli; + + /// + /// Veto controllo status x log... + /// + protected DateTime vetoCheckStatus = DateTime.Now; + + #endregion Protected Fields + + #region Protected Methods + + protected void AdsCli_ValueChanged(TcAdsClient sender, string key, string value) + { + lg.Info($"Monitored Value changed | sender: {sender} | key: {key} | value: {value}"); + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobBeckhoffCpa.cs b/IOB-WIN-NEXT/IobBeckhoffCpa.cs index 7822573f..52282e64 100644 --- a/IOB-WIN-NEXT/IobBeckhoffCpa.cs +++ b/IOB-WIN-NEXT/IobBeckhoffCpa.cs @@ -2,34 +2,14 @@ using MapoSDK; using System; using System.Collections.Generic; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { public class IobBeckhoffCpa : IobBeckhoff { - #region Private Fields - - private string counterVar = "VarADS.BuoniLancio"; - private string setArtVar = "VarADS.NomeDisegnoRichiesto"; - private string setCommVar = "VarADS.NomeLancioRichiesto"; - private string setParamsVar = "VarADS.bCambioArticolo"; - private string setPzReqVar = "VarADS.nQuantitaRichiesta"; - private string statusVar = "VarADS.StatoMacchina"; - - #endregion Private Fields - - #region Protected Fields - - protected int currStatus = 0; - - #endregion Protected Fields - #region Public Constructors + /// /// Estende l'init della classe base /// @@ -48,15 +28,12 @@ namespace IOB_WIN_NEXT counterVar = getOptPar("CPA_PZCOUNT"); } - if (getOptPar("ADD_VARS").ToLower() == "true") { // fixme conf var gestite ad eventi da json dataVal.Add(statusVar); } - - if (getOptPar("EARLY_CONNECT").ToLower() == "true") { tryConnect(); @@ -69,22 +46,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - protected void AdsCli_CountChanged(TcAdsClient sender, int newCount) - { - contapezziPLC = newCount; - lg.Info($"Nuova lettura contapezzi | contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); - } - - protected void AdsCli_StatusChanged(TcAdsClient sender, int newStatus) - { - currStatus = newStatus; - lg.Info($"Status changed: {newStatus}"); - } - - #endregion Protected Methods - #region Public Methods /// @@ -304,6 +265,39 @@ namespace IOB_WIN_NEXT #endregion Public Methods + #region Protected Fields + + protected int currStatus = 0; + + #endregion Protected Fields + + #region Protected Methods + + protected void AdsCli_CountChanged(TcAdsClient sender, int newCount) + { + contapezziPLC = newCount; + lg.Info($"Nuova lettura contapezzi | contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); + } + + protected void AdsCli_StatusChanged(TcAdsClient sender, int newStatus) + { + currStatus = newStatus; + lg.Info($"Status changed: {newStatus}"); + } + + #endregion Protected Methods + + #region Private Fields + + private string counterVar = "VarADS.BuoniLancio"; + private string setArtVar = "VarADS.NomeDisegnoRichiesto"; + private string setCommVar = "VarADS.NomeLancioRichiesto"; + private string setParamsVar = "VarADS.bCambioArticolo"; + private string setPzReqVar = "VarADS.nQuantitaRichiesta"; + private string statusVar = "VarADS.StatoMacchina"; + + #endregion Private Fields + #if false public enum EnuStates //Stato Macchina { diff --git a/IOB-WIN-NEXT/IobConfiguration.cs b/IOB-WIN-NEXT/IobConfiguration.cs index ad0b9aee..af6eb8c3 100644 --- a/IOB-WIN-NEXT/IobConfiguration.cs +++ b/IOB-WIN-NEXT/IobConfiguration.cs @@ -5,10 +5,8 @@ using System.Collections.Generic; namespace IOB_WIN_NEXT { /// - /// This Configuration class is basically just a set of - /// properties with a couple of static methods to manage - /// the serialization to and deserialization from a - /// simple XML file. + /// This Configuration class is basically just a set of properties with a couple of static + /// methods to manage the serialization to and deserialization from a simple XML file. /// /// ref: http://www.cambiaresearch.com/articles/33/how-can-i-easily-manage-an-xml-configuration-file-in-dotnet /// @@ -63,6 +61,11 @@ namespace IOB_WIN_NEXT /// public int MAX_COUNTER_BLINK { get; set; } = 10; + /// + /// Minimo delta in sec x considerare variazioni info + /// + public int minDeltaSec { get; set; } = 2; + /// /// Modello della macchina /// @@ -86,7 +89,7 @@ namespace IOB_WIN_NEXT /// /// Dati di conf del server MoonPro cui comunicare /// - public serverMapo serverData { get; set; } = new serverMapo("127.0.0.1", "/", "/IOB/input/", "/IOB/flog/", "/IOB/ulog/", "/IOB", "/IOB/enabled/", "/sendReboot.aspx?idxMacchina=", "/IOB/getCurrOdlStart/","SteamWare","/IOB/forceSplitOdlFull", "/IOB/getIdlePeriod", "/IOB/rawTransfJson"); + public serverMapo serverData { get; set; } = new serverMapo("127.0.0.1", "/", "/IOB/input/", "/IOB/flog/", "/IOB/ulog/", "/IOB", "/IOB/enabled/", "/sendReboot.aspx?idxMacchina=", "/IOB/getCurrOdlStart/", "SteamWare", "/IOB/forceSplitOdlFull", "/IOB/getIdlePeriod", "/IOB/rawTransfJson"); /// /// Slot (Siemens S7) @@ -123,11 +126,6 @@ namespace IOB_WIN_NEXT /// public string versIOB { get; set; } = "0"; - /// - /// Minimo delta in sec x considerare variazioni info - /// - public int minDeltaSec { get; set; } = 2; - #endregion Public Properties } @@ -241,30 +239,33 @@ namespace IOB_WIN_NEXT public string CMDFLOG { get; set; } = ""; /// - /// comando base x LOG di FLUSSO generico - salvataggio parametri extra sistema MAPO in modalità JSON payload come lista + /// comando base x LOG di FLUSSO generico - salvataggio parametri extra sistema MAPO in + /// modalità JSON payload come lista /// public string CMDFLOG_JSON { get; set; } = ""; + /// + /// comando base x Raw Transf LOG - salvataggio valori generici in modalità JSON payload + /// come lista + /// + public string CMDRAWTRANSF_JSON { get; set; } = ""; + + /// + /// comando base x comando reboot + /// + public string CMDREBO { get; set; } = ""; + /// /// comando base x USER LOG - salvataggio parametri extra sistema MAPO /// public string CMDULOG { get; set; } = ""; /// - /// comando base x Raw Transf LOG - salvataggio valori generici in modalità JSON payload come lista - /// - public string CMDRAWTRANSF_JSON { get; set; } = ""; - - /// - /// comando base x USER LOG - salvataggio parametri extra sistema MAPO in modalità JSON payload come lista + /// comando base x USER LOG - salvataggio parametri extra sistema MAPO in modalità JSON + /// payload come lista /// public string CMDULOG_JSON { get; set; } = ""; - /// - /// comando base x comando reboot - /// - public string CMDREBO { get; set; } = ""; - /// /// Indirizzo IP server /// diff --git a/IOB-WIN-NEXT/IobFanuc.cs b/IOB-WIN-NEXT/IobFanuc.cs index 44d56aa6..26cd8084 100644 --- a/IOB-WIN-NEXT/IobFanuc.cs +++ b/IOB-WIN-NEXT/IobFanuc.cs @@ -10,69 +10,6 @@ namespace IOB_WIN_NEXT { public class IobFanuc : IobGeneric { - #region Private Fields - - /// - /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO - /// - internal Dictionary signLUT = new Dictionary(); - - #endregion Private Fields - - #region Protected Fields - - /// - /// Dati dell'area D - /// - protected memAreaFanuc areaD; - - /// - /// Dati dell'area PARameters - /// - protected memAreaFanuc areaPAR; - - /// - /// Dati dell'area R - /// - protected memAreaFanuc areaR; - - /// - /// Dati dell'area X - /// - protected memAreaFanuc areaX; - - /// - /// Dati dell'area Y - /// - protected memAreaFanuc areaY; - - /// - /// Oggetto MAIN x connessione FANUC - /// - protected FANUC FANUC_ref; - - /// - /// Area memoria G (copia) - /// - protected byte[] MemBlockG = new byte[2]; - - /// - /// Area memoria R (copia) - /// - protected byte[] MemBlockR = new byte[2]; - - /// - /// Area memoria X (copia) - /// - protected byte[] MemBlockX = new byte[2]; - - /// - /// Area memoria Y (copia) - /// - protected byte[] MemBlockY = new byte[2]; - - #endregion Protected Fields - #region Public Constructors /// @@ -186,7 +123,8 @@ namespace IOB_WIN_NEXT lgInfo("FANUC: inizio gestione contapezzi"); try { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) { if (getOptPar("PZCOUNT_MODE").StartsWith("STD")) @@ -221,6 +159,968 @@ namespace IOB_WIN_NEXT #endregion Public Constructors + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... + Dictionary taskDone = new Dictionary(); + if (task2exe != null) + { + bool taskOk = false; + string taskVal = ""; + // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 + foreach (var item in task2exe) + { + taskOk = false; + taskVal = ""; + // converto richiesta in enum... + taskType tName = taskType.nihil; + Enum.TryParse(item.Key, out tName); + switch (tName) + { + case taskType.nihil: + case taskType.fixStopSetup: + case taskType.forceResetPzCount: + case taskType.forceSetPzCount: + case taskType.setArt: + case taskType.setComm: + case taskType.setProg: + case taskType.sendWatchDogMes2Plc: + taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; + lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + + case taskType.startSetup: + // reset contapezzi inizio setup + taskOk = resetcontapezziPLC(); + taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC"; + lgInfo($"Chiamata startSetup: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + + case taskType.stopSetup: + // reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET_stopSetup") == "TRUE") + { + taskOk = resetcontapezziPLC(); + } + taskVal = taskOk ? "RESET: SETUP END" : "PZ RESET DISABLED | NO EXEC"; + lgInfo($"Chiamata stopSetup: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + + default: + taskVal = "SKIPPED | NO EXEC"; + lgInfo($"Chiamata default senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + } + // aggiungo task! + taskDone.Add(item.Key, taskVal); + } + } + return taskDone; + } + + /// + /// wrapper chiamata lettura/scrittura SINGOLO BYTE... + /// + /// + /// + /// + /// + /// + public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte Value) + { + bool answ = false; + if (connectionOk) + { + if (FANUC_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); + } + catch + { } + } + } + parentForm.commPlcActive = false; + return answ; + } + + /// + /// wrapper chiamata lettura/scrittura MULTI BYTE... + /// + /// + /// + /// + /// + /// + public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte[] Value) + { + bool answ = false; + if (connectionOk) + { + if (FANUC_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); + } + catch + { } + } + } + parentForm.commPlcActive = false; + return answ; + } + + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() + { + Dictionary outVal = new Dictionary(); + // processo SOLO SE connected... + if (connectionOk) + { + if (FANUC_ref.Connected) + { + stopwatch.Restart(); + EgwProxy.MultiCncLib.Focas1.ODBDY2_1 answ = FANUC_ref.getAllDynData(); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("PROC-DYN-DATA"), stopwatch.ElapsedTicks); + } + + try + { + string actf = answ.actf.ToString(); + string acts = answ.acts.ToString(); + //string numAlarm = answ.alarm.ToString(); + // preparo i singoli valori dell'array... + //outVal.Add("DYNDATA", string.Format("{0}#{1}#{2}", actf, acts, numAlarm)); + outVal.Add("DYNDATA", string.Format("FEED {0}#SPEED_RPM {1}", actf, acts)); + if (utils.CRB("SendFeedSpeed")) + { + outVal.Add("FEED", actf); + outVal.Add("SPEED_RPM", acts); + //outVal.Add("NUM_ALARM", numAlarm); + } + if (utils.CRB("SendAxPos")) + { + // salvo le posizioni... + EgwProxy.MultiCncLib.Focas1.FAXIS posAx = answ.pos; + int[] currPosAbs = posAx.absolute; + int i = 0; + foreach (var item in currPosAbs) + { + i++; + outVal.Add(string.Format("POS_{0:00}", i), item.ToString()); + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in getDynData"); + } + stopwatch.Stop(); + } + } + return outVal; + } + + /// + /// Recupero dati override (da area G che è già stata letta...) + /// + /// + public override Dictionary getOverrides() + { + Dictionary outVal = new Dictionary(); + // processo SOLO SE connected... + if (connectionOk) + { + if (FANUC_ref.Connected) + { + if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) + { + outVal.Add("FEED_OVER", MemBlockG[30].ToString()); + outVal.Add("RAPID_OVER", MemBlockG[12].ToString()); + } + } + } + return outVal; + } + + /// + /// Recupero programma in lavorazione + /// + /// + public override string getPrgName() + { + string prgName = ""; + // recupero NUOVO prgName... + try + { + // recupero nome programma MAIN + prgName = utils.purgedChar2String(FANUC_ref.getPrgNameMain()); + // trimmo path del programma, ovvero "CNCMEMUSERPATH1" + prgName = prgName.Replace(utils.CRS("basePrgMemPath"), ""); + lgInfo("Current PROG: {0}", prgName); + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in recupero PRG NAME MAIN:{0}{1}", Environment.NewLine, exc)); + connectionOk = false; + } + return prgName; + } + + /// + /// Recupero programma in lavorazione come Dictionary FANUC... + /// - SYSINFO: (prima KEY globale) TUTTI i valori separati da # (x fare check modifica) + /// - altre stringhe: ogni singolo parametro / valore + /// + /// + public override Dictionary getSysInfo() + { + Dictionary outVal = new Dictionary(); + stopwatch.Restart(); + EgwProxy.MultiCncLib.Focas1.ODBSYS answ = FANUC_ref.getSysInfo(); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("SYS-INFO"), stopwatch.ElapsedTicks); + } + + try + { + string cnc_type = new string(answ.cnc_type); + string mt_type = new string(answ.mt_type); + string series = new string(answ.series); + string version = new string(answ.version); + string axes = new string(answ.axes); + //short addInfo = answ.addinfo; + short max_axis = answ.max_axis; + // preparo i singoli valori dell'array... + outVal.Add("SYSINFO", string.Format("{0}#{1}#{2}#{3}#{4}#{5}", cnc_type, mt_type, series, version, axes, max_axis)); + outVal.Add("CNC", cnc_type); + outVal.Add("MTT", mt_type); + outVal.Add("SER", series); + outVal.Add("VER", version); + outVal.Add("AXS", string.Format("{0}|{1}", axes, max_axis)); + } + catch (Exception exc) + { + lgError(exc, "Errore in getSysInfo"); + connectionOk = false; + } + return outVal; + } + + /// + /// Effettua vero processing contapezzi: + /// 6711: pezzi lavorati + /// 6712: pezzi lavorati totali + /// 6713: pezzi richiesti + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + // procedo SOLO SE ho connessione... + if (connectionOk) + { + try + { + // controllo di AVERE parametri opzionali x conteggi vari + if (cIobConf.optPar.Count > 0) + { + // contapezzi ATTUALE + if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT + // (Custom, con indicazione area) + string memAddr = getOptPar("PZCOUNT_MODE"); + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + // var di appoggio + int cntAddr = 0; + object outputVal = new object(); + // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 + if (memAddr.StartsWith("PAR.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 6711; + } + // processo parametro contapezzi (lavorati) + stopwatch.Restart(); + FANUC_ref.F_RW_Param_Integer(false, cntAddr, 3, ref outputVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks); + } + // salvo ultimo conteggio rilevato + int newVal = -1; + Int32.TryParse(outputVal.ToString(), out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + // 2022.05.23 gestione MACRO da testare (Jetco) + else if (memAddr.StartsWith("MACRO.")) + { + lgTrace($"Decodifica memoria MACRO | memAddr: {memAddr}"); + // recupero parametro... + int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr); + // processo parametro + stopwatch.Restart(); + double macroVal = 0; + FANUC_ref.F_Read_macro(cntAddr, ref macroVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-MACRO", 5), stopwatch.ElapsedTicks); + } + // salvo ultimo conteggio rilevato + int newVal = -1; + Int32.TryParse($"{macroVal}", out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + // altrimenti se legge da area memoria specifica leggo da li... + // formto tipo STD.D.1604.DW + else + { + memAddressFanuc areaCounter = new memAddressFanuc(memAddr); + if (isVerboseLog) + { + lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); + } + // leggo! + stopwatch.Restart(); + // switch x tipo dati --> tipo lettura... e salvo ultimo + // conteggio rilevato + switch (areaCounter.vType) + { + case "B": + byte valB = 0; + FANUC_ref.F_RW_Byte(false, areaCounter.mType, areaCounter.mPos, ref valB); + outputVal = valB; + break; + + case "D": + ushort valW = 0; + FANUC_ref.F_RW_Word(false, areaCounter.mType, areaCounter.mPos, ref valW); + outputVal = valW; + break; + + case "DW": + uint valDW = 0; + FANUC_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); + if (isVerboseLog) + { + lgInfo("[1] valDW contapezzi: {0}", valDW); + } + + outputVal = valDW; + if (isVerboseLog) + { + lgInfo("[2] outputVal contapezzi: {0}", outputVal); + } + + break; + + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + // salvo... + int newVal = -1; + Int32.TryParse(outputVal.ToString(), out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + //if (isVerboseLog) + //{ + lgInfo("[3] contapezziPLC contapezzi: {0}", contapezziPLC); + //} + } + stopwatch.Stop(); + } + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi FANUC 02"); + connectionOk = false; + } + } + else + { + lgError("Errore: manca connessione in contapezzi FANUC"); + } + } + } + + /// + /// Esegue processing MODE (e nel contempo recupera altri dati dell'area G) + /// + public override void processMode() + { + // processo SOLO SE connected... + if (connectionOk) + { + if (FANUC_ref.Connected) + { + if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) + { + try + { + // leggo tutto da 0 a 43... + int memIndex = 0; + // controllo modalità lettura memoria + stopwatch.Restart(); + FanucMemRW(R, FANUC.MemType.G, memIndex, ref MemBlockG); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-G-AREA", MemBlockG.Length), stopwatch.ElapsedTicks); + } + + stopwatch.Stop(); + // verifico modo con valore corrente, se cambia aggiorno... + CNC_MODE newMode = decodeG43(MemBlockG[43]); + if (newMode != currMode) + { + // aggiorno! + currMode = newMode; + // conversione NUM MODE in descrizione da ENUM + string descrMode = Enum.GetName(typeof(CNC_MODE), currMode); + // accodo x invio + string sVal = string.Format("[CNC_MODE]{0}", descrMode); + // chiamo accodamento... + accodaFLog(sVal, qEncodeFLog("CNC_MODE", descrMode)); + } + } + catch (Exception exc) + { + lgError(exc, string.Format("Errore in process Mode G43: {0}{1}", Environment.NewLine, exc)); + connectionOk = false; + stopwatch.Stop(); + } + } + } + } + } + + /// + /// Recupero altri counters se ci sono + /// + public override void processOtherCounters() + { + try + { + // controllo di AVERE parametri opzionali x conteggi vari + if (cIobConf.optPar.Count > 0) + { + string newVal = ""; +#if false + // controllo SE salvare contapezzo + if (getOptPar("PZCOUNT_MODE") != "") + { + sendOptVal("PZ_COUNT", contapezziPLC); + } +#endif + // controllo SE devo gestire contatore pezzi REQUESTED (lanciati) + if (!string.IsNullOrEmpty(getOptPar("PZREQ_MODE"))) + { + newVal = getValByParam("PZREQ_MODE"); + sendOptVal("PZ_REQ", newVal); + } + // controllo SE devo gestire contatore PEZZI TOTALI + if (!string.IsNullOrEmpty(getOptPar("PZGTOT_MODE"))) + { + newVal = getValByParam("PZGTOT_MODE"); + sendOptVal("PZ_GTOT", newVal); + } + // controllo SE devo gestire contatore CADENZA (secondi ciclo rilevati) + if (!string.IsNullOrEmpty(getOptPar("PZCAD_MODE"))) + { + newVal = getValByParam("PZCAD_MODE"); + sendOptVal("CICLE_CAD", newVal); + } + } + } + catch (Exception exc) + { + lgError(exc, "Eccezione in processOtherCounters"); + } + } + + /// + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + base.readSemafori(ref currDispData); + try + { + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + + currDispData.semIn = Semaforo.SV; + // inizio letture, SEMPRE DA ZERO (possibile ottimizzazione...) + int memIndex = 0; + // controllo area R: se ha dati (> 0 byte) --> leggo! + if (MemBlockR.Length > 0) + { + stopwatch.Restart(); + FanucMemRW(R, FANUC.MemType.R, memIndex, ref MemBlockR); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-R", MemBlockR.Length), stopwatch.ElapsedTicks); + } + // log + if (verboseLog) + { + for (int i = 0; i < MemBlockR.Length; i++) + { + lgInfo(string.Format("MemBlockR{0}: {1}", i, utils.binaryForm(MemBlockR[i]))); + } + } + } + // controllo area X: se ha dati (> 0 byte) --> leggo! + if (MemBlockX.Length > 0) + { + stopwatch.Restart(); + FanucMemRW(R, FANUC.MemType.X, memIndex, ref MemBlockX); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-X", MemBlockX.Length), stopwatch.ElapsedTicks); + } + // log + if (verboseLog) + { + for (int i = 0; i < MemBlockX.Length; i++) + { + lgInfo(string.Format("MemBlockX{0}: {1}", i, utils.binaryForm(MemBlockX[i]))); + } + } + } + // controllo area Y: se ha dati (> 0 byte) --> leggo! + if (MemBlockY.Length > 0) + { + stopwatch.Restart(); + FanucMemRW(R, FANUC.MemType.Y, memIndex, ref MemBlockY); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-Y", MemBlockY.Length), stopwatch.ElapsedTicks); + } + // log + if (verboseLog) + { + for (int i = 0; i < MemBlockY.Length; i++) + { + lgInfo(string.Format("MemBlockY{0}: {1}", i, utils.binaryForm(MemBlockY[i]))); + } + } + } + stopwatch.Stop(); + // salvo il solo BYTE dell'input decifrando il semaforo... + decodeToBitmap(); + reportRawInput(ref currDispData); + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in readSemafori:{0}{1}", Environment.NewLine, exc)); + connectionOk = false; + currDispData.semIn = Semaforo.SR; + } + } + + /// + /// Effettua reset del contapezzi + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; + // ...SE abilitato da conf IOB + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") + { + // scrivo valore 0 x il contapezzi + try + { + // contapezzi ATTUALE + if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) + string memAddr = getOptPar("PZCOUNT_MODE"); + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + // var di appoggio + int cntAddr = 0; + // var contapezzi a zero.... + object newVal = new object(); + newVal = 0; + // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 + if (memAddr.StartsWith("PAR.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 6711; + } + + // processo RESET contapezzi (lavorati) + stopwatch.Restart(); + FANUC_ref.F_RW_Param_Integer(true, cntAddr, 3, ref newVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("W{0}-PAR", 4), stopwatch.ElapsedTicks); + } + } + // altrimenti se legge da area memoria specifica leggo da li... formto + // tipo STD.D.1604.DW + else + { + memAddressFanuc areaCounter = new memAddressFanuc(memAddr); + + if (isVerboseLog) + { + lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); + } + // leggo! + stopwatch.Restart(); + // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato + switch (areaCounter.vType) + { + case "B": + byte valB = 0; + FANUC_ref.F_RW_Byte(true, areaCounter.mType, areaCounter.mPos, ref valB); + newVal = valB; + break; + + case "D": + ushort valW = 0; + FANUC_ref.F_RW_Word(true, areaCounter.mType, areaCounter.mPos, ref valW); + newVal = valW; + break; + + case "DW": + uint valDW = 0; + FANUC_ref.F_RW_DWord(true, areaCounter.mType, areaCounter.mPos, ref valDW); + break; + + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("W-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + } + stopwatch.Stop(); + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in RESET contapezzi FANUC"); + connectionOk = false; + } + answ = true; + } + return answ; + } + + /// + /// Override salvataggio valori in memoria... + /// + /// tipo di DUMP + public override void saveMemDump(dumpType tipo) + { + // se l'area ha una size > 0... + if (areaD.arraySize > 0) + { + dump_MemArea(tipo, FANUC.MemType.D, areaD.startIdx, areaD.arraySize); + } + // se l'area ha una size > 0... + if (areaR.arraySize > 0) + { + dump_MemArea(tipo, FANUC.MemType.R, areaR.startIdx, areaR.arraySize); + } + // se l'area ha una size > 0... + if (areaX.arraySize > 0) + { + dump_MemArea(tipo, FANUC.MemType.X, areaX.startIdx, areaX.arraySize); + } + // se l'area ha una size > 0... + if (areaY.arraySize > 0) + { + dump_MemArea(tipo, FANUC.MemType.Y, areaY.startIdx, areaY.arraySize); + } + // se l'area ha una size > 0... + if (areaPAR.arraySize > 0) + { + dump_ParArea(tipo, areaPAR.startIdx, areaPAR.arraySize); + } + } + + /// + /// Override connessione + /// + 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("FANUC: ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // ora PING!!! + Ping pingSender = new Ping(); + IPAddress address = IPAddress.Loopback; + IPAddress.TryParse(cIobConf.cncIpAddr, out address); + PingReply reply; + try + { + // se != null --> uso address... + if (address != null) + { + reply = pingSender.Send(address, 100); + } + else + { + reply = pingSender.Send(cIobConf.cncIpAddr, 100); + } + } + catch + { + reply = pingSender.Send(IPAddress.Loopback, 100); + } + // se passa il ping faccio il resto... + if (reply.Status == IPStatus.Success) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + FANUC_ref.Connect(ref szStatusConnection); + parentForm.commPlcActive = false; + lgInfo("szStatusConnection: " + szStatusConnection); + connectionOk = true; + // refresh stato allarmi!!! + if (connectionOk) + { + dtAvvioAdp = DateTime.Now; + if (adpRunning) + { + lgInfo("Connessione OK"); + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal(string.Format("Errore nella connessione all'adapter FANUC: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); + connectionOk = false; + lgInfo(string.Format("Eccezione in TryConnect, Adapter NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec"))); + } + } + else + { + // loggo no risposta ping ... + connectionOk = false; + if (verboseLog || periodicLog) + { + lgInfo(string.Format("Attenzione: controllo PING fallito per IP {0} - {1}", cIobConf.cncIpAddr, reply.Status)); + } + } + } + } + // se non è ancora connesso faccio procesisng memoria caso disconnesso... + if (!connectionOk) + { + // processo semafori ed invio... + processMemoryDiscon(); + } + } + + /// + /// Override disconnessione + /// + public override void tryDisconnect() + { + if (connectionOk) + { + string szStatusConnection = ""; + try + { + FANUC_ref.Disconnect(ref szStatusConnection); + connectionOk = false; + // resetto timing! + TimingData.resetData(); + lgInfo(szStatusConnection); + lgInfo("Effettuata disconnessione adapter FANUC!"); + } + catch (Exception exc) + { + lgFatal(exc, "Errore nella disconnessione dall'adapter FANUC"); + } + } + else + { + lgError("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile..."); + } + } + + #endregion Public Methods + + #region Internal Fields + + /// + /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO + /// + internal Dictionary signLUT = new Dictionary(); + + #endregion Internal Fields + + #region Protected Fields + + /// + /// Dati dell'area D + /// + protected memAreaFanuc areaD; + + /// + /// Dati dell'area PARameters + /// + protected memAreaFanuc areaPAR; + + /// + /// Dati dell'area R + /// + protected memAreaFanuc areaR; + + /// + /// Dati dell'area X + /// + protected memAreaFanuc areaX; + + /// + /// Dati dell'area Y + /// + protected memAreaFanuc areaY; + + /// + /// Oggetto MAIN x connessione FANUC + /// + protected FANUC FANUC_ref; + + /// + /// Area memoria G (copia) + /// + protected byte[] MemBlockG = new byte[2]; + + /// + /// Area memoria R (copia) + /// + protected byte[] MemBlockR = new byte[2]; + + /// + /// Area memoria X (copia) + /// + protected byte[] MemBlockX = new byte[2]; + + /// + /// Area memoria Y (copia) + /// + protected byte[] MemBlockY = new byte[2]; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// decodifica il modo dai valori del byte G43 + /// + /// + /// + protected static CNC_MODE decodeG43(byte currVal) + { + // hard coded da valori tabellari a MODI definiti in CNC_MODE... + CNC_MODE answ = CNC_MODE.ND; + switch (currVal) + { + case 0: + answ = CNC_MODE.MDI; + break; + + case 1: + answ = CNC_MODE.MEN; + break; + + case 3: + answ = CNC_MODE.EDIT; + break; + + case 4: + answ = CNC_MODE.HANDLE_INC; + break; + + case 5: + answ = CNC_MODE.JOG; + break; + + case 6: + answ = CNC_MODE.TJOG; + break; + + case 7: + answ = CNC_MODE.THND; + break; + + case 33: + answ = CNC_MODE.RMT; + break; + + case 133: + answ = CNC_MODE.REF; + break; + + default: + answ = CNC_MODE.ND; + break; + } + return answ; + } + + #endregion Protected Methods + #region Private Methods /// @@ -305,7 +1205,8 @@ namespace IOB_WIN_NEXT } if (!string.IsNullOrEmpty(currODL) && currODL != "0") { - // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture + // controllo se è passato intervallo minimo tra 2 + // controlli/elaborazioni x distanziare invio e ridurre letture if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) { // se sono differenti MOSTRO... @@ -317,7 +1218,8 @@ namespace IOB_WIN_NEXT // verifico se variato contapezzi... if (contapezziPLC > contapezziIOB) { - // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio + // salvo nuovo contapezzi (incremento di 1...) + richiesta + // refresh conteggio contapezziIOB++; needRefreshPzCount = true; // salvo in semaforo! @@ -368,7 +1270,8 @@ namespace IOB_WIN_NEXT { int.TryParse(memIdx[1], out bitNum); } - // in base al nome cerco in una delle aree.. e prendo solo solo quel bit di quel byte... + // in base al nome cerco in una delle aree.. e prendo solo solo quel bit + // di quel byte... switch (area) { case 'G': @@ -668,899 +1571,5 @@ namespace IOB_WIN_NEXT } #endregion Private Methods - - #region Protected Methods - - /// - /// decodifica il modo dai valori del byte G43 - /// - /// - /// - protected static CNC_MODE decodeG43(byte currVal) - { - // hard coded da valori tabellari a MODI definiti in CNC_MODE... - CNC_MODE answ = CNC_MODE.ND; - switch (currVal) - { - case 0: - answ = CNC_MODE.MDI; - break; - - case 1: - answ = CNC_MODE.MEN; - break; - - case 3: - answ = CNC_MODE.EDIT; - break; - - case 4: - answ = CNC_MODE.HANDLE_INC; - break; - - case 5: - answ = CNC_MODE.JOG; - break; - - case 6: - answ = CNC_MODE.TJOG; - break; - - case 7: - answ = CNC_MODE.THND; - break; - - case 33: - answ = CNC_MODE.RMT; - break; - - case 133: - answ = CNC_MODE.REF; - break; - - default: - answ = CNC_MODE.ND; - break; - } - return answ; - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... - Dictionary taskDone = new Dictionary(); - if (task2exe != null) - { - bool taskOk = false; - string taskVal = ""; - // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 - foreach (var item in task2exe) - { - taskOk = false; - taskVal = ""; - // converto richiesta in enum... - taskType tName = taskType.nihil; - Enum.TryParse(item.Key, out tName); - switch (tName) - { - case taskType.nihil: - case taskType.fixStopSetup: - case taskType.forceResetPzCount: - case taskType.forceSetPzCount: - case taskType.setArt: - case taskType.setComm: - case taskType.setProg: - case taskType.sendWatchDogMes2Plc: - taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; - lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - - case taskType.startSetup: - // reset contapezzi inizio setup - taskOk = resetcontapezziPLC(); - taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC"; - lgInfo($"Chiamata startSetup: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - - case taskType.stopSetup: - // reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO - if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET_stopSetup") == "TRUE") - { - taskOk = resetcontapezziPLC(); - } - taskVal = taskOk ? "RESET: SETUP END" : "PZ RESET DISABLED | NO EXEC"; - lgInfo($"Chiamata stopSetup: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - - default: - taskVal = "SKIPPED | NO EXEC"; - lgInfo($"Chiamata default senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - } - // aggiungo task! - taskDone.Add(item.Key, taskVal); - } - } - return taskDone; - } - - /// - /// wrapper chiamata lettura/scrittura SINGOLO BYTE... - /// - /// - /// - /// - /// - /// - public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte Value) - { - bool answ = false; - if (connectionOk) - { - if (FANUC_ref.Connected) - { - try - { - parentForm.commPlcActive = true; - answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); - } - catch - { } - } - } - parentForm.commPlcActive = false; - return answ; - } - - /// - /// wrapper chiamata lettura/scrittura MULTI BYTE... - /// - /// - /// - /// - /// - /// - public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte[] Value) - { - bool answ = false; - if (connectionOk) - { - if (FANUC_ref.Connected) - { - try - { - parentForm.commPlcActive = true; - answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); - } - catch - { } - } - } - parentForm.commPlcActive = false; - return answ; - } - - /// - /// Recupero dati dinamici... - /// - public override Dictionary getDynData() - { - Dictionary outVal = new Dictionary(); - // processo SOLO SE connected... - if (connectionOk) - { - if (FANUC_ref.Connected) - { - stopwatch.Restart(); - EgwProxy.MultiCncLib.Focas1.ODBDY2_1 answ = FANUC_ref.getAllDynData(); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("PROC-DYN-DATA"), stopwatch.ElapsedTicks); - } - - try - { - string actf = answ.actf.ToString(); - string acts = answ.acts.ToString(); - //string numAlarm = answ.alarm.ToString(); - // preparo i singoli valori dell'array... - //outVal.Add("DYNDATA", string.Format("{0}#{1}#{2}", actf, acts, numAlarm)); - outVal.Add("DYNDATA", string.Format("FEED {0}#SPEED_RPM {1}", actf, acts)); - if (utils.CRB("SendFeedSpeed")) - { - outVal.Add("FEED", actf); - outVal.Add("SPEED_RPM", acts); - //outVal.Add("NUM_ALARM", numAlarm); - } - if (utils.CRB("SendAxPos")) - { - // salvo le posizioni... - EgwProxy.MultiCncLib.Focas1.FAXIS posAx = answ.pos; - int[] currPosAbs = posAx.absolute; - int i = 0; - foreach (var item in currPosAbs) - { - i++; - outVal.Add(string.Format("POS_{0:00}", i), item.ToString()); - } - } - } - catch (Exception exc) - { - lgError(exc, "Errore in getDynData"); - } - stopwatch.Stop(); - } - } - return outVal; - } - - /// - /// Recupero dati override (da area G che è già stata letta...) - /// - /// - public override Dictionary getOverrides() - { - Dictionary outVal = new Dictionary(); - // processo SOLO SE connected... - if (connectionOk) - { - if (FANUC_ref.Connected) - { - if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) - { - outVal.Add("FEED_OVER", MemBlockG[30].ToString()); - outVal.Add("RAPID_OVER", MemBlockG[12].ToString()); - } - } - } - return outVal; - } - - /// - /// Recupero programma in lavorazione - /// - /// - public override string getPrgName() - { - string prgName = ""; - // recupero NUOVO prgName... - try - { - // recupero nome programma MAIN - prgName = utils.purgedChar2String(FANUC_ref.getPrgNameMain()); - // trimmo path del programma, ovvero "CNCMEMUSERPATH1" - prgName = prgName.Replace(utils.CRS("basePrgMemPath"), ""); - lgInfo("Current PROG: {0}", prgName); - } - catch (Exception exc) - { - lgError(string.Format("Eccezione in recupero PRG NAME MAIN:{0}{1}", Environment.NewLine, exc)); - connectionOk = false; - } - return prgName; - } - - /// - /// Recupero programma in lavorazione come Dictionary FANUC... - /// - SYSINFO: (prima KEY globale) TUTTI i valori separati da # (x fare check modifica) - /// - altre stringhe: ogni singolo parametro / valore - /// - /// - public override Dictionary getSysInfo() - { - Dictionary outVal = new Dictionary(); - stopwatch.Restart(); - EgwProxy.MultiCncLib.Focas1.ODBSYS answ = FANUC_ref.getSysInfo(); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("SYS-INFO"), stopwatch.ElapsedTicks); - } - - try - { - string cnc_type = new string(answ.cnc_type); - string mt_type = new string(answ.mt_type); - string series = new string(answ.series); - string version = new string(answ.version); - string axes = new string(answ.axes); - //short addInfo = answ.addinfo; - short max_axis = answ.max_axis; - // preparo i singoli valori dell'array... - outVal.Add("SYSINFO", string.Format("{0}#{1}#{2}#{3}#{4}#{5}", cnc_type, mt_type, series, version, axes, max_axis)); - outVal.Add("CNC", cnc_type); - outVal.Add("MTT", mt_type); - outVal.Add("SER", series); - outVal.Add("VER", version); - outVal.Add("AXS", string.Format("{0}|{1}", axes, max_axis)); - } - catch (Exception exc) - { - lgError(exc, "Errore in getSysInfo"); - connectionOk = false; - } - return outVal; - } - - /// - /// Effettua vero processing contapezzi: - /// 6711: pezzi lavorati - /// 6712: pezzi lavorati totali - /// 6713: pezzi richiesti - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { - // procedo SOLO SE ho connessione... - if (connectionOk) - { - try - { - // controllo di AVERE parametri opzionali x conteggi vari - if (cIobConf.optPar.Count > 0) - { - // contapezzi ATTUALE - if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) - { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - string memAddr = getOptPar("PZCOUNT_MODE"); - if (memAddr.StartsWith("STD")) - { - // inizio verifica area memoria/parametro levando prima parte codice - memAddr = memAddr.Replace("STD.", ""); - // var di appoggio - int cntAddr = 0; - object outputVal = new object(); - // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 - if (memAddr.StartsWith("PAR.")) - { - // recupero parametro... - int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); - if (cntAddr == 0) - { - cntAddr = 6711; - } - // processo parametro contapezzi (lavorati) - stopwatch.Restart(); - FANUC_ref.F_RW_Param_Integer(false, cntAddr, 3, ref outputVal); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks); - } - // salvo ultimo conteggio rilevato - int newVal = -1; - Int32.TryParse(outputVal.ToString(), out newVal); - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - } - // 2022.05.23 gestione MACRO da testare (Jetco) - else if (memAddr.StartsWith("MACRO.")) - { - lgTrace($"Decodifica memoria MACRO | memAddr: {memAddr}"); - // recupero parametro... - int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr); - // processo parametro - stopwatch.Restart(); - double macroVal = 0; - FANUC_ref.F_Read_macro(cntAddr, ref macroVal); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-MACRO", 5), stopwatch.ElapsedTicks); - } - // salvo ultimo conteggio rilevato - int newVal = -1; - Int32.TryParse($"{macroVal}", out newVal); - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - } - // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW - else - { - memAddressFanuc areaCounter = new memAddressFanuc(memAddr); - if (isVerboseLog) - { - lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); - } - // leggo! - stopwatch.Restart(); - // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato - switch (areaCounter.vType) - { - case "B": - byte valB = 0; - FANUC_ref.F_RW_Byte(false, areaCounter.mType, areaCounter.mPos, ref valB); - outputVal = valB; - break; - - case "D": - ushort valW = 0; - FANUC_ref.F_RW_Word(false, areaCounter.mType, areaCounter.mPos, ref valW); - outputVal = valW; - break; - - case "DW": - uint valDW = 0; - FANUC_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); - if (isVerboseLog) - { - lgInfo("[1] valDW contapezzi: {0}", valDW); - } - - outputVal = valDW; - if (isVerboseLog) - { - lgInfo("[2] outputVal contapezzi: {0}", outputVal); - } - - break; - - default: - break; - } - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); - } - // salvo... - int newVal = -1; - Int32.TryParse(outputVal.ToString(), out newVal); - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - //if (isVerboseLog) - //{ - lgInfo("[3] contapezziPLC contapezzi: {0}", contapezziPLC); - //} - } - stopwatch.Stop(); - } - } - } - } - catch (Exception exc) - { - lgError(exc, "Errore in contapezzi FANUC 02"); - connectionOk = false; - } - } - else - { - lgError("Errore: manca connessione in contapezzi FANUC"); - } - } - } - - /// - /// Esegue processing MODE (e nel contempo recupera altri dati dell'area G) - /// - public override void processMode() - { - // processo SOLO SE connected... - if (connectionOk) - { - if (FANUC_ref.Connected) - { - if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) - { - try - { - // leggo tutto da 0 a 43... - int memIndex = 0; - // controllo modalità lettura memoria - stopwatch.Restart(); - FanucMemRW(R, FANUC.MemType.G, memIndex, ref MemBlockG); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-G-AREA", MemBlockG.Length), stopwatch.ElapsedTicks); - } - - stopwatch.Stop(); - // verifico modo con valore corrente, se cambia aggiorno... - CNC_MODE newMode = decodeG43(MemBlockG[43]); - if (newMode != currMode) - { - // aggiorno! - currMode = newMode; - // conversione NUM MODE in descrizione da ENUM - string descrMode = Enum.GetName(typeof(CNC_MODE), currMode); - // accodo x invio - string sVal = string.Format("[CNC_MODE]{0}", descrMode); - // chiamo accodamento... - accodaFLog(sVal, qEncodeFLog("CNC_MODE", descrMode)); - } - } - catch (Exception exc) - { - lgError(exc, string.Format("Errore in process Mode G43: {0}{1}", Environment.NewLine, exc)); - connectionOk = false; - stopwatch.Stop(); - } - } - } - } - } - - /// - /// Recupero altri counters se ci sono - /// - public override void processOtherCounters() - { - try - { - // controllo di AVERE parametri opzionali x conteggi vari - if (cIobConf.optPar.Count > 0) - { - string newVal = ""; -#if false - // controllo SE salvare contapezzo - if (getOptPar("PZCOUNT_MODE") != "") - { - sendOptVal("PZ_COUNT", contapezziPLC); - } -#endif - // controllo SE devo gestire contatore pezzi REQUESTED (lanciati) - if (!string.IsNullOrEmpty(getOptPar("PZREQ_MODE"))) - { - newVal = getValByParam("PZREQ_MODE"); - sendOptVal("PZ_REQ", newVal); - } - // controllo SE devo gestire contatore PEZZI TOTALI - if (!string.IsNullOrEmpty(getOptPar("PZGTOT_MODE"))) - { - newVal = getValByParam("PZGTOT_MODE"); - sendOptVal("PZ_GTOT", newVal); - } - // controllo SE devo gestire contatore CADENZA (secondi ciclo rilevati) - if (!string.IsNullOrEmpty(getOptPar("PZCAD_MODE"))) - { - newVal = getValByParam("PZCAD_MODE"); - sendOptVal("CICLE_CAD", newVal); - } - } - } - catch (Exception exc) - { - lgError(exc, "Eccezione in processOtherCounters"); - } - } - - /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form - /// - public override void readSemafori(ref newDisplayData currDispData) - { - base.readSemafori(ref currDispData); - try - { - if (verboseLog) - { - lgInfo("inizio read semafori"); - } - - currDispData.semIn = Semaforo.SV; - // inizio letture, SEMPRE DA ZERO (possibile ottimizzazione...) - int memIndex = 0; - // controllo area R: se ha dati (> 0 byte) --> leggo! - if (MemBlockR.Length > 0) - { - stopwatch.Restart(); - FanucMemRW(R, FANUC.MemType.R, memIndex, ref MemBlockR); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-R", MemBlockR.Length), stopwatch.ElapsedTicks); - } - // log - if (verboseLog) - { - for (int i = 0; i < MemBlockR.Length; i++) - { - lgInfo(string.Format("MemBlockR{0}: {1}", i, utils.binaryForm(MemBlockR[i]))); - } - } - } - // controllo area X: se ha dati (> 0 byte) --> leggo! - if (MemBlockX.Length > 0) - { - stopwatch.Restart(); - FanucMemRW(R, FANUC.MemType.X, memIndex, ref MemBlockX); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-X", MemBlockX.Length), stopwatch.ElapsedTicks); - } - // log - if (verboseLog) - { - for (int i = 0; i < MemBlockX.Length; i++) - { - lgInfo(string.Format("MemBlockX{0}: {1}", i, utils.binaryForm(MemBlockX[i]))); - } - } - } - // controllo area Y: se ha dati (> 0 byte) --> leggo! - if (MemBlockY.Length > 0) - { - stopwatch.Restart(); - FanucMemRW(R, FANUC.MemType.Y, memIndex, ref MemBlockY); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-Y", MemBlockY.Length), stopwatch.ElapsedTicks); - } - // log - if (verboseLog) - { - for (int i = 0; i < MemBlockY.Length; i++) - { - lgInfo(string.Format("MemBlockY{0}: {1}", i, utils.binaryForm(MemBlockY[i]))); - } - } - } - stopwatch.Stop(); - // salvo il solo BYTE dell'input decifrando il semaforo... - decodeToBitmap(); - reportRawInput(ref currDispData); - } - catch (Exception exc) - { - lgError(string.Format("Eccezione in readSemafori:{0}{1}", Environment.NewLine, exc)); - connectionOk = false; - currDispData.semIn = Semaforo.SR; - } - } - - /// - /// Effettua reset del contapezzi - /// - /// - public override bool resetcontapezziPLC() - { - bool answ = false; - // ...SE abilitato da conf IOB - if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") - { - // scrivo valore 0 x il contapezzi - try - { - // contapezzi ATTUALE - if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) - { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - string memAddr = getOptPar("PZCOUNT_MODE"); - if (memAddr.StartsWith("STD")) - { - // inizio verifica area memoria/parametro levando prima parte codice - memAddr = memAddr.Replace("STD.", ""); - // var di appoggio - int cntAddr = 0; - // var contapezzi a zero.... - object newVal = new object(); - newVal = 0; - // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 - if (memAddr.StartsWith("PAR.")) - { - // recupero parametro... - int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); - if (cntAddr == 0) - { - cntAddr = 6711; - } - - // processo RESET contapezzi (lavorati) - stopwatch.Restart(); - FANUC_ref.F_RW_Param_Integer(true, cntAddr, 3, ref newVal); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("W{0}-PAR", 4), stopwatch.ElapsedTicks); - } - } - // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW - else - { - memAddressFanuc areaCounter = new memAddressFanuc(memAddr); - - if (isVerboseLog) - { - lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); - } - // leggo! - stopwatch.Restart(); - // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato - switch (areaCounter.vType) - { - case "B": - byte valB = 0; - FANUC_ref.F_RW_Byte(true, areaCounter.mType, areaCounter.mPos, ref valB); - newVal = valB; - break; - - case "D": - ushort valW = 0; - FANUC_ref.F_RW_Word(true, areaCounter.mType, areaCounter.mPos, ref valW); - newVal = valW; - break; - - case "DW": - uint valDW = 0; - FANUC_ref.F_RW_DWord(true, areaCounter.mType, areaCounter.mPos, ref valDW); - break; - - default: - break; - } - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("W-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); - } - } - stopwatch.Stop(); - } - } - } - catch (Exception exc) - { - lgError(exc, "Errore in RESET contapezzi FANUC"); - connectionOk = false; - } - answ = true; - } - return answ; - } - - /// - /// Override salvataggio valori in memoria... - /// - /// tipo di DUMP - public override void saveMemDump(dumpType tipo) - { - // se l'area ha una size > 0... - if (areaD.arraySize > 0) - { - dump_MemArea(tipo, FANUC.MemType.D, areaD.startIdx, areaD.arraySize); - } - // se l'area ha una size > 0... - if (areaR.arraySize > 0) - { - dump_MemArea(tipo, FANUC.MemType.R, areaR.startIdx, areaR.arraySize); - } - // se l'area ha una size > 0... - if (areaX.arraySize > 0) - { - dump_MemArea(tipo, FANUC.MemType.X, areaX.startIdx, areaX.arraySize); - } - // se l'area ha una size > 0... - if (areaY.arraySize > 0) - { - dump_MemArea(tipo, FANUC.MemType.Y, areaY.startIdx, areaY.arraySize); - } - // se l'area ha una size > 0... - if (areaPAR.arraySize > 0) - { - dump_ParArea(tipo, areaPAR.startIdx, areaPAR.arraySize); - } - } - - /// - /// Override connessione - /// - 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("FANUC: ConnKO - tryConnect"); - } - // in primis salvo data ping... - lastPING = DateTime.Now; - // ora PING!!! - Ping pingSender = new Ping(); - IPAddress address = IPAddress.Loopback; - IPAddress.TryParse(cIobConf.cncIpAddr, out address); - PingReply reply; - try - { - // se != null --> uso address... - if (address != null) - { - reply = pingSender.Send(address, 100); - } - else - { - reply = pingSender.Send(cIobConf.cncIpAddr, 100); - } - } - catch - { - reply = pingSender.Send(IPAddress.Loopback, 100); - } - // se passa il ping faccio il resto... - if (reply.Status == IPStatus.Success) - { - string szStatusConnection = ""; - try - { - // ora provo connessione... - parentForm.commPlcActive = true; - FANUC_ref.Connect(ref szStatusConnection); - parentForm.commPlcActive = false; - lgInfo("szStatusConnection: " + szStatusConnection); - connectionOk = true; - // refresh stato allarmi!!! - if (connectionOk) - { - dtAvvioAdp = DateTime.Now; - if (adpRunning) - { - lgInfo("Connessione OK"); - } - } - else - { - lgError("Impossibile procedere, connessione mancante..."); - } - } - catch (Exception exc) - { - lgFatal(string.Format("Errore nella connessione all'adapter FANUC: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); - connectionOk = false; - lgInfo(string.Format("Eccezione in TryConnect, Adapter NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec"))); - } - } - else - { - // loggo no risposta ping ... - connectionOk = false; - if (verboseLog || periodicLog) - { - lgInfo(string.Format("Attenzione: controllo PING fallito per IP {0} - {1}", cIobConf.cncIpAddr, reply.Status)); - } - } - } - } - // se non è ancora connesso faccio procesisng memoria caso disconnesso... - if (!connectionOk) - { - // processo semafori ed invio... - processMemoryDiscon(); - } - } - - /// - /// Override disconnessione - /// - public override void tryDisconnect() - { - if (connectionOk) - { - string szStatusConnection = ""; - try - { - FANUC_ref.Disconnect(ref szStatusConnection); - connectionOk = false; - // resetto timing! - TimingData.resetData(); - lgInfo(szStatusConnection); - lgInfo("Effettuata disconnessione adapter FANUC!"); - } - catch (Exception exc) - { - lgFatal(exc, "Errore nella disconnessione dall'adapter FANUC"); - } - } - else - { - lgError("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile..."); - } - } - - #endregion Public Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobFile.cs b/IOB-WIN-NEXT/IobFile.cs index 46d4dd91..16e299eb 100644 --- a/IOB-WIN-NEXT/IobFile.cs +++ b/IOB-WIN-NEXT/IobFile.cs @@ -1,16 +1,9 @@ using IOB_UT_NEXT; using MapoSDK; -using Newtonsoft.Json; -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Firefox; using System; using System.Collections.Generic; using System.IO; -using System.Net.NetworkInformation; using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; namespace IOB_WIN_NEXT { @@ -24,25 +17,6 @@ namespace IOB_WIN_NEXT * * -------------------------------------------------------------------------------- */ - #region Protected Fields - - /// - /// Cartella di base per interscambio - /// - protected string BaseDir = @"C:\Steamware"; - - /// - /// Array di configurazione degli oggetti da cercare x decodifica e recupero info - /// - protected Dictionary dataLocatorLUT; - - /// - /// Vettore della frequenza di ogni status trovato... invio ogni 100 rilevazioni (modulo 100, resto == 1) - /// - protected Dictionary freqUnknStatus = new Dictionary(); - - #endregion Protected Fields - #region Public Constructors /// @@ -58,95 +32,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Methods - - /// - /// Processo stati unknown... - /// - /// - private void processUnknStatus(string cKey) - { - // cerco se avevo già una key nella dictionary... - if (freqUnknStatus.ContainsKey(cKey)) - { - freqUnknStatus[cKey]++; - // se è 1 ogni 100 (%100, resto ==1) --> loggo... - if (freqUnknStatus[cKey] % 100 == 1) - { - lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey} | freq: {freqUnknStatus[cKey]}"); - // accodo come invio di tipo FLOG... - string sVal = string.Format("[UnknStatus] {0}, freq: {1}", cKey, freqUnknStatus); - // chiamo accodamento... - accodaFLog(sVal, qEncodeFLog("UnknStatus", sVal)); - } - } - else - { - // creo chiave con freq = 1 - freqUnknStatus.Add(cKey, 1); - // log iniziale - lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey}"); - } - } - - #endregion Private Methods - - #region Internal Methods - - /// - /// Pulizia preliminare folder comunicazione - /// - internal virtual void cleanupFolder() - { - // - } - - /// - /// Ricarica conf adapter... - /// - internal virtual void reloadAdapterConf() - { -#if false - // init obj display - newDisplayData currDispData = new newDisplayData(); - lgInfo("BEGIN reloadAdapterConf"); - // inizializzo LUT decodifica - string jsonConf = getOptPar("LUT_CONF"); - if (!string.IsNullOrEmpty(jsonConf)) - { - string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{jsonConf}"; - lgInfo($"Apertura file {jsonFullPath}"); - StreamReader reader = new StreamReader(jsonFullPath); - string jsonData = reader.ReadToEnd(); - if (!string.IsNullOrEmpty(jsonData)) - { - try - { - monitoredItems = JsonConvert.DeserializeObject(jsonData); - // salvo baseUri - baseDir = monitoredItems.SrvData.baseUri; - lgInfo($"baseUri = {baseDir}"); - // imposto a zero la bitmap x riavvio! - B_input = 0; - // FORZO invio dati... - accodaSigIN(ref currDispData); - // loggo! - lgInfo($"init input bitmap to zero: {B_input}"); - } - catch (Exception exc) - { - lgError(exc, "Eccezione in decodifica conf json"); - } - } - reader.Dispose(); - } - lgInfo("DONE reloadAdapterConf"); - raiseRefresh(currDispData); -#endif - } - - #endregion Internal Methods - #region Public Methods public void Dispose() @@ -358,5 +243,114 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Internal Methods + + /// + /// Pulizia preliminare folder comunicazione + /// + internal virtual void cleanupFolder() + { + + } + + /// + /// Ricarica conf adapter... + /// + internal virtual void reloadAdapterConf() + { +#if false + // init obj display + newDisplayData currDispData = new newDisplayData(); + lgInfo("BEGIN reloadAdapterConf"); + // inizializzo LUT decodifica + string jsonConf = getOptPar("LUT_CONF"); + if (!string.IsNullOrEmpty(jsonConf)) + { + string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{jsonConf}"; + lgInfo($"Apertura file {jsonFullPath}"); + StreamReader reader = new StreamReader(jsonFullPath); + string jsonData = reader.ReadToEnd(); + if (!string.IsNullOrEmpty(jsonData)) + { + try + { + monitoredItems = JsonConvert.DeserializeObject(jsonData); + // salvo baseUri + baseDir = monitoredItems.SrvData.baseUri; + lgInfo($"baseUri = {baseDir}"); + // imposto a zero la bitmap x riavvio! + B_input = 0; + // FORZO invio dati... + accodaSigIN(ref currDispData); + // loggo! + lgInfo($"init input bitmap to zero: {B_input}"); + } + catch (Exception exc) + { + lgError(exc, "Eccezione in decodifica conf json"); + } + } + reader.Dispose(); + } + lgInfo("DONE reloadAdapterConf"); + raiseRefresh(currDispData); +#endif + } + + #endregion Internal Methods + + #region Protected Fields + + /// + /// Cartella di base per interscambio + /// + protected string BaseDir = @"C:\Steamware"; + + /// + /// Array di configurazione degli oggetti da cercare x decodifica e recupero info + /// + protected Dictionary dataLocatorLUT; + + /// + /// Vettore della frequenza di ogni status trovato... invio ogni 100 rilevazioni (modulo + /// 100, resto == 1) + /// + protected Dictionary freqUnknStatus = new Dictionary(); + + #endregion Protected Fields + + #region Private Methods + + /// + /// Processo stati unknown... + /// + /// + private void processUnknStatus(string cKey) + { + // cerco se avevo già una key nella dictionary... + if (freqUnknStatus.ContainsKey(cKey)) + { + freqUnknStatus[cKey]++; + // se è 1 ogni 100 (%100, resto ==1) --> loggo... + if (freqUnknStatus[cKey] % 100 == 1) + { + lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey} | freq: {freqUnknStatus[cKey]}"); + // accodo come invio di tipo FLOG... + string sVal = string.Format("[UnknStatus] {0}, freq: {1}", cKey, freqUnknStatus); + // chiamo accodamento... + accodaFLog(sVal, qEncodeFLog("UnknStatus", sVal)); + } + } + else + { + // creo chiave con freq = 1 + freqUnknStatus.Add(cKey, 1); + // log iniziale + lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey}"); + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobFileEurom63.cs b/IOB-WIN-NEXT/IobFileEurom63.cs index c6905aa0..befe3583 100644 --- a/IOB-WIN-NEXT/IobFileEurom63.cs +++ b/IOB-WIN-NEXT/IobFileEurom63.cs @@ -1,12 +1,9 @@ -using EgwProxy.MultiCncLib.OPENcontrol; -using IOB_UT_NEXT; +using IOB_UT_NEXT; using MapoSDK; using Newtonsoft.Json; using System; -using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; @@ -15,47 +12,6 @@ namespace IOB_WIN_NEXT { public class IobFileEurom63 : IobFile { - #region Protected Fields - - protected static DateTime lastStatusDecr = DateTime.Now; - - /// - /// step di comunicazione attivo - /// - protected Eurom63.ComLevel actLevel = Eurom63.ComLevel.None; - - /// - /// DIrectory eseguibile corrente - /// - protected string appPath = Directory.GetCurrentDirectory(); - - /// - /// Moltiplicatore durata cache - /// - protected int cacheMult = 4; - - /// - /// Oggetti decodificati da pagina - /// - protected Eurom63.ProtoConf confE63; - - /// - /// Valore currStatus validato (per gestione "disconnessioni") - /// - protected CachedInt Last_B_Input = new CachedInt() { Value = 0 }; - - /// - /// Valore currStatus validato (per gestione "disconnessioni") - /// - protected CachedString Last_CurrStatus = new CachedString() { Value = "00000" }; - - /// - /// Massimo delay lettura dati prima di considerarli scaduti (30 sec, ma x test 1 gg) - /// - protected int maxDelaySec = 30; - - #endregion Protected Fields - #region Public Constructors /// @@ -80,448 +36,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Methods - - /// - /// Se la sessione fosse scaduta o non attiva --> torna al livello indicato - /// - /// - private void checkSessionActive(Eurom63.Session currSession, Eurom63.ComLevel nextLevel) - { - // SOLO SE ha senso che controllo (sono in sampling...) - if (actLevel > Eurom63.ComLevel.HasInfo) - { - DateTime adesso = DateTime.Now; - // devono essere ATTIVE le sessioni di campionamento... e NON scadute - if (!currSession.Active || currSession.SessionValidUntil < adesso) - { - // controllo ultimo downgrade status - if (lastStatusDecr.AddSeconds(3) < adesso) - { - // elimino TUTTE le risposte... - cleanupResp(currSession.SessionName); - // registro downgrade status... - lastStatusDecr = adesso; - // imposto livellotornando indietro di 1 alla volta... senza andare in negativoS - actLevel = actLevel - 1; - actLevel = actLevel > 0 ? actLevel : 0; - lgInfo($"Sessione inattiva, {actLevel + 1} --> {actLevel}"); - } - } - } - } - - /// - /// Effettua copia file richeiste + update timing - /// - /// - /// - private void copyRequestFiles(Eurom63.Session connectSession, DateTime adesso) - { - // processo richiesta - processSessionFile(connectSession); - if (adesso > connectSession.SessionValidUntil) - { - connectSession.Active = !connectSession.Cycle; - } - connectSession.Passed = false; - connectSession.SessionStarted = adesso; - connectSession.SessionValidUntil = adesso.AddMinutes(connectSession.ValidityMinutes); - connectSession.RetryVeto = adesso.AddSeconds(connectSession.RetrySec); - } - - #endregion Private Methods - - #region Protected Methods - - protected void abortPrevJob() - { - var nextLevel = Eurom63.ComLevel.ChannelOk; - var connectSession = confE63.ActiveSessions[3]; - processSession(nextLevel, ref connectSession); -#if false - // qui per sicurezza PULISCE TUTTO - cleanupFolder(); -#endif - } - - /// - /// Verifica una sessione configurata (ovvero la comunicazione su TUTTI i file associati) - /// - /// - /// - protected bool checkRequest(Eurom63.Session session) - { - bool answ = false; - string fileName = ""; - if (session != null) - { - fileName = $"{BaseDir}\\{session.SessionName}.REQ"; - answ = File.Exists(fileName); - } - return answ; - } - - /// - /// Verifica se ci sia una risposta POSITIVA - /// - /// - /// - protected bool checkResp(Eurom63.Session session) - { - bool answ = false; - string fileName = ""; - if (session != null) - { - fileName = $"{BaseDir}\\{session.SessionName}.RSP"; - if (File.Exists(fileName)) - { - // verifico contenuto - //string rawData = File.ReadAllText(fileName); - string rawData = ""; - // lettura in modo NON esclusivo... - using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - using (var textReader = new StreamReader(fileStream)) - { - rawData = textReader.ReadToEnd(); - } - // se la stringa session.RespOk contiene | significa ci sono + valori ammessi e li controlla tutti - if (session.RespOk.Contains("|")) - { - // splitto e testo tutti... - string[] validRespOk = session.RespOk.Split('|'); - foreach (var item in validRespOk) - { - answ = answ || rawData.Contains(item); - } - } - else - { - answ = rawData.Contains(session.RespOk); - } - } - } - return answ; - } - - /// - /// verifica periodica dei campionamenti: - /// - i due jobs devono essere attivi e non scaduti - /// - non devo aver già resettato... - /// - protected void checkSampling() - { - var currSession = confE63.ActiveSessions[4]; - checkSessionActive(currSession, Eurom63.ComLevel.ChannelOk); - - currSession = confE63.ActiveSessions[5]; - checkSessionActive(currSession, Eurom63.ComLevel.ChannelOk); - } - - /// - /// Elimina i file della sessione indicata (SE è un task ciclico --> solo RSP) - /// - /// - /// - protected bool cleanupSession(Eurom63.Session session) - { - bool answ = false; - if (session != null) - { - // solo se scaduta validità... - if (session.SessionValidUntil < DateTime.Now) - { - string searchPattern = $"{session.SessionName}.*"; - // task ciclico? - if (session.Cycle) - { - // solo risposta! - searchPattern = $"{session.SessionName}.RSP"; - } - string[] file2del = Directory.GetFiles(BaseDir, searchPattern); - foreach (var file in file2del) - { - try - { - File.Delete(file); - } - catch - { } - } - } - } - return answ; - } - - /// - /// Processa una sessione - /// - andando a verificare l'esistenza della REQ + se esito positivo pulizia - /// - andando a richeidere di nuovo risposta - /// - /// - /// - protected void processSession(Eurom63.ComLevel nextLevel, ref Eurom63.Session connectSession) - { - if (connectSession != null) - { - // controllo esistenza directory --> segno connected... - connectionOk = Directory.Exists(BaseDir); - DateTime adesso = DateTime.Now; - if (connectionOk) - { - // verifico se ci sia risp CONNECT - if (checkResp(connectSession)) - { - // aggiorno livello - actLevel = nextLevel; - parentForm.displayTaskAndLog($"Adp Level: {nextLevel}"); - // elimino file sessione - cleanupSession(connectSession); - connectSession.Active = connectSession.Cycle; - connectSession.Passed = true; - } - // verifico SE ci sia la richiesta sennò la chiedo... - else if (!checkRequest(connectSession)) - { - copyRequestFiles(connectSession, adesso); - } - // richiedo SE non ci fosse i dati CONNECT... - else - { - // evito di richiedere SE non fosse già scaduta richiesta... - if (adesso > connectSession.RetryVeto || !checkRequest(connectSession)) - { - // pulisco eventuali risp vecchie - cleanupResp(connectSession.SessionName); - copyRequestFiles(connectSession, adesso); - } - } - } - else - { - // aspetto prima di riprovare... - Thread.Sleep(50); - } - } - else - { - // aspetto prima di riprovare... - Thread.Sleep(50); - } - } - - /// - /// Processa i file della sessione indicata (copy + transform) - /// - /// - /// - protected bool processSessionFile(Eurom63.Session session) - { - bool answ = false; - if (session != null) - { - string fileFrom = ""; - string fileTo = ""; - // processo OGNI file sessione x farne copia - foreach (var file2Proc in session.FileList) - { - fileFrom = $"{appPath}\\{file2Proc.Path}"; - fileTo = $"{BaseDir}\\{Path.GetFileName(file2Proc.Path)}"; - string rawData = File.ReadAllText(fileFrom); - - if (file2Proc.OprReq == Eurom63.FileOpr.Copy) - { - // scrivo! - File.WriteAllText(fileTo, rawData); - } - else - { - // leggo file originale... e processo sostituzioni - rawData = rawData.Replace("{DTNow}", DateTime.Now.ToString("HHmmssyyyyMMdd")); - // ora in posizione definitiva - File.WriteAllText(fileTo, rawData); - } - } - } - return answ; - } - - /// - /// Effettua richiesta info x macchina (validare startup process) - /// - protected void requestInfo() - { - var nextLevel = Eurom63.ComLevel.HasInfo; - var connectSession = confE63.ActiveSessions[1]; - processSession(nextLevel, ref connectSession); - } - - protected void requestProdData() - { - var nextLevel = Eurom63.ComLevel.ProdRequested; - var connectSession = confE63.ActiveSessions[5]; - processSession(nextLevel, ref connectSession); - } - - protected void requestStatusData() - { - var nextLevel = Eurom63.ComLevel.StatusRequested; - var connectSession = confE63.ActiveSessions[4]; - processSession(nextLevel, ref connectSession); - } - - protected void setMachineTime() - { - var nextLevel = Eurom63.ComLevel.TimeSet; - var connectSession = confE63.ActiveSessions[2]; - processSession(nextLevel, ref connectSession); - } - - #endregion Protected Methods - - #region Internal Methods - - /// - /// Metodi preliminari x comunicazione: - /// - richiesta connessione - /// - richiesta stato attivo - /// - internal void checkCommStatus() - { - // init obj display - newDisplayData currDispData = new newDisplayData(); - currDispData.semIn = Semaforo.ND; - - switch (actLevel) - { - case Eurom63.ComLevel.None: - tryConnect(); - currDispData.semIn = Semaforo.SS; - break; - - case Eurom63.ComLevel.IsConnected: - requestInfo(); - currDispData.semIn = Semaforo.SS; - break; - - case Eurom63.ComLevel.HasInfo: - setMachineTime(); - currDispData.semIn = Semaforo.SS; - break; - - case Eurom63.ComLevel.TimeSet: - abortPrevJob(); - currDispData.semIn = Semaforo.SG; - break; - - case Eurom63.ComLevel.ChannelOk: - requestStatusData(); - currDispData.semIn = Semaforo.SG; - break; - - case Eurom63.ComLevel.StatusRequested: - requestProdData(); - currDispData.semIn = Semaforo.SV; - break; - - case Eurom63.ComLevel.ProdRequested: - checkSampling(); - currDispData.semIn = Semaforo.SV; - break; - - default: - break; - } - if (utils.CRB("verbose")) - { - lgInfo($"DONE checkCommStatus | actLevel {actLevel}"); - } - raiseRefresh(currDispData); - } - - /// - /// Pulizia preliminare folder comunicazione - /// - internal override void cleanupFolder() - { - // elimino OGNI file per tipo configurato - foreach (var cleanExt in confE63.cleanupExt) - { - string[] file2del = Directory.GetFiles(BaseDir, cleanExt); - foreach (var file in file2del) - { - try - { - File.Delete(file); - } - catch - { } - } - } - } - - /// - /// Pulizia folder dai file RSP della sessione - /// - internal void cleanupResp(string sessionName) - { - string[] file2del = Directory.GetFiles(BaseDir, $"{sessionName}.RSP"); - foreach (var file in file2del) - { - try - { - File.Delete(file); - } - catch - { } - } - } - - /// - /// Ricarica conf adapter... - /// - internal override void reloadAdapterConf() - { - // init obj display - newDisplayData currDispData = new newDisplayData(); - lgInfo("BEGIN reloadAdapterConf"); - // inizializzo LUT decodifica - string jsonConf = getOptPar("LUT_CONF"); - if (!string.IsNullOrEmpty(jsonConf)) - { - string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{jsonConf}"; - lgInfo($"Apertura file {jsonFullPath}"); - StreamReader reader = new StreamReader(jsonFullPath); - string jsonData = reader.ReadToEnd(); - if (!string.IsNullOrEmpty(jsonData)) - { - try - { - confE63 = JsonConvert.DeserializeObject(jsonData); - - // salvo baseUri - BaseDir = confE63.BaseDir; - lgInfo($"baseDir = {BaseDir}"); - // imposto a zero la bitmap x riavvio! - B_input = 0; - // FORZO invio dati... - accodaSigIN(ref currDispData); - // loggo! - lgInfo($"init input bitmap to zero: {B_input}"); - } - catch (Exception exc) - { - lgError(exc, "Eccezione in decodifica conf json"); - } - } - reader.Dispose(); - } - lgInfo("DONE reloadAdapterConf"); - raiseRefresh(currDispData); - } - - #endregion Internal Methods - #region Public Methods /// @@ -578,7 +92,8 @@ namespace IOB_WIN_NEXT { int newVal = -1; Int32.TryParse(currPzCount, out newVal); - // verifico SE il contapezzi vada moltiplicato x il fattore pzPallet... + // verifico SE il contapezzi vada moltiplicato x il + // fattore pzPallet... if (confE63.PzPallet > 1) { newVal = newVal * confE63.PzPallet; @@ -586,7 +101,8 @@ namespace IOB_WIN_NEXT // aggiorno contapezzi contapezziPLC = newVal > -1 ? newVal : contapezziPLC; } - // ora verifico SE siano validi anche le dataora dei valori letti (< 20 sec ritardo da ora...) + // ora verifico SE siano validi anche le dataora dei valori + // letti (< 20 sec ritardo da ora...) string data = statusData[0].Trim(); string ora = statusData[1].Trim(); DateTime adesso = DateTime.Now; @@ -626,8 +142,8 @@ namespace IOB_WIN_NEXT } /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form /// public override void readSemafori(ref newDisplayData currDispData) { @@ -733,7 +249,8 @@ namespace IOB_WIN_NEXT Last_CurrStatus.Value = currStatus; Last_CurrStatus.ValidUntil = DateTime.Now.AddSeconds(maxDelaySec * cacheMult); - // ora verifico SE siano validi anche le dataora dei valori letti (< 20 sec ritardo da ora...) + // ora verifico SE siano validi anche le dataora dei + // valori letti (< 20 sec ritardo da ora...) string data = statusData[0].Trim(); string ora = statusData[1].Trim(); DateTime lastPub = adesso.AddMinutes(-1); @@ -916,5 +433,489 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Internal Methods + + /// + /// Metodi preliminari x comunicazione: + /// - richiesta connessione + /// - richiesta stato attivo + /// + internal void checkCommStatus() + { + // init obj display + newDisplayData currDispData = new newDisplayData(); + currDispData.semIn = Semaforo.ND; + + switch (actLevel) + { + case Eurom63.ComLevel.None: + tryConnect(); + currDispData.semIn = Semaforo.SS; + break; + + case Eurom63.ComLevel.IsConnected: + requestInfo(); + currDispData.semIn = Semaforo.SS; + break; + + case Eurom63.ComLevel.HasInfo: + setMachineTime(); + currDispData.semIn = Semaforo.SS; + break; + + case Eurom63.ComLevel.TimeSet: + abortPrevJob(); + currDispData.semIn = Semaforo.SG; + break; + + case Eurom63.ComLevel.ChannelOk: + requestStatusData(); + currDispData.semIn = Semaforo.SG; + break; + + case Eurom63.ComLevel.StatusRequested: + requestProdData(); + currDispData.semIn = Semaforo.SV; + break; + + case Eurom63.ComLevel.ProdRequested: + checkSampling(); + currDispData.semIn = Semaforo.SV; + break; + + default: + break; + } + if (utils.CRB("verbose")) + { + lgInfo($"DONE checkCommStatus | actLevel {actLevel}"); + } + raiseRefresh(currDispData); + } + + /// + /// Pulizia preliminare folder comunicazione + /// + internal override void cleanupFolder() + { + // elimino OGNI file per tipo configurato + foreach (var cleanExt in confE63.cleanupExt) + { + string[] file2del = Directory.GetFiles(BaseDir, cleanExt); + foreach (var file in file2del) + { + try + { + File.Delete(file); + } + catch + { } + } + } + } + + /// + /// Pulizia folder dai file RSP della sessione + /// + internal void cleanupResp(string sessionName) + { + string[] file2del = Directory.GetFiles(BaseDir, $"{sessionName}.RSP"); + foreach (var file in file2del) + { + try + { + File.Delete(file); + } + catch + { } + } + } + + /// + /// Ricarica conf adapter... + /// + internal override void reloadAdapterConf() + { + // init obj display + newDisplayData currDispData = new newDisplayData(); + lgInfo("BEGIN reloadAdapterConf"); + // inizializzo LUT decodifica + string jsonConf = getOptPar("LUT_CONF"); + if (!string.IsNullOrEmpty(jsonConf)) + { + string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{jsonConf}"; + lgInfo($"Apertura file {jsonFullPath}"); + StreamReader reader = new StreamReader(jsonFullPath); + string jsonData = reader.ReadToEnd(); + if (!string.IsNullOrEmpty(jsonData)) + { + try + { + confE63 = JsonConvert.DeserializeObject(jsonData); + + // salvo baseUri + BaseDir = confE63.BaseDir; + lgInfo($"baseDir = {BaseDir}"); + // imposto a zero la bitmap x riavvio! + B_input = 0; + // FORZO invio dati... + accodaSigIN(ref currDispData); + // loggo! + lgInfo($"init input bitmap to zero: {B_input}"); + } + catch (Exception exc) + { + lgError(exc, "Eccezione in decodifica conf json"); + } + } + reader.Dispose(); + } + lgInfo("DONE reloadAdapterConf"); + raiseRefresh(currDispData); + } + + #endregion Internal Methods + + #region Protected Fields + + protected static DateTime lastStatusDecr = DateTime.Now; + + /// + /// step di comunicazione attivo + /// + protected Eurom63.ComLevel actLevel = Eurom63.ComLevel.None; + + /// + /// DIrectory eseguibile corrente + /// + protected string appPath = Directory.GetCurrentDirectory(); + + /// + /// Moltiplicatore durata cache + /// + protected int cacheMult = 4; + + /// + /// Oggetti decodificati da pagina + /// + protected Eurom63.ProtoConf confE63; + + /// + /// Valore currStatus validato (per gestione "disconnessioni") + /// + protected CachedInt Last_B_Input = new CachedInt() { Value = 0 }; + + /// + /// Valore currStatus validato (per gestione "disconnessioni") + /// + protected CachedString Last_CurrStatus = new CachedString() { Value = "00000" }; + + /// + /// Massimo delay lettura dati prima di considerarli scaduti (30 sec, ma x test 1 gg) + /// + protected int maxDelaySec = 30; + + #endregion Protected Fields + + #region Protected Methods + + protected void abortPrevJob() + { + var nextLevel = Eurom63.ComLevel.ChannelOk; + var connectSession = confE63.ActiveSessions[3]; + processSession(nextLevel, ref connectSession); +#if false + // qui per sicurezza PULISCE TUTTO + cleanupFolder(); +#endif + } + + /// + /// Verifica una sessione configurata (ovvero la comunicazione su TUTTI i file associati) + /// + /// + /// + protected bool checkRequest(Eurom63.Session session) + { + bool answ = false; + string fileName = ""; + if (session != null) + { + fileName = $"{BaseDir}\\{session.SessionName}.REQ"; + answ = File.Exists(fileName); + } + return answ; + } + + /// + /// Verifica se ci sia una risposta POSITIVA + /// + /// + /// + protected bool checkResp(Eurom63.Session session) + { + bool answ = false; + string fileName = ""; + if (session != null) + { + fileName = $"{BaseDir}\\{session.SessionName}.RSP"; + if (File.Exists(fileName)) + { + // verifico contenuto + //string rawData = File.ReadAllText(fileName); + string rawData = ""; + // lettura in modo NON esclusivo... + using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (var textReader = new StreamReader(fileStream)) + { + rawData = textReader.ReadToEnd(); + } + // se la stringa session.RespOk contiene | significa ci sono + valori ammessi e + // li controlla tutti + if (session.RespOk.Contains("|")) + { + // splitto e testo tutti... + string[] validRespOk = session.RespOk.Split('|'); + foreach (var item in validRespOk) + { + answ = answ || rawData.Contains(item); + } + } + else + { + answ = rawData.Contains(session.RespOk); + } + } + } + return answ; + } + + /// + /// verifica periodica dei campionamenti: + /// - i due jobs devono essere attivi e non scaduti + /// - non devo aver già resettato... + /// + protected void checkSampling() + { + var currSession = confE63.ActiveSessions[4]; + checkSessionActive(currSession, Eurom63.ComLevel.ChannelOk); + + currSession = confE63.ActiveSessions[5]; + checkSessionActive(currSession, Eurom63.ComLevel.ChannelOk); + } + + /// + /// Elimina i file della sessione indicata (SE è un task ciclico --> solo RSP) + /// + /// + /// + protected bool cleanupSession(Eurom63.Session session) + { + bool answ = false; + if (session != null) + { + // solo se scaduta validità... + if (session.SessionValidUntil < DateTime.Now) + { + string searchPattern = $"{session.SessionName}.*"; + // task ciclico? + if (session.Cycle) + { + // solo risposta! + searchPattern = $"{session.SessionName}.RSP"; + } + string[] file2del = Directory.GetFiles(BaseDir, searchPattern); + foreach (var file in file2del) + { + try + { + File.Delete(file); + } + catch + { } + } + } + } + return answ; + } + + /// + /// Processa una sessione + /// - andando a verificare l'esistenza della REQ + se esito positivo pulizia + /// - andando a richeidere di nuovo risposta + /// + /// + /// + protected void processSession(Eurom63.ComLevel nextLevel, ref Eurom63.Session connectSession) + { + if (connectSession != null) + { + // controllo esistenza directory --> segno connected... + connectionOk = Directory.Exists(BaseDir); + DateTime adesso = DateTime.Now; + if (connectionOk) + { + // verifico se ci sia risp CONNECT + if (checkResp(connectSession)) + { + // aggiorno livello + actLevel = nextLevel; + parentForm.displayTaskAndLog($"Adp Level: {nextLevel}"); + // elimino file sessione + cleanupSession(connectSession); + connectSession.Active = connectSession.Cycle; + connectSession.Passed = true; + } + // verifico SE ci sia la richiesta sennò la chiedo... + else if (!checkRequest(connectSession)) + { + copyRequestFiles(connectSession, adesso); + } + // richiedo SE non ci fosse i dati CONNECT... + else + { + // evito di richiedere SE non fosse già scaduta richiesta... + if (adesso > connectSession.RetryVeto || !checkRequest(connectSession)) + { + // pulisco eventuali risp vecchie + cleanupResp(connectSession.SessionName); + copyRequestFiles(connectSession, adesso); + } + } + } + else + { + // aspetto prima di riprovare... + Thread.Sleep(50); + } + } + else + { + // aspetto prima di riprovare... + Thread.Sleep(50); + } + } + + /// + /// Processa i file della sessione indicata (copy + transform) + /// + /// + /// + protected bool processSessionFile(Eurom63.Session session) + { + bool answ = false; + if (session != null) + { + string fileFrom = ""; + string fileTo = ""; + // processo OGNI file sessione x farne copia + foreach (var file2Proc in session.FileList) + { + fileFrom = $"{appPath}\\{file2Proc.Path}"; + fileTo = $"{BaseDir}\\{Path.GetFileName(file2Proc.Path)}"; + string rawData = File.ReadAllText(fileFrom); + + if (file2Proc.OprReq == Eurom63.FileOpr.Copy) + { + // scrivo! + File.WriteAllText(fileTo, rawData); + } + else + { + // leggo file originale... e processo sostituzioni + rawData = rawData.Replace("{DTNow}", DateTime.Now.ToString("HHmmssyyyyMMdd")); + // ora in posizione definitiva + File.WriteAllText(fileTo, rawData); + } + } + } + return answ; + } + + /// + /// Effettua richiesta info x macchina (validare startup process) + /// + protected void requestInfo() + { + var nextLevel = Eurom63.ComLevel.HasInfo; + var connectSession = confE63.ActiveSessions[1]; + processSession(nextLevel, ref connectSession); + } + + protected void requestProdData() + { + var nextLevel = Eurom63.ComLevel.ProdRequested; + var connectSession = confE63.ActiveSessions[5]; + processSession(nextLevel, ref connectSession); + } + + protected void requestStatusData() + { + var nextLevel = Eurom63.ComLevel.StatusRequested; + var connectSession = confE63.ActiveSessions[4]; + processSession(nextLevel, ref connectSession); + } + + protected void setMachineTime() + { + var nextLevel = Eurom63.ComLevel.TimeSet; + var connectSession = confE63.ActiveSessions[2]; + processSession(nextLevel, ref connectSession); + } + + #endregion Protected Methods + + #region Private Methods + + /// + /// Se la sessione fosse scaduta o non attiva --> torna al livello indicato + /// + /// + private void checkSessionActive(Eurom63.Session currSession, Eurom63.ComLevel nextLevel) + { + // SOLO SE ha senso che controllo (sono in sampling...) + if (actLevel > Eurom63.ComLevel.HasInfo) + { + DateTime adesso = DateTime.Now; + // devono essere ATTIVE le sessioni di campionamento... e NON scadute + if (!currSession.Active || currSession.SessionValidUntil < adesso) + { + // controllo ultimo downgrade status + if (lastStatusDecr.AddSeconds(3) < adesso) + { + // elimino TUTTE le risposte... + cleanupResp(currSession.SessionName); + // registro downgrade status... + lastStatusDecr = adesso; + // imposto livellotornando indietro di 1 alla volta... senza andare in negativoS + actLevel = actLevel - 1; + actLevel = actLevel > 0 ? actLevel : 0; + lgInfo($"Sessione inattiva, {actLevel + 1} --> {actLevel}"); + } + } + } + } + + /// + /// Effettua copia file richeiste + update timing + /// + /// + /// + private void copyRequestFiles(Eurom63.Session connectSession, DateTime adesso) + { + // processo richiesta + processSessionFile(connectSession); + if (adesso > connectSession.SessionValidUntil) + { + connectSession.Active = !connectSession.Cycle; + } + connectSession.Passed = false; + connectSession.SessionStarted = adesso; + connectSession.SessionValidUntil = adesso.AddMinutes(connectSession.ValidityMinutes); + connectSession.RetryVeto = adesso.AddSeconds(connectSession.RetrySec); + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobGeneric.cs b/IOB-WIN-NEXT/IobGeneric.cs index 7a77bda8..ef08ecc8 100644 --- a/IOB-WIN-NEXT/IobGeneric.cs +++ b/IOB-WIN-NEXT/IobGeneric.cs @@ -2980,6 +2980,36 @@ namespace IOB_WIN_NEXT return false; } + /// + /// Effettua salvataggio in LUT del valore ricevuto (valori string) + /// - non serve calcolo medie o altro + /// - accoda in out val e basta + /// + /// Array eventi da popolare + /// valore da salvare + /// ID/chiave di riferimento + /// + public virtual void saveAlarmString(ref Dictionary outVal, string valore, string chiave) + { + DateTime adesso = DateTime.Now; + //check obj preliminare + if (outVal == null) + { + outVal = new Dictionary(); + } + // default invio: blindato a 120 sec (rivedere da conf?) + int vetoSendAlarms = 120; + // verifico se sia scaduto OVVERO variato rispetto a prima oppure oltre tempo + bool scaduto = !LastTSSSend.ContainsKey(chiave) || (LastTSSSend[chiave].AddSeconds(vetoSendAlarms) < adesso); + bool cambiato = !LastTSS.ContainsKey(chiave) || !LastTSS[chiave].Equals(valore); + if (scaduto || cambiato) + { + outVal.Add(chiave, valore); + LastTSS[chiave] = valore; + LastTSSSend[chiave] = adesso; + } + } + /// /// metodo dummy x salvataggio aree memoria conf x CN /// @@ -3031,36 +3061,6 @@ namespace IOB_WIN_NEXT LastTSVC[chiave] = valore; } - /// - /// Effettua salvataggio in LUT del valore ricevuto (valori string) - /// - non serve calcolo medie o altro - /// - accoda in out val e basta - /// - /// Array eventi da popolare - /// valore da salvare - /// ID/chiave di riferimento - /// - public virtual void saveAlarmString(ref Dictionary outVal, string valore, string chiave) - { - DateTime adesso = DateTime.Now; - //check obj preliminare - if (outVal == null) - { - outVal = new Dictionary(); - } - // default invio: blindato a 120 sec (rivedere da conf?) - int vetoSendAlarms = 120; - // verifico se sia scaduto OVVERO variato rispetto a prima oppure oltre tempo - bool scaduto = !LastTSSSend.ContainsKey(chiave) || (LastTSSSend[chiave].AddSeconds(vetoSendAlarms) < adesso); - bool cambiato = !LastTSS.ContainsKey(chiave) || !LastTSS[chiave].Equals(valore); - if (scaduto || cambiato) - { - outVal.Add(chiave, valore); - LastTSS[chiave] = valore; - LastTSSSend[chiave] = adesso; - } - } - /// /// Effettua salvataggio in LUT del valore ricevuto (valori string) /// - non serve calcolo medie o altro @@ -3826,6 +3826,21 @@ namespace IOB_WIN_NEXT /// protected int demFactDynData = 1; + /// + /// Boolean x indicare contapezzi disabilitato forzatamente da IOB + /// + protected bool disablePzCounteByIob = false; + + /// + /// Boolean x indicare contapezzi abilitato a livello di conf apoplicazione + /// + protected bool enablePzCountByApp = true; + + /// + /// Boolean x indicare contapezzi abilitato forzatamente da IOB + /// + protected bool enablePzCountByIob = true; + /// /// Array dei contatori x segnali blinking /// @@ -3896,6 +3911,11 @@ namespace IOB_WIN_NEXT /// protected int maxSendErrors = utils.CRI("maxSendErrors"); + /// + /// Numero massimo di tentativi x test ping preliminare + /// + protected int maxTryPing = 1; + /// /// indica se serva refresh parametri e quindi PLC... /// @@ -3942,20 +3962,6 @@ namespace IOB_WIN_NEXT /// protected int watchDogPeriod = 2; - /// - /// Boolean x indicare contapezzi abilitato a livello di conf apoplicazione - /// - protected bool enablePzCountByApp = true; - - /// - /// Boolean x indicare contapezzi abilitato forzatamente da IOB - /// - protected bool enablePzCountByIob = true; - /// - /// Boolean x indicare contapezzi disabilitato forzatamente da IOB - /// - protected bool disablePzCounteByIob = false; - #endregion Protected Fields #region Protected Properties diff --git a/IOB-WIN-NEXT/IobIcoelDb.cs b/IOB-WIN-NEXT/IobIcoelDb.cs index 3276646d..a02825ae 100644 --- a/IOB-WIN-NEXT/IobIcoelDb.cs +++ b/IOB-WIN-NEXT/IobIcoelDb.cs @@ -38,7 +38,6 @@ namespace IOB_WIN_NEXT string SyncStatePwd = getOptPar("SyncStatePwd"); string SyncStateCTout = getOptPar("SyncStateCTout"); - string connSyncState = $"data source={SyncStateDb};initial catalog=MoonPro_ISF;persist security info=True;user id={SyncStateUser};password={SyncStatePwd};MultipleActiveResultSets=True;App=IOB-WIN-NEXT"; // gestione command timeout da https://erikej.github.io/sqlclient/2020/10/26/sqlclient-commandtimeout-preview.html @@ -47,7 +46,6 @@ namespace IOB_WIN_NEXT connSyncState = $"{connSyncState};Command Timeout={SyncStateCTout}"; } - // eccezione: NON TROVA EntityFramework 6.0.0 o successivo... why?!? dbProxy = new DbProxy(connSyncState); diff --git a/IOB-WIN-NEXT/IobIcoelSoap.cs b/IOB-WIN-NEXT/IobIcoelSoap.cs index 93309c38..bb1bd477 100644 --- a/IOB-WIN-NEXT/IobIcoelSoap.cs +++ b/IOB-WIN-NEXT/IobIcoelSoap.cs @@ -90,7 +90,6 @@ namespace IOB_WIN_NEXT taskVal = executeSetSupplier(cmdArgs); break; - case taskType.setParameter: // richiedo da URL i parametri WRITE da popolare lgInfo("Chiamata setParameter --> processMemWriteRequests"); @@ -129,114 +128,6 @@ namespace IOB_WIN_NEXT return taskDone; } - private string executeSetSupplier(string cmdArgs) - { - string taskVal; - // loggo i parametri ricevuti da popolare - lgInfo($"Chiamata setSupplier --> params payload: {cmdArgs}"); - // recupero batch corrente x preselezionare i dati guid layout/varietà... - var currBatch = IcoelSizer.GetCurrentBatch(); - // recupero GUID x variety e layout di default - var varGuid = currBatch[1].VarietyId; - var layGuid = currBatch[1].LayoutId; - // predispongo grower di default - GrowerInfo GrowerData = new GrowerInfo(); - // le info sono una stringa separata da valore | di GrowerCode|GrowerName|varietyGuid|LayoutGuid; - string[] reqParams = cmdArgs.Split('|'); - // se ho dati sistemo grower... - if (reqParams.Length >= 2) - { - //GrowerData.GrowerCode = reqParams[0]; - //GrowerData.GrowerName = reqParams[1]; - // sistemo commenti - var comments = new List(); - comments.Add($"sent {DateTime.Now: yyyy.MM.dd HH:mm:ss}"); - comments.Add("Qty: no set"); - comments.Add("------------"); - //GrowerData.Comments = comments; - - GrowerData = new GrowerInfo() - { - GrowerCode = reqParams[0], - GrowerName = reqParams[1], - Comments = comments - }; - lgInfo($"Set grower data | GrowerCode: {GrowerData.GrowerCode} | GrowerName: {GrowerData.GrowerName}"); - } - if (reqParams.Length >= 3) - { - Guid.TryParse(reqParams[2], out varGuid); - lgInfo($"Set Variety data | VarGUID: {varGuid}"); - } - if (reqParams.Length >= 4) - { - Guid.TryParse(reqParams[3], out layGuid); - lgInfo($"Set Layout data | LayGUID: {layGuid}"); - } - - // invio richiesta!!! - IcoelSizer.EnqueueBatch(GrowerData, varGuid, layGuid); - lgInfo($"Request sent!"); - - - - taskVal = $"REQUEST SET SUPPLIER | EnqueueBatch | GrowCode: {GrowerData.GrowerCode} | GrowName: {GrowerData.GrowerName} | Var: {varGuid} | Lay: {layGuid} "; - // se restituiscce "" faccio altra prova... - if (string.IsNullOrEmpty(taskVal)) - { - // i parametri me li aspetto come stringa composta paramName|paramvalue - if (cmdArgs.Contains("|")) - { - string[] paramsJob = cmdArgs.Split('|'); - taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; - } - else - { - taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {cmdArgs} doesnt contain pipe for splitting key/value"; - } - } - - return taskVal; - } - - /// - /// Metodo da overridare x scrivere DAVVERO i parametri sul PLC - /// - /// - protected override void plcWriteParams(ref List updatedPar) - { - foreach (var item in updatedPar) - { - // cerco se sia setSupplier - if (item.uid == "setSupplier") - { - string reqVal = !string.IsNullOrEmpty(item.reqValue) ? item.reqValue : item.value; - // chiamo - var taskVal = executeSetSupplier(reqVal); - bool fatto = taskVal.StartsWith("REQUEST"); - // se fatto --> aggiorno! - if (fatto) - { - //item.value = item.reqValue; - item.reqValue = ""; - item.lastRead = DateTime.Now; - item.UM = ""; - } - } - - } - } - - /// - /// Dizionario parametri correnti - /// - protected Dictionary perfParamDict { get; set; } = new Dictionary(); - - /// - /// Dizionario dati Batch correnti - /// - protected Dictionary batchDataDict { get; set; } = new Dictionary(); - /// /// Recupero dati dinamici... /// @@ -342,7 +233,7 @@ namespace IOB_WIN_NEXT if (currBatchList[1].EndTime == DateTime.MinValue || currBatchList[1].EndTime == DateTime.MinValue) { B_input = 3; - } + } #endif } // accodo NON emergenza @@ -435,6 +326,11 @@ namespace IOB_WIN_NEXT #region Protected Properties + /// + /// Dizionario dati Batch correnti + /// + protected Dictionary batchDataDict { get; set; } = new Dictionary(); + /// /// elenco dei BAtch correntemente caricati x testing variazione /// @@ -442,10 +338,42 @@ namespace IOB_WIN_NEXT protected Connector IcoelSizer { get; set; } + /// + /// Dizionario parametri correnti + /// + protected Dictionary perfParamDict { get; set; } = new Dictionary(); + #endregion Protected Properties #region Protected Methods + /// + /// Metodo da overridare x scrivere DAVVERO i parametri sul PLC + /// + /// + protected override void plcWriteParams(ref List updatedPar) + { + foreach (var item in updatedPar) + { + // cerco se sia setSupplier + if (item.uid == "setSupplier") + { + string reqVal = !string.IsNullOrEmpty(item.reqValue) ? item.reqValue : item.value; + // chiamo + var taskVal = executeSetSupplier(reqVal); + bool fatto = taskVal.StartsWith("REQUEST"); + // se fatto --> aggiorno! + if (fatto) + { + //item.value = item.reqValue; + item.reqValue = ""; + item.lastRead = DateTime.Now; + item.UM = ""; + } + } + } + } + /// /// recupera le variety ed i rispettivi layout e li invia al sistema MP/IO /// @@ -465,5 +393,77 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods + + #region Private Methods + + private string executeSetSupplier(string cmdArgs) + { + string taskVal; + // loggo i parametri ricevuti da popolare + lgInfo($"Chiamata setSupplier --> params payload: {cmdArgs}"); + // recupero batch corrente x preselezionare i dati guid layout/varietà... + var currBatch = IcoelSizer.GetCurrentBatch(); + // recupero GUID x variety e layout di default + var varGuid = currBatch[1].VarietyId; + var layGuid = currBatch[1].LayoutId; + // predispongo grower di default + GrowerInfo GrowerData = new GrowerInfo(); + // le info sono una stringa separata da valore | di GrowerCode|GrowerName|varietyGuid|LayoutGuid; + string[] reqParams = cmdArgs.Split('|'); + // se ho dati sistemo grower... + if (reqParams.Length >= 2) + { + //GrowerData.GrowerCode = reqParams[0]; + //GrowerData.GrowerName = reqParams[1]; + // sistemo commenti + var comments = new List(); + comments.Add($"sent {DateTime.Now: yyyy.MM.dd HH:mm:ss}"); + comments.Add("Qty: no set"); + comments.Add("------------"); + //GrowerData.Comments = comments; + + GrowerData = new GrowerInfo() + { + GrowerCode = reqParams[0], + GrowerName = reqParams[1], + Comments = comments + }; + lgInfo($"Set grower data | GrowerCode: {GrowerData.GrowerCode} | GrowerName: {GrowerData.GrowerName}"); + } + if (reqParams.Length >= 3) + { + Guid.TryParse(reqParams[2], out varGuid); + lgInfo($"Set Variety data | VarGUID: {varGuid}"); + } + if (reqParams.Length >= 4) + { + Guid.TryParse(reqParams[3], out layGuid); + lgInfo($"Set Layout data | LayGUID: {layGuid}"); + } + + // invio richiesta!!! + IcoelSizer.EnqueueBatch(GrowerData, varGuid, layGuid); + lgInfo($"Request sent!"); + + taskVal = $"REQUEST SET SUPPLIER | EnqueueBatch | GrowCode: {GrowerData.GrowerCode} | GrowName: {GrowerData.GrowerName} | Var: {varGuid} | Lay: {layGuid} "; + // se restituiscce "" faccio altra prova... + if (string.IsNullOrEmpty(taskVal)) + { + // i parametri me li aspetto come stringa composta paramName|paramvalue + if (cmdArgs.Contains("|")) + { + string[] paramsJob = cmdArgs.Split('|'); + taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; + } + else + { + taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {cmdArgs} doesnt contain pipe for splitting key/value"; + } + } + + return taskVal; + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobKawasaki.cs b/IOB-WIN-NEXT/IobKawasaki.cs index fc0010a4..4b92bc11 100644 --- a/IOB-WIN-NEXT/IobKawasaki.cs +++ b/IOB-WIN-NEXT/IobKawasaki.cs @@ -8,69 +8,6 @@ namespace IOB_WIN_NEXT { public class IobKawasaki : IobGeneric, IDisposable { - #region Private Fields - - /// - /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO - /// - private Dictionary signLUT = new Dictionary(); - - #endregion Private Fields - - #region Protected Fields - - /// - /// Comando inviato al robot - /// - protected string comando; - - /// - /// Variabile SIGNALS corrente (8bit INT) - /// - protected string cSignals; - - /// - /// Variabile STATUS corrente (8bit INT) - /// - protected string cStatus; - - /// - /// Oggetto MAIN x connessione KAWASAKI - /// - protected KRcc.Commu KAWASAKI_ref; - - /// - /// Ultima missione svolta da robot - /// - protected string lastMissRobot; - - /// - /// Ultimo TC registrato da robot - /// - protected decimal lastRecTC; - - /// - /// Nome e seriale macchina - /// - protected string macName = ""; - - /// - /// Num pezzi prelevati - /// - protected int numPzPrel; - - /// - /// Array delle risposte dal controllo KAWASAKI - /// - protected System.Collections.ArrayList resDataArray; - - /// - /// Variabile verifica thread comunicazione - /// - protected bool threadOk = false; - - #endregion Protected Fields - #region Public Constructors /// @@ -133,567 +70,6 @@ namespace IOB_WIN_NEXT #endregion Public Enums - #region Protected Properties - - /// - /// Verifica se il thread 4 di comm sia attivo - /// - protected bool commThreadOk - { - get - { - bool answ = false; - if (KAWASAKI_ref.IsConnected) - { - int retVal = 0; - resDataArray = KAWASAKI_ref.command("TYPE TASK (1004)", 3000); // thread 4 ok --> " 1\r\n" - int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out retVal); - answ = (retVal == 1); - } - return answ; - } - } - - /// - /// Restituisce SEGNALI macchina nel formato: - /// B0: Transfer in auto - /// B1: Punzonatrice in AUTO - /// B2: Barriera tavola ripristinata - /// B3: Aria in linea OK - /// B4: Console Transfer in fuori ingombro - /// B5: TAV A - /// B6: TAV B - /// B7: Richiesta accesso attiva - /// - protected string currBitmapSignals - { - get - { - string answ = ""; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE $signal", 3000); // segnali --> "1|0|1|1|1|0|0|0\r\n" - answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace("|", ""); -#if false - // reverse stringa (B0 portato a sx) - szBitmap = utils.reverseStr(szBitmap); - // ora converto bitmap string in INT - answ = Convert.ToInt32(szBitmap, 2); -#endif - } - return answ; - } - } - - /// - /// Restituisce stato macchina nel formato (da sx a dx): - /// B0: POWER_ON - /// B1: AUTO - /// B2: RUN - /// B3: ERROR - /// B4: ALLARME - /// B5: EMERGENZA OK - /// B6: PORTA CHIUSA - /// B7: PRONTO AL LOAD - /// - protected string currBitmapStatus - { - get - { - string answ = ""; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE $status", 3000); // status --> "0|0|1|0|0|1|0|0\r\n" - answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace("|", ""); -#if false - // reverse stringa (B0 portato a sx) - szBitmap = utils.reverseStr(szBitmap); - // ora converto bitmap string in INT - answ = Convert.ToInt32(szBitmap, 2); -#endif - } - return answ; - } - } - - /// - /// Recupera ultima missione svolta - /// - protected string lastMission - { - get - { - string answ = ""; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE $exe", 3000); // missione --> "\r\n" (vuoto, no missione) - answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""); - } - return answ; - } - } - - /// - /// Oggetto per lettura ULTIMO TC rilevato - /// - protected decimal lastTC - { - get - { - decimal answ = 0; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE r_tempo", 3000); // ultimo TCiclo rilevato --> " 349.19\r\n" - decimal.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace(".", ","), out answ); - } - return answ; - } - } - - /// - /// Recupera nome e seriale macchina - /// - protected string machineName - { - get - { - string answ = ""; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE $id_true", 3000); // id macchina --> "BX100N-B001 Sn. 2366\r\n" - answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""); - } - return answ; - } - } - - /// - /// Oggetto per lettura/scrittura counter pezzi robot - /// - protected int pzCounter - { - get - { - int answ = 0; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE i_cicli", 3000); // num cicli depositati/fatti --> " 0\r\n" - int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out answ); - } - return answ; - } - set - { - if (KAWASAKI_ref.IsConnected) - { - comando = string.Format("i_cicli={0}", value); - // scrivo valore cicli - resDataArray = KAWASAKI_ref.command(comando, 3000); // imposto cicli depositati/fatti --> " 0\r\n" - } - } - } - - /// - /// Oggetto per lettura counter pezzi PRELEVATI - /// - protected int pzPrelevati - { - get - { - int answ = 0; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE i_prelevati", 3000); // num pz prelevati --> "0\r\n" - int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out answ); - } - return answ; - } - } - - #endregion Protected Properties - - #region Private Methods - - /// - /// Decodifica il resto dell'area x i dati accessori (allarmi, ...) - /// - private void decodeOtherData() - { - if (verboseLog) - { - } - } - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - private void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - /* ----------------------------------------------------- - * bitmap MAPO - * B0: POWER_ON - * B1: RUN - * B2: pzCount - * B3: allarme - * B4: manuale - * B5: emergenza - * B6: error prog - * B7: auto mode - ----------------------------------------------------- */ - // bit 0 (poweron) imposto a 1 SE connected... - B_input = KAWASAKI_ref.IsConnected ? 1 : 0; - // RUN - if (cStatus[2] == '1') - { - B_input += (1 << 1); - } - // ERROR prog/macchina - if (cStatus[3] == '1') - { - B_input += (1 << 6); - } - // allarme - if (cStatus[4] == '1') - { - B_input += (1 << 3); - } - // Automatico (porta chiusa) - if (cStatus[6] == '1' || cStatus[1] == '1') - { - B_input += (1 << 4); - } - // NON EMERGENZA (1=armed, 0=triggered) - if (cStatus[5] == '0') - { - B_input += (1 << 5); - } - // procedo SOLO SE è enabled IOB - if (IobOnline) - { - try - { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrEmpty(currODL) || currODL == "0") - { - if (periodicLog) - { - lgInfo(string.Format("Kawasaki | Lettura ODL andata a vuoto: currODL: {0}", currODL)); - } - } - else - { // se variato o scaduto timeout log... - if (periodicLog || (currIdxODL.ToString() != currODL)) - { - lgInfo(string.Format("Kawasaki | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); - } - // provo a salvare nuovo ODL - int.TryParse(currODL, out currIdxODL); - } - } - catch (Exception exc) - { - if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) - { - lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); - lastWarnODL = DateTime.Now; - } - } - } - else - { - // imposto currODL a vuoto! - currODL = ""; - if (periodicLog) - { - lgInfo($"Kawasaki | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); - } - } - if (!string.IsNullOrEmpty(currODL)) - { - if (currODL != "0") - { - // ora processo il contapezzi... - // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - // se sono differenti MOSTRO... - if (contapezziPLC != contapezziIOB) - { - // registro contapezzi - lgInfo($"Differenza Contapezzi CNC/IOB: contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); - } - // verifico se variato contapezzi... e se passato ritardo minimo... - if (contapezziPLC > contapezziIOB) - { - // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio - contapezziIOB++; - needRefreshPzCount = true; - // salvo in semaforo! - B_input += (1 << 2); - // registro contapezzi - lgInfo($"contapezziPLC KAWASAKI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - else if (contapezziIOB > contapezziPLC) - { - lgInfo($"Contapezzi IOB > CNC --> NON INVIO (contapezziPLC: {contapezziPLC} < contapezziIOB: {contapezziIOB})"); - } - - // invio a server contapezzi (aggiornato) - string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK - if (retVal != contapezziIOB.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio Contapezzi KAWASAKI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - else - { - lgError("Attenzione non trovato ODL --> currODL = 0"); - } - } - else - { - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - lgError($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC KAWASAKI {contapezziPLC} | contapezziIOB {contapezziIOB}"); - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - - // log opzionale! - if (verboseLog) - { - lgInfo($"Trasformazione B_input: {B_input}"); - } - } - - /// - /// Test completo funzioni kawasaki - /// - private void kawasakiFullTest() - { - // faccio un try-catch di test vari... - try - { - //string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); - //KAWASAKI_ref = new KRcc.Commu(connPar); - //KAWASAKI_ref = new KRcc.Commu("TCP 192.168.0.92"); - if (KAWASAKI_ref.IsConnected) - { - // connect ok - resDataArray = KAWASAKI_ref.command("where", 3000); - // WHERE [RET] - // Console.WriteLine(resDataArray[1]); - // [0] = 0 - // [1] = JT1 JT2 JT3 JT4 JT5 JT6 - // -23.205 - 39.967 - 13.176 95.663 71.402 - 21.512 - // X[mm] Y[mm] Z[mm] O[deg] A[deg] T[deg] - // - 489.620 693.940 1564.733 92.612 131.285 7.482 - - threadOk = commThreadOk; - macName = machineName; - cStatus = currBitmapStatus; - cSignals = currBitmapSignals; - contapezziPLC = pzCounter; - numPzPrel = pzPrelevati; - lastRecTC = lastTC; - lastMissRobot = lastMission; - } - // test contapezzi -#if false - // leggo i pezzi - int currCount = pzCounter; - // imposto a 100 - pzCounter = 100; - // rileggo x verifica - int newCount = pzCounter; - // reimposto corretti - pzCounter = currCount; -#endif - // test gest programmi -#if true - //saveProgram("prog", "default"); - sendProgram("prog", "default2"); -#endif - } - catch (Exception e) - { // e.Message = "can't connect TCP/IP" or // "can't login" - Console.WriteLine(e.Message); - } - } - - /// - /// Effettua salvataggio del programma corrente - /// - /// Dir di riferimento - /// Nome Programma (se mancasse *.as lo aggiunge) - private void saveProgram(string progDir = "prog", string progName = "current.as") - { - // path completo - progName = progName.EndsWith(".as") ? progName : progName + ".as"; - string prgPath = progName;// string.Format("{0}/{1}", progDir, progName); - if (KAWASAKI_ref.IsConnected) - { - // comandi x setup programma... - resDataArray = KAWASAKI_ref.command("ferma", 3000); // ferma processi (all) --> "" - resDataArray = KAWASAKI_ref.command("togli", 3000); // toglie processi da pronta esecuzione --> "" - - //resp = com.command("SAVE nome_del_file", 3000); // salvataggio file... FORSE --> "\u0005\u0002Bnome_del_file.as\u0017" --> verificare DOVE salva... - - int ret = KAWASAKI_ref.save(prgPath); // SAVE current.as[RET] - if (ret == 0) - { - // Success - } - if (ret == -1) - { - // Communication error - } - if (ret == -2) - { - // Robot Controller error - } - if (ret == -3) - { - // Internal error - } - } - } - - /// - /// Effettua invio del programma di alvorazione al ROBOT - /// Dir di riferimento - /// Nome Programma (se mancasse *.as lo aggiunge) - /// - private void sendProgram(string progDir = "prog", string progName = "default.as") - { - // path completo - progName = progName.EndsWith(".as") ? progName : progName + ".as"; - string prgPath = progName;// string.Format("{0}/{1}", progDir, progName); - - // comandi x setup programma... - resDataArray = KAWASAKI_ref.command("ferma", 3000); // ferma processi (all) --> "" - resDataArray = KAWASAKI_ref.command("togli", 3000); // toglie processi da pronta esecuzione --> "" - - if (KAWASAKI_ref.IsConnected) - { - // carico... - KAWASAKI_ref.asInquiry = delegate (string as_msg) - { - Console.WriteLine(as_msg); if (as_msg.StartsWith("Are you sure ?")) - { - return "0\n"; // 0 [RET] - } - - if (as_msg.StartsWith("Load data?")) - { - return "1\n"; // 1 [RET] - } - - return null; - }; - int retLoad = KAWASAKI_ref.load(prgPath, "/Q"); // LOAD/Q default.as[RET] - } - } - - #endregion Private Methods - - #region Protected Methods - - /// - /// Imposto connessione - /// - protected virtual void setConnection() - { - // Creo oggetto connessione NC - parentForm.commPlcActive = true; - lgInfoStartup("Start init Adapter KAWASAKI all'IP {0} | --> IOB {1}", cIobConf.cncIpAddr, cIobConf.codIOB); - - // inizializzo correttamente aree memoria secondo CONF - iniFileName - IniFile fIni = new IniFile(cIobConf.iniFileName); - // fix enable prgName - enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true); - - // SE è necessario refresh... - if (needRefresh) - { - lgInfoStartup("Refreshing connection..."); - // ora tento avvio PLC... SE PING OK... - if (testPingMachine == IPStatus.Success) - { - try - { - string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); - KAWASAKI_ref = new KRcc.Commu(connPar); - // disconnetto e connetto... - if (isVerboseLog) - { - lgInfo("KAWASAKI: tryDisconnect"); - } - - lgInfo("End init Adapter KAWASAKI"); - if (isVerboseLog) - { - lgInfo("KAWASAKI CONNESSIONE AVVENUTA"); - } - } - catch (Exception exc) - { - lgError(exc, "Errore in INIT KAWASAKI Commu"); - } - needRefresh = false; - } - parentForm.commPlcActive = false; - // gestione pzCounter - if (utils.CRB("enableContapezzi")) - { - lgInfo("KAWASAKI: inizio gestione contapezzi"); - try - { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) - { - if (getOptPar("PZCOUNT_MODE").StartsWith("STD")) - { - lgInfo("Init contapezzi KAWASAKI: pzCntReload(true)"); - pzCntReload(true); - // refresh associazione Macchina - IOB - sendM2IOB(); - // per adesso imposto lettura fanuc == contapezzi (poi farà vera lettura...) - contapezziPLC = contapezziIOB; - } - else - { - contapezziIOB = 0; - lgInfo("Contapezzi STD disabilitato: modalità {0}", getOptPar("PZCOUNT_MODE")); - } - } - else - { - contapezziIOB = 0; - lgInfo("Parametro mancante PZCOUNT_MODE"); - } - } - catch (Exception exc) - { - lgError(exc, "Errore in contapezzi KAWASAKI"); - } - } - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -764,7 +140,8 @@ namespace IOB_WIN_NEXT break; case taskType.stopSetup: - // reset contapezzi fine setup // reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO + // reset contapezzi fine setup // reset contapezzi fine setup SE + // ESPLICITAMENTE IMPOSTATO if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET_stopSetup") == "TRUE") { resetcontapezziPLC(); @@ -808,9 +185,7 @@ namespace IOB_WIN_NEXT return prgName; } - /// - /// Recupero info sistema generiche - /// + /// Recupero info sistema generiche public override Dictionary getSysInfo() { // valore non presente in vers default... se gestito fare override @@ -828,9 +203,10 @@ namespace IOB_WIN_NEXT { try { - // hard coded... !!!FARE!!! rivedere megio conf + // hard coded... !!!FARE!!! rivedere megio conf contapezziPLC = pzCounter; - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) { #if false @@ -849,7 +225,8 @@ namespace IOB_WIN_NEXT { lgInfo("[0] area memoria: {1}.{2}.{3}", memAddr, areaCounter.DbNum, areaCounter.indiceMem, areaCounter.tipoMem); } - // copio da blocco già letto... con switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato + // copio da blocco già letto... con switch x tipo dati --> tipo lettura... e salvo + // ultimo conteggio rilevato switch (areaCounter.tipoMem) { case "B": @@ -899,8 +276,8 @@ namespace IOB_WIN_NEXT } /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form /// public override void readSemafori(ref newDisplayData currDispData) { @@ -1089,5 +466,627 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + /// + /// Comando inviato al robot + /// + protected string comando; + + /// + /// Variabile SIGNALS corrente (8bit INT) + /// + protected string cSignals; + + /// + /// Variabile STATUS corrente (8bit INT) + /// + protected string cStatus; + + /// + /// Oggetto MAIN x connessione KAWASAKI + /// + protected KRcc.Commu KAWASAKI_ref; + + /// + /// Ultima missione svolta da robot + /// + protected string lastMissRobot; + + /// + /// Ultimo TC registrato da robot + /// + protected decimal lastRecTC; + + /// + /// Nome e seriale macchina + /// + protected string macName = ""; + + /// + /// Num pezzi prelevati + /// + protected int numPzPrel; + + /// + /// Array delle risposte dal controllo KAWASAKI + /// + protected System.Collections.ArrayList resDataArray; + + /// + /// Variabile verifica thread comunicazione + /// + protected bool threadOk = false; + + #endregion Protected Fields + + #region Protected Properties + + /// + /// Verifica se il thread 4 di comm sia attivo + /// + protected bool commThreadOk + { + get + { + bool answ = false; + if (KAWASAKI_ref.IsConnected) + { + int retVal = 0; + resDataArray = KAWASAKI_ref.command("TYPE TASK (1004)", 3000); // thread 4 ok --> " 1\r\n" + int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out retVal); + answ = (retVal == 1); + } + return answ; + } + } + + /// + /// Restituisce SEGNALI macchina nel formato: + /// B0: Transfer in auto + /// B1: Punzonatrice in AUTO + /// B2: Barriera tavola ripristinata + /// B3: Aria in linea OK + /// B4: Console Transfer in fuori ingombro + /// B5: TAV A + /// B6: TAV B + /// B7: Richiesta accesso attiva + /// + protected string currBitmapSignals + { + get + { + string answ = ""; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE $signal", 3000); // segnali --> "1|0|1|1|1|0|0|0\r\n" + answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace("|", ""); +#if false + // reverse stringa (B0 portato a sx) + szBitmap = utils.reverseStr(szBitmap); + // ora converto bitmap string in INT + answ = Convert.ToInt32(szBitmap, 2); +#endif + } + return answ; + } + } + + /// + /// Restituisce stato macchina nel formato (da sx a dx): + /// B0: POWER_ON + /// B1: AUTO + /// B2: RUN + /// B3: ERROR + /// B4: ALLARME + /// B5: EMERGENZA OK + /// B6: PORTA CHIUSA + /// B7: PRONTO AL LOAD + /// + protected string currBitmapStatus + { + get + { + string answ = ""; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE $status", 3000); // status --> "0|0|1|0|0|1|0|0\r\n" + answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace("|", ""); +#if false + // reverse stringa (B0 portato a sx) + szBitmap = utils.reverseStr(szBitmap); + // ora converto bitmap string in INT + answ = Convert.ToInt32(szBitmap, 2); +#endif + } + return answ; + } + } + + /// + /// Recupera ultima missione svolta + /// + protected string lastMission + { + get + { + string answ = ""; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE $exe", 3000); // missione --> "\r\n" (vuoto, no missione) + answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""); + } + return answ; + } + } + + /// + /// Oggetto per lettura ULTIMO TC rilevato + /// + protected decimal lastTC + { + get + { + decimal answ = 0; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE r_tempo", 3000); // ultimo TCiclo rilevato --> " 349.19\r\n" + decimal.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace(".", ","), out answ); + } + return answ; + } + } + + /// + /// Recupera nome e seriale macchina + /// + protected string machineName + { + get + { + string answ = ""; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE $id_true", 3000); // id macchina --> "BX100N-B001 Sn. 2366\r\n" + answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""); + } + return answ; + } + } + + /// + /// Oggetto per lettura/scrittura counter pezzi robot + /// + protected int pzCounter + { + get + { + int answ = 0; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE i_cicli", 3000); // num cicli depositati/fatti --> " 0\r\n" + int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out answ); + } + return answ; + } + set + { + if (KAWASAKI_ref.IsConnected) + { + comando = string.Format("i_cicli={0}", value); + // scrivo valore cicli + resDataArray = KAWASAKI_ref.command(comando, 3000); // imposto cicli depositati/fatti --> " 0\r\n" + } + } + } + + /// + /// Oggetto per lettura counter pezzi PRELEVATI + /// + protected int pzPrelevati + { + get + { + int answ = 0; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE i_prelevati", 3000); // num pz prelevati --> "0\r\n" + int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out answ); + } + return answ; + } + } + + #endregion Protected Properties + + #region Protected Methods + + /// + /// Imposto connessione + /// + protected virtual void setConnection() + { + // Creo oggetto connessione NC + parentForm.commPlcActive = true; + lgInfoStartup("Start init Adapter KAWASAKI all'IP {0} | --> IOB {1}", cIobConf.cncIpAddr, cIobConf.codIOB); + + // inizializzo correttamente aree memoria secondo CONF - iniFileName + IniFile fIni = new IniFile(cIobConf.iniFileName); + // fix enable prgName + enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true); + + // SE è necessario refresh... + if (needRefresh) + { + lgInfoStartup("Refreshing connection..."); + // ora tento avvio PLC... SE PING OK... + if (testPingMachine == IPStatus.Success) + { + try + { + string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); + KAWASAKI_ref = new KRcc.Commu(connPar); + // disconnetto e connetto... + if (isVerboseLog) + { + lgInfo("KAWASAKI: tryDisconnect"); + } + + lgInfo("End init Adapter KAWASAKI"); + if (isVerboseLog) + { + lgInfo("KAWASAKI CONNESSIONE AVVENUTA"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in INIT KAWASAKI Commu"); + } + needRefresh = false; + } + parentForm.commPlcActive = false; + // gestione pzCounter + if (utils.CRB("enableContapezzi")) + { + lgInfo("KAWASAKI: inizio gestione contapezzi"); + try + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) + if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + if (getOptPar("PZCOUNT_MODE").StartsWith("STD")) + { + lgInfo("Init contapezzi KAWASAKI: pzCntReload(true)"); + pzCntReload(true); + // refresh associazione Macchina - IOB + sendM2IOB(); + // per adesso imposto lettura fanuc == contapezzi (poi farà vera lettura...) + contapezziPLC = contapezziIOB; + } + else + { + contapezziIOB = 0; + lgInfo("Contapezzi STD disabilitato: modalità {0}", getOptPar("PZCOUNT_MODE")); + } + } + else + { + contapezziIOB = 0; + lgInfo("Parametro mancante PZCOUNT_MODE"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi KAWASAKI"); + } + } + } + } + + #endregion Protected Methods + + #region Private Fields + + /// + /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO + /// + private Dictionary signLUT = new Dictionary(); + + #endregion Private Fields + + #region Private Methods + + /// + /// Decodifica il resto dell'area x i dati accessori (allarmi, ...) + /// + private void decodeOtherData() + { + if (verboseLog) + { + } + } + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + private void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + /* ----------------------------------------------------- + * bitmap MAPO + * B0: POWER_ON + * B1: RUN + * B2: pzCount + * B3: allarme + * B4: manuale + * B5: emergenza + * B6: error prog + * B7: auto mode + ----------------------------------------------------- */ + // bit 0 (poweron) imposto a 1 SE connected... + B_input = KAWASAKI_ref.IsConnected ? 1 : 0; + // RUN + if (cStatus[2] == '1') + { + B_input += (1 << 1); + } + // ERROR prog/macchina + if (cStatus[3] == '1') + { + B_input += (1 << 6); + } + // allarme + if (cStatus[4] == '1') + { + B_input += (1 << 3); + } + // Automatico (porta chiusa) + if (cStatus[6] == '1' || cStatus[1] == '1') + { + B_input += (1 << 4); + } + // NON EMERGENZA (1=armed, 0=triggered) + if (cStatus[5] == '0') + { + B_input += (1 << 5); + } + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo(string.Format("Kawasaki | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + } + } + else + { // se variato o scaduto timeout log... + if (periodicLog || (currIdxODL.ToString() != currODL)) + { + lgInfo(string.Format("Kawasaki | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + } + // provo a salvare nuovo ODL + int.TryParse(currODL, out currIdxODL); + } + } + catch (Exception exc) + { + if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) + { + lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); + lastWarnODL = DateTime.Now; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"Kawasaki | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + if (!string.IsNullOrEmpty(currODL)) + { + if (currODL != "0") + { + // ora processo il contapezzi... controllo se è passato intervallo minimo tra 2 + // controlli/elaborazioni x distanziare invio e ridurre letture + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + // se sono differenti MOSTRO... + if (contapezziPLC != contapezziIOB) + { + // registro contapezzi + lgInfo($"Differenza Contapezzi CNC/IOB: contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); + } + // verifico se variato contapezzi... e se passato ritardo minimo... + if (contapezziPLC > contapezziIOB) + { + // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio + contapezziIOB++; + needRefreshPzCount = true; + // salvo in semaforo! + B_input += (1 << 2); + // registro contapezzi + lgInfo($"contapezziPLC KAWASAKI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + else if (contapezziIOB > contapezziPLC) + { + lgInfo($"Contapezzi IOB > CNC --> NON INVIO (contapezziPLC: {contapezziPLC} < contapezziIOB: {contapezziIOB})"); + } + + // invio a server contapezzi (aggiornato) + string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi KAWASAKI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else + { + lgError("Attenzione non trovato ODL --> currODL = 0"); + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgError($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC KAWASAKI {contapezziPLC} | contapezziIOB {contapezziIOB}"); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione B_input: {B_input}"); + } + } + + /// + /// Test completo funzioni kawasaki + /// + private void kawasakiFullTest() + { + // faccio un try-catch di test vari... + try + { + //string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); + //KAWASAKI_ref = new KRcc.Commu(connPar); + //KAWASAKI_ref = new KRcc.Commu("TCP 192.168.0.92"); + if (KAWASAKI_ref.IsConnected) + { + // connect ok + resDataArray = KAWASAKI_ref.command("where", 3000); + // WHERE [RET] Console.WriteLine(resDataArray[1]); [0] = 0 [1] = JT1 JT2 JT3 JT4 + // JT5 JT6 + // -23.205 - 39.967 - 13.176 95.663 71.402 - 21.512 X[mm] Y[mm] Z[mm] O[deg] + // A[deg] T[deg] + // - 489.620 693.940 1564.733 92.612 131.285 7.482 + + threadOk = commThreadOk; + macName = machineName; + cStatus = currBitmapStatus; + cSignals = currBitmapSignals; + contapezziPLC = pzCounter; + numPzPrel = pzPrelevati; + lastRecTC = lastTC; + lastMissRobot = lastMission; + } + // test contapezzi +#if false + // leggo i pezzi + int currCount = pzCounter; + // imposto a 100 + pzCounter = 100; + // rileggo x verifica + int newCount = pzCounter; + // reimposto corretti + pzCounter = currCount; +#endif + // test gest programmi +#if true + //saveProgram("prog", "default"); + sendProgram("prog", "default2"); +#endif + } + catch (Exception e) + { // e.Message = "can't connect TCP/IP" or // "can't login" + Console.WriteLine(e.Message); + } + } + + /// + /// Effettua salvataggio del programma corrente + /// + /// Dir di riferimento + /// Nome Programma (se mancasse *.as lo aggiunge) + private void saveProgram(string progDir = "prog", string progName = "current.as") + { + // path completo + progName = progName.EndsWith(".as") ? progName : progName + ".as"; + string prgPath = progName;// string.Format("{0}/{1}", progDir, progName); + if (KAWASAKI_ref.IsConnected) + { + // comandi x setup programma... + resDataArray = KAWASAKI_ref.command("ferma", 3000); // ferma processi (all) --> "" + resDataArray = KAWASAKI_ref.command("togli", 3000); // toglie processi da pronta esecuzione --> "" + + //resp = com.command("SAVE nome_del_file", 3000); // salvataggio file... FORSE --> "\u0005\u0002Bnome_del_file.as\u0017" --> verificare DOVE salva... + + int ret = KAWASAKI_ref.save(prgPath); // SAVE current.as[RET] + if (ret == 0) + { + // Success + } + if (ret == -1) + { + // Communication error + } + if (ret == -2) + { + // Robot Controller error + } + if (ret == -3) + { + // Internal error + } + } + } + + /// + /// Effettua invio del programma di alvorazione al ROBOT Dir di + /// riferimentoNome Programma (se mancasse *.as lo aggiunge) + /// + private void sendProgram(string progDir = "prog", string progName = "default.as") + { + // path completo + progName = progName.EndsWith(".as") ? progName : progName + ".as"; + string prgPath = progName;// string.Format("{0}/{1}", progDir, progName); + + // comandi x setup programma... + resDataArray = KAWASAKI_ref.command("ferma", 3000); // ferma processi (all) --> "" + resDataArray = KAWASAKI_ref.command("togli", 3000); // toglie processi da pronta esecuzione --> "" + + if (KAWASAKI_ref.IsConnected) + { + // carico... + KAWASAKI_ref.asInquiry = delegate (string as_msg) + { + Console.WriteLine(as_msg); if (as_msg.StartsWith("Are you sure ?")) + { + return "0\n"; // 0 [RET] + } + + if (as_msg.StartsWith("Load data?")) + { + return "1\n"; // 1 [RET] + } + + return null; + }; + int retLoad = KAWASAKI_ref.load(prgPath, "/Q"); // LOAD/Q default.as[RET] + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobMTC.cs b/IOB-WIN-NEXT/IobMTC.cs index 3ab51905..baaca474 100644 --- a/IOB-WIN-NEXT/IobMTC.cs +++ b/IOB-WIN-NEXT/IobMTC.cs @@ -15,49 +15,6 @@ namespace IOB_WIN_NEXT { public class IobMTC : IobGeneric { - #region Private Fields - - /// - /// Struttura dove vengono memorizzati i dataitem ed i rispettivi valori x processing - /// - private Dictionary dataItemMem = new Dictionary(); - - #endregion Private Fields - - #region Protected Fields - - /// - /// Gestione filtraggio dati - /// - protected bool enableDataFilter = false; - - /// - /// Abilitazione restart (da opt par...) - /// - protected bool enableMtcRestart = false; - - /// - /// Determina se ha effettuata lettura items in memoria x confronto... - /// - protected bool hasReadItems = false; - - /// - /// Ultimo current received x gestione update periodico... - /// - protected DateTime lastCurrent = DateTime.Now; - - /// - /// Oggetto MAIN x connessione MTC - /// - protected MTConnectClient MTC_ref; - - /// - /// Veto controllos tatus x log... - /// - protected DateTime vetoCheckStatus = DateTime.Now; - - #endregion Protected Fields - #region Public Constructors /// @@ -96,6 +53,252 @@ namespace IOB_WIN_NEXT #endregion Public Constructors + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // uso metodo base x ora + return base.executeTasks(task2exe); + } + + /// + /// Recupera uno specifico dataItem + /// + /// + /// + public string getDataItemValue(string diKey) + { + string answ = ""; + try + { + var currDataItem = dataItemMem[diKey]; + answ = currDataItem.value; + } + catch (Exception exc) + { + Logging.Instance.Error($"Errore in getDataItemValue per {diKey}{Environment.NewLine}{exc}"); + } + return answ; + } + + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() + { + Dictionary outVal = new Dictionary(); + return outVal; + } + + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + // cerco parametro contapezzi... + string currPzCount = getDataItemValue(mtcParams.keyPartCount); + + if (isVerboseLog) + { + lgInfo($"contapezzi: {mtcParams.keyPartCount} --> {currPzCount}"); + } + + // se ho un contapezzi... processo... + if (!string.IsNullOrEmpty(currPzCount)) + { + int newVal = -1; + Int32.TryParse(currPzCount, out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + } + } + + /// + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + base.readSemafori(ref currDispData); + try + { + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + + currDispData.semIn = Semaforo.SV; + + // decodifica e gestione + decodeToBaseBitmap(); + reportRawInput(ref currDispData); + } + catch (Exception exc) + { + currDispData.semIn = Semaforo.SR; + lgError($"Eccezione in readSemafori:{Environment.NewLine}{exc}"); + } + } + + /// + /// Effettua reset del contapezzi, NON POSSIBILE per MTC (read only) + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; + return answ; + } + + /// + /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE per MTC (read only) + /// + /// + public override bool setcontapezziPLC(int newPzCount) + { + bool answ = false; + return answ; + } + + /// + /// Override connessione + /// + 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("MTC: 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; + short esitoLink = doConnect(); + lgInfo($"szStatusConnection MTC, esitoLink: {esitoLink}"); + parentForm.commPlcActive = false; + connectionOk = true; + // refresh stato allarmi!!! + if (connectionOk) + { + if (adpRunning) + { + lgInfo("Connessione OK"); + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal($"Errore nella connessione all'adapter MTC: {szStatusConnection}{Environment.NewLine}{exc}"); + connectionOk = false; + lgInfo($"Eccezione in TryConnect, Adapter MTC 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: MTC controllo PING fallito per IP {cIobConf.cncIpAddr}"); + } + } + } + } + else + { + needRefresh = true; + } + // se non è ancora connesso faccio procesisng memoria caso disconnesso... + if (!connectionOk) + { + // processo semafori ed invio... + processMemoryDiscon(); + } + } + + /// + /// Override disconnessione + /// + public override void tryDisconnect() + { + if (connectionOk) + { + string szStatusConnection = ""; + try + { + MTC_ref.Stop(); + connectionOk = false; + lgInfo(szStatusConnection); + lgInfo("Effettuata disconnessione adapter MTC!"); + } + catch (Exception exc) + { + lgFatal(exc, "Errore nella disconnessione dall'adapter MTC"); + } + } + else + { + lgError("IMPOSSIBILE effettuare disconnessione MTC: Connessione non disponibile..."); + } + } + + #endregion Public Methods + + #region Protected Fields + + /// + /// Gestione filtraggio dati + /// + protected bool enableDataFilter = false; + + /// + /// Abilitazione restart (da opt par...) + /// + protected bool enableMtcRestart = false; + + /// + /// Determina se ha effettuata lettura items in memoria x confronto... + /// + protected bool hasReadItems = false; + + /// + /// Ultimo current received x gestione update periodico... + /// + protected DateTime lastCurrent = DateTime.Now; + + /// + /// Oggetto MAIN x connessione MTC + /// + protected MTConnectClient MTC_ref; + + /// + /// Veto controllos tatus x log... + /// + protected DateTime vetoCheckStatus = DateTime.Now; + + #endregion Protected Fields + #region Protected Properties /// @@ -177,6 +380,390 @@ namespace IOB_WIN_NEXT #endregion Protected Properties + #region Protected Methods + + /// + /// Verifica un DataItem e se il valore corrisponde a quello indicato come "true value" + /// restituisce true + /// + /// + /// + /// + protected bool checkDataItem(string itemName, string trueVal) + { + bool answ = false; + MtcDataItemExt currValue = null; + try + { + currValue = dataItemMem[itemName]; + answ = (currValue.value.Equals(trueVal)); + } + catch + { + lgError($"Errore in decodifica valore per {itemName} rispetto a {trueVal} | recuperato {currValue} / {currValue.value}"); + } + return answ; + } + + /// + /// Verifica / Salva valore generico (NON SAMPLE) + /// + /// + /// + protected bool checkSaveItem(MTConnectStreams.DataItem newValue) + { + bool answ = !enableDataFilter; + + if (newValue != null) + { + if (isVerboseLog) + { + lgInfo($"Richiesta checkSaveItem per {newValue} | id: {newValue.DataItemId} | CDATA: {newValue.CDATA}"); + } + // verifico in memoria se ho l'oggetto condition ed il suo valore.. + if (dataItemMem.ContainsKey(newValue.DataItemId)) + { + // salvo sempre! + dataItemMem[newValue.DataItemId].value = newValue.CDATA; + dataItemMem[newValue.DataItemId].valueTimestamp = newValue.Timestamp; + answ = true; + } + else + { + // registro non trovato da aggiungere... + lgInfo($"DataItem non trovato in checkSaveItem: {newValue.DataItemId}"); + try + { + // provo a creare oggetot in memoria... + List elencoDataItems = new List(); + int dSamplePeriod = 0; + int threshDBand = 0; + string uuid = ""; + var currDataItem = formatDataItem(ref dSamplePeriod, ref threshDBand, ref uuid, newValue); + // aggiungo + dataItemMem.Add(newValue.DataItemId, currDataItem); + // salvo oggetto x registrazione su server MP-IO + var currMapoDataItem = new machDataItem() + { + uuid = newValue.DataItemId, + Category = (DataItemCategory)newValue.Category, + Name = newValue.Name, + Type = newValue.Type, + SubType = newValue.SubType, + //Units = newValue.Units + }; + // aggiungo + elencoDataItems.Add(currMapoDataItem); + // invio il dataItem serializzato... + sendDataItemsList(elencoDataItems); + } + catch (Exception exc) + { + lgError($"Eccezione in checkSaveSample{Environment.NewLine}{exc}"); + } + } + } + else + { + lgError("Attenzione: checkSaveItem con newValue null!"); + } + return answ; + } + + /// + /// Verifica / Salva valore SAMPLE e restitusice SE sia variato (e quindi da inviare...) + /// + /// + /// + protected bool checkSaveSample(MTConnectStreams.Sample newValue) + { + bool answ = !enableDataFilter; + double oldVal = 0; + double newVal = 0; + if (newValue != null) + { + lgTrace($"Richiesta checkSaveSample per {newValue} | id: {newValue.DataItemId} | CDATA: {newValue.CDATA}"); + // verifico in memoria se ho l'oggetto condition ed il suo valore.. + if (dataItemMem.ContainsKey(newValue.DataItemId)) + { + MtcDataItemExt currDataItemMem = dataItemMem[newValue.DataItemId]; + // controllo SE SIA scaduto il tempo massimo... + if (Math.Abs(dataItemMem[newValue.DataItemId].valueTimestamp.Subtract(newValue.Timestamp).TotalSeconds) > currDataItemMem.samplePeriod) + { + answ = true; + } + else + { + // ALTRIMENTI controllo SE diverso + if (dataItemMem[newValue.DataItemId].value != newValue.CDATA) + { + // controllo SE ho DeadBand... + if (dataItemMem[newValue.DataItemId].thresholdDeadBand > 0) + { + if (isVerboseLog) + { + lgInfo($"Test deadband: oldVal: {oldVal} | newVal: {newVal}"); + } + // recupero i valori e testo DeadBand... + double.TryParse(dataItemMem[newValue.DataItemId].value.Replace(".", ","), out oldVal); + double.TryParse(newValue.CDATA.Replace(".", ","), out newVal); + // test deadband! + if (Math.Abs(newVal - oldVal) > dataItemMem[newValue.DataItemId].thresholdDeadBand) + { + // indico da salvare.. + answ = true; + } + } + } + } + if (answ) + { + // salvo! + dataItemMem[newValue.DataItemId].value = newValue.CDATA; + dataItemMem[newValue.DataItemId].valueTimestamp = newValue.Timestamp; + } + } + else + { + // registro non trovato da aggiungere... + lgInfo($"DataItem non trovato in checkSaveSample: {newValue.DataItemId}"); + // provo a creare oggetto in memoria... + try + { + List elencoDataItems = new List(); + int dSamplePeriod = 0; + int threshDBand = 0; + string uuid = ""; + var currDataItem = formatDataItem(ref dSamplePeriod, ref threshDBand, ref uuid, newValue); + // aggiungo + dataItemMem.Add(newValue.DataItemId, currDataItem); + // salvo oggetto x registrazione su server MP-IO + var currMapoDataItem = new machDataItem() + { + uuid = newValue.DataItemId, + Category = (DataItemCategory)newValue.Category, + Name = newValue.Name, + Type = newValue.Type, + SubType = newValue.SubType, + //Units = newValue.Units + }; + // aggiungo + elencoDataItems.Add(currMapoDataItem); + // invio il dataItem serializzato... + sendDataItemsList(elencoDataItems); + } + catch (Exception exc) + { + lgError($"Eccezione in checkSaveSample{Environment.NewLine}{exc}"); + } + } + } + else + { + lgError("Attenzione: checkSaveItem con newValue null!"); + } + return answ; + } + + /// + /// Effettuata discovery iniziale valori CURRENT + /// + /// + /// + protected void CurrentSuccessful(MTConnectStreams.Document document) + { + if (document != null) + { + lgInfo($"DiscoverySuccessful: discovery per {document.Url}"); + if (document.DeviceStreams != null) + { + lgInfo($"DiscoverySuccessful: trovati {document.DeviceStreams.Count} streams"); + } + checkAndSend(document, true); + } + else + { + lgError("StreamsSuccessful ERROR: document è null"); + } + } + + /// + /// Evento lanciato alla corretta ricezione del PROBE + /// + /// + protected void DevicesSuccessful(MTConnectDevices.Document document) + { + lgInfo("STEP 01 DevicesSuccessful reached!"); + MtcDataItemExt currDataItem = null; + machDataItem currMapoDataItem = null; + List elencoDataItems = new List(); + int dSamplePeriod = 0; + int threshDBand = 0; + string uuid = ""; + if (document != null) + { + foreach (var device in document.Devices) + { + List dataItems = device.GetDataItems(); + lgInfo($"Inizio STEP 02 per caricare {dataItems.Count} dataItems"); + foreach (var dataItem in dataItems) + { + try + { + currDataItem = formatDataItem(ref dSamplePeriod, ref threshDBand, ref uuid, dataItem); + // aggiungo se non c'è... + if (!dataItemMem.ContainsKey(dataItem.Id)) + { + dataItemMem.Add(dataItem.Id, currDataItem); + } + // salvo oggetto x registrazione su server MP-IO + currMapoDataItem = new machDataItem() + { + uuid = dataItem.Id, + Category = (DataItemCategory)dataItem.Category, + Name = dataItem.Name, + Type = dataItem.Type, + SubType = dataItem.SubType, + Units = dataItem.Units + }; + // aggiungo se non ci fosse + if (!elencoDataItems.Contains(currMapoDataItem)) + { + elencoDataItems.Add(currMapoDataItem); + } + } + catch (Exception exc) + { + lgError($"Eccezione in DevicesSuccessful / DataItem:{Environment.NewLine}{exc}"); + } + } + } + // invio IN BLOCCO il dataItem serializzati... + if (elencoDataItems.Count > 0) + { + lgInfo($"STEP 04 invio dati di {elencoDataItems.Count} records"); + sendDataItemsList(elencoDataItems); + } + hasReadItems = true; + lgInfo($"STEP 05: memorizzati {dataItemMem.Count} oggetti in memoria"); + } + else + { + lgError("STEP 06 error: document null!"); + } + } + + /// + /// Effettua traduzione ITEM da LUT parametrica (key: tipo+id) del file di conf, se non trovo uso key + /// + /// + /// + /// + protected string itemTranslation(string tipo, string id) + { + string answ = ""; + string lemma = $"{tipo}_{id}"; + // cerco nel dizionario delle traduzioni SE esiste un valore e prendo quello, altrimenti + // uso il lemma... + if (mtcParams.itemTranslation.ContainsKey(lemma)) + { + answ = mtcParams.itemTranslation[lemma]; + } + else + { + answ = lemma; + } + return answ; + } + + /// + /// Effettua log di un elenco componenti + /// + /// + protected void logComponentsList(List elencoComponenti) + { + if (elencoComponenti != null) + { + foreach (var item in elencoComponenti) + { + lgInfo($"Component data | ID: {item.Id} | Name: {item.Name} | Type: {item.Type} | # items: {item.DataItems.Count}"); + // se ho sottocomponenti richiamo... + if (item.SubComponents != null) + { + if (item.SubComponents.Components.Count > 0) + { + logComponentsList(item.SubComponents.Components); + } + } + if (item.DataItems.Count > 0) + { + logDataItemList(item.DataItems); + } + } + } + } + + /// + /// Log elenco DataItems + /// + /// + protected void logDataItemList(List elencoItems) + { + if (elencoItems != null) + { + // loggo devices principali... + foreach (var item in elencoItems) + { + lgInfo($"Device data | ID: {item.Id} | Name: {item.Name} | Category: {item.Category} | # Type: {item.Type}"); + } + } + } + + /// + /// Effettua log di un devices (ed eventualmente dei sub-devices... + /// + /// + protected void logDevicesList(List elencoDevices) + { + if (elencoDevices != null) + { + // loggo devices principali... + foreach (var item in elencoDevices) + { + lgInfo($"Device data | ID: {item.Id} | Name: {item.Name} | UUID: {item.Uuid} | # items: {item.DataItems.Count}"); + // se ho subItems descrivo pure loro... + if (item.DataItems.Count > 0) + { + logDataItemList(item.DataItems); + } + if (item.Components.Components.Count > 0) + { + logComponentsList(item.Components.Components); + } + } + } + } + + /// + /// Ricevuta modifica come stream da campionamenti ricevuti + /// + /// + protected void StreamsSuccessful(MTConnectStreams.Document document) + { + checkAndSend(document, false); + } + + #endregion Protected Methods + + #region Private Fields + + /// + /// Struttura dove vengono memorizzati i dataitem ed i rispettivi valori x processing + /// + private Dictionary dataItemMem = new Dictionary(); + + #endregion Private Fields + #region Private Methods /// @@ -210,7 +797,8 @@ namespace IOB_WIN_NEXT bool changed = checkSaveItem(dataItem); if (changed || forceSend) { - // accodare ed invia nella coda ALARMS (che POI salva in document MongoDB anche ultimi x minuti di FluxLog...) + // accodare ed invia nella coda ALARMS (che POI salva in document + // MongoDB anche ultimi x minuti di FluxLog...) accodaAlarmLog(sVal, qEncodeFLog(time2, descr, dataItem.CDATA)); } } @@ -335,7 +923,7 @@ namespace IOB_WIN_NEXT string currPowerOn = getDataItemValue(mtcParams.condPowerOn.keyName); // se valido il check ping lo eseguo... altrimenti lo do x buono bool isPingOk = (testPingMachine == IPStatus.Success); - + // verifico da target value richiesto... bool checkPowerOn = (currPowerOn == mtcParams.condPowerOn.targetValue); @@ -628,8 +1216,8 @@ namespace IOB_WIN_NEXT } /// - /// Effettua lettura file di conf specifico MTC da oggetto serializzato json - /// Nome file da cui leggere i parametri json + /// Effettua lettura file di conf specifico MTC da oggetto serializzato json Nome file da cui leggere i parametri json /// private void loadMtcConf(string fileName) { @@ -668,590 +1256,5 @@ namespace IOB_WIN_NEXT } #endregion Private Methods - - #region Protected Methods - - /// - /// Verifica un DataItem e se il valore corrisponde a quello indicato come "true value" restituisce true - /// - /// - /// - /// - protected bool checkDataItem(string itemName, string trueVal) - { - bool answ = false; - MtcDataItemExt currValue = null; - try - { - currValue = dataItemMem[itemName]; - answ = (currValue.value.Equals(trueVal)); - } - catch - { - lgError($"Errore in decodifica valore per {itemName} rispetto a {trueVal} | recuperato {currValue} / {currValue.value}"); - } - return answ; - } - - /// - /// Verifica / Salva valore generico (NON SAMPLE) - /// - /// - /// - protected bool checkSaveItem(MTConnectStreams.DataItem newValue) - { - bool answ = !enableDataFilter; - - if (newValue != null) - { - if (isVerboseLog) - { - lgInfo($"Richiesta checkSaveItem per {newValue} | id: {newValue.DataItemId} | CDATA: {newValue.CDATA}"); - } - // verifico in memoria se ho l'oggetto condition ed il suo valore.. - if (dataItemMem.ContainsKey(newValue.DataItemId)) - { - // salvo sempre! - dataItemMem[newValue.DataItemId].value = newValue.CDATA; - dataItemMem[newValue.DataItemId].valueTimestamp = newValue.Timestamp; - answ = true; - } - else - { - // registro non trovato da aggiungere... - lgInfo($"DataItem non trovato in checkSaveItem: {newValue.DataItemId}"); - try - { - // provo a creare oggetot in memoria... - List elencoDataItems = new List(); - int dSamplePeriod = 0; - int threshDBand = 0; - string uuid = ""; - var currDataItem = formatDataItem(ref dSamplePeriod, ref threshDBand, ref uuid, newValue); - // aggiungo - dataItemMem.Add(newValue.DataItemId, currDataItem); - // salvo oggetto x registrazione su server MP-IO - var currMapoDataItem = new machDataItem() - { - uuid = newValue.DataItemId, - Category = (DataItemCategory)newValue.Category, - Name = newValue.Name, - Type = newValue.Type, - SubType = newValue.SubType, - //Units = newValue.Units - }; - // aggiungo - elencoDataItems.Add(currMapoDataItem); - // invio il dataItem serializzato... - sendDataItemsList(elencoDataItems); - } - catch (Exception exc) - { - lgError($"Eccezione in checkSaveSample{Environment.NewLine}{exc}"); - } - } - } - else - { - lgError("Attenzione: checkSaveItem con newValue null!"); - } - return answ; - } - - /// - /// Verifica / Salva valore SAMPLE e restitusice SE sia variato (e quindi da inviare...) - /// - /// - /// - protected bool checkSaveSample(MTConnectStreams.Sample newValue) - { - bool answ = !enableDataFilter; - double oldVal = 0; - double newVal = 0; - if (newValue != null) - { - lgTrace($"Richiesta checkSaveSample per {newValue} | id: {newValue.DataItemId} | CDATA: {newValue.CDATA}"); - // verifico in memoria se ho l'oggetto condition ed il suo valore.. - if (dataItemMem.ContainsKey(newValue.DataItemId)) - { - MtcDataItemExt currDataItemMem = dataItemMem[newValue.DataItemId]; - // controllo SE SIA scaduto il tempo massimo... - if (Math.Abs(dataItemMem[newValue.DataItemId].valueTimestamp.Subtract(newValue.Timestamp).TotalSeconds) > currDataItemMem.samplePeriod) - { - answ = true; - } - else - { - // ALTRIMENTI controllo SE diverso - if (dataItemMem[newValue.DataItemId].value != newValue.CDATA) - { - // controllo SE ho DeadBand... - if (dataItemMem[newValue.DataItemId].thresholdDeadBand > 0) - { - if (isVerboseLog) - { - lgInfo($"Test deadband: oldVal: {oldVal} | newVal: {newVal}"); - } - // recupero i valori e testo DeadBand... - double.TryParse(dataItemMem[newValue.DataItemId].value.Replace(".", ","), out oldVal); - double.TryParse(newValue.CDATA.Replace(".", ","), out newVal); - // test deadband! - if (Math.Abs(newVal - oldVal) > dataItemMem[newValue.DataItemId].thresholdDeadBand) - { - // indico da salvare.. - answ = true; - } - } - } - } - if (answ) - { - // salvo! - dataItemMem[newValue.DataItemId].value = newValue.CDATA; - dataItemMem[newValue.DataItemId].valueTimestamp = newValue.Timestamp; - } - } - else - { - // registro non trovato da aggiungere... - lgInfo($"DataItem non trovato in checkSaveSample: {newValue.DataItemId}"); - // provo a creare oggetto in memoria... - try - { - List elencoDataItems = new List(); - int dSamplePeriod = 0; - int threshDBand = 0; - string uuid = ""; - var currDataItem = formatDataItem(ref dSamplePeriod, ref threshDBand, ref uuid, newValue); - // aggiungo - dataItemMem.Add(newValue.DataItemId, currDataItem); - // salvo oggetto x registrazione su server MP-IO - var currMapoDataItem = new machDataItem() - { - uuid = newValue.DataItemId, - Category = (DataItemCategory)newValue.Category, - Name = newValue.Name, - Type = newValue.Type, - SubType = newValue.SubType, - //Units = newValue.Units - }; - // aggiungo - elencoDataItems.Add(currMapoDataItem); - // invio il dataItem serializzato... - sendDataItemsList(elencoDataItems); - } - catch (Exception exc) - { - lgError($"Eccezione in checkSaveSample{Environment.NewLine}{exc}"); - } - } - } - else - { - lgError("Attenzione: checkSaveItem con newValue null!"); - } - return answ; - } - - /// - /// Effettuata discovery iniziale valori CURRENT - /// - /// - /// - protected void CurrentSuccessful(MTConnectStreams.Document document) - { - if (document != null) - { - lgInfo($"DiscoverySuccessful: discovery per {document.Url}"); - if (document.DeviceStreams != null) - { - lgInfo($"DiscoverySuccessful: trovati {document.DeviceStreams.Count} streams"); - } - checkAndSend(document, true); - } - else - { - lgError("StreamsSuccessful ERROR: document è null"); - } - } - - /// - /// Evento lanciato alla corretta ricezione del PROBE - /// - /// - protected void DevicesSuccessful(MTConnectDevices.Document document) - { - lgInfo("STEP 01 DevicesSuccessful reached!"); - MtcDataItemExt currDataItem = null; - machDataItem currMapoDataItem = null; - List elencoDataItems = new List(); - int dSamplePeriod = 0; - int threshDBand = 0; - string uuid = ""; - if (document != null) - { - foreach (var device in document.Devices) - { - List dataItems = device.GetDataItems(); - lgInfo($"Inizio STEP 02 per caricare {dataItems.Count} dataItems"); - foreach (var dataItem in dataItems) - { - try - { - currDataItem = formatDataItem(ref dSamplePeriod, ref threshDBand, ref uuid, dataItem); - // aggiungo se non c'è... - if (!dataItemMem.ContainsKey(dataItem.Id)) - { - dataItemMem.Add(dataItem.Id, currDataItem); - } - // salvo oggetto x registrazione su server MP-IO - currMapoDataItem = new machDataItem() - { - uuid = dataItem.Id, - Category = (DataItemCategory)dataItem.Category, - Name = dataItem.Name, - Type = dataItem.Type, - SubType = dataItem.SubType, - Units = dataItem.Units - }; - // aggiungo se non ci fosse - if (!elencoDataItems.Contains(currMapoDataItem)) - { - elencoDataItems.Add(currMapoDataItem); - } - } - catch (Exception exc) - { - lgError($"Eccezione in DevicesSuccessful / DataItem:{Environment.NewLine}{exc}"); - } - } - } - // invio IN BLOCCO il dataItem serializzati... - if (elencoDataItems.Count > 0) - { - lgInfo($"STEP 04 invio dati di {elencoDataItems.Count} records"); - sendDataItemsList(elencoDataItems); - } - hasReadItems = true; - lgInfo($"STEP 05: memorizzati {dataItemMem.Count} oggetti in memoria"); - } - else - { - lgError("STEP 06 error: document null!"); - } - } - - /// - /// Effettua traduzione ITEM da LUT parametrica (key: tipo+id) del file di conf, se non trovo uso key - /// - /// - /// - /// - protected string itemTranslation(string tipo, string id) - { - string answ = ""; - string lemma = $"{tipo}_{id}"; - // cerco nel dizionario delle traduzioni SE esiste un valore e prendo quello, altrimenti uso il lemma... - if (mtcParams.itemTranslation.ContainsKey(lemma)) - { - answ = mtcParams.itemTranslation[lemma]; - } - else - { - answ = lemma; - } - return answ; - } - - /// - /// Effettua log di un elenco componenti - /// - /// - protected void logComponentsList(List elencoComponenti) - { - if (elencoComponenti != null) - { - foreach (var item in elencoComponenti) - { - lgInfo($"Component data | ID: {item.Id} | Name: {item.Name} | Type: {item.Type} | # items: {item.DataItems.Count}"); - // se ho sottocomponenti richiamo... - if (item.SubComponents != null) - { - if (item.SubComponents.Components.Count > 0) - { - logComponentsList(item.SubComponents.Components); - } - } - if (item.DataItems.Count > 0) - { - logDataItemList(item.DataItems); - } - } - } - } - - /// - /// Log elenco DataItems - /// - /// - protected void logDataItemList(List elencoItems) - { - if (elencoItems != null) - { - // loggo devices principali... - foreach (var item in elencoItems) - { - lgInfo($"Device data | ID: {item.Id} | Name: {item.Name} | Category: {item.Category} | # Type: {item.Type}"); - } - } - } - - /// - /// Effettua log di un devices (ed eventualmente dei sub-devices... - /// - /// - protected void logDevicesList(List elencoDevices) - { - if (elencoDevices != null) - { - // loggo devices principali... - foreach (var item in elencoDevices) - { - lgInfo($"Device data | ID: {item.Id} | Name: {item.Name} | UUID: {item.Uuid} | # items: {item.DataItems.Count}"); - // se ho subItems descrivo pure loro... - if (item.DataItems.Count > 0) - { - logDataItemList(item.DataItems); - } - if (item.Components.Components.Count > 0) - { - logComponentsList(item.Components.Components); - } - } - } - } - - /// - /// Ricevuta modifica come stream da campionamenti ricevuti - /// - /// - protected void StreamsSuccessful(MTConnectStreams.Document document) - { - checkAndSend(document, false); - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - // uso metodo base x ora - return base.executeTasks(task2exe); - } - - /// - /// Recupera uno specifico dataItem - /// - /// - /// - public string getDataItemValue(string diKey) - { - string answ = ""; - try - { - var currDataItem = dataItemMem[diKey]; - answ = currDataItem.value; - } - catch (Exception exc) - { - Logging.Instance.Error($"Errore in getDataItemValue per {diKey}{Environment.NewLine}{exc}"); - } - return answ; - } - - /// - /// Recupero dati dinamici... - /// - public override Dictionary getDynData() - { - Dictionary outVal = new Dictionary(); - return outVal; - } - - /// - /// Effettua vero processing contapezzi - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { - // cerco parametro contapezzi... - string currPzCount = getDataItemValue(mtcParams.keyPartCount); - - if (isVerboseLog) - { - lgInfo($"contapezzi: {mtcParams.keyPartCount} --> {currPzCount}"); - } - - // se ho un contapezzi... processo... - if (!string.IsNullOrEmpty(currPzCount)) - { - int newVal = -1; - Int32.TryParse(currPzCount, out newVal); - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - } - } - } - - /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form - /// - public override void readSemafori(ref newDisplayData currDispData) - { - base.readSemafori(ref currDispData); - try - { - if (verboseLog) - { - lgInfo("inizio read semafori"); - } - - currDispData.semIn = Semaforo.SV; - - // decodifica e gestione - decodeToBaseBitmap(); - reportRawInput(ref currDispData); - } - catch (Exception exc) - { - currDispData.semIn = Semaforo.SR; - lgError($"Eccezione in readSemafori:{Environment.NewLine}{exc}"); - } - } - - /// - /// Effettua reset del contapezzi, NON POSSIBILE per MTC (read only) - /// - /// - public override bool resetcontapezziPLC() - { - bool answ = false; - return answ; - } - - /// - /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE per MTC (read only) - /// - /// - public override bool setcontapezziPLC(int newPzCount) - { - bool answ = false; - return answ; - } - - /// - /// Override connessione - /// - 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("MTC: 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; - short esitoLink = doConnect(); - lgInfo($"szStatusConnection MTC, esitoLink: {esitoLink}"); - parentForm.commPlcActive = false; - connectionOk = true; - // refresh stato allarmi!!! - if (connectionOk) - { - if (adpRunning) - { - lgInfo("Connessione OK"); - } - } - else - { - lgError("Impossibile procedere, connessione mancante..."); - } - } - catch (Exception exc) - { - lgFatal($"Errore nella connessione all'adapter MTC: {szStatusConnection}{Environment.NewLine}{exc}"); - connectionOk = false; - lgInfo($"Eccezione in TryConnect, Adapter MTC 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: MTC controllo PING fallito per IP {cIobConf.cncIpAddr}"); - } - } - } - } - else - { - needRefresh = true; - } - // se non è ancora connesso faccio procesisng memoria caso disconnesso... - if (!connectionOk) - { - // processo semafori ed invio... - processMemoryDiscon(); - } - } - - /// - /// Override disconnessione - /// - public override void tryDisconnect() - { - if (connectionOk) - { - string szStatusConnection = ""; - try - { - MTC_ref.Stop(); - connectionOk = false; - lgInfo(szStatusConnection); - lgInfo("Effettuata disconnessione adapter MTC!"); - } - catch (Exception exc) - { - lgFatal(exc, "Errore nella disconnessione dall'adapter MTC"); - } - } - else - { - lgError("IMPOSSIBILE effettuare disconnessione MTC: Connessione non disponibile..."); - } - } - - #endregion Public Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobModbusTCP.cs b/IOB-WIN-NEXT/IobModbusTCP.cs index d0a2fe80..38a37bb4 100644 --- a/IOB-WIN-NEXT/IobModbusTCP.cs +++ b/IOB-WIN-NEXT/IobModbusTCP.cs @@ -801,7 +801,6 @@ namespace IOB_WIN_NEXT fatto = writeInputReg(currMem.index, CurrVal, parametri.holdRegBaseAddr); break; - case plcDataType.IntLH: valInt = getScaledInt(currMem, true); if (byteSize == 1) @@ -1155,8 +1154,6 @@ namespace IOB_WIN_NEXT #region Private Methods - - /// /// converte valore in tipo desiderato /// @@ -1241,7 +1238,6 @@ namespace IOB_WIN_NEXT valore = ModbusClient.ConvertRegistersToInt(listInt); } break; - } return valore; } @@ -1258,6 +1254,7 @@ namespace IOB_WIN_NEXT return valDouble; } + /// /// Effettua scalatura valore secondo fattore /// Read --> * (moltiplico) diff --git a/IOB-WIN-NEXT/IobModbusTCPCedax.cs b/IOB-WIN-NEXT/IobModbusTCPCedax.cs index a67ef056..66501e2e 100644 --- a/IOB-WIN-NEXT/IobModbusTCPCedax.cs +++ b/IOB-WIN-NEXT/IobModbusTCPCedax.cs @@ -1,19 +1,11 @@ using EasyModbus; -using IOB_UT_NEXT; -using MapoSDK; -using Newtonsoft.Json; using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { /* -------------------------------------------------------------------------------- * Controlli ModBusTCP Hunitronix Cedax - * - protocollo ModBus TCP + * - protocollo ModBus TCP * - specifico comportamento impianti Unitronix Cedax * - nessuna gestione allarmi * @@ -54,42 +46,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Methods - - private void testBlockRead(int baseAddr, int numByte) - { - int baseHold = 40001; - int[] readTestFull = new int[2]; - lgTrace($"-------------------- Inizio test lettura {baseAddr} --------------------"); - try - { - stopwatch.Restart(); - readTestFull = currPLC.ReadHoldingRegisters(baseAddr - baseHold, numByte); - stopwatch.Stop(); - lgTrace($"Stats lettura | {readTestFull.Length} val | {stopwatch.ElapsedMilliseconds}ms"); - } - catch - { } - - for (int i = 0; i < readTestFull.Length / 2; i++) - { - int[] thisSet = new int[2]; - Array.Copy(readTestFull, i * 2, thisSet, 0, 2); - lgTrace($"{baseAddr + i * 2:000} | HoldingRegisters: {thisSet[0]} / {thisSet[1]} | Val Real: {ModbusClient.ConvertRegistersToFloat(thisSet):N6}"); - } - lgTrace("-------------------- Completato test lettura {baseAddr} --------------------"); - } - - private void testRead() - { - foreach (var item in memSetR) - { - testBlockRead(item.Key, item.Value); - } - } - - #endregion Private Methods - #region Protected Methods /// @@ -140,5 +96,41 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods + + #region Private Methods + + private void testBlockRead(int baseAddr, int numByte) + { + int baseHold = 40001; + int[] readTestFull = new int[2]; + lgTrace($"-------------------- Inizio test lettura {baseAddr} --------------------"); + try + { + stopwatch.Restart(); + readTestFull = currPLC.ReadHoldingRegisters(baseAddr - baseHold, numByte); + stopwatch.Stop(); + lgTrace($"Stats lettura | {readTestFull.Length} val | {stopwatch.ElapsedMilliseconds}ms"); + } + catch + { } + + for (int i = 0; i < readTestFull.Length / 2; i++) + { + int[] thisSet = new int[2]; + Array.Copy(readTestFull, i * 2, thisSet, 0, 2); + lgTrace($"{baseAddr + i * 2:000} | HoldingRegisters: {thisSet[0]} / {thisSet[1]} | Val Real: {ModbusClient.ConvertRegistersToFloat(thisSet):N6}"); + } + lgTrace("-------------------- Completato test lettura {baseAddr} --------------------"); + } + + private void testRead() + { + foreach (var item in memSetR) + { + testBlockRead(item.Key, item.Value); + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobModbusTCPCenterfrigo.cs b/IOB-WIN-NEXT/IobModbusTCPCenterfrigo.cs index 47302ac3..52adbcd3 100644 --- a/IOB-WIN-NEXT/IobModbusTCPCenterfrigo.cs +++ b/IOB-WIN-NEXT/IobModbusTCPCenterfrigo.cs @@ -1,19 +1,11 @@ using EasyModbus; -using IOB_UT_NEXT; -using MapoSDK; -using Newtonsoft.Json; using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { /* -------------------------------------------------------------------------------- * Controlli ModBusTCP Centerfrigo - * - protocollo ModBus TCP + * - protocollo ModBus TCP * - specifico comportamento impianti Centerfrigo * - gestione allarmi * - gestione stati salvati come dynData @@ -23,7 +15,7 @@ namespace IOB_WIN_NEXT * lettura: xxx byte, * scrittura yyy byte * G:\Drive condivisi\30_Clienti\Giacovelli - WIL\CenterFrigo - * + * * ATTENZIONE! leggere al max 44 byte alla volta * * -------------------------------------------------------------------------------- */ @@ -57,42 +49,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Methods - - private void testBlockRead(int baseAddr, int numByte) - { - int baseHold = 40001; - int[] readTestFull = new int[2]; - lgTrace($"-------------------- Inizio test lettura {baseAddr} --------------------"); - try - { - stopwatch.Restart(); - readTestFull = currPLC.ReadHoldingRegisters(baseAddr - baseHold, numByte); - stopwatch.Stop(); - lgTrace($"Stats lettura | {readTestFull.Length} val | {stopwatch.ElapsedMilliseconds}ms"); - } - catch - { } - - for (int i = 0; i < readTestFull.Length / 2; i++) - { - int[] thisSet = new int[2]; - Array.Copy(readTestFull, i * 2, thisSet, 0, 2); - lgTrace($"{baseAddr + i * 2:000} | HoldingRegisters: {thisSet[0]} / {thisSet[1]} | Val Real: {ModbusClient.ConvertRegistersToFloat(thisSet):N6}"); - } - lgTrace("-------------------- Completato test lettura {baseAddr} --------------------"); - } - - private void testRead() - { - foreach (var item in memSetR) - { - testBlockRead(item.Key, item.Value); - } - } - - #endregion Private Methods - #region Protected Methods /// @@ -143,5 +99,41 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods + + #region Private Methods + + private void testBlockRead(int baseAddr, int numByte) + { + int baseHold = 40001; + int[] readTestFull = new int[2]; + lgTrace($"-------------------- Inizio test lettura {baseAddr} --------------------"); + try + { + stopwatch.Restart(); + readTestFull = currPLC.ReadHoldingRegisters(baseAddr - baseHold, numByte); + stopwatch.Stop(); + lgTrace($"Stats lettura | {readTestFull.Length} val | {stopwatch.ElapsedMilliseconds}ms"); + } + catch + { } + + for (int i = 0; i < readTestFull.Length / 2; i++) + { + int[] thisSet = new int[2]; + Array.Copy(readTestFull, i * 2, thisSet, 0, 2); + lgTrace($"{baseAddr + i * 2:000} | HoldingRegisters: {thisSet[0]} / {thisSet[1]} | Val Real: {ModbusClient.ConvertRegistersToFloat(thisSet):N6}"); + } + lgTrace("-------------------- Completato test lettura {baseAddr} --------------------"); + } + + private void testRead() + { + foreach (var item in memSetR) + { + testBlockRead(item.Key, item.Value); + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobModbusTCPHam.cs b/IOB-WIN-NEXT/IobModbusTCPHam.cs index 96017aa2..627374b1 100644 --- a/IOB-WIN-NEXT/IobModbusTCPHam.cs +++ b/IOB-WIN-NEXT/IobModbusTCPHam.cs @@ -1,13 +1,5 @@ using EasyModbus; -using IOB_UT_NEXT; -using MapoSDK; -using Newtonsoft.Json; using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { @@ -51,49 +43,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Methods - - private void testBlockRead(int baseAddr, int numByte) - { - int baseHold = 40001; - int[] readTestFull = new int[2]; - lgTrace($"-------------------- Inizio test lettura {baseAddr} --------------------"); - try - { - stopwatch.Restart(); - readTestFull = currPLC.ReadHoldingRegisters(baseAddr - baseHold, numByte); - stopwatch.Stop(); - lgTrace($"Stats lettura | {readTestFull.Length} val | {stopwatch.ElapsedMilliseconds}ms"); - } - catch - { } - - for (int i = 0; i < readTestFull.Length / 2; i++) - { - int[] thisSet = new int[2]; - Array.Copy(readTestFull, i * 2, thisSet, 0, 2); - lgTrace($"{baseAddr + i * 2:000} | HoldingRegisters: {thisSet[0]} / {thisSet[1]} | Val Real: {ModbusClient.ConvertRegistersToFloat(thisSet):N6}"); - } - lgTrace("-------------------- Completato test lettura {baseAddr} --------------------"); - } - - private void testRead() - { - //Ip-Address and Port of Modbus-TCP-Server - //currPLC = new ModbusClient(cIobConf.cncIpAddr, 502); - ////Connect to Server - //currPLC.Connect(); - //modbusClient.WriteMultipleCoils(4, new bool[] { true, true, true, true, true, true, true, true, true, true }); //Write Coils starting with Address 5 - //bool[] readCoils = modbusClient.ReadCoils(9, 10); //Read 10 Coils from Server, starting with address 10 - //int[] readHoldingRegisters = currPLC.ReadHoldingRegisters(0, 34); //Read 10 Holding Registers from Server, starting with Address 1 - foreach (var item in memSetR) - { - testBlockRead(item.Key, item.Value); - } - } - - #endregion Private Methods - #region Protected Methods /// @@ -138,5 +87,48 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods + + #region Private Methods + + private void testBlockRead(int baseAddr, int numByte) + { + int baseHold = 40001; + int[] readTestFull = new int[2]; + lgTrace($"-------------------- Inizio test lettura {baseAddr} --------------------"); + try + { + stopwatch.Restart(); + readTestFull = currPLC.ReadHoldingRegisters(baseAddr - baseHold, numByte); + stopwatch.Stop(); + lgTrace($"Stats lettura | {readTestFull.Length} val | {stopwatch.ElapsedMilliseconds}ms"); + } + catch + { } + + for (int i = 0; i < readTestFull.Length / 2; i++) + { + int[] thisSet = new int[2]; + Array.Copy(readTestFull, i * 2, thisSet, 0, 2); + lgTrace($"{baseAddr + i * 2:000} | HoldingRegisters: {thisSet[0]} / {thisSet[1]} | Val Real: {ModbusClient.ConvertRegistersToFloat(thisSet):N6}"); + } + lgTrace("-------------------- Completato test lettura {baseAddr} --------------------"); + } + + private void testRead() + { + //Ip-Address and Port of Modbus-TCP-Server + //currPLC = new ModbusClient(cIobConf.cncIpAddr, 502); + ////Connect to Server + //currPLC.Connect(); + //modbusClient.WriteMultipleCoils(4, new bool[] { true, true, true, true, true, true, true, true, true, true }); //Write Coils starting with Address 5 + //bool[] readCoils = modbusClient.ReadCoils(9, 10); //Read 10 Coils from Server, starting with address 10 + //int[] readHoldingRegisters = currPLC.ReadHoldingRegisters(0, 34); //Read 10 Holding Registers from Server, starting with Address 1 + foreach (var item in memSetR) + { + testBlockRead(item.Key, item.Value); + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobModbusTCPHelpi.cs b/IOB-WIN-NEXT/IobModbusTCPHelpi.cs index 894dd39c..35ec1d1c 100644 --- a/IOB-WIN-NEXT/IobModbusTCPHelpi.cs +++ b/IOB-WIN-NEXT/IobModbusTCPHelpi.cs @@ -1,21 +1,13 @@ using EasyModbus; -using IOB_UT_NEXT; -using MapoSDK; -using Newtonsoft.Json; using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { /* -------------------------------------------------------------------------------- * Controlli ModBusTCP Helpi - * - protocollo ModBus TCP + * - protocollo ModBus TCP * - specifico comportamento impianti confezionatrici Helpi - * + * * NRicetta UINT 16bit 41060 W * ApplicaRicetta UINT 16bit 41061 R/W * IDOrdine STRING [30] 41062 W @@ -28,7 +20,7 @@ namespace IOB_WIN_NEXT * EpochStop UDINT 32bit 41104 R * PPM REAL 32bit 41106 R * StatusLavoro UINT 16bit 41108 R - * + * * StatusLavoro indica lo stato della macchina: * 0. macchina completamente ferma * 1. macchina in riscaldamento @@ -44,7 +36,6 @@ namespace IOB_WIN_NEXT { #region Public Constructors - /// /// Classe base con i metodi x ModBusTCP /// @@ -74,41 +65,53 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Methods + #region Protected Properties - private void testBlockRead(int baseAddr, int numByte) + /// + /// Restituisce status di emergenza, hard coded dall'area di allarmi + /// + protected bool EStop { - int baseHold = 41060; - int[] readTestFull = new int[50]; - lgTrace($"-------------------- Inizio test lettura {baseAddr} --------------------"); - try + get { - stopwatch.Restart(); - readTestFull = currPLC.ReadHoldingRegisters(baseAddr - baseHold, numByte); - stopwatch.Stop(); - lgTrace($"Stats lettura | {readTestFull.Length} val | {stopwatch.ElapsedMilliseconds}ms"); - } - catch - { } - - for (int i = 0; i < readTestFull.Length / 2; i++) - { - int[] thisSet = new int[2]; - Array.Copy(readTestFull, i * 2, thisSet, 0, 2); - lgTrace($"{baseAddr + i * 2:000} | HoldingRegisters: {thisSet[0]} / {thisSet[1]} | Val Real: {ModbusClient.ConvertRegistersToFloat(thisSet):N6}"); - } - lgTrace("-------------------- Completato test lettura {baseAddr} --------------------"); - } - - private void testRead() - { - foreach (var item in memSetR) - { - testBlockRead(item.Key, item.Value); + bool answ = false; + int currStatus = 0; + // hard coded + int statusReg = 41094; + // deve avere allarmi (è un allarme EStop) + if (hasAlarms) + { + int[] listInt = new int[2]; + listInt = HoldingRegisterLUT[statusReg]; + currStatus = ModbusClient.ConvertRegistersToInt(listInt); + // hard coded il 5° bit + answ = ((currStatus & (1 << 4)) > 0); + } + return answ; } } - #endregion Private Methods + /// + /// Restituisce status di lavorazione, hard coded dall'area di memoria 41108 + /// + protected int StatusLavoro + { + get + { + int answ = 0; + // hard coded + int statusReg = 41108; + if (HoldingRegisterLUT.ContainsKey(statusReg)) + { + int[] listInt = new int[2]; + listInt = HoldingRegisterLUT[statusReg]; + answ = ModbusClient.ConvertRegistersToInt(listInt); + } + return answ; + } + } + + #endregion Protected Properties #region Protected Methods @@ -160,13 +163,16 @@ namespace IOB_WIN_NEXT case 0: default: break; + case 1: byteSignals += (1 << 6); break; + case 2: case 3: byteSignals += (1 << 4); break; + case 4: byteSignals += (1 << 1); break; @@ -177,51 +183,42 @@ namespace IOB_WIN_NEXT B_input = byteSignals; } - /// - /// Restituisce status di lavorazione, hard coded dall'area di memoria 41108 - /// - protected int StatusLavoro - { - get - { - int answ = 0; - // hard coded - int statusReg = 41108; - if (HoldingRegisterLUT.ContainsKey(statusReg)) - { - int[] listInt = new int[2]; - listInt = HoldingRegisterLUT[statusReg]; - answ = ModbusClient.ConvertRegistersToInt(listInt); - } - return answ; - } - } - - /// - /// Restituisce status di emergenza, hard coded dall'area di allarmi - /// - protected bool EStop - { - get - { - bool answ = false; - int currStatus = 0; - // hard coded - int statusReg = 41094; - // deve avere allarmi (è un allarme EStop) - if (hasAlarms) - { - int[] listInt = new int[2]; - listInt = HoldingRegisterLUT[statusReg]; - currStatus = ModbusClient.ConvertRegistersToInt(listInt); - // hard coded il 5° bit - answ = ((currStatus & (1 << 4)) > 0); - } - return answ; - } - } - #endregion Protected Methods + #region Private Methods + + private void testBlockRead(int baseAddr, int numByte) + { + int baseHold = 41060; + int[] readTestFull = new int[50]; + lgTrace($"-------------------- Inizio test lettura {baseAddr} --------------------"); + try + { + stopwatch.Restart(); + readTestFull = currPLC.ReadHoldingRegisters(baseAddr - baseHold, numByte); + stopwatch.Stop(); + lgTrace($"Stats lettura | {readTestFull.Length} val | {stopwatch.ElapsedMilliseconds}ms"); + } + catch + { } + + for (int i = 0; i < readTestFull.Length / 2; i++) + { + int[] thisSet = new int[2]; + Array.Copy(readTestFull, i * 2, thisSet, 0, 2); + lgTrace($"{baseAddr + i * 2:000} | HoldingRegisters: {thisSet[0]} / {thisSet[1]} | Val Real: {ModbusClient.ConvertRegistersToFloat(thisSet):N6}"); + } + lgTrace("-------------------- Completato test lettura {baseAddr} --------------------"); + } + + private void testRead() + { + foreach (var item in memSetR) + { + testBlockRead(item.Key, item.Value); + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOSAI.cs b/IOB-WIN-NEXT/IobOSAI.cs index 23ee4c86..98b2b144 100644 --- a/IOB-WIN-NEXT/IobOSAI.cs +++ b/IOB-WIN-NEXT/IobOSAI.cs @@ -1,39 +1,16 @@ using CndexLinkDotNet; +using EgwProxy.OsaiCncLib; using IOB_UT_NEXT; using MapoSDK; using System; using System.Collections.Generic; using System.Net; using System.Net.NetworkInformation; -using EgwProxy.OsaiCncLib; namespace IOB_WIN_NEXT { public class IobOSAI : IobGeneric { - #region Private Fields - - /// - /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO - /// - private Dictionary signLUT = new Dictionary(); - - #endregion Private Fields - - #region Protected Fields - - /// - /// Struttura dati principale in continuo update... - /// - protected Cndex.GETINFO1DATA oData; - - /// - /// Oggetto MAIN x connessione OSAI - /// - protected ComCNOsai OSAI_ref; - - #endregion Protected Fields - #region Public Fields /// @@ -145,7 +122,8 @@ namespace IOB_WIN_NEXT lgInfo("OSAI: inizio gestione contapezzi"); try { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) { if (getOptPar("PZCOUNT_MODE").StartsWith("OVAR")) @@ -180,204 +158,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - private void decodeToBitmap() - { - // init a zero... - B_input = 0; - // SE SI E' CONNESSO al CNC allora è 1=powerON... - if (OSAI_ref.Connected) - { - B_input += 1 << 0; - } - - // decodifico impiegando dictionary... cercando il TIPO di memoria & co... - string bKey = ""; - string bVal = ""; - for (int i = 0; i < 8; i++) - { - bKey = string.Format("BIT{0}", i); - // cerco se ci sia in LUT - if (signLUT.ContainsKey(bKey)) - { - // recupero nome variabile... - bVal = signLUT[bKey]; - // se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI... - if (bVal.StartsWith("PZCOUNT")) - { - // procedo SOLO SE è enabled IOB - if (IobOnline) - { - try - { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrEmpty(currODL) || currODL == "0") - { - if (periodicLog) - { - lgInfo(string.Format("Osai | Lettura ODL andata a vuoto: currODL: {0}", currODL)); - } - } - else - { - lgInfo(string.Format("Osai | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); - // provo a salvare nuovo ODL - int.TryParse(currODL, out currIdxODL); - } - } - catch (Exception exc) - { - if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) - { - lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); - lastWarnODL = DateTime.Now; - } - } - } - else - { - // imposto currODL a vuoto! - currODL = ""; - if (periodicLog) - { - lgInfo($"OSAI | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); - } - } - if (!string.IsNullOrEmpty(currODL) && currODL != "0") - { - // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - // se sono differenti MOSTRO... - if (contapezziPLC != contapezziIOB) - { - // registro contapezzi - lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - // verifico se variato contapezzi in area STD PAR6711... e se passato ritardo minimo... - if (contapezziPLC > contapezziIOB) - { - // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio - contapezziIOB++; - needRefreshPzCount = true; - // salvo in semaforo! - B_input += 1 << 2; - // registro contapezzi - lgInfo($"contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - - // invio a server contapezzi (aggiornato) - string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK - if (retVal != contapezziIOB.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio Contapezzi OSAI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - else - { - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - } - // controllo le condizioni x costruire il bit1 RUN! - if (oData.mode_select == 2 && oData.status == 2) - { - B_input += 1 << 1; - } - // errore su bit3 - if (oData.mode_select == 6) - { - B_input += 1 << 3; - } - // auto su bit4 - if (oData.mode_select != 2) - { - B_input += 1 << 4; - } - // emergenza su bit5 - if (oData.mode_select == 9) - { - B_input += 1 << 5; - } - } - } - // log opzionale! - if (verboseLog) - { - lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); - } - } - - #endregion Private Methods - - #region Protected Methods - - /// - /// Decodifica del MODE selezionato - /// - /// - /// - protected static CNC_MODE decodeModeOsai(int mode) - { - CNC_MODE answ = CNC_MODE.ND; - switch (mode) - { - case 1: - answ = CNC_MODE.MDI; - break; - - case 2: - answ = CNC_MODE.AUTO; - break; - - case 3: - answ = CNC_MODE.SEMI; - break; - - case 4: - answ = CNC_MODE.JOG_MAN; - break; - - case 5: - answ = CNC_MODE.JOG_INC; - break; - - case 6: - answ = CNC_MODE.PROFILE; - break; - - case 7: - answ = CNC_MODE.HOME; - break; - - case 8: - answ = CNC_MODE.HANDLE_INC; - break; - - default: - break; - } - return answ; - } - - #endregion Protected Methods - #region Public Methods /// @@ -481,7 +261,8 @@ namespace IOB_WIN_NEXT { try { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) { string memAddr = getOptPar("PZCOUNT_MODE"); @@ -588,8 +369,8 @@ namespace IOB_WIN_NEXT } /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form /// public override void readSemafori(ref newDisplayData currDispData) { @@ -758,5 +539,229 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + /// + /// Struttura dati principale in continuo update... + /// + protected Cndex.GETINFO1DATA oData; + + /// + /// Oggetto MAIN x connessione OSAI + /// + protected ComCNOsai OSAI_ref; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// Decodifica del MODE selezionato + /// + /// + /// + protected static CNC_MODE decodeModeOsai(int mode) + { + CNC_MODE answ = CNC_MODE.ND; + switch (mode) + { + case 1: + answ = CNC_MODE.MDI; + break; + + case 2: + answ = CNC_MODE.AUTO; + break; + + case 3: + answ = CNC_MODE.SEMI; + break; + + case 4: + answ = CNC_MODE.JOG_MAN; + break; + + case 5: + answ = CNC_MODE.JOG_INC; + break; + + case 6: + answ = CNC_MODE.PROFILE; + break; + + case 7: + answ = CNC_MODE.HOME; + break; + + case 8: + answ = CNC_MODE.HANDLE_INC; + break; + + default: + break; + } + return answ; + } + + #endregion Protected Methods + + #region Private Fields + + /// + /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO + /// + private Dictionary signLUT = new Dictionary(); + + #endregion Private Fields + + #region Private Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + private void decodeToBitmap() + { + // init a zero... + B_input = 0; + // SE SI E' CONNESSO al CNC allora è 1=powerON... + if (OSAI_ref.Connected) + { + B_input += 1 << 0; + } + + // decodifico impiegando dictionary... cercando il TIPO di memoria & co... + string bKey = ""; + string bVal = ""; + for (int i = 0; i < 8; i++) + { + bKey = string.Format("BIT{0}", i); + // cerco se ci sia in LUT + if (signLUT.ContainsKey(bKey)) + { + // recupero nome variabile... + bVal = signLUT[bKey]; + // se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI... + if (bVal.StartsWith("PZCOUNT")) + { + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo(string.Format("Osai | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + } + } + else + { + lgInfo(string.Format("Osai | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + // provo a salvare nuovo ODL + int.TryParse(currODL, out currIdxODL); + } + } + catch (Exception exc) + { + if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) + { + lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); + lastWarnODL = DateTime.Now; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"OSAI | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + if (!string.IsNullOrEmpty(currODL) && currODL != "0") + { + // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni + // x distanziare invio e ridurre letture + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + // se sono differenti MOSTRO... + if (contapezziPLC != contapezziIOB) + { + // registro contapezzi + lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + // verifico se variato contapezzi in area STD PAR6711... e se + // passato ritardo minimo... + if (contapezziPLC > contapezziIOB) + { + // salvo nuovo contapezzi (incremento di 1...) + richiesta + // refresh conteggio + contapezziIOB++; + needRefreshPzCount = true; + // salvo in semaforo! + B_input += 1 << 2; + // registro contapezzi + lgInfo($"contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + + // invio a server contapezzi (aggiornato) + string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi OSAI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + } + // controllo le condizioni x costruire il bit1 RUN! + if (oData.mode_select == 2 && oData.status == 2) + { + B_input += 1 << 1; + } + // errore su bit3 + if (oData.mode_select == 6) + { + B_input += 1 << 3; + } + // auto su bit4 + if (oData.mode_select != 2) + { + B_input += 1 << 4; + } + // emergenza su bit5 + if (oData.mode_select == 9) + { + B_input += 1 << 5; + } + } + } + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOmron.cs b/IOB-WIN-NEXT/IobOmron.cs index 93e5dd6f..ec322109 100644 --- a/IOB-WIN-NEXT/IobOmron.cs +++ b/IOB-WIN-NEXT/IobOmron.cs @@ -10,64 +10,6 @@ namespace IOB_WIN_NEXT { public class IobOmron : IobGeneric { - #region Private Fields - - /// - /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO - /// - private Dictionary signLUT = new Dictionary(); - - #endregion Private Fields - - #region Protected Fields - - /// - /// Array valori letti da memoria CIO INGRESSI - /// - protected short[] memReadCIO_IN; - - /// - /// Array valori letti da memoria CIO USCITE - /// - protected short[] memReadCIO_OUT; - - /// - /// Array valori letti da memoria DM - /// - protected short[] memReadDM; - - /// - /// Array valori letti da memoria WR - /// - protected short[] memReadWR; - - /// - /// Array valori SCRITTI su memoria CIO - /// - protected short[] memWriteCIO; - - /// - /// Array valori SCRITTI su memoria DM - /// - protected short[] memWriteDM; - - /// - /// Array valori SCRITTI su memoria WR - /// - protected short[] memWriteWR; - - /// - /// Oggetto MAIN x connessione OMRON - /// - protected OmronFinsTCP.Net.EtherNetPLC OMRON_ref; - - /// - /// Array delle risposte dal controllo OMRON - /// - protected System.Collections.ArrayList resDataArray; - - #endregion Protected Fields - #region Public Constructors /// @@ -88,489 +30,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Properties - - /// - /// Lettura scrittura commessa da OMRON (come array di coppie di byte) - /// - protected string commessa - { - get - { - string answ = ""; - short[] response; - byte[] byteData = new byte[20]; - try - { - // leggo - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 10, out response); - // copio come byte... - Buffer.BlockCopy(response, 0, byteData, 0, response.Length); - answ = Encoding.ASCII.GetString(byteData); - } - catch - { } - return answ; - } - set - { - // converto in byte la mia stringa - byte[] valByte = Encoding.ASCII.GetBytes(value); - // limite 20 char... imposto a 20! - int maxChar = valByte.Length < 20 ? valByte.Length : 20; - // creao un array di 10 short MAX - short[] valoriWord = new short[10]; - // copio i valori - Buffer.BlockCopy(valByte, 0, valoriWord, 0, maxChar); - // scrivo su OMRON! - OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 10, valoriWord); - } - } - - /// - /// Verifico se abbia ALMENO un errore... - /// - protected bool hasError - { - get - { - bool answ = false; - if (memReadCIO_OUT != null) - { - answ = ((memReadCIO_OUT[4] & (1 << 7)) != 0); - } -#if false - bool answ = false; - // controllo primi errori, parto dal primo e poi OR - answ = answ || ((memReadCIO[0] & (1 << 7)) == 1); - answ = answ || ((memReadCIO[1] & (1 << 0)) == 1); - answ = answ || ((memReadCIO[1] & (1 << 1)) == 1); - answ = answ || ((memReadCIO[1] & (1 << 3)) == 1); - answ = answ || (memReadCIO[2] > 0); - answ = answ || ((memReadCIO[3] & (1 << 0)) == 1); - answ = answ || ((memReadCIO[3] & (1 << 1)) == 1); -#endif - return answ; - } - } - - /// - /// Oggetto get/set per lettura (DM22-23) /scrittura (DM26-27) PESO RICHIESTO - /// - protected int pesoRichiesto - { - get - { - int answ = 0; - try - { - short[] valDM; - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 22, 2, out valDM); - answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); - } - catch - { } - return answ; - } - set - { - short[] valDM = intToShort(value); - OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.DM, 26, 2, valDM); - // ora devo "comandare scrittura" su OMRON... - - // sollevo bit 65.0 x azzeramento - OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 1); - Thread.Sleep(500); - // ora sollevo bit e 65.1 x indicare nuovo valore... - OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 2); - // ora attendo ed abbasso tutti i bit - Thread.Sleep(500); - OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 0); - } - } - - /// - /// Oggetto per lettura PESO rilevato (DM20-21) - /// - protected int pesoRilevato - { - get - { - int answ = 0; - try - { - short[] valDM; - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 20, 2, out valDM); - // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) - // esempio 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] - answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); - } - catch - { } - return answ; - } - } - - /// - /// Oggetto get/set x portata - /// - protected int portata - { - get - { - int answ = 0; - try - { - short valDM; - OMRON_ref.ReadWord(OmronFinsTCP.Net.PlcMemory.DM, 50, out valDM); - answ = convDHD(valDM); - } - catch - { } - return answ; - } - set - { - // scrivo portata su memoria DM50... - short portata = (short)convHD("0x" + value.ToString("0000")); - OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.DM, 50, portata); - } - } - - /// - /// Oggetto get/set x quantità richiesta LOTTO - /// - protected int quantitaLotto - { - get - { - int answ = 0; - try - { - short[] valDM; - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 52, 2, out valDM); - answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); - } - catch - { } - return answ; - } - set - { - short[] valDM = intToShort(value); - OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.DM, 52, 2, valDM); - } - } - - #endregion Protected Properties - - #region Private Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - private void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - - /* ----------------------------------------------------- - * bitmap MAPO - * B0: POWER_ON - * B1: RUN - * B2: pzCount - * B3: allarme - * B4: manuale - * B5: carico SILOS - * B6: carico AUTOBOTTE - ----------------------------------------------------- */ - // bit 0 (poweron) imposto a 1 SE pingo... - B_input = testPingMachine == IPStatus.Success ? 1 : 0; - - bool caricoSilos = ((memReadCIO_IN[55] & (1 << 2)) != 0); - bool caricoAutobotte = ((memReadCIO_IN[50] & (1 << 2)) != 0); - // filtro DEVE ANDARE ma VIENE RILEVATO DOPO, POTREBEB andare da solo x scaricare... - bool runFiltro = ((memReadCIO_IN[0] & (1 << 1)) != 0); - - // RUN se CIO_bit 0.01 è RUN FILTRO... - if ((caricoAutobotte || caricoSilos)) - { - // SE HO carico silos OPPURE carico autobotte --> RUN - B_input += (1 << 1); - } - // ERROR generale (CORREGGERE!) - if (hasError) - { - B_input += (1 << 3); - } - - // carico SILOS - if (caricoSilos) - { - B_input += (1 << 5); - } - // carico AUTOBOTTE - if (caricoAutobotte) - { - B_input += (1 << 6); - } - - // procedo SOLO SE è enabled IOB - if (IobOnline) - { - try - { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrEmpty(currODL) || currODL == "0") - { - if (periodicLog) - { - lgInfo(string.Format("OMRON | Lettura ODL andata a vuoto: currODL: {0}", currODL)); - } - } - else - { - // se variato o scaduto timeout log... - if (periodicLog || (currIdxODL.ToString() != currODL)) - { - lgInfo(string.Format("OMRON | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); - } - // provo a salvare nuovo ODL - int.TryParse(currODL, out currIdxODL); - } - } - catch (Exception exc) - { - if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) - { - lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); - lastWarnODL = DateTime.Now; - } - } - } - else - { - // imposto currODL a vuoto! - currODL = ""; - if (periodicLog) - { - lgInfo($"Omron | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); - } - } - // log opzionale! - if (verboseLog) - { - lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); - } - } - - /// - /// Vera connessione ad OMRON - /// - /// - private short doConnect() - { - // avvio un oggetto di comunicazione OMRON - OMRON_ref = new OmronFinsTCP.Net.EtherNetPLC(); - short port = 9600; - short.TryParse(cIobConf.cncPort, out port); - lgInfo($"Chiamata apertura OMRON FINS: {cIobConf.cncIpAddr}:{port}"); - short esitoLink = OMRON_ref.Link(cIobConf.cncIpAddr, port, 500); - return esitoLink; - } - - /// - /// Test completo funzioni OMRON - /// - private void omronWriteTest() - { - commessa = "OMRON EDF TEST"; - - // scrivo portata - portata = 444; - - // scrivo pesatura richiesta - pesoRichiesto = 22222; - - // scrivo DM 52-53 del lotto richiesto - quantitaLotto = 66666; - } - - /// - /// Lettura e log valori x debug - /// - private void readAndLog() - { - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 0, 8, out memReadCIO_IN); - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 100, 8, out memReadCIO_OUT); - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 0, 8, out memReadDM); - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 8, out memReadWR); - - if (isVerboseLog) - { - lgInfo("Effettuata lettura dati CIO"); - foreach (var item in memReadCIO_IN) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - lgInfo("Effettuata lettura dati DM"); - foreach (var item in memReadDM) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - lgInfo("Effettuata lettura dati WR"); - foreach (var item in memReadWR) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - } - short[] respDM20; - short[] respDM22; - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 20, 2, out respDM20); - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 22, 2, out respDM22); - if (isVerboseLog) - { - // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) - lgInfo("Effettuata lettura dati respDM20"); - foreach (var item in respDM20) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - lgInfo("Effettuata lettura dati respDM22"); - foreach (var item in respDM22) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - } - } - - #endregion Private Methods - - #region Protected Methods - - /// - /// Calcola la conversione da byte --> num decimale --> HEX --> conversione come stringa in INT - /// - /// - /// - protected static int convDHD(short valore) - { - // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) - // esempio 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] - int answ = 0; - string hexVal = valore.ToString("x"); - int.TryParse(hexVal, out answ); - return answ; - } - - /// - /// Converte un valore di 2 short in un unico numero accostato: - /// es: legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) - /// 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] - /// - /// - /// - protected static int convFromHex(short[] valori) - { - int answ = 0; - string fullVal = $"{convDHD(valori[1]).ToString("D4")}{convDHD(valori[0]).ToString("D4")}"; - int.TryParse(fullVal, out answ); - return answ; - } - - /// - /// Calcola la conversione da INTERO a intero HEX x OMRON - /// - /// - /// - protected static int convHD(string hexVal) - { - int answ = 0; - if (!string.IsNullOrEmpty(hexVal)) - { - try - { - if (!hexVal.StartsWith("0x")) - { - hexVal = "0x" + hexVal; - } - answ = Convert.ToInt32(hexVal, 16); - } - catch - { } - } - return answ; - } - - /// - /// Converte un valore INT in un array di due SHORT valido x scrivere su OMRON - /// - /// - /// - protected static short[] intToShort(int value) - { - short[] valDM = new short[2]; - short highVal = (short)(value / 10000); - short lowVal = (short)(value - highVal * 10000); - valDM[0] = (short)convHD("0x" + lowVal.ToString("0000")); - valDM[1] = (short)convHD("0x" + highVal.ToString("0000")); - return valDM; - } - - /// - /// OVerride metodo x scrittura parametri su PLC - /// - /// - protected override void plcWriteParams(ref List updatedPar) - { - int valInt = 0; - if (updatedPar != null) - { - // controllo i parametri... ne gestisco 4... - foreach (var item in updatedPar) - { - lgInfo($"Richiesti processing plcWriteParams per {item.name} | valore richiesto {item.reqValue} | valore attuale {item.value}"); - string readBackVal = ""; - switch (item.uid) - { - case "kgRich": - int.TryParse(item.value, out valInt); - pesoRichiesto = valInt; - readBackVal = pesoRichiesto.ToString(); - break; - - case "kgLotto": - int.TryParse(item.value, out valInt); - quantitaLotto = valInt; - readBackVal = quantitaLotto.ToString(); - break; - - case "portata": - int.TryParse(item.value, out valInt); - portata = valInt; - readBackVal = portata.ToString(); - break; - - case "setComm": - commessa = item.value; - readBackVal = commessa; - break; - - default: - break; - } - // SE non corrispondessero LOGGO ERRORE... - if (item.value != readBackVal) - { - lgError($"Errore in plcWriteParams: uid {item.uid} | Wrote {item.value} | ReadBack {readBackVal}"); - } - } - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -605,7 +64,7 @@ namespace IOB_WIN_NEXT #if false try { - // hard coded... !!!FARE!!! rivedere megio conf + // hard coded... !!!FARE!!! rivedere megio conf contapezziPLC = pzCounter; // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) if (cIobConf.optPar.Count > 0 && getOptPar("PZCOUNT_MODE") != "") @@ -621,8 +80,8 @@ namespace IOB_WIN_NEXT } /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form /// public override void readSemafori(ref newDisplayData currDispData) { @@ -815,5 +274,552 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + /// + /// Array valori letti da memoria CIO INGRESSI + /// + protected short[] memReadCIO_IN; + + /// + /// Array valori letti da memoria CIO USCITE + /// + protected short[] memReadCIO_OUT; + + /// + /// Array valori letti da memoria DM + /// + protected short[] memReadDM; + + /// + /// Array valori letti da memoria WR + /// + protected short[] memReadWR; + + /// + /// Array valori SCRITTI su memoria CIO + /// + protected short[] memWriteCIO; + + /// + /// Array valori SCRITTI su memoria DM + /// + protected short[] memWriteDM; + + /// + /// Array valori SCRITTI su memoria WR + /// + protected short[] memWriteWR; + + /// + /// Oggetto MAIN x connessione OMRON + /// + protected OmronFinsTCP.Net.EtherNetPLC OMRON_ref; + + /// + /// Array delle risposte dal controllo OMRON + /// + protected System.Collections.ArrayList resDataArray; + + #endregion Protected Fields + + #region Protected Properties + + /// + /// Lettura scrittura commessa da OMRON (come array di coppie di byte) + /// + protected string commessa + { + get + { + string answ = ""; + short[] response; + byte[] byteData = new byte[20]; + try + { + // leggo + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 10, out response); + // copio come byte... + Buffer.BlockCopy(response, 0, byteData, 0, response.Length); + answ = Encoding.ASCII.GetString(byteData); + } + catch + { } + return answ; + } + set + { + // converto in byte la mia stringa + byte[] valByte = Encoding.ASCII.GetBytes(value); + // limite 20 char... imposto a 20! + int maxChar = valByte.Length < 20 ? valByte.Length : 20; + // creao un array di 10 short MAX + short[] valoriWord = new short[10]; + // copio i valori + Buffer.BlockCopy(valByte, 0, valoriWord, 0, maxChar); + // scrivo su OMRON! + OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 10, valoriWord); + } + } + + /// + /// Verifico se abbia ALMENO un errore... + /// + protected bool hasError + { + get + { + bool answ = false; + if (memReadCIO_OUT != null) + { + answ = ((memReadCIO_OUT[4] & (1 << 7)) != 0); + } +#if false + bool answ = false; + // controllo primi errori, parto dal primo e poi OR + answ = answ || ((memReadCIO[0] & (1 << 7)) == 1); + answ = answ || ((memReadCIO[1] & (1 << 0)) == 1); + answ = answ || ((memReadCIO[1] & (1 << 1)) == 1); + answ = answ || ((memReadCIO[1] & (1 << 3)) == 1); + answ = answ || (memReadCIO[2] > 0); + answ = answ || ((memReadCIO[3] & (1 << 0)) == 1); + answ = answ || ((memReadCIO[3] & (1 << 1)) == 1); +#endif + return answ; + } + } + + /// + /// Oggetto get/set per lettura (DM22-23) /scrittura (DM26-27) PESO RICHIESTO + /// + protected int pesoRichiesto + { + get + { + int answ = 0; + try + { + short[] valDM; + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 22, 2, out valDM); + answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); + } + catch + { } + return answ; + } + set + { + short[] valDM = intToShort(value); + OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.DM, 26, 2, valDM); + // ora devo "comandare scrittura" su OMRON... + + // sollevo bit 65.0 x azzeramento + OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 1); + Thread.Sleep(500); + // ora sollevo bit e 65.1 x indicare nuovo valore... + OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 2); + // ora attendo ed abbasso tutti i bit + Thread.Sleep(500); + OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 0); + } + } + + /// + /// Oggetto per lettura PESO rilevato (DM20-21) + /// + protected int pesoRilevato + { + get + { + int answ = 0; + try + { + short[] valDM; + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 20, 2, out valDM); + // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, + // dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) esempio + // 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su + // byte[0] e 1 su byte[1] + answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); + } + catch + { } + return answ; + } + } + + /// + /// Oggetto get/set x portata + /// + protected int portata + { + get + { + int answ = 0; + try + { + short valDM; + OMRON_ref.ReadWord(OmronFinsTCP.Net.PlcMemory.DM, 50, out valDM); + answ = convDHD(valDM); + } + catch + { } + return answ; + } + set + { + // scrivo portata su memoria DM50... + short portata = (short)convHD("0x" + value.ToString("0000")); + OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.DM, 50, portata); + } + } + + /// + /// Oggetto get/set x quantità richiesta LOTTO + /// + protected int quantitaLotto + { + get + { + int answ = 0; + try + { + short[] valDM; + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 52, 2, out valDM); + answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); + } + catch + { } + return answ; + } + set + { + short[] valDM = intToShort(value); + OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.DM, 52, 2, valDM); + } + } + + #endregion Protected Properties + + #region Protected Methods + + /// + /// Calcola la conversione da byte --> num decimale --> HEX --> conversione come + /// stringa in INT + /// + /// + /// + protected static int convDHD(short valore) + { + // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il + // primo è x 1 e il secondo x 10000 (in pratica va in testa) esempio 12540 --> diviso in + // 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] + int answ = 0; + string hexVal = valore.ToString("x"); + int.TryParse(hexVal, out answ); + return answ; + } + + /// + /// Converte un valore di 2 short in un unico numero accostato: + /// es: legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il + /// primo è x 1 e il secondo x 10000 (in pratica va in testa) 12540 --> diviso in 1 | + /// 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] + /// + /// + /// + protected static int convFromHex(short[] valori) + { + int answ = 0; + string fullVal = $"{convDHD(valori[1]).ToString("D4")}{convDHD(valori[0]).ToString("D4")}"; + int.TryParse(fullVal, out answ); + return answ; + } + + /// + /// Calcola la conversione da INTERO a intero HEX x OMRON + /// + /// + /// + protected static int convHD(string hexVal) + { + int answ = 0; + if (!string.IsNullOrEmpty(hexVal)) + { + try + { + if (!hexVal.StartsWith("0x")) + { + hexVal = "0x" + hexVal; + } + answ = Convert.ToInt32(hexVal, 16); + } + catch + { } + } + return answ; + } + + /// + /// Converte un valore INT in un array di due SHORT valido x scrivere su OMRON + /// + /// + /// + protected static short[] intToShort(int value) + { + short[] valDM = new short[2]; + short highVal = (short)(value / 10000); + short lowVal = (short)(value - highVal * 10000); + valDM[0] = (short)convHD("0x" + lowVal.ToString("0000")); + valDM[1] = (short)convHD("0x" + highVal.ToString("0000")); + return valDM; + } + + /// + /// OVerride metodo x scrittura parametri su PLC + /// + /// + protected override void plcWriteParams(ref List updatedPar) + { + int valInt = 0; + if (updatedPar != null) + { + // controllo i parametri... ne gestisco 4... + foreach (var item in updatedPar) + { + lgInfo($"Richiesti processing plcWriteParams per {item.name} | valore richiesto {item.reqValue} | valore attuale {item.value}"); + string readBackVal = ""; + switch (item.uid) + { + case "kgRich": + int.TryParse(item.value, out valInt); + pesoRichiesto = valInt; + readBackVal = pesoRichiesto.ToString(); + break; + + case "kgLotto": + int.TryParse(item.value, out valInt); + quantitaLotto = valInt; + readBackVal = quantitaLotto.ToString(); + break; + + case "portata": + int.TryParse(item.value, out valInt); + portata = valInt; + readBackVal = portata.ToString(); + break; + + case "setComm": + commessa = item.value; + readBackVal = commessa; + break; + + default: + break; + } + // SE non corrispondessero LOGGO ERRORE... + if (item.value != readBackVal) + { + lgError($"Errore in plcWriteParams: uid {item.uid} | Wrote {item.value} | ReadBack {readBackVal}"); + } + } + } + } + + #endregion Protected Methods + + #region Private Fields + + /// + /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO + /// + private Dictionary signLUT = new Dictionary(); + + #endregion Private Fields + + #region Private Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + private void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + + /* ----------------------------------------------------- + * bitmap MAPO + * B0: POWER_ON + * B1: RUN + * B2: pzCount + * B3: allarme + * B4: manuale + * B5: carico SILOS + * B6: carico AUTOBOTTE + ----------------------------------------------------- */ + // bit 0 (poweron) imposto a 1 SE pingo... + B_input = testPingMachine == IPStatus.Success ? 1 : 0; + + bool caricoSilos = ((memReadCIO_IN[55] & (1 << 2)) != 0); + bool caricoAutobotte = ((memReadCIO_IN[50] & (1 << 2)) != 0); + // filtro DEVE ANDARE ma VIENE RILEVATO DOPO, POTREBEB andare da solo x scaricare... + bool runFiltro = ((memReadCIO_IN[0] & (1 << 1)) != 0); + + // RUN se CIO_bit 0.01 è RUN FILTRO... + if ((caricoAutobotte || caricoSilos)) + { + // SE HO carico silos OPPURE carico autobotte --> RUN + B_input += (1 << 1); + } + // ERROR generale (CORREGGERE!) + if (hasError) + { + B_input += (1 << 3); + } + + // carico SILOS + if (caricoSilos) + { + B_input += (1 << 5); + } + // carico AUTOBOTTE + if (caricoAutobotte) + { + B_input += (1 << 6); + } + + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo(string.Format("OMRON | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + } + } + else + { + // se variato o scaduto timeout log... + if (periodicLog || (currIdxODL.ToString() != currODL)) + { + lgInfo(string.Format("OMRON | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + } + // provo a salvare nuovo ODL + int.TryParse(currODL, out currIdxODL); + } + } + catch (Exception exc) + { + if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) + { + lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); + lastWarnODL = DateTime.Now; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"Omron | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); + } + } + + /// + /// Vera connessione ad OMRON + /// + /// + private short doConnect() + { + // avvio un oggetto di comunicazione OMRON + OMRON_ref = new OmronFinsTCP.Net.EtherNetPLC(); + short port = 9600; + short.TryParse(cIobConf.cncPort, out port); + lgInfo($"Chiamata apertura OMRON FINS: {cIobConf.cncIpAddr}:{port}"); + short esitoLink = OMRON_ref.Link(cIobConf.cncIpAddr, port, 500); + return esitoLink; + } + + /// + /// Test completo funzioni OMRON + /// + private void omronWriteTest() + { + commessa = "OMRON EDF TEST"; + + // scrivo portata + portata = 444; + + // scrivo pesatura richiesta + pesoRichiesto = 22222; + + // scrivo DM 52-53 del lotto richiesto + quantitaLotto = 66666; + } + + /// + /// Lettura e log valori x debug + /// + private void readAndLog() + { + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 0, 8, out memReadCIO_IN); + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 100, 8, out memReadCIO_OUT); + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 0, 8, out memReadDM); + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 8, out memReadWR); + + if (isVerboseLog) + { + lgInfo("Effettuata lettura dati CIO"); + foreach (var item in memReadCIO_IN) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + lgInfo("Effettuata lettura dati DM"); + foreach (var item in memReadDM) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + lgInfo("Effettuata lettura dati WR"); + foreach (var item in memReadWR) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + } + short[] respDM20; + short[] respDM22; + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 20, 2, out respDM20); + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 22, 2, out respDM22); + if (isVerboseLog) + { + // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove + // il primo è x 1 e il secondo x 10000 (in pratica va in testa) + lgInfo("Effettuata lettura dati respDM20"); + foreach (var item in respDM20) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + lgInfo("Effettuata lettura dati respDM22"); + foreach (var item in respDM22) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOpcUa.cs b/IOB-WIN-NEXT/IobOpcUa.cs index 8d5d4675..5f21d2cb 100644 --- a/IOB-WIN-NEXT/IobOpcUa.cs +++ b/IOB-WIN-NEXT/IobOpcUa.cs @@ -29,6 +29,12 @@ namespace IOB_WIN_NEXT // gestione invio ritardato contapezzi pzCountDelay = utils.CRI("pzCountDelay"); + // gestione restart OpcUa client... + if (!string.IsNullOrEmpty(getOptPar("MAX_TRY_PING"))) + { + int.TryParse(getOptPar("MAX_TRY_PING"), out maxTryPing); + } + enablePzCountByApp = utils.CRB("enableContapezzi"); enablePzCountByIob = (getOptPar("ENABLE_PZCOUNT") == "TRUE"); disablePzCounteByIob = (getOptPar("DISABLE_PZCOUNT") == "TRUE"); @@ -476,6 +482,35 @@ namespace IOB_WIN_NEXT return changed; } + internal void procRunMode(ref string currRun) + { + // variabili RUN... se richiesto invio runMode + if (opcUaParams.runModeSend) + { + if (!string.IsNullOrEmpty(opcUaParams.keyRunMode)) + { + currRun = getDataItemValue(opcUaParams.keyRunMode); + if (!string.IsNullOrEmpty(currRun)) + { + // se ho valore --> invio + string sVal = ""; + string descr = $"RunModeVal"; + DateTime locTStamp = DateTime.Now; + sVal = $"Change: {locTStamp.ToString()} | descr: {descr} | Id: {opcUaParams.keyRunMode} | Val: {currRun}"; + accodaFLog(sVal, qEncodeFLog(descr, currRun)); + + // se richiesto provo a tradurre + if (opcUaParams.runModeTrad) + { + string RunModeDescr = itemTranslation("RunMode", currRun); + descr = $"RunMode"; + accodaFLog(sVal, qEncodeFLog(descr, RunModeDescr)); + } + } + } + } + } + internal void sendDataItemListToServer(NodeId StartNodeId) { // converto gli attuali nell'elenco dataitem... @@ -922,16 +957,29 @@ namespace IOB_WIN_NEXT // se valido il check ping lo eseguo... altrimenti lo do x buono bool checkPing = !opcUaParams.pingAsPowerOn; string currRun = ""; - if (!checkPing) + int currTryPing = maxTryPing; + while (currTryPing > 0 && !checkPing) { - checkPing = (testPingMachine == IPStatus.Success); + if (!checkPing) + { + checkPing = (testPingMachine == IPStatus.Success); + } + currTryPing--; + // se ping KO --> aspetto prima di ripetere test + if (!checkPing) + { + Random rand = new Random(); + Thread.Sleep(rand.Next(pingServerMsTimeout * 2)); + } } + // bit 0 (poweron) imposto a 1 SE pingo + PowerOn=="ON"... bool powerOnOk = checkPing && hasPowerOn; // controllo se sono poweroff e se non ho dati buoni da > lastCurrentMaxElapsed --> disconnetto - if (!powerOnOk && adesso.Subtract(lastCurrent).TotalSeconds > lastCurrentMaxElapsed) + if (!powerOnOk && (adesso.Subtract(lastCurrent).TotalSeconds > lastCurrentMaxElapsed)) { + lgInfo("Timeout per mencata comunicazione --> disconnessione adapter OpcUa!"); tryDisconnect(); } @@ -1113,7 +1161,7 @@ namespace IOB_WIN_NEXT application.ApplicationType = ApplicationType.Client; // load the application configuration. - string confPath = $"{Application.StartupPath}\\DATA\\CONF\\IobOpcUaClient.Config.xml"; + string confPath = $"{Application.StartupPath}\\DATA\\IobOpcUaClient.Config.xml"; await application.LoadApplicationConfiguration(confPath, silent: false).ConfigureAwait(false); // check the application certificate. await application.CheckApplicationInstanceCertificate(silent: false, minimumKeySize: 0).ConfigureAwait(false); diff --git a/IOB-WIN-NEXT/IobOpcUaCMS.cs b/IOB-WIN-NEXT/IobOpcUaCMS.cs index 4a0eb835..c7a37b46 100644 --- a/IOB-WIN-NEXT/IobOpcUaCMS.cs +++ b/IOB-WIN-NEXT/IobOpcUaCMS.cs @@ -3,26 +3,12 @@ using Newtonsoft.Json; using Opc.Ua; using System; using System.Collections.Generic; -using System.Linq; using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { public class IobOpcUaCMS : IobOpcUa { - #region Protected Fields - - /// - /// Modalità cambio ODL - /// - protected string CHANGE_ODL_MODE = ""; - - protected bool testDone = false; - - #endregion Protected Fields - #region Public Constructors /// @@ -44,6 +30,113 @@ namespace IOB_WIN_NEXT #endregion Public Constructors + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // uso metodo base x ora + return base.executeTasks(task2exe); + } + + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + // check condizione validazione + if (checkMultiCondition(opcUaParams.condCountEnabled) || opcUaParams.condCountEnabled.checkList.Count == 0) + { + // cerco parametro contapezzi... + string currPzCount = getDataItemValue(opcUaParams.keyPartCount); + + // se ho un contapezzi... processo... + if (!string.IsNullOrEmpty(currPzCount)) + { + int newVal = -1; + bool fatto = Int32.TryParse(currPzCount, out newVal); + + if (fatto) + { + // gestione decremento contapezzi: viene "messo via" solo SE c'è un + // effettivo decremento contapezzi... + if (newVal < contapezziPLC) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC) --> pzCountResetted = true"); + } + + // salvo nuovo valore contapezziPLC + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + else + { + lgError($"Errore in decodifica valore contapezzi, valore rilevato: {currPzCount}"); + } + } + else + { + lgError($"Errore in decodifica valore contapezzi da {opcUaParams.keyPartCount} | valore vuoto!"); + } + } + + if (CHANGE_ODL_MODE == "PZCOUNT_RESET") + { + // controllo comunque, se è ZERO il contapezzi, e sul server è maggiore il + // valore x ODL e NON abilitato il trigger reset --> abilito trigger... + if (!pzCountResetted && contapezziPLC == 0 && contapezziIOB > 0) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC==0 e IOB>PLC) --> pzCountResetted = true"); + } + } + } + } + + /// + /// Effettua reset del contapezzi, NON POSSIBILE in questa versione + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; + return answ; + } + + /// + /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE in questa versione + /// + /// + public override bool setcontapezziPLC(int newPzCount) + { + bool answ = false; + return answ; + } + + #endregion Public Methods + + #region Protected Fields + + /// + /// Modalità cambio ODL + /// + protected string CHANGE_ODL_MODE = ""; + + protected bool testDone = false; + + #endregion Protected Fields + #region Protected Methods /// @@ -85,6 +178,27 @@ namespace IOB_WIN_NEXT // variabili RUN... currRun = getDataItemValue(opcUaParams.keyRunMode); + // variabili RUN... se richiesto invio runMode + if (opcUaParams.runModeSend) + { + if (!string.IsNullOrEmpty(currRun)) + { + // se ho valore --> invio + string sVal = ""; + string descr = $"RunModeVal"; + DateTime locTStamp = DateTime.Now; + sVal = $"Change: {locTStamp.ToString()} | descr: {descr} | Id: {opcUaParams.keyRunMode} | Val: {currRun}"; + accodaFLog(sVal, qEncodeFLog(descr, currRun)); + + // se richiesto provo a tradurre + if (opcUaParams.runModeTrad) + { + string RunModeDescr = itemTranslation("RunMode", currRun); + descr = $"RunMode"; + accodaFLog(sVal, qEncodeFLog(descr, RunModeDescr)); + } + } + } // salvo running come = working... isRunning = isWorking; @@ -274,99 +388,5 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods - - #region Public Methods - - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - // uso metodo base x ora - return base.executeTasks(task2exe); - } - - /// - /// Effettua vero processing contapezzi - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { - // check condizione validazione - if (checkMultiCondition(opcUaParams.condCountEnabled) || opcUaParams.condCountEnabled.checkList.Count == 0) - { - // cerco parametro contapezzi... - string currPzCount = getDataItemValue(opcUaParams.keyPartCount); - - // se ho un contapezzi... processo... - if (!string.IsNullOrEmpty(currPzCount)) - { - int newVal = -1; - bool fatto = Int32.TryParse(currPzCount, out newVal); - - if (fatto) - { - // gestione decremento contapezzi: viene "messo via" solo SE c'è un effettivo decremento contapezzi... - if (newVal < contapezziPLC) - { - pzCountResetted = true; - // incremento contatore richiesta - countKeyRichiesta = countKeyRichiesta + 1; - // log - lgInfo("Contapezzi resettato (PLC) --> pzCountResetted = true"); - } - - // salvo nuovo valore contapezziPLC - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - } - else - { - lgError($"Errore in decodifica valore contapezzi, valore rilevato: {currPzCount}"); - } - } - else - { - lgError($"Errore in decodifica valore contapezzi da {opcUaParams.keyPartCount} | valore vuoto!"); - } - } - - if (CHANGE_ODL_MODE == "PZCOUNT_RESET") - { - // controllo comunque, se è ZERO il contapezzi, e sul server è maggiore il valore x ODL e NON abilitato il trigger reset --> abilito trigger... - if (!pzCountResetted && contapezziPLC == 0 && contapezziIOB > 0) - { - pzCountResetted = true; - // incremento contatore richiesta - countKeyRichiesta = countKeyRichiesta + 1; - // log - lgInfo("Contapezzi resettato (PLC==0 e IOB>PLC) --> pzCountResetted = true"); - } - } - } - } - - /// - /// Effettua reset del contapezzi, NON POSSIBILE in questa versione - /// - /// - public override bool resetcontapezziPLC() - { - bool answ = false; - return answ; - } - - /// - /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE in questa versione - /// - /// - public override bool setcontapezziPLC(int newPzCount) - { - bool answ = false; - return answ; - } - - #endregion Public Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOpcUaEwon.cs b/IOB-WIN-NEXT/IobOpcUaEwon.cs index 42208645..4c111292 100644 --- a/IOB-WIN-NEXT/IobOpcUaEwon.cs +++ b/IOB-WIN-NEXT/IobOpcUaEwon.cs @@ -3,26 +3,12 @@ using Newtonsoft.Json; using Opc.Ua; using System; using System.Collections.Generic; -using System.Linq; using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { public class IobOpcUaEwon : IobOpcUa { - #region Protected Fields - - /// - /// Modalità cambio ODL - /// - protected string CHANGE_ODL_MODE = ""; - - protected bool testDone = false; - - #endregion Protected Fields - #region Public Constructors /// @@ -43,6 +29,113 @@ namespace IOB_WIN_NEXT #endregion Public Constructors + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // uso metodo base x ora + return base.executeTasks(task2exe); + } + + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + // check condizione validazione + if (checkMultiCondition(opcUaParams.condCountEnabled) || opcUaParams.condCountEnabled.checkList.Count == 0) + { + // cerco parametro contapezzi... + string currPzCount = getDataItemValue(opcUaParams.keyPartCount); + + // se ho un contapezzi... processo... + if (!string.IsNullOrEmpty(currPzCount)) + { + int newVal = -1; + bool fatto = Int32.TryParse(currPzCount, out newVal); + + if (fatto) + { + // gestione decremento contapezzi: viene "messo via" solo SE c'è un + // effettivo decremento contapezzi... + if (newVal < contapezziPLC) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC) --> pzCountResetted = true"); + } + + // salvo nuovo valore contapezziPLC + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + else + { + lgError($"Errore in decodifica valore contapezzi, valore rilevato: {currPzCount}"); + } + } + else + { + lgError("Errore in decodifica valore contapezzi, valore vuoto!"); + } + } + + if (CHANGE_ODL_MODE == "PZCOUNT_RESET") + { + // controllo comunque, se è ZERO il contapezzi, e sul server è maggiore il + // valore x ODL e NON abilitato il trigger reset --> abilito trigger... + if (!pzCountResetted && contapezziPLC == 0 && contapezziIOB > 0) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC==0 e IOB>PLC) --> pzCountResetted = true"); + } + } + } + } + + /// + /// Effettua reset del contapezzi, NON POSSIBILE in questa versione + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; + return answ; + } + + /// + /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE in questa versione + /// + /// + public override bool setcontapezziPLC(int newPzCount) + { + bool answ = false; + return answ; + } + + #endregion Public Methods + + #region Protected Fields + + /// + /// Modalità cambio ODL + /// + protected string CHANGE_ODL_MODE = ""; + + protected bool testDone = false; + + #endregion Protected Fields + #region Protected Methods /// @@ -82,11 +175,15 @@ namespace IOB_WIN_NEXT { B_input = powerOnOk ? 1 : 0; +#if false // variabili RUN... if (!string.IsNullOrEmpty(opcUaParams.keyRunMode)) { currRun = getDataItemValue(opcUaParams.keyRunMode); } +#endif + + procRunMode(ref currRun); // salvo running come = working... isRunning = isWorking; @@ -137,7 +234,7 @@ namespace IOB_WIN_NEXT List nodes2Write = new List(); nodes2Write.Add(commWriteVal); - + UA_ref.WriteNodes(nodes2Write); } catch (Exception exc) @@ -271,99 +368,5 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods - - #region Public Methods - - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - // uso metodo base x ora - return base.executeTasks(task2exe); - } - - /// - /// Effettua vero processing contapezzi - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { - // check condizione validazione - if (checkMultiCondition(opcUaParams.condCountEnabled) || opcUaParams.condCountEnabled.checkList.Count == 0) - { - // cerco parametro contapezzi... - string currPzCount = getDataItemValue(opcUaParams.keyPartCount); - - // se ho un contapezzi... processo... - if (!string.IsNullOrEmpty(currPzCount)) - { - int newVal = -1; - bool fatto = Int32.TryParse(currPzCount, out newVal); - - if (fatto) - { - // gestione decremento contapezzi: viene "messo via" solo SE c'è un effettivo decremento contapezzi... - if (newVal < contapezziPLC) - { - pzCountResetted = true; - // incremento contatore richiesta - countKeyRichiesta = countKeyRichiesta + 1; - // log - lgInfo("Contapezzi resettato (PLC) --> pzCountResetted = true"); - } - - // salvo nuovo valore contapezziPLC - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - } - else - { - lgError($"Errore in decodifica valore contapezzi, valore rilevato: {currPzCount}"); - } - } - else - { - lgError("Errore in decodifica valore contapezzi, valore vuoto!"); - } - } - - if (CHANGE_ODL_MODE == "PZCOUNT_RESET") - { - // controllo comunque, se è ZERO il contapezzi, e sul server è maggiore il valore x ODL e NON abilitato il trigger reset --> abilito trigger... - if (!pzCountResetted && contapezziPLC == 0 && contapezziIOB > 0) - { - pzCountResetted = true; - // incremento contatore richiesta - countKeyRichiesta = countKeyRichiesta + 1; - // log - lgInfo("Contapezzi resettato (PLC==0 e IOB>PLC) --> pzCountResetted = true"); - } - } - } - } - - /// - /// Effettua reset del contapezzi, NON POSSIBILE in questa versione - /// - /// - public override bool resetcontapezziPLC() - { - bool answ = false; - return answ; - } - - /// - /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE in questa versione - /// - /// - public override bool setcontapezziPLC(int newPzCount) - { - bool answ = false; - return answ; - } - - #endregion Public Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOpcUaEwonBLM.cs b/IOB-WIN-NEXT/IobOpcUaEwonBLM.cs index ff46d3d3..b931accf 100644 --- a/IOB-WIN-NEXT/IobOpcUaEwonBLM.cs +++ b/IOB-WIN-NEXT/IobOpcUaEwonBLM.cs @@ -1,22 +1,10 @@ using MapoSDK; -using Newtonsoft.Json; -using Opc.Ua; -using System; using System.Collections.Generic; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { public class IobOpcUaEwonBLM : IobOpcUaEwon { - #region Protected Fields - - - #endregion Protected Fields - #region Public Constructors /// @@ -37,6 +25,10 @@ namespace IOB_WIN_NEXT sendKeyRichiesta = true; } + #endregion Public Constructors + + #region Protected Methods + /// /// Effettua vera scrittura parametri /// @@ -49,7 +41,8 @@ namespace IOB_WIN_NEXT if (opcUaParams.SetupConf.SetupMode == IOB_UT_NEXT.MachineSetupMode.MECOLPRESS) { List nodes2Write = new List(); - // faccio un check tra i valori in memoria che devono corrispondere e se NON corrispondono --> metto valore in scrittura... + // faccio un check tra i valori in memoria che devono corrispondere e se NON + // corrispondono --> metto valore in scrittura... int numDiff = 0; foreach (var item in opcUaParams.SetupConf.checkParList) { @@ -98,11 +91,10 @@ namespace IOB_WIN_NEXT UA_ref.WriteNodes(nodes2Write); } } - } + } #endif } - #endregion Public Constructors - + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOpcUaEwonMecolpress.cs b/IOB-WIN-NEXT/IobOpcUaEwonMecolpress.cs index 6d88f79b..790f3c6a 100644 --- a/IOB-WIN-NEXT/IobOpcUaEwonMecolpress.cs +++ b/IOB-WIN-NEXT/IobOpcUaEwonMecolpress.cs @@ -1,22 +1,12 @@ using MapoSDK; -using Newtonsoft.Json; using Opc.Ua; -using System; using System.Collections.Generic; using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { public class IobOpcUaEwonMecolpress : IobOpcUaEwon { - #region Protected Fields - - - #endregion Protected Fields - #region Public Constructors /// @@ -37,6 +27,10 @@ namespace IOB_WIN_NEXT sendKeyRichiesta = true; } + #endregion Public Constructors + + #region Protected Methods + /// /// Effettua vera scrittura parametri /// @@ -49,7 +43,8 @@ namespace IOB_WIN_NEXT if (opcUaParams.SetupConf.SetupMode == IOB_UT_NEXT.MachineSetupMode.MECOLPRESS) { List nodes2Write = new List(); - // faccio un check tra i valori in memoria che devono corrispondere e se NON corrispondono --> metto valore in scrittura... + // faccio un check tra i valori in memoria che devono corrispondere e se NON + // corrispondono --> metto valore in scrittura... int numDiff = 0; foreach (var item in opcUaParams.SetupConf.checkParList) { @@ -86,7 +81,7 @@ namespace IOB_WIN_NEXT // accodo x scrittura nodes2Write.Add(commWriteVal); - lgInfo($"richiesta scrittura valore | nodeId: {commWriteVal.NodeId } | targetPar: {item.TargetParam} | val {commWriteVal.Value.Value}"); + lgInfo($"richiesta scrittura valore | nodeId: {commWriteVal.NodeId} | targetPar: {item.TargetParam} | val {commWriteVal.Value.Value}"); } // x ora NON eseguo @@ -101,7 +96,6 @@ namespace IOB_WIN_NEXT } } - #endregion Public Constructors - + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOpcUaEwonMonti.cs b/IOB-WIN-NEXT/IobOpcUaEwonMonti.cs index 1c7d81a6..b75e1f88 100644 --- a/IOB-WIN-NEXT/IobOpcUaEwonMonti.cs +++ b/IOB-WIN-NEXT/IobOpcUaEwonMonti.cs @@ -31,6 +31,72 @@ namespace IOB_WIN_NEXT #endregion Public Constructors + #region Public Methods + + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + // check condizione validazione + if (checkMultiCondition(opcUaParams.condCountEnabled) || opcUaParams.condCountEnabled.checkList.Count == 0) + { + // cerco parametro contapezzi... + string currPzCount = getDataItemValue(opcUaParams.keyPartCount); + + // se ho un contapezzi... processo... + if (!string.IsNullOrEmpty(currPzCount)) + { + int newVal = -1; + bool fatto = Int32.TryParse(currPzCount, out newVal); + + if (fatto) + { + // gestione decremento contapezzi: viene "messo via" solo SE c'è un + // effettivo decremento contapezzi... + if (newVal < contapezziPLC) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC) --> pzCountResetted = true"); + } + + // salvo nuovo valore contapezziPLC + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + else + { + lgError($"Errore in decodifica valore contapezzi, valore rilevato: {currPzCount}"); + } + } + else + { + lgError("Errore in decodifica valore contapezzi, valore vuoto!"); + } + } + + if (CHANGE_ODL_MODE == "PZCOUNT_RESET") + { + // controllo comunque, se è ZERO il contapezzi, e sul server è maggiore il + // valore x ODL e NON abilitato il trigger reset --> abilito trigger... + if (!pzCountResetted && contapezziPLC == 0 && contapezziIOB > 0) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC==0 e IOB>PLC) --> pzCountResetted = true"); + } + } + } + } + + #endregion Public Methods + #region Protected Methods /// @@ -151,69 +217,5 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods - - #region Public Methods - - /// - /// Effettua vero processing contapezzi - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { - // check condizione validazione - if (checkMultiCondition(opcUaParams.condCountEnabled) || opcUaParams.condCountEnabled.checkList.Count == 0) - { - // cerco parametro contapezzi... - string currPzCount = getDataItemValue(opcUaParams.keyPartCount); - - // se ho un contapezzi... processo... - if (!string.IsNullOrEmpty(currPzCount)) - { - int newVal = -1; - bool fatto = Int32.TryParse(currPzCount, out newVal); - - if (fatto) - { - // gestione decremento contapezzi: viene "messo via" solo SE c'è un effettivo decremento contapezzi... - if (newVal < contapezziPLC) - { - pzCountResetted = true; - // incremento contatore richiesta - countKeyRichiesta = countKeyRichiesta + 1; - // log - lgInfo("Contapezzi resettato (PLC) --> pzCountResetted = true"); - } - - // salvo nuovo valore contapezziPLC - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - } - else - { - lgError($"Errore in decodifica valore contapezzi, valore rilevato: {currPzCount}"); - } - } - else - { - lgError("Errore in decodifica valore contapezzi, valore vuoto!"); - } - } - - if (CHANGE_ODL_MODE == "PZCOUNT_RESET") - { - // controllo comunque, se è ZERO il contapezzi, e sul server è maggiore il valore x ODL e NON abilitato il trigger reset --> abilito trigger... - if (!pzCountResetted && contapezziPLC == 0 && contapezziIOB > 0) - { - pzCountResetted = true; - // incremento contatore richiesta - countKeyRichiesta = countKeyRichiesta + 1; - // log - lgInfo("Contapezzi resettato (PLC==0 e IOB>PLC) --> pzCountResetted = true"); - } - } - } - } - - #endregion Public Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOpcUaMBH.cs b/IOB-WIN-NEXT/IobOpcUaMBH.cs index 13e53759..09569b65 100644 --- a/IOB-WIN-NEXT/IobOpcUaMBH.cs +++ b/IOB-WIN-NEXT/IobOpcUaMBH.cs @@ -176,11 +176,34 @@ namespace IOB_WIN_NEXT { B_input = powerOnOk ? 1 : 0; - // variabili RUN... - if (!string.IsNullOrEmpty(opcUaParams.keyRunMode)) + procRunMode(ref currRun); +#if false + // variabili RUN... se richiesto invio runMode + if (opcUaParams.runModeSend) { - currRun = getDataItemValue(opcUaParams.keyRunMode); + if (!string.IsNullOrEmpty(opcUaParams.keyRunMode)) + { + currRun = getDataItemValue(opcUaParams.keyRunMode); + if (!string.IsNullOrEmpty(currRun)) + { + // se ho valore --> invio + string sVal = ""; + string descr = $"RunModeVal"; + DateTime locTStamp = DateTime.Now; + sVal = $"Change: {locTStamp.ToString()} | descr: {descr} | Id: {opcUaParams.keyRunMode} | Val: {currRun}"; + accodaFLog(sVal, qEncodeFLog(descr, currRun)); + + // se richiesto provo a tradurre + if (opcUaParams.runModeTrad) + { + string RunModeDescr = itemTranslation("RunMode", currRun); + descr = $"RunMode"; + accodaFLog(sVal, qEncodeFLog(descr, RunModeDescr)); + } + } + } } +#endif // salvo running come = working... isRunning = isWorking; diff --git a/IOB-WIN-NEXT/IobOpcUaMBHCimolai.cs b/IOB-WIN-NEXT/IobOpcUaMBHCimolai.cs index 4693511d..81585114 100644 --- a/IOB-WIN-NEXT/IobOpcUaMBHCimolai.cs +++ b/IOB-WIN-NEXT/IobOpcUaMBHCimolai.cs @@ -111,6 +111,14 @@ namespace IOB_WIN_NEXT return writeResult; } + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + // non fa nulal (non ha contapezzi) + } + public override bool resetcontapezziPLC() { bool answ = false; diff --git a/IOB-WIN-NEXT/IobOpcUaOmron.cs b/IOB-WIN-NEXT/IobOpcUaOmron.cs index e3a109d5..4d31c719 100644 --- a/IOB-WIN-NEXT/IobOpcUaOmron.cs +++ b/IOB-WIN-NEXT/IobOpcUaOmron.cs @@ -3,26 +3,12 @@ using Newtonsoft.Json; using Opc.Ua; using System; using System.Collections.Generic; -using System.Linq; using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { public class IobOpcUaOmron : IobOpcUa { - #region Protected Fields - - /// - /// Modalità cambio ODL - /// - protected string CHANGE_ODL_MODE = ""; - - protected bool testDone = false; - - #endregion Protected Fields - #region Public Constructors /// @@ -43,6 +29,113 @@ namespace IOB_WIN_NEXT #endregion Public Constructors + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // uso metodo base x ora + return base.executeTasks(task2exe); + } + + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + // check condizione validazione + if (checkMultiCondition(opcUaParams.condCountEnabled) || opcUaParams.condCountEnabled.checkList.Count == 0) + { + // cerco parametro contapezzi... + string currPzCount = getDataItemValue(opcUaParams.keyPartCount); + + // se ho un contapezzi... processo... + if (!string.IsNullOrEmpty(currPzCount)) + { + int newVal = -1; + bool fatto = Int32.TryParse(currPzCount, out newVal); + + if (fatto) + { + // gestione decremento contapezzi: viene "messo via" solo SE c'è un + // effettivo decremento contapezzi... + if (newVal < contapezziPLC) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC) --> pzCountResetted = true"); + } + + // salvo nuovo valore contapezziPLC + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + else + { + lgError($"Errore in decodifica valore contapezzi, valore rilevato: {currPzCount}"); + } + } + else + { + lgError("Errore in decodifica valore contapezzi, valore vuoto!"); + } + } + + if (CHANGE_ODL_MODE == "PZCOUNT_RESET") + { + // controllo comunque, se è ZERO il contapezzi, e sul server è maggiore il + // valore x ODL e NON abilitato il trigger reset --> abilito trigger... + if (!pzCountResetted && contapezziPLC == 0 && contapezziIOB > 0) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC==0 e IOB>PLC) --> pzCountResetted = true"); + } + } + } + } + + /// + /// Effettua reset del contapezzi, NON POSSIBILE in questa versione + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; + return answ; + } + + /// + /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE in questa versione + /// + /// + public override bool setcontapezziPLC(int newPzCount) + { + bool answ = false; + return answ; + } + + #endregion Public Methods + + #region Protected Fields + + /// + /// Modalità cambio ODL + /// + protected string CHANGE_ODL_MODE = ""; + + protected bool testDone = false; + + #endregion Protected Fields + #region Protected Methods /// @@ -82,11 +175,15 @@ namespace IOB_WIN_NEXT { B_input = powerOnOk ? 1 : 0; +#if false // variabili RUN... if (!string.IsNullOrEmpty(opcUaParams.keyRunMode)) { currRun = getDataItemValue(opcUaParams.keyRunMode); } +#endif + + procRunMode(ref currRun); // salvo running come = working... isRunning = isWorking; @@ -271,100 +368,5 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods - - #region Public Methods - - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - // uso metodo base x ora - return base.executeTasks(task2exe); - } - - /// - /// Effettua vero processing contapezzi - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { - // check condizione validazione - if (checkMultiCondition(opcUaParams.condCountEnabled) || opcUaParams.condCountEnabled.checkList.Count == 0) - { - // cerco parametro contapezzi... - string currPzCount = getDataItemValue(opcUaParams.keyPartCount); - - // se ho un contapezzi... processo... - if (!string.IsNullOrEmpty(currPzCount)) - { - int newVal = -1; - bool fatto = Int32.TryParse(currPzCount, out newVal); - - if (fatto) - { - // gestione decremento contapezzi: viene "messo via" solo SE c'è un effettivo decremento contapezzi... - if (newVal < contapezziPLC) - { - pzCountResetted = true; - // incremento contatore richiesta - countKeyRichiesta = countKeyRichiesta + 1; - // log - lgInfo("Contapezzi resettato (PLC) --> pzCountResetted = true"); - } - - // salvo nuovo valore contapezziPLC - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - } - else - { - lgError($"Errore in decodifica valore contapezzi, valore rilevato: {currPzCount}"); - } - } - else - { - lgError("Errore in decodifica valore contapezzi, valore vuoto!"); - } - } - - if (CHANGE_ODL_MODE == "PZCOUNT_RESET") - { - // controllo comunque, se è ZERO il contapezzi, e sul server è maggiore il valore x ODL e NON abilitato il trigger reset --> abilito trigger... - if (!pzCountResetted && contapezziPLC == 0 && contapezziIOB > 0) - { - pzCountResetted = true; - // incremento contatore richiesta - countKeyRichiesta = countKeyRichiesta + 1; - // log - lgInfo("Contapezzi resettato (PLC==0 e IOB>PLC) --> pzCountResetted = true"); - } - } - } - } - - /// - /// Effettua reset del contapezzi, NON POSSIBILE in questa versione - /// - /// - public override bool resetcontapezziPLC() - { - bool answ = false; - return answ; - } - - /// - /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE in questa versione - /// - /// - public override bool setcontapezziPLC(int newPzCount) - { - bool answ = false; - return answ; - } - - #endregion Public Methods - } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOpcUaOmronIcoel.cs b/IOB-WIN-NEXT/IobOpcUaOmronIcoel.cs index bc31f488..6772b696 100644 --- a/IOB-WIN-NEXT/IobOpcUaOmronIcoel.cs +++ b/IOB-WIN-NEXT/IobOpcUaOmronIcoel.cs @@ -427,7 +427,6 @@ namespace IOB_WIN_NEXT { B_input += (1 << 3); } - } // controllo se sono poweroff e se non ho dati buoni da > 2 minuti --> disconnetto @@ -488,7 +487,8 @@ namespace IOB_WIN_NEXT lgTrace($"Invio variazione dataitem per {dataItemMem.Count} elementi"); sendDataItemListToServer(startNodeId); } - else { + else + { lgTrace("Nessuna variazione DataItem da trasmettere"); } } diff --git a/IOB-WIN-NEXT/IobOpcUaSiemens.cs b/IOB-WIN-NEXT/IobOpcUaSiemens.cs index 6c77f1ef..db879a43 100644 --- a/IOB-WIN-NEXT/IobOpcUaSiemens.cs +++ b/IOB-WIN-NEXT/IobOpcUaSiemens.cs @@ -176,11 +176,15 @@ namespace IOB_WIN_NEXT { B_input = powerOnOk ? 1 : 0; +#if false // variabili RUN... if (!string.IsNullOrEmpty(opcUaParams.keyRunMode)) { currRun = getDataItemValue(opcUaParams.keyRunMode); } +#endif + + procRunMode(ref currRun); // salvo running come = working... isRunning = isWorking; diff --git a/IOB-WIN-NEXT/IobPing.cs b/IOB-WIN-NEXT/IobPing.cs index 01aa5b77..c0582621 100644 --- a/IOB-WIN-NEXT/IobPing.cs +++ b/IOB-WIN-NEXT/IobPing.cs @@ -1,27 +1,12 @@ using IOB_UT_NEXT; using MapoSDK; using System; -using System.Collections.Generic; -using System.Linq; using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { public class IobPing : IobGeneric { - #region Protected Fields - - protected int PoweroffTimeoutSec = 100; - - /// - /// Veto controllo status x log... - /// - protected DateTime vetoCheckStatus = DateTime.Now; - - #endregion Protected Fields - #region Public Constructors /// @@ -111,6 +96,7 @@ namespace IOB_WIN_NEXT } } + /// /// Override connessione /// public override void tryConnect() @@ -156,5 +142,16 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected int PoweroffTimeoutSec = 100; + + /// + /// Veto controllo status x log... + /// + protected DateTime vetoCheckStatus = DateTime.Now; + + #endregion Protected Fields } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemens.cs b/IOB-WIN-NEXT/IobSiemens.cs index c97c504f..bc1d2f8f 100644 --- a/IOB-WIN-NEXT/IobSiemens.cs +++ b/IOB-WIN-NEXT/IobSiemens.cs @@ -22,45 +22,6 @@ namespace IOB_WIN_NEXT * * -------------------------------------------------------------------------------- */ - #region Protected Fields - - /// - /// Oggetto PLC da ri-utilizzare... - /// - protected Plc currPLC; - - /// - /// Ultimo controllo ping x evitare ping flood... - /// - protected DateTime lastPingConn = DateTime.Now.AddMinutes(-10); - - /// - /// Esito ultimo ping - /// - protected bool lastPingOk = false; - - /// - /// Lungh massima stringhe - /// - protected int maxStrChar = 20; - - /// - /// parametri di connessione - /// - protected connParamS7 parametri; - - /// - /// Oggetto cronometro x test vari... - /// - protected Stopwatch sw = new Stopwatch(); - - /// - /// indica se scrivere i primi byte x string siemens x indicare lung max e corrente - /// - protected bool writePre = true; - - #endregion Protected Fields - #region Public Fields /// @@ -126,608 +87,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Properties - - /// - /// Dizionario delle ultime operazioni di scrittura per OGNI memoria (in modo che fa log ogni x sec...) - /// - protected Dictionary lastMemWrite { get; set; } = new Dictionary(); - - #endregion Protected Properties - - #region Private Methods - - private static int getScaledInt(dataConf currMem) - { - int valInt; - // prima faccio eventuale fattore di scala... - int.TryParse(currMem.value, out valInt); - if (currMem.factor != 1) - { - valInt = (int)(valInt * currMem.factor); - } - - return valInt; - } - - private static uint getScaledUInt(dataConf currMem) - { - uint valUInt; - // prima faccio eventuale fattore di scala... - uint.TryParse(currMem.value, out valUInt); - if (currMem.factor != 1) - { - valUInt = valUInt * (uint)currMem.factor; - } - - return valUInt; - } - - /// - /// Verifica SE sia il caso di fare il log della memoria indicata - /// - /// - /// - private void maybeLogWrite(string memAddrWrite, string logValue) - { - bool doWrite = true; - DateTime adesso = DateTime.Now; - if (!lastMemWrite.ContainsKey(memAddrWrite)) - { - lastMemWrite.Add(memAddrWrite, adesso.AddMinutes(-1)); - } - // ora mi leggo valore ultima scrittura e confronto con adesso - try - { - doWrite = (lastMemWrite[memAddrWrite].AddSeconds(vetoSeconds) < adesso); - } - catch (Exception exc) - { - lgError($"Eccezione in maybeLogWrite{Environment.NewLine}{exc}"); - } - // se encessario --> LOG! - if (doWrite) - { - // 2022.03.16 portato a livello TRACE x evitare log troppo verboso - lgTrace(logValue); - lastMemWrite[memAddrWrite] = adesso; - } - } - - /// - /// Effettua lettura del contatore e restitusice la stringa grezza del dato - /// - /// - /// - private string readCountVal(ref string memAddrPzCount) - { - object outputVal = new object(); - string strOutVal; - // cerco i pezzi contati STANDARD - if (memAddrPzCount.StartsWith("STD")) - { - // inizio verifica area memoria/parametro levando prima parte codice - memAddrPzCount = memAddrPzCount.Replace("STD.", ""); - // verifico se si tratta di lettura area DB... formato tipo STD.DB700.DBB22.W - if (memAddrPzCount.StartsWith("DB")) - { - memAreaSiemens areaCounter = new memAreaSiemens(memAddrPzCount); - - if (isVerboseLog) - { - lgInfo("[0] area memoria: {1}.{2}.{3}", memAddrPzCount, areaCounter.DbNum, areaCounter.indiceMem, areaCounter.tipoMem); - } - // copio da blocco già letto... con switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato - switch (areaCounter.tipoMem) - { - case "B": - byte valB = RawInput[areaCounter.indiceMem]; - outputVal = valB; - break; - - case "W": - ushort valW = S7.Net.Types.Word.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(2).ToArray()); - outputVal = valW; - break; - - case "DW": - uint valDW = S7.Net.Types.DWord.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(4).ToArray()); - outputVal = valDW; - break; - - case "DI": - int valSDW = S7.Net.Types.DInt.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(4).ToArray()); - outputVal = valSDW; - break; - - case "RE": - double valRe = S7.Net.Types.Double.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(4).ToArray()); - outputVal = valRe; - break; - - default: - break; - } - } - } - else if (memAddrPzCount.StartsWith("SPEC")) - { - // inizio verifica area memoria/parametro levando prima parte codice - memAddrPzCount = memAddrPzCount.Replace("SPEC.", ""); - // verifico se si tratta di lettura area DB... formato tipo SPEC.DB700.DBB22.W - if (memAddrPzCount.StartsWith("DB")) - { - memAreaSiemens areaCounter = new memAreaSiemens(memAddrPzCount); - - if (isVerboseLog) - { - lgInfo("[0] area memoria: {1}.{2}.{3}", memAddrPzCount, areaCounter.DbNum, areaCounter.indiceMem, areaCounter.tipoMem); - } - // leggo i dati SPECIFICI... - byte[] MemBlockPZ = new byte[8]; - bool fatto = false; - // copio da blocco LEGGENDO con switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato - switch (areaCounter.tipoMem) - { - case "B": - MemBlockPZ = new byte[1]; - fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 1); - outputVal = MemBlockPZ[0]; - break; - - case "W": - MemBlockPZ = new byte[2]; - fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 2); - ushort valW = S7.Net.Types.Word.FromByteArray(MemBlockPZ.ToArray()); - outputVal = valW; - break; - - case "DW": - MemBlockPZ = new byte[4]; - fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 4); - uint valDW = S7.Net.Types.DWord.FromByteArray(MemBlockPZ.ToArray()); - outputVal = valDW; - break; - - case "DI": - MemBlockPZ = new byte[4]; - fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 4); - int valSDW = S7.Net.Types.DInt.FromByteArray(MemBlockPZ.ToArray()); - outputVal = valSDW; - break; - - case "RE": - MemBlockPZ = new byte[4]; - fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 4); - double valRe = S7.Net.Types.Double.FromByteArray(MemBlockPZ.ToArray()); - outputVal = valRe; - break; - - default: - break; - } - } - } - strOutVal = $"{outputVal}"; - return strOutVal; - } - - #endregion Private Methods - - #region Protected Methods - - /// - /// decodifica da bitmap il CURRENT MODE del controllo - /// - /// - /// - protected virtual string decodeCurrMode(byte currModeBitmap) - { - string answ = ""; - if (verboseLog) - { - lgInfo(string.Format("CURR_MODE raw data: {0}", utils.binaryForm(currModeBitmap))); - } - // decodifica del MODO... B21 - /* - * CURR MODE diviso in BIT: - * B0 (01) = AUTO - * B1 (02) = MDI - * B2 (04) = JOG - * B3 (08) = TeachIN (associato a MDI --> 10) - * B4 (16) = Repos (associato a JOG --> 20) - * B5 (32) = RefPoint (associato a Jog --> 36) - * B6 (64) = Incr1 (associato a Jog --> 68) - * B7 (128) = Incr10 (associato a Jog --> -124 / 132 se UInt) - * */ - - // modi principali - if (currModeBitmap.SelectBit(0)) - { - answ = "AUTO"; - } - else if (currModeBitmap.SelectBit(1)) - { - answ = "MDI"; - } - else if (currModeBitmap.SelectBit(2)) - { - answ = "JOG"; - } - // modi accessori - if (currModeBitmap.SelectBit(3)) - { - answ += " | TEACH-IN"; - } - if (currModeBitmap.SelectBit(4)) - { - answ += " | REPOS"; - } - if (currModeBitmap.SelectBit(5)) - { - answ += " | REF-POINT"; - } - if (currModeBitmap.SelectBit(6)) - { - answ += " | INCR-1"; - } - if (currModeBitmap.SelectBit(7)) - { - answ += " | INCR-10"; - } - return answ; - } - - /// - /// Decodifica il resto dell'area x i dati accessori (allarmi, ...) - /// - protected virtual void decodeOtherData() - { - if (verboseLog) - { - } - } - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - protected virtual void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - } - - /// - /// Restituisce path completo file da chiave configurazione - /// - /// chiave conf x file richiesto - /// - protected string filePath(string keyFile) - { - string answ = ""; - try - { - answ = $"{utils.confDir}\\{utils.CRS(keyFile)}"; - } - catch (Exception exc) - { - lgError(exc, "Eccezione in recupero filePath"); - } - return answ; - } - - /// - /// Override metodo x scrittura parametri su PLC - /// - /// - protected override void plcWriteParams(ref List updatedPar) - { - dataConf currMem = null; - int byteSize = 0; - byte[] MemBlock = new byte[1]; - string memAddrWrite = ""; - bool fatto = false; - string serObj = ""; - if (updatedPar != null) - { - // controllo i parametri... ne gestisco 4... - foreach (var item in updatedPar) - { - try - { - memAddrWrite = ""; - int valInt = 0; - uint valUInt = 0; - // cerco in area memMapWrite... - if (memMap.mMapWrite.ContainsKey(item.uid)) - { - // recupero! - currMem = memMap.mMapWrite[item.uid]; - byteSize = currMem.size; - memAddrWrite = currMem.memAddr; - MemBlock = new byte[byteSize]; - // faccio preliminarmente upsertKey... - upsertKey(currMem.name, currMem.value); - serObj = JsonConvert.SerializeObject(item, Formatting.Indented); - lgInfo($"Inizio processing plcWriteParams per {currMem.name} | valore richiesto {currMem.value}{Environment.NewLine}---------------UPDATED PARAM---------------{Environment.NewLine}{serObj}{Environment.NewLine}---------------"); - serObj = JsonConvert.SerializeObject(currMem, Formatting.Indented); - lgInfo($"---------------MEMORY CONTENT---------------{Environment.NewLine}{serObj}{Environment.NewLine}---------------"); - switch (currMem.tipoMem) - { - case plcDataType.Boolean: - break; - - case plcDataType.Int: - valInt = getScaledInt(currMem); - saveIntOnMemBlock(ref MemBlock, 0, valInt.ToString()); - break; - - case plcDataType.DInt: - valInt = getScaledInt(currMem); - saveDIntOnMemBlock(ref MemBlock, 0, valInt.ToString()); - break; - - case plcDataType.Word: - valUInt = getScaledUInt(currMem); - saveWordOnMemBlock(ref MemBlock, 0, valInt.ToString()); - break; - - case plcDataType.DWord: - valUInt = getScaledUInt(currMem); - saveDWordOnMemBlock(ref MemBlock, 0, valInt.ToString()); - break; - - case plcDataType.Real: - saveRealOnMemBlock(ref MemBlock, 0, currMem.value); - break; - - case plcDataType.String: - // se ho writePre --> "allungo" di 2 la dimensione della stringa x MemBlock... - if (writePre) - { - MemBlock = new byte[byteSize + 2]; - } - saveStringOnMemBlock(ref MemBlock, 0, currMem.size, currMem.value); - break; - - default: - break; - } - lgInfo($"Preparo scrittura{Environment.NewLine}---------------MemBlock data---------------{Environment.NewLine}{BitConverter.ToString(MemBlock)}{Environment.NewLine}--------------- END data ---------------"); - if (!string.IsNullOrEmpty(memAddrWrite)) - { - // scrivo su siemens - fatto = S7WriteBB(ref MemBlock, memAddrWrite); - // se fatto --> aggiorno! - if (fatto) - { - item.value = item.reqValue; - item.reqValue = ""; - item.lastRead = DateTime.Now; - } - // se configurato faccio verifica write... - if (getOptPar("WRITE_CHECK") == "TRUE") - { - byte[] MemBlockRead = new byte[MemBlock.Length]; - S7ReadBB(ref MemBlockRead, memAddrWrite, MemBlock.Length); - // se non corrispondessero loggo! - if (!MemBlock.SequenceEqual(MemBlockRead)) - { - lgError($"Errore: mancata corrispondenza tra dati scritti e letti:{Environment.NewLine}Write: {BitConverter.ToString(MemBlock)}{Environment.NewLine}read: {BitConverter.ToString(MemBlockRead)}"); - } - else - { - lgInfo($"Scrittura corretta: {BitConverter.ToString(MemBlockRead)}"); - } - } - } - else - { - lgInfo($"Errore: memAddrWrite vuoto!"); - } - } - else - { - lgInfo($"Errore uid non trovato in area write memory: {item.uid}, ci sono {memMap.mMapWrite.Count} in area write"); - } - } - catch (Exception exc) - { - lgError($"Eccezione in fase di plcWriteParams per item {item.uid} con valore {item.value}{Environment.NewLine}{exc}"); - } - } - } - } - - /// - /// Imposto parametri PLC - /// - protected override void setParamPlc() - { - // Creo oggetto connessione NC - parentForm.commPlcActive = true; - lgInfoStartup("Start init Adapter SIEMENS all'IP {0} | CPU: {1} | R/S: {2}/{3} | --> IOB {4}", cIobConf.cncIpAddr, cIobConf.cpuType, cIobConf.rack, cIobConf.slot, cIobConf.codIOB); - // SE è necessario refresh... - if (needRefresh) - { - lgInfoStartup("Refreshing connection..."); - if (parametri != null) - { - try - { - parametri.slot = cIobConf.slot; - parametri.rack = cIobConf.rack; - parametri.tipoCpu = (CpuType)Enum.Parse(typeof(CpuType), cIobConf.cpuType); - parametri.ipAdrr = cIobConf.cncIpAddr; - // leggo file init... - lgInfoStartup("Reading ini file..."); - IniFile fIni = new IniFile(cIobConf.iniFileName); - // ora leggo valori speciali - parametri.memAddrRead = fIni.ReadString("MEMORY", "ADDR_READ", ""); - parametri.memAddrWrite = fIni.ReadString("MEMORY", "ADDR_WRITE", ""); - parametri.memSizeRead = fIni.ReadInteger("MEMORY", "SIZE_READ", 0); - parametri.memSizeWrite = fIni.ReadInteger("MEMORY", "SIZE_WRITE", 0); - // salvo vettori memoria... - lgInfoStartup("Set RawInput dimensions..."); - RawInput = new byte[parametri.memSizeRead]; - RawOutput = new byte[parametri.memSizeWrite]; - // salvo parametri conn! - lgInfoStartup(string.Format("Parametri memoria: memAddrRead: {0} | memAddrWrite: {1} | memSizeRead: {2} | memSizeWrite: {3}", parametri.memAddrRead, parametri.memAddrWrite, parametri.memSizeRead, parametri.memSizeWrite)); - } - catch (Exception exc) - { - lgError(exc, "Errore in parse parametri da IOBConf"); - } - // ora tento avvio PLC... SE PING OK... - IPStatus esitoPing = testPingMachine; - if (esitoPing == IPStatus.Success) - { - needRefresh = false; - try - { - currPLC = new Plc(parametri.tipoCpu, parametri.ipAdrr, parametri.rack, parametri.slot); - // disconnetto e connetto... - if (isVerboseLog) - { - lgInfo("SIEMENS: tryDisconnect"); - } - - tryDisconnect(); - // lo ripeto x evitare che ci sia un loop... e tryConnect richiami la procedura corrente... - needRefresh = false; - lgInfoStartup("SIEMENS: tryConnect"); - lastConnectTry = DateTime.Now; - tryConnect(); - lgInfoStartup("End init Adapter SIEMENS"); - if (isVerboseLog) - { - lgInfo("S7+ CONNESSIONE AVVENUTA"); - } - } - catch (Exception exc) - { - lgError(exc, "Errore in INIT PLC S7+"); - } - } - else - { - lgError($"IOB SIEMENS | Errore in ping: esito {esitoPing}"); - } - parentForm.commPlcActive = false; - // carico conf vettore memoria... - loadMemConf(); - bool enableByApp = utils.CRB("enableContapezzi"); - bool enableByIob = (getOptPar("ENABLE_PZCOUNT") == "TRUE"); - bool disableByIob = (getOptPar("DISABLE_PZCOUNT") == "TRUE"); - if ((enableByApp || enableByIob) && !(disableByIob)) - { - lgDebug("SIEMENS: inizio gestione contapezzi"); - try - { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - if (cIobConf.optPar.Count > 0 && !string.IsNullOrWhiteSpace(getOptPar("PZCOUNT_MODE"))) - { - if (getOptPar("PZCOUNT_MODE").StartsWith("STD")) - { - lgDebug("Init contapezzi SIEMENS: pzCntReload(true)"); - pzCntReload(true); - // refresh associazione Macchina - IOB - sendM2IOB(); - // per adesso imposto lettura PLC == contapezzi (poi farà vera lettura...) - contapezziPLC = contapezziIOB; - } - else - { - contapezziIOB = 0; - lgDebug("Contapezzi STD disabilitato: modalità {0}", getOptPar("PZCOUNT_MODE")); - } - } - else - { - contapezziIOB = 0; - lgDebug("Parametro mancante PZCOUNT_MODE"); - } - } - catch (Exception exc) - { - lgError(exc, "Errore in contapezzi SIEMENS"); - } - } - } - else - { - lgError("Parametri null!"); - } - } - } - - /// - /// Test connessione CNC - /// - /// - protected bool testCncConn() - { - bool answ = false; - // riduco i controlli ping.. li faccio solo ogni 5 ping period se precedente positivo... - DateTime adesso = DateTime.Now; - if (lastPingOk && adesso.Subtract(lastPingConn).TotalMilliseconds < 5 * parametri.pingMsTimeout) - { - answ = lastPingOk; - } - else - { - IPStatus pingStatus = testPingMachine; - - // se non ok riprovo 1 volta dopo attesa - if (pingStatus != IPStatus.Success) - { - Thread.Sleep(2 * cIobConf.pingMsTimeout); - pingStatus = testPingMachine; - } - // se non passa ancora errore! - if (pingStatus != IPStatus.Success) - { - lgError($"Errore in testCncConn | reply Status {pingStatus} | IP: {parametri.ipAdrr} | T.Out: {parametri.pingMsTimeout}ms"); - } - // se passa il ping faccio il resto... - else - { - if (!currPLC.IsConnected) - { - currPLC.Open(); - } - - if (!currPLC.IsAvailable) - { - lgError($"PLC Siemens NON disponibile:{currPLC.LastErrorCode} | {currPLC.LastErrorString}"); - currPLC.ClearLastError(); - } - else - { - if (!currPLC.IsConnected) - { - lgError($"PLC Siemens NON connesso:{currPLC.LastErrorCode} | {currPLC.LastErrorString}"); - currPLC.ClearLastError(); - parentForm.updateComStats("NO connection"); - } - else - { - // tutto ok - parentForm.updateComStats("Connection OK"); - answ = true; - } - } - } - // salvo stato ping - lastPingOk = answ; - lastPingConn = adesso; - } - - return answ; - } - - #endregion Protected Methods - #region Public Methods /// @@ -939,7 +298,8 @@ namespace IOB_WIN_NEXT { try { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) if (cIobConf.optPar.Count > 0) { int pzCountBuoni = -1; @@ -1155,7 +515,8 @@ namespace IOB_WIN_NEXT } /// - /// wrapper chiamata SCRITTURA in blocco MULTI BYTE, DI DEFAULT su area configurata x scrittura CONTINUA... + /// wrapper chiamata SCRITTURA in blocco MULTI BYTE, DI DEFAULT su area configurata x + /// scrittura CONTINUA... /// /// /// @@ -1478,7 +839,9 @@ namespace IOB_WIN_NEXT /// /// Blocco memoria come byte[] dove scrivere /// Posizione inizio scrittura - /// Lunghezza max stringa (se ci sono 2 byte iniziali verrà ridotta di 2) + /// + /// Lunghezza max stringa (se ci sono 2 byte iniziali verrà ridotta di 2) + /// /// valore da scrivere public void saveStringOnMemBlock(ref byte[] MemBlock, int startPos, int totLen, string valore) { @@ -1519,7 +882,9 @@ namespace IOB_WIN_NEXT /// Blocco memoria come byte[] dove scrivere /// Nome del parametro da recuperare da prodData x scrivere /// Posizione inizio scrittura - /// Lunghezza max stringa (se ci sono 2 byte iniziali verrà ridotta di 2) + /// + /// Lunghezza max stringa (se ci sono 2 byte iniziali verrà ridotta di 2) + /// public void saveStringOnMemBlock(ref byte[] MemBlock, string stringKey, int startPos, int totLen) { if (currProdData.ContainsKey(stringKey)) @@ -1739,6 +1104,47 @@ namespace IOB_WIN_NEXT #endregion Public Methods + #region Protected Fields + + /// + /// Oggetto PLC da ri-utilizzare... + /// + protected Plc currPLC; + + /// + /// Ultimo controllo ping x evitare ping flood... + /// + protected DateTime lastPingConn = DateTime.Now.AddMinutes(-10); + + /// + /// Esito ultimo ping + /// + protected bool lastPingOk = false; + + /// + /// Lungh massima stringhe + /// + protected int maxStrChar = 20; + + /// + /// parametri di connessione + /// + protected connParamS7 parametri; + + /// + /// Oggetto cronometro x test vari... + /// + protected Stopwatch sw = new Stopwatch(); + + /// + /// indica se scrivere i primi byte x string siemens x indicare lung max e corrente + /// + protected bool writePre = true; + + #endregion Protected Fields + + #region Protected Properties + /// /// Verifica presenza allarmi (tra quelli configurati) /// @@ -1761,9 +1167,11 @@ namespace IOB_WIN_NEXT // verifica e decremento blink... item.checkBlinkCounter(i, (uint)currStatus); - // verifico SE sia variato... confronto allarmi filtrato stile blink per bit status: + // verifico SE sia variato... confronto allarmi filtrato stile blink per + // bit status: // - allarmi che iniziano per # IGNORATI - // - altri allarmi con un countdown da MAX_COUNTER_BLINK a 0 per il fronte di discesa + // - altri allarmi con un countdown da MAX_COUNTER_BLINK a 0 per il + // fronte di discesa if (item.isChanged(i, currStatus)) { if (currStatus > 0) @@ -1784,5 +1192,611 @@ namespace IOB_WIN_NEXT return answ; } } + + /// + /// Dizionario delle ultime operazioni di scrittura per OGNI memoria (in modo che fa log + /// ogni x sec...) + /// + protected Dictionary lastMemWrite { get; set; } = new Dictionary(); + + #endregion Protected Properties + + #region Protected Methods + + /// + /// decodifica da bitmap il CURRENT MODE del controllo + /// + /// + /// + protected virtual string decodeCurrMode(byte currModeBitmap) + { + string answ = ""; + if (verboseLog) + { + lgInfo(string.Format("CURR_MODE raw data: {0}", utils.binaryForm(currModeBitmap))); + } + // decodifica del MODO... B21 + /* + * CURR MODE diviso in BIT: + * B0 (01) = AUTO + * B1 (02) = MDI + * B2 (04) = JOG + * B3 (08) = TeachIN (associato a MDI --> 10) + * B4 (16) = Repos (associato a JOG --> 20) + * B5 (32) = RefPoint (associato a Jog --> 36) + * B6 (64) = Incr1 (associato a Jog --> 68) + * B7 (128) = Incr10 (associato a Jog --> -124 / 132 se UInt) + * */ + + // modi principali + if (currModeBitmap.SelectBit(0)) + { + answ = "AUTO"; + } + else if (currModeBitmap.SelectBit(1)) + { + answ = "MDI"; + } + else if (currModeBitmap.SelectBit(2)) + { + answ = "JOG"; + } + // modi accessori + if (currModeBitmap.SelectBit(3)) + { + answ += " | TEACH-IN"; + } + if (currModeBitmap.SelectBit(4)) + { + answ += " | REPOS"; + } + if (currModeBitmap.SelectBit(5)) + { + answ += " | REF-POINT"; + } + if (currModeBitmap.SelectBit(6)) + { + answ += " | INCR-1"; + } + if (currModeBitmap.SelectBit(7)) + { + answ += " | INCR-10"; + } + return answ; + } + + /// + /// Decodifica il resto dell'area x i dati accessori (allarmi, ...) + /// + protected virtual void decodeOtherData() + { + if (verboseLog) + { + } + } + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + protected virtual void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + } + + /// + /// Restituisce path completo file da chiave configurazione + /// + /// chiave conf x file richiesto + /// + protected string filePath(string keyFile) + { + string answ = ""; + try + { + answ = $"{utils.confDir}\\{utils.CRS(keyFile)}"; + } + catch (Exception exc) + { + lgError(exc, "Eccezione in recupero filePath"); + } + return answ; + } + + /// + /// Override metodo x scrittura parametri su PLC + /// + /// + protected override void plcWriteParams(ref List updatedPar) + { + dataConf currMem = null; + int byteSize = 0; + byte[] MemBlock = new byte[1]; + string memAddrWrite = ""; + bool fatto = false; + string serObj = ""; + if (updatedPar != null) + { + // controllo i parametri... ne gestisco 4... + foreach (var item in updatedPar) + { + try + { + memAddrWrite = ""; + int valInt = 0; + uint valUInt = 0; + // cerco in area memMapWrite... + if (memMap.mMapWrite.ContainsKey(item.uid)) + { + // recupero! + currMem = memMap.mMapWrite[item.uid]; + byteSize = currMem.size; + memAddrWrite = currMem.memAddr; + MemBlock = new byte[byteSize]; + // faccio preliminarmente upsertKey... + upsertKey(currMem.name, currMem.value); + serObj = JsonConvert.SerializeObject(item, Formatting.Indented); + lgInfo($"Inizio processing plcWriteParams per {currMem.name} | valore richiesto {currMem.value}{Environment.NewLine}---------------UPDATED PARAM---------------{Environment.NewLine}{serObj}{Environment.NewLine}---------------"); + serObj = JsonConvert.SerializeObject(currMem, Formatting.Indented); + lgInfo($"---------------MEMORY CONTENT---------------{Environment.NewLine}{serObj}{Environment.NewLine}---------------"); + switch (currMem.tipoMem) + { + case plcDataType.Boolean: + break; + + case plcDataType.Int: + valInt = getScaledInt(currMem); + saveIntOnMemBlock(ref MemBlock, 0, valInt.ToString()); + break; + + case plcDataType.DInt: + valInt = getScaledInt(currMem); + saveDIntOnMemBlock(ref MemBlock, 0, valInt.ToString()); + break; + + case plcDataType.Word: + valUInt = getScaledUInt(currMem); + saveWordOnMemBlock(ref MemBlock, 0, valInt.ToString()); + break; + + case plcDataType.DWord: + valUInt = getScaledUInt(currMem); + saveDWordOnMemBlock(ref MemBlock, 0, valInt.ToString()); + break; + + case plcDataType.Real: + saveRealOnMemBlock(ref MemBlock, 0, currMem.value); + break; + + case plcDataType.String: + // se ho writePre --> "allungo" di 2 la dimensione della stringa + // x MemBlock... + if (writePre) + { + MemBlock = new byte[byteSize + 2]; + } + saveStringOnMemBlock(ref MemBlock, 0, currMem.size, currMem.value); + break; + + default: + break; + } + lgInfo($"Preparo scrittura{Environment.NewLine}---------------MemBlock data---------------{Environment.NewLine}{BitConverter.ToString(MemBlock)}{Environment.NewLine}--------------- END data ---------------"); + if (!string.IsNullOrEmpty(memAddrWrite)) + { + // scrivo su siemens + fatto = S7WriteBB(ref MemBlock, memAddrWrite); + // se fatto --> aggiorno! + if (fatto) + { + item.value = item.reqValue; + item.reqValue = ""; + item.lastRead = DateTime.Now; + } + // se configurato faccio verifica write... + if (getOptPar("WRITE_CHECK") == "TRUE") + { + byte[] MemBlockRead = new byte[MemBlock.Length]; + S7ReadBB(ref MemBlockRead, memAddrWrite, MemBlock.Length); + // se non corrispondessero loggo! + if (!MemBlock.SequenceEqual(MemBlockRead)) + { + lgError($"Errore: mancata corrispondenza tra dati scritti e letti:{Environment.NewLine}Write: {BitConverter.ToString(MemBlock)}{Environment.NewLine}read: {BitConverter.ToString(MemBlockRead)}"); + } + else + { + lgInfo($"Scrittura corretta: {BitConverter.ToString(MemBlockRead)}"); + } + } + } + else + { + lgInfo($"Errore: memAddrWrite vuoto!"); + } + } + else + { + lgInfo($"Errore uid non trovato in area write memory: {item.uid}, ci sono {memMap.mMapWrite.Count} in area write"); + } + } + catch (Exception exc) + { + lgError($"Eccezione in fase di plcWriteParams per item {item.uid} con valore {item.value}{Environment.NewLine}{exc}"); + } + } + } + } + + /// + /// Imposto parametri PLC + /// + protected override void setParamPlc() + { + // Creo oggetto connessione NC + parentForm.commPlcActive = true; + lgInfoStartup("Start init Adapter SIEMENS all'IP {0} | CPU: {1} | R/S: {2}/{3} | --> IOB {4}", cIobConf.cncIpAddr, cIobConf.cpuType, cIobConf.rack, cIobConf.slot, cIobConf.codIOB); + // SE è necessario refresh... + if (needRefresh) + { + lgInfoStartup("Refreshing connection..."); + if (parametri != null) + { + try + { + parametri.slot = cIobConf.slot; + parametri.rack = cIobConf.rack; + parametri.tipoCpu = (CpuType)Enum.Parse(typeof(CpuType), cIobConf.cpuType); + parametri.ipAdrr = cIobConf.cncIpAddr; + // leggo file init... + lgInfoStartup("Reading ini file..."); + IniFile fIni = new IniFile(cIobConf.iniFileName); + // ora leggo valori speciali + parametri.memAddrRead = fIni.ReadString("MEMORY", "ADDR_READ", ""); + parametri.memAddrWrite = fIni.ReadString("MEMORY", "ADDR_WRITE", ""); + parametri.memSizeRead = fIni.ReadInteger("MEMORY", "SIZE_READ", 0); + parametri.memSizeWrite = fIni.ReadInteger("MEMORY", "SIZE_WRITE", 0); + // salvo vettori memoria... + lgInfoStartup("Set RawInput dimensions..."); + RawInput = new byte[parametri.memSizeRead]; + RawOutput = new byte[parametri.memSizeWrite]; + // salvo parametri conn! + lgInfoStartup(string.Format("Parametri memoria: memAddrRead: {0} | memAddrWrite: {1} | memSizeRead: {2} | memSizeWrite: {3}", parametri.memAddrRead, parametri.memAddrWrite, parametri.memSizeRead, parametri.memSizeWrite)); + } + catch (Exception exc) + { + lgError(exc, "Errore in parse parametri da IOBConf"); + } + // ora tento avvio PLC... SE PING OK... + IPStatus esitoPing = testPingMachine; + if (esitoPing == IPStatus.Success) + { + needRefresh = false; + try + { + currPLC = new Plc(parametri.tipoCpu, parametri.ipAdrr, parametri.rack, parametri.slot); + // disconnetto e connetto... + if (isVerboseLog) + { + lgInfo("SIEMENS: tryDisconnect"); + } + + tryDisconnect(); + // lo ripeto x evitare che ci sia un loop... e tryConnect richiami la + // procedura corrente... + needRefresh = false; + lgInfoStartup("SIEMENS: tryConnect"); + lastConnectTry = DateTime.Now; + tryConnect(); + lgInfoStartup("End init Adapter SIEMENS"); + if (isVerboseLog) + { + lgInfo("S7+ CONNESSIONE AVVENUTA"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in INIT PLC S7+"); + } + } + else + { + lgError($"IOB SIEMENS | Errore in ping: esito {esitoPing}"); + } + parentForm.commPlcActive = false; + // carico conf vettore memoria... + loadMemConf(); + bool enableByApp = utils.CRB("enableContapezzi"); + bool enableByIob = (getOptPar("ENABLE_PZCOUNT") == "TRUE"); + bool disableByIob = (getOptPar("DISABLE_PZCOUNT") == "TRUE"); + if ((enableByApp || enableByIob) && !(disableByIob)) + { + lgDebug("SIEMENS: inizio gestione contapezzi"); + try + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, + // con indicazione area) + if (cIobConf.optPar.Count > 0 && !string.IsNullOrWhiteSpace(getOptPar("PZCOUNT_MODE"))) + { + if (getOptPar("PZCOUNT_MODE").StartsWith("STD")) + { + lgDebug("Init contapezzi SIEMENS: pzCntReload(true)"); + pzCntReload(true); + // refresh associazione Macchina - IOB + sendM2IOB(); + // per adesso imposto lettura PLC == contapezzi (poi farà vera lettura...) + contapezziPLC = contapezziIOB; + } + else + { + contapezziIOB = 0; + lgDebug("Contapezzi STD disabilitato: modalità {0}", getOptPar("PZCOUNT_MODE")); + } + } + else + { + contapezziIOB = 0; + lgDebug("Parametro mancante PZCOUNT_MODE"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi SIEMENS"); + } + } + } + else + { + lgError("Parametri null!"); + } + } + } + + /// + /// Test connessione CNC + /// + /// + protected bool testCncConn() + { + bool answ = false; + // riduco i controlli ping.. li faccio solo ogni 5 ping period se precedente positivo... + DateTime adesso = DateTime.Now; + if (lastPingOk && adesso.Subtract(lastPingConn).TotalMilliseconds < 5 * parametri.pingMsTimeout) + { + answ = lastPingOk; + } + else + { + IPStatus pingStatus = testPingMachine; + + // se non ok riprovo 1 volta dopo attesa + if (pingStatus != IPStatus.Success) + { + Thread.Sleep(2 * cIobConf.pingMsTimeout); + pingStatus = testPingMachine; + } + // se non passa ancora errore! + if (pingStatus != IPStatus.Success) + { + lgError($"Errore in testCncConn | reply Status {pingStatus} | IP: {parametri.ipAdrr} | T.Out: {parametri.pingMsTimeout}ms"); + } + // se passa il ping faccio il resto... + else + { + if (!currPLC.IsConnected) + { + currPLC.Open(); + } + + if (!currPLC.IsAvailable) + { + lgError($"PLC Siemens NON disponibile:{currPLC.LastErrorCode} | {currPLC.LastErrorString}"); + currPLC.ClearLastError(); + } + else + { + if (!currPLC.IsConnected) + { + lgError($"PLC Siemens NON connesso:{currPLC.LastErrorCode} | {currPLC.LastErrorString}"); + currPLC.ClearLastError(); + parentForm.updateComStats("NO connection"); + } + else + { + // tutto ok + parentForm.updateComStats("Connection OK"); + answ = true; + } + } + } + // salvo stato ping + lastPingOk = answ; + lastPingConn = adesso; + } + + return answ; + } + + #endregion Protected Methods + + #region Private Methods + + private static int getScaledInt(dataConf currMem) + { + int valInt; + // prima faccio eventuale fattore di scala... + int.TryParse(currMem.value, out valInt); + if (currMem.factor != 1) + { + valInt = (int)(valInt * currMem.factor); + } + + return valInt; + } + + private static uint getScaledUInt(dataConf currMem) + { + uint valUInt; + // prima faccio eventuale fattore di scala... + uint.TryParse(currMem.value, out valUInt); + if (currMem.factor != 1) + { + valUInt = valUInt * (uint)currMem.factor; + } + + return valUInt; + } + + /// + /// Verifica SE sia il caso di fare il log della memoria indicata + /// + /// + /// + private void maybeLogWrite(string memAddrWrite, string logValue) + { + bool doWrite = true; + DateTime adesso = DateTime.Now; + if (!lastMemWrite.ContainsKey(memAddrWrite)) + { + lastMemWrite.Add(memAddrWrite, adesso.AddMinutes(-1)); + } + // ora mi leggo valore ultima scrittura e confronto con adesso + try + { + doWrite = (lastMemWrite[memAddrWrite].AddSeconds(vetoSeconds) < adesso); + } + catch (Exception exc) + { + lgError($"Eccezione in maybeLogWrite{Environment.NewLine}{exc}"); + } + // se encessario --> LOG! + if (doWrite) + { + // 2022.03.16 portato a livello TRACE x evitare log troppo verboso + lgTrace(logValue); + lastMemWrite[memAddrWrite] = adesso; + } + } + + /// + /// Effettua lettura del contatore e restitusice la stringa grezza del dato + /// + /// + /// + private string readCountVal(ref string memAddrPzCount) + { + object outputVal = new object(); + string strOutVal; + // cerco i pezzi contati STANDARD + if (memAddrPzCount.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddrPzCount = memAddrPzCount.Replace("STD.", ""); + // verifico se si tratta di lettura area DB... formato tipo STD.DB700.DBB22.W + if (memAddrPzCount.StartsWith("DB")) + { + memAreaSiemens areaCounter = new memAreaSiemens(memAddrPzCount); + + if (isVerboseLog) + { + lgInfo("[0] area memoria: {1}.{2}.{3}", memAddrPzCount, areaCounter.DbNum, areaCounter.indiceMem, areaCounter.tipoMem); + } + // copio da blocco già letto... con switch x tipo dati --> tipo lettura... e + // salvo ultimo conteggio rilevato + switch (areaCounter.tipoMem) + { + case "B": + byte valB = RawInput[areaCounter.indiceMem]; + outputVal = valB; + break; + + case "W": + ushort valW = S7.Net.Types.Word.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(2).ToArray()); + outputVal = valW; + break; + + case "DW": + uint valDW = S7.Net.Types.DWord.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(4).ToArray()); + outputVal = valDW; + break; + + case "DI": + int valSDW = S7.Net.Types.DInt.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(4).ToArray()); + outputVal = valSDW; + break; + + case "RE": + double valRe = S7.Net.Types.Double.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(4).ToArray()); + outputVal = valRe; + break; + + default: + break; + } + } + } + else if (memAddrPzCount.StartsWith("SPEC")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddrPzCount = memAddrPzCount.Replace("SPEC.", ""); + // verifico se si tratta di lettura area DB... formato tipo SPEC.DB700.DBB22.W + if (memAddrPzCount.StartsWith("DB")) + { + memAreaSiemens areaCounter = new memAreaSiemens(memAddrPzCount); + + if (isVerboseLog) + { + lgInfo("[0] area memoria: {1}.{2}.{3}", memAddrPzCount, areaCounter.DbNum, areaCounter.indiceMem, areaCounter.tipoMem); + } + // leggo i dati SPECIFICI... + byte[] MemBlockPZ = new byte[8]; + bool fatto = false; + // copio da blocco LEGGENDO con switch x tipo dati --> tipo lettura... e salvo + // ultimo conteggio rilevato + switch (areaCounter.tipoMem) + { + case "B": + MemBlockPZ = new byte[1]; + fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 1); + outputVal = MemBlockPZ[0]; + break; + + case "W": + MemBlockPZ = new byte[2]; + fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 2); + ushort valW = S7.Net.Types.Word.FromByteArray(MemBlockPZ.ToArray()); + outputVal = valW; + break; + + case "DW": + MemBlockPZ = new byte[4]; + fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 4); + uint valDW = S7.Net.Types.DWord.FromByteArray(MemBlockPZ.ToArray()); + outputVal = valDW; + break; + + case "DI": + MemBlockPZ = new byte[4]; + fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 4); + int valSDW = S7.Net.Types.DInt.FromByteArray(MemBlockPZ.ToArray()); + outputVal = valSDW; + break; + + case "RE": + MemBlockPZ = new byte[4]; + fatto = S7ReadBB(ref MemBlockPZ, memAddrPzCount, 4); + double valRe = S7.Net.Types.Double.FromByteArray(MemBlockPZ.ToArray()); + outputVal = valRe; + break; + + default: + break; + } + } + } + strOutVal = $"{outputVal}"; + return strOutVal; + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensAprochim.cs b/IOB-WIN-NEXT/IobSiemensAprochim.cs index 34903edd..734a5470 100644 --- a/IOB-WIN-NEXT/IobSiemensAprochim.cs +++ b/IOB-WIN-NEXT/IobSiemensAprochim.cs @@ -77,75 +77,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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 - * - DB60.DBX3.0: AUSILIARI INSERITI = NO EMERGENZA - * - DB60.DBX3.1: Filtro (macchina) in LAVORAZIONE - * - DB60.DBX3.2: Selettore in AUTOMATICO (sennò GIALLO) - * - DB60.DBX3.3: WARNING MIN LIV VASCA (arancio) - * - DB60.DBX3.4: WARNING MIN LIV CELLULOSA (blu) - * - DB60.DBX3.5: LAMPADA ROSSA (allarmi almeno 1 attivo) - ----------------------------------------------------- */ - - /* ----------------------------------------------------- - * bitmap MAPO FILTRO Aprochim - * B0: POWER_ON - * B1: RUN - * B2: AUTOMATICO - * B3: WARN_MIN_VASCA - * B4: WARN_MIN_CELL - * B5: ALARM - * B6: EMERGENZA - ----------------------------------------------------- */ - - // bit 0 (poweron) imposto a 1 SE connected... - B_input = currPLC.IsConnected ? 1 : 0; - - // recupero byte segnali... - int byteSignals = RawInput[3]; - // aggiungo "in coda" primo bit emergenza...essendo un bit negato (NON emergenza) lo cambio di segno - if ((byteSignals & (1 << 0)) == 0) - { - byteSignals += (1 << 6); - } - // cancello primo bit (faccio uno shift a dx e poi a sx di 1...) - byteSignals = ((byteSignals >> 1) << 1); - // bit 0 (poweron) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSignals += (1 << 0); - } - // salvo! - B_input = byteSignals; - - // log opzionale! - if (verboseLog) - { - lgInfo(string.Format($"Trasformazione dati: RawInput:{RawInput[3]} --> B_input: {B_input}")); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -216,5 +147,75 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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 + * - DB60.DBX3.0: AUSILIARI INSERITI = NO EMERGENZA + * - DB60.DBX3.1: Filtro (macchina) in LAVORAZIONE + * - DB60.DBX3.2: Selettore in AUTOMATICO (sennò GIALLO) + * - DB60.DBX3.3: WARNING MIN LIV VASCA (arancio) + * - DB60.DBX3.4: WARNING MIN LIV CELLULOSA (blu) + * - DB60.DBX3.5: LAMPADA ROSSA (allarmi almeno 1 attivo) + ----------------------------------------------------- */ + + /* ----------------------------------------------------- + * bitmap MAPO FILTRO Aprochim + * B0: POWER_ON + * B1: RUN + * B2: AUTOMATICO + * B3: WARN_MIN_VASCA + * B4: WARN_MIN_CELL + * B5: ALARM + * B6: EMERGENZA + ----------------------------------------------------- */ + + // bit 0 (poweron) imposto a 1 SE connected... + B_input = currPLC.IsConnected ? 1 : 0; + + // recupero byte segnali... + int byteSignals = RawInput[3]; + // aggiungo "in coda" primo bit emergenza...essendo un bit negato (NON emergenza) lo + // cambio di segno + if ((byteSignals & (1 << 0)) == 0) + { + byteSignals += (1 << 6); + } + // cancello primo bit (faccio uno shift a dx e poi a sx di 1...) + byteSignals = ((byteSignals >> 1) << 1); + // bit 0 (poweron) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSignals += (1 << 0); + } + // salvo! + B_input = byteSignals; + + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format($"Trasformazione dati: RawInput:{RawInput[3]} --> B_input: {B_input}")); + } + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensAt2001.cs b/IOB-WIN-NEXT/IobSiemensAt2001.cs index 93559a0c..bd1f86ca 100644 --- a/IOB-WIN-NEXT/IobSiemensAt2001.cs +++ b/IOB-WIN-NEXT/IobSiemensAt2001.cs @@ -18,14 +18,6 @@ namespace IOB_WIN_NEXT * -------------------------------------------------------------------------------- */ - #region Protected Fields - - protected int counterMes2Plc = 0; - protected int counterPlc2Mes = 0; - protected DateTime lastPLCWatchDog; - - #endregion Protected Fields - #region Public Constructors /// @@ -41,95 +33,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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: avvio/spegnimento - * B6: emergenza - * - * - * - BYTE di stato - * - +0.0 AutoStatus BYTE B#16#0 Valore 0=Fermo/1->3=Avviamento/4=Avviato/5=Pausa/6->8spegnimento/9->10 allarme - * - +1.0 Dosatore BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - * - +2.0 V_Dosatore BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - * - +3.0 Nas_Lancio BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - * - +4.0 Cilindro BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - * - +5.0 Bruciatore BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - * - +6.0 Aspiratore BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - * - +7.0 Nas_Raccolta BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - * - +8.0 Nas_Brandeg BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - * - +9.0 Coclea_Filtro BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - * - +10.0 Ciclico_Filtro BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) - ----------------------------------------------------- */ - - // recupero byte segnali... - int byteSignals = RawInput[0]; - - // bit 0 (poweron) imposto a 1 SE connected... - B_input = currPLC.IsConnected ? 1 : 0; - - // avviamento --> manuale - switch (byteSignals) - { - case 0: - B_input = 1; - break; - - case 1: - case 2: - case 3: - B_input += (1 << 5); - break; - - case 4: - B_input += (1 << 1); - break; - - case 5: - B_input += (1 << 4); - break; - - case 6: - case 7: - case 8: - B_input += (1 << 5); - break; - - case 9: - B_input += (1 << 3); - break; - - case 10: - B_input += (1 << 6); - break; - - default: - break; - } - - // log opzionale! - if (verboseLog) - { - lgInfo(string.Format($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}")); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -168,7 +71,8 @@ namespace IOB_WIN_NEXT case taskType.forceResetPzCount: case taskType.startSetup: - // alzo il bit x registrare richiesta reset contapezzi... POI quando ha eseguito abbassa il PLC il bit a zero... + // alzo il bit x registrare richiesta reset contapezzi... POI quando ha + // eseguito abbassa il PLC il bit a zero... MemBlock[0] = 1; memAddrWrite = "DB1001.DBB88"; break; @@ -265,7 +169,8 @@ namespace IOB_WIN_NEXT taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value"; } } - // alzo il bit x registrare RICHEISTA modifica (secondo BIT)... POI quando ha eseguito abbassa il PLC il bit a zero... + // alzo il bit x registrare RICHEISTA modifica (secondo BIT)... POI + // quando ha eseguito abbassa il PLC il bit a zero... MemBlock[0] = 2; memAddrWrite = "DB1001.DBB88"; break; @@ -349,5 +254,102 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected int counterMes2Plc = 0; + protected int counterPlc2Mes = 0; + protected DateTime lastPLCWatchDog; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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: avvio/spegnimento + * B6: emergenza + * + * + * - BYTE di stato + * - +0.0 AutoStatus BYTE B#16#0 Valore 0=Fermo/1->3=Avviamento/4=Avviato/5=Pausa/6->8spegnimento/9->10 allarme + * - +1.0 Dosatore BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + * - +2.0 V_Dosatore BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + * - +3.0 Nas_Lancio BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + * - +4.0 Cilindro BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + * - +5.0 Bruciatore BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + * - +6.0 Aspiratore BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + * - +7.0 Nas_Raccolta BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + * - +8.0 Nas_Brandeg BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + * - +9.0 Coclea_Filtro BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + * - +10.0 Ciclico_Filtro BYTE B#16#0 Stato (bit0=in avviamento/1=marcia sx/2=marcia dx/3=in allarme/4=by-pass on) + ----------------------------------------------------- */ + + // recupero byte segnali... + int byteSignals = RawInput[0]; + + // bit 0 (poweron) imposto a 1 SE connected... + B_input = currPLC.IsConnected ? 1 : 0; + + // avviamento --> manuale + switch (byteSignals) + { + case 0: + B_input = 1; + break; + + case 1: + case 2: + case 3: + B_input += (1 << 5); + break; + + case 4: + B_input += (1 << 1); + break; + + case 5: + B_input += (1 << 4); + break; + + case 6: + case 7: + case 8: + B_input += (1 << 5); + break; + + case 9: + B_input += (1 << 3); + break; + + case 10: + B_input += (1 << 6); + break; + + default: + break; + } + + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}")); + } + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensComeca.cs b/IOB-WIN-NEXT/IobSiemensComeca.cs index e4416c40..00b902af 100644 --- a/IOB-WIN-NEXT/IobSiemensComeca.cs +++ b/IOB-WIN-NEXT/IobSiemensComeca.cs @@ -35,12 +35,6 @@ namespace IOB_WIN_NEXT * * -------------------------------------------------------------------------------- */ - #region Protected Fields - - protected int strobeVal = 0; - - #endregion Protected Fields - #region Public Constructors /// @@ -55,137 +49,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Properties - -#if false - protected bool hasAlarms - { - get - { - bool answ = false; - int numErrors = 0; - uint currStatus = 0; - if (alarmMaps != null) - { - // leggo a ciclo le aree degli allarmi CONFIGURATI, se ne trovo --> segnalo allarme... - foreach (var item in alarmMaps) - { - // banchi in WORD (2 byte) --> scompongo - for (int i = 0; i < item.size / 2; i++) - { - currStatus = S7.Net.Types.Counter.FromByteArray(RawInput.Skip(item.index + 2 * i).Take(2).ToArray()); - // verifica e decremento blink... - item.checkBlinkCounter(i, (uint)currStatus); - - // verifico SE sia variato... confronto allarmi filtrato stile blink per bit status: - // - allarmi che iniziano per # IGNORATI - // - altri allarmi con un countdown da MAX_COUNTER_BLINK a 0 per il fronte di discesa - if (item.isChanged(i, currStatus)) - { - if (currStatus > 0) - { - numErrors++; - } - // registro gli allarmi attivi e trasmetto... - if (sendAlarmVariations(item.memAddr, i, item.alarmsState[i], (uint)(item.alarmsMask[i] & currStatus), item.messages)) - { - // se inviato --> salvo stato da current... - item.updStatusVal(i, (uint)(item.alarmsMask[i] & currStatus)); - } - } - } - } - } - answ = numErrors > 0; - return answ; - } - } -#endif - - #endregion Protected Properties - - #region Private Methods - - private void checkStrobeHack() - { - // verifico SE ho un hack sulla var DB85.DB268 - byte[] byteCtrlW = new byte[2]; - bool fatto = S7ReadBB(ref byteCtrlW, "DB85.DBB268", 2); - ushort valCtrlW = S7.Net.Types.Word.FromByteArray(byteCtrlW.ToArray()); - // se vale 1 --> resetto strobe! - if (valCtrlW == 1) - { - // aggiunta finale bit a 0 x chiusura processing.. - var MemBlock = S7.Net.Types.Int.ToByteArray(0); - var memAddrWrite = "DB85.DBB308"; - // imposto valore strobe x check successivi - var taskOk = S7WriteBB(ref MemBlock, memAddrWrite); - if (taskOk) - { - strobeVal = 0; - } - } - else - { - lgInfo("SiemensComeca: Strobe attivo su DBB308, ack non rilevato su DBB268"); - } - } - - #endregion Private Methods - - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - per lo scopo specifico IN REALTA' non conta lo stato macchina.... ma lo inviamo lo stesso - /// - protected override void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - - /* ----------------------------------------------------- - * bitmap MAPO STANDARD - * B0: POWER_ON - * B1: RUN - * B2: pzCount - * B3: allarme - * - ----------------------------------------------------- */ - - //bool fatto = false; - //ushort valW = 0; - - var MemInt = new byte[2]; - - int byteSignals = 0; - // bit 0 (poweron) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSignals += (1 << 0); - } - - // processo dagli stati + gravi... - if (hasAlarms) - { - byteSignals += (1 << 3); - } - else - { - byteSignals += (1 << 1); - } - - // verifico SE ho strobe/hack da chiudere - if (strobeVal != 0) - { - checkStrobeHack(); - } - // salvo! - B_input = byteSignals; - } - - #endregion Protected Methods - #region Public Methods /// @@ -278,5 +141,140 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected int strobeVal = 0; + + #endregion Protected Fields + +#if false + protected bool hasAlarms + { + get + { + bool answ = false; + int numErrors = 0; + uint currStatus = 0; + if (alarmMaps != null) + { + // leggo a ciclo le aree degli allarmi CONFIGURATI, se ne trovo --> segnalo allarme... + foreach (var item in alarmMaps) + { + // banchi in WORD (2 byte) --> scompongo + for (int i = 0; i < item.size / 2; i++) + { + currStatus = S7.Net.Types.Counter.FromByteArray(RawInput.Skip(item.index + 2 * i).Take(2).ToArray()); + // verifica e decremento blink... + item.checkBlinkCounter(i, (uint)currStatus); + + // verifico SE sia variato... confronto allarmi filtrato stile blink per + // bit status: + // - allarmi che iniziano per # IGNORATI + // - altri allarmi con un countdown da MAX_COUNTER_BLINK a 0 per il + // fronte di discesa + if (item.isChanged(i, currStatus)) + { + if (currStatus > 0) + { + numErrors++; + } + // registro gli allarmi attivi e trasmetto... + if (sendAlarmVariations(item.memAddr, i, item.alarmsState[i], (uint)(item.alarmsMask[i] & currStatus), item.messages)) + { + // se inviato --> salvo stato da current... + item.updStatusVal(i, (uint)(item.alarmsMask[i] & currStatus)); + } + } + } + } + } + answ = numErrors > 0; + return answ; + } + } +#endif + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// - per lo scopo specifico IN REALTA' non conta lo stato macchina.... ma lo inviamo lo stesso + /// + protected override void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + + /* ----------------------------------------------------- + * bitmap MAPO STANDARD + * B0: POWER_ON + * B1: RUN + * B2: pzCount + * B3: allarme + * + ----------------------------------------------------- */ + + //bool fatto = false; + //ushort valW = 0; + + var MemInt = new byte[2]; + + int byteSignals = 0; + // bit 0 (poweron) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSignals += (1 << 0); + } + + // processo dagli stati + gravi... + if (hasAlarms) + { + byteSignals += (1 << 3); + } + else + { + byteSignals += (1 << 1); + } + + // verifico SE ho strobe/hack da chiudere + if (strobeVal != 0) + { + checkStrobeHack(); + } + // salvo! + B_input = byteSignals; + } + + #endregion Protected Methods + + #region Private Methods + + private void checkStrobeHack() + { + // verifico SE ho un hack sulla var DB85.DB268 + byte[] byteCtrlW = new byte[2]; + bool fatto = S7ReadBB(ref byteCtrlW, "DB85.DBB268", 2); + ushort valCtrlW = S7.Net.Types.Word.FromByteArray(byteCtrlW.ToArray()); + // se vale 1 --> resetto strobe! + if (valCtrlW == 1) + { + // aggiunta finale bit a 0 x chiusura processing.. + var MemBlock = S7.Net.Types.Int.ToByteArray(0); + var memAddrWrite = "DB85.DBB308"; + // imposto valore strobe x check successivi + var taskOk = S7WriteBB(ref MemBlock, memAddrWrite); + if (taskOk) + { + strobeVal = 0; + } + } + else + { + lgInfo("SiemensComeca: Strobe attivo su DBB308, ack non rilevato su DBB268"); + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensComur.cs b/IOB-WIN-NEXT/IobSiemensComur.cs index d9ce976a..80afb3a1 100644 --- a/IOB-WIN-NEXT/IobSiemensComur.cs +++ b/IOB-WIN-NEXT/IobSiemensComur.cs @@ -63,80 +63,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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: allarme creatore - * - * - * - BIT di stato - * - DBX0.0 - Macchina On: Segnale pulito di informazione sullo stato della macchina. 0->Aux OFF, 1->Aux ON - * - DBX0.1 – Macchina in Allarme: Segnale pulito di macchina in allarme. 0->Nessun Allarme, 1->E’ presente almeno un allarme/anomalia - * - DBX0.2 – Macchina in Ciclo: Segnale pulito sullo stato di funzionamento. 0->La macchina NON sta eseguendo un ciclo automatico, 1->La macchina sta eseguendo un ciclo automatico. - * - DBX0.3 – Macchina Non in Produzione: Segnale pulito sullo stato della macchina. 0->Macchina accesa e in lavorazione automatica, 1->Macchina accesa ma NON sta eseguendo un ciclo automatico. - * - DBX0.4 – Macchina In Ciclo Continuità: Segnale pulito sullo stato di funzionamento. 1->La macchina sta eseguendo un ciclo automatico con carico/scarico pezzo autonomo, 0-> Altrimenti. NON HA SENSO perché NON HANNO il robot... - * - DBX0.7 – Assi In Moto: Segnale pulito sullo stato di movimento Assi. 0->Tutti gli assi della macchina sono fermi, 1->Almeno un asse si sta muovendo. - * - DBX1.0 – Impulso Start Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Start Ciclo. - * - DBX1.1 – Impulso Fine Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Fine Ciclo. Attenzione! Questo impulso viene generato solo se il Ciclo Automatico finisce correttamente. Non viene generato nel caso in cui il Ciclo Automatico venga interrotto da allarmi. - * - DBX1.3 – Impulso Conta Pezzi: Impulso a fronte positivo (0->1) della durata di 1’’ generato al completamento di ogni programma pezzo. - * - DBX2.0 – Preallarmi Pezzi: Segnale pulito di segnalazione Preallarme Pezzi impostabile su CN. 0->Preallarme Disattivo, 1->Preallarme Attivo - * - DBX2.1 – Allarme Pezzi: Segnale pulito di segnalazione Allarme Pezzi impostabile su CN. 0->Allarme Disattivo, 1->Allarme Attivo. - * - DBX2.3 – Fine Vita Utensile: Segnale pulito di segnalazione Allarme Fine Vita Creatore. 0->Allarme Disattivo, 1->Allarme Attivo. - * - DBX2.7 – Ciclo In Attesa: Segnale pulito sullo stato di funzionamento. 1->Ciclo Automatico attivo ma tutti assi fermi, 0->Altrimenti. - * - ----------------------------------------------------- */ - - byte mainData = RawInput[0]; - - int byteSignals = 0; - // bit 0 (poweron) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSignals += (1 << 0); - } - if ((mainData & (1 << 2)) != 0) - { - byteSignals += (1 << 1); - } - - // controllo il bit MAIN dello status - if ((mainData & (1 << 1)) != 0) - { - byteSignals += (1 << 3); - } - - // considero come MANUALE NON ciclo in continuo... - if ((mainData & (1 << 3)) != 0) - { - byteSignals += (1 << 4); - } - - // salvo! - B_input = byteSignals; - - // log opzionale! - if (verboseLog) - { - lgInfo($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}"); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -277,5 +203,79 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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: allarme creatore + * + * + * - BIT di stato + * - DBX0.0 - Macchina On: Segnale pulito di informazione sullo stato della macchina. 0->Aux OFF, 1->Aux ON + * - DBX0.1 – Macchina in Allarme: Segnale pulito di macchina in allarme. 0->Nessun Allarme, 1->E’ presente almeno un allarme/anomalia + * - DBX0.2 – Macchina in Ciclo: Segnale pulito sullo stato di funzionamento. 0->La macchina NON sta eseguendo un ciclo automatico, 1->La macchina sta eseguendo un ciclo automatico. + * - DBX0.3 – Macchina Non in Produzione: Segnale pulito sullo stato della macchina. 0->Macchina accesa e in lavorazione automatica, 1->Macchina accesa ma NON sta eseguendo un ciclo automatico. + * - DBX0.4 – Macchina In Ciclo Continuità: Segnale pulito sullo stato di funzionamento. 1->La macchina sta eseguendo un ciclo automatico con carico/scarico pezzo autonomo, 0-> Altrimenti. NON HA SENSO perché NON HANNO il robot... + * - DBX0.7 – Assi In Moto: Segnale pulito sullo stato di movimento Assi. 0->Tutti gli assi della macchina sono fermi, 1->Almeno un asse si sta muovendo. + * - DBX1.0 – Impulso Start Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Start Ciclo. + * - DBX1.1 – Impulso Fine Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Fine Ciclo. Attenzione! Questo impulso viene generato solo se il Ciclo Automatico finisce correttamente. Non viene generato nel caso in cui il Ciclo Automatico venga interrotto da allarmi. + * - DBX1.3 – Impulso Conta Pezzi: Impulso a fronte positivo (0->1) della durata di 1’’ generato al completamento di ogni programma pezzo. + * - DBX2.0 – Preallarmi Pezzi: Segnale pulito di segnalazione Preallarme Pezzi impostabile su CN. 0->Preallarme Disattivo, 1->Preallarme Attivo + * - DBX2.1 – Allarme Pezzi: Segnale pulito di segnalazione Allarme Pezzi impostabile su CN. 0->Allarme Disattivo, 1->Allarme Attivo. + * - DBX2.3 – Fine Vita Utensile: Segnale pulito di segnalazione Allarme Fine Vita Creatore. 0->Allarme Disattivo, 1->Allarme Attivo. + * - DBX2.7 – Ciclo In Attesa: Segnale pulito sullo stato di funzionamento. 1->Ciclo Automatico attivo ma tutti assi fermi, 0->Altrimenti. + * + ----------------------------------------------------- */ + + byte mainData = RawInput[0]; + + int byteSignals = 0; + // bit 0 (poweron) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSignals += (1 << 0); + } + if ((mainData & (1 << 2)) != 0) + { + byteSignals += (1 << 1); + } + + // controllo il bit MAIN dello status + if ((mainData & (1 << 1)) != 0) + { + byteSignals += (1 << 3); + } + + // considero come MANUALE NON ciclo in continuo... + if ((mainData & (1 << 3)) != 0) + { + byteSignals += (1 << 4); + } + + // salvo! + B_input = byteSignals; + + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}"); + } + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensCosmap.cs b/IOB-WIN-NEXT/IobSiemensCosmap.cs index 373910de..d3436ffb 100644 --- a/IOB-WIN-NEXT/IobSiemensCosmap.cs +++ b/IOB-WIN-NEXT/IobSiemensCosmap.cs @@ -3,7 +3,6 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; -using System.Threading; namespace IOB_WIN_NEXT { @@ -50,88 +49,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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 (1=attiva/premuta, 0=armed) - * - ----------------------------------------------------- */ - - //bool fatto = false; - ushort currStatus = 0; - ushort allarme = 0; - //ushort valW = 0; - - var MemInt = new byte[2]; - - // recupero - //fatto = S7ReadBB(ref MemInt, "DB6.DBW204", 2); - //valW = S7.Net.Types.Word.FromByteArray(MemInt.ToArray()); - //var testalW = S7.Net.Types.Word.FromByteArray(RawInput.Skip(204).Take(2).ToArray()); - currStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(204).Take(2).ToArray()); - - //fatto = S7ReadBB(ref MemInt, "DB6.DBW206", 2); - //valW = S7.Net.Types.Word.FromByteArray(MemInt.ToArray()); - //allarme = valW; - allarme = S7.Net.Types.Word.FromByteArray(RawInput.Skip(206).Take(2).ToArray()); - - int byteSignals = 0; - // bit 0 (poweron) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSignals += (1 << 0); - } - - // processo dagli stati + gravi... - if (allarme > 0) - { - byteSignals += (1 << 3); - } - - switch (currStatus) - { - case 1: - byteSignals += (1 << 1); - break; - - case 2: - byteSignals += (1 << 4); - break; - - case 3: - byteSignals += (1 << 5); - break; - - default: - break; - } - - // salvo! - B_input = byteSignals; - - // log opzionale! - if (verboseLog) - { - lgInfo($"Trasformazione dati: Status:{currStatus} | alarm:{allarme} --> B_input: {B_input}"); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -280,5 +197,87 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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 (1=attiva/premuta, 0=armed) + * + ----------------------------------------------------- */ + + //bool fatto = false; + ushort currStatus = 0; + ushort allarme = 0; + //ushort valW = 0; + + var MemInt = new byte[2]; + + // recupero + //fatto = S7ReadBB(ref MemInt, "DB6.DBW204", 2); + //valW = S7.Net.Types.Word.FromByteArray(MemInt.ToArray()); + //var testalW = S7.Net.Types.Word.FromByteArray(RawInput.Skip(204).Take(2).ToArray()); + currStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(204).Take(2).ToArray()); + + //fatto = S7ReadBB(ref MemInt, "DB6.DBW206", 2); + //valW = S7.Net.Types.Word.FromByteArray(MemInt.ToArray()); + //allarme = valW; + allarme = S7.Net.Types.Word.FromByteArray(RawInput.Skip(206).Take(2).ToArray()); + + int byteSignals = 0; + // bit 0 (poweron) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSignals += (1 << 0); + } + + // processo dagli stati + gravi... + if (allarme > 0) + { + byteSignals += (1 << 3); + } + + switch (currStatus) + { + case 1: + byteSignals += (1 << 1); + break; + + case 2: + byteSignals += (1 << 4); + break; + + case 3: + byteSignals += (1 << 5); + break; + + default: + break; + } + + // salvo! + B_input = byteSignals; + + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione dati: Status:{currStatus} | alarm:{allarme} --> B_input: {B_input}"); + } + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensFape.cs b/IOB-WIN-NEXT/IobSiemensFape.cs index 6c2d6bfd..81fac982 100644 --- a/IOB-WIN-NEXT/IobSiemensFape.cs +++ b/IOB-WIN-NEXT/IobSiemensFape.cs @@ -95,6 +95,31 @@ namespace IOB_WIN_NEXT #endregion Public Enums + #region Public Methods + + /// + /// Recupero dati override in formato dictionary + /// + /// + public override Dictionary getDynData() + { + Dictionary outVal = new Dictionary(); + ushort valStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); + ushort valPosit = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray()); + outVal.Add("CURR_STATO", ((statoMacchina)valStatus).ToString()); + outVal.Add("CURR_POSIT", ((posizioneSequenza)valPosit).ToString()); + return outVal; + } + + /// + /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid) + /// + public override void processOverride() + { + } + + #endregion Public Methods + #region Protected Methods /// @@ -263,30 +288,5 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods - - #region Public Methods - - /// - /// Recupero dati override in formato dictionary - /// - /// - public override Dictionary getDynData() - { - Dictionary outVal = new Dictionary(); - ushort valStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); - ushort valPosit = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray()); - outVal.Add("CURR_STATO", ((statoMacchina)valStatus).ToString()); - outVal.Add("CURR_POSIT", ((posizioneSequenza)valPosit).ToString()); - return outVal; - } - - /// - /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid) - /// - public override void processOverride() - { - } - - #endregion Public Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensIngenia.cs b/IOB-WIN-NEXT/IobSiemensIngenia.cs index 145bfd45..4ae5811f 100644 --- a/IOB-WIN-NEXT/IobSiemensIngenia.cs +++ b/IOB-WIN-NEXT/IobSiemensIngenia.cs @@ -58,14 +58,6 @@ namespace IOB_WIN_NEXT * * -------------------------------------------------------------------------------- */ - #region Protected Fields - - protected int counterMes2Plc = 0; - protected int counterPlc2Mes = 0; - protected DateTime lastPLCWatchDog; - - #endregion Protected Fields - #region Public Constructors /// @@ -81,80 +73,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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 - #region Public Methods /// @@ -299,5 +217,87 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected int counterMes2Plc = 0; + protected int counterPlc2Mes = 0; + protected DateTime lastPLCWatchDog; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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 } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensLasco.cs b/IOB-WIN-NEXT/IobSiemensLasco.cs index 90a71f2a..5650c47f 100644 --- a/IOB-WIN-NEXT/IobSiemensLasco.cs +++ b/IOB-WIN-NEXT/IobSiemensLasco.cs @@ -60,16 +60,6 @@ namespace IOB_WIN_NEXT * -------------------------------------------------------------------------------- */ - #region Protected Fields - - protected int counterMes2Plc = 0; - protected int counterPlc2Mes = 0; - protected int counterPlc2MesWrote = 0; - protected DateTime lastPLCWatchDog; - protected bool useNewSend = false; - - #endregion Protected Fields - #region Public Constructors /// @@ -118,77 +108,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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: RUN STATE - * - DBX0.1: CYCLE - * - DBX0.2: MANUAL MODE - * - DBX0.3: GENERAL ALARM - * - DBX0.4: ESTOP (1=OK, 0 = emergency) - * - DBX0.5: SAFETY DOORS - ----------------------------------------------------- */ - - byte mainData = RawInput[0]; - - int byteSignals = 0; - // bit 0 (poweron) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSignals += (1 << 0); - } - if ((mainData & (1 << 0)) == 1) - { - byteSignals += (1 << 1); - } - - // EMERGENZA - if ((mainData & (1 << 5)) == 1) - { - byteSignals += (1 << 5); - } - // ALLARME - if ((mainData & (1 << 3)) == 1) - { - byteSignals += (1 << 3); - } - - // MANUALE ... - if ((mainData & (1 << 2)) == 1) - { - byteSignals += (1 << 4); - } - - // salvo! - B_input = byteSignals; - - // log opzionale! - if (verboseLog) - { - lgInfo(string.Format($"Trasformazione dati: RawInput:{RawInput[3]} --> B_input: {B_input}")); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -561,8 +480,8 @@ namespace IOB_WIN_NEXT public override void processWhatchDog() { - // scrive nel primo byte, ultimo bit, il watchdog, mentre scrive nel primo 1 = setup, 0 = run - // scrivo 1 volta al secondo il contatore incrementale su area apposita + // scrive nel primo byte, ultimo bit, il watchdog, mentre scrive nel primo 1 = setup, 0 + // = run scrivo 1 volta al secondo il contatore incrementale su area apposita DateTime adesso = DateTime.Now; if (adesso.Subtract(lastPLCWatchDog).TotalSeconds > watchDogPeriod) { @@ -581,5 +500,86 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected int counterMes2Plc = 0; + protected int counterPlc2Mes = 0; + protected int counterPlc2MesWrote = 0; + protected DateTime lastPLCWatchDog; + protected bool useNewSend = false; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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: RUN STATE + * - DBX0.1: CYCLE + * - DBX0.2: MANUAL MODE + * - DBX0.3: GENERAL ALARM + * - DBX0.4: ESTOP (1=OK, 0 = emergency) + * - DBX0.5: SAFETY DOORS + ----------------------------------------------------- */ + + byte mainData = RawInput[0]; + + int byteSignals = 0; + // bit 0 (poweron) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSignals += (1 << 0); + } + if ((mainData & (1 << 0)) == 1) + { + byteSignals += (1 << 1); + } + + // EMERGENZA + if ((mainData & (1 << 5)) == 1) + { + byteSignals += (1 << 5); + } + // ALLARME + if ((mainData & (1 << 3)) == 1) + { + byteSignals += (1 << 3); + } + + // MANUALE ... + if ((mainData & (1 << 2)) == 1) + { + byteSignals += (1 << 4); + } + + // salvo! + B_input = byteSignals; + + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format($"Trasformazione dati: RawInput:{RawInput[3]} --> B_input: {B_input}")); + } + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensNWSE.cs b/IOB-WIN-NEXT/IobSiemensNWSE.cs index a96f3a0a..45ece468 100644 --- a/IOB-WIN-NEXT/IobSiemensNWSE.cs +++ b/IOB-WIN-NEXT/IobSiemensNWSE.cs @@ -1,8 +1,6 @@ using MapoSDK; -using Newtonsoft.Json; using System; using System.Collections.Generic; -using System.Linq; using System.Threading; namespace IOB_WIN_NEXT @@ -25,12 +23,12 @@ namespace IOB_WIN_NEXT * B00..B15 --> 16 byte di allarmi (osmosi, depurazione, 6 x filtri) * B20..B35 --> 16 byte di stati (osmosi, depurazione, 6 x filtri) * B40..B49 --> 5 valori uint lettura parametri - * + * * * * STRUTTURA MEMORIA DB101: (scrittura) 14byte, solo 2 impiegati x ora * NB: segnali da tenere attivi ALMENO 3 secondi x farli recepire - * + * * B0.0 Bit Azzeramento volume acqua OSMOSI * B0.1 Bit Azzeramento volume acqua DEPURAZIONE * @@ -38,12 +36,6 @@ namespace IOB_WIN_NEXT * * -------------------------------------------------------------------------------- */ - #region Protected Fields - - protected bool EmergencyBypass = false; - - #endregion Protected Fields - #region Public Constructors /// @@ -64,6 +56,114 @@ namespace IOB_WIN_NEXT #endregion Public Constructors + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + lgInfo($"Chiamata executeTasks specifica IobSiemensNWS: {task2exe.Count} task ricevuti"); + // Verificare il protocollo: dovrebeb togliere SOLO i task eseguiti... + Dictionary taskDone = new Dictionary(); + bool taskOk = false; + string taskVal = ""; + // inizio con 1 byte di default + byte[] MemBlock = new byte[1]; + string memAddrWrite = ""; + if (task2exe != null) + { + // cerco task specifici + foreach (var item in task2exe) + { + taskOk = false; + taskVal = ""; + // converto richiesta in enum... + taskType tName = taskType.nihil; + Enum.TryParse(item.Key, out tName); + // controllo sulla KEY + switch (tName) + { + case taskType.forceResetPzCount: + // usato x resettare i contatori osmosi inversa e depurazione processo + // scrittura BIT su DB101.DBB0 per + MemBlock = new byte[1]; + // scrivo 3 x resettare entrambi i contatori + MemBlock = S7.Net.Types.Byte.ToByteArray(3); + memAddrWrite = "DB101.DB0"; + // scrivo! + taskOk = S7WriteBB(ref MemBlock, memAddrWrite); + // attesa 3.5 sec sec + Thread.Sleep(3500); + // predispongo x reset valore 0... + MemBlock = S7.Net.Types.Byte.ToByteArray(0); + + break; + + // lasciato commentato, da rivalutare... +#if false + case taskType.setParameter: + // richiedo da URL i parametri WRITE da popolare + lgInfo("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; +#endif + + default: + taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; + break; + } + + lgInfo($"executeTask | task name: {tName} | task value: {taskVal}"); + // aggiungo task! + taskDone.Add(item.Key, taskVal); + if (!string.IsNullOrEmpty(memAddrWrite)) + { + // scrivo! + taskOk = S7WriteBB(ref MemBlock, memAddrWrite); + } + if (taskOk) + { + // aggiorno valore memoria... SE presente + if (memMap.mMapWrite.ContainsKey(item.Key)) + { + memMap.mMapWrite[item.Key].value = item.Value; + lgInfo($"Aggiornato valore in mMapWrite per {item.Key}"); + } + lgInfo($"Eseguita con successo S7WriteBB per executeTasks: {item.Key} | {item.Value}"); + } + else + { + lgError($"Errore in S7WriteBB durante executeTasks: {item.Key} | {item.Value}"); + } + } + } + return taskDone; + } + + #endregion Public Methods + + #region Protected Fields + + protected bool EmergencyBypass = false; + + #endregion Protected Fields + #region Protected Methods /// @@ -116,107 +216,5 @@ namespace IOB_WIN_NEXT } #endregion Protected Methods - - #region Public Methods - - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - lgInfo($"Chiamata executeTasks specifica IobSiemensNWS: {task2exe.Count} task ricevuti"); - // Verificare il protocollo: dovrebeb togliere SOLO i task eseguiti... - Dictionary taskDone = new Dictionary(); - bool taskOk = false; - string taskVal = ""; - // inizio con 1 byte di default - byte[] MemBlock = new byte[1]; - string memAddrWrite = ""; - if (task2exe != null) - { - // cerco task specifici - foreach (var item in task2exe) - { - taskOk = false; - taskVal = ""; - // converto richiesta in enum... - taskType tName = taskType.nihil; - Enum.TryParse(item.Key, out tName); - // controllo sulla KEY - switch (tName) - { - case taskType.forceResetPzCount: - // usato x resettare i contatori osmosi inversa e depurazione - // processo scrittura BIT su DB101.DBB0 per - MemBlock = new byte[1]; - // scrivo 3 x resettare entrambi i contatori - MemBlock = S7.Net.Types.Byte.ToByteArray(3); - memAddrWrite = "DB101.DB0"; - // scrivo! - taskOk = S7WriteBB(ref MemBlock, memAddrWrite); - // attesa 3.5 sec sec - Thread.Sleep(3500); - // predispongo x reset valore 0... - MemBlock = S7.Net.Types.Byte.ToByteArray(0); - - break; - - // lasciato commentato, da rivalutare... -#if false - case taskType.setParameter: - // richiedo da URL i parametri WRITE da popolare - lgInfo("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; -#endif - - default: - taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; - break; - } - - lgInfo($"executeTask | task name: {tName} | task value: {taskVal}"); - // aggiungo task! - taskDone.Add(item.Key, taskVal); - if (!string.IsNullOrEmpty(memAddrWrite)) - { - // scrivo! - taskOk = S7WriteBB(ref MemBlock, memAddrWrite); - } - if (taskOk) - { - // aggiorno valore memoria... SE presente - if (memMap.mMapWrite.ContainsKey(item.Key)) - { - memMap.mMapWrite[item.Key].value = item.Value; - lgInfo($"Aggiornato valore in mMapWrite per {item.Key}"); - } - lgInfo($"Eseguita con successo S7WriteBB per executeTasks: {item.Key} | {item.Value}"); - } - else - { - lgError($"Errore in S7WriteBB durante executeTasks: {item.Key} | {item.Value}"); - } - } - } - return taskDone; - } - - #endregion Public Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensPressoilCei.cs b/IOB-WIN-NEXT/IobSiemensPressoilCei.cs index 8926faa3..92205721 100644 --- a/IOB-WIN-NEXT/IobSiemensPressoilCei.cs +++ b/IOB-WIN-NEXT/IobSiemensPressoilCei.cs @@ -18,14 +18,6 @@ namespace IOB_WIN_NEXT * -------------------------------------------------------------------------------- */ - #region Protected Fields - - protected int counterMes2Plc = 0; - protected int counterPlc2Mes = 0; - protected DateTime lastPLCWatchDog; - - #endregion Protected Fields - #region Public Constructors /// @@ -40,77 +32,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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 - Life bit - * - DBX0.1 – Macchina lavora - * - DBX0.2 – Macchina in ciclo - * - DBX0.3 – Macchina in manuale - * - DBX0.4 – Macchina in allarme - * - DBX0.5 – Macchina in emergenza - * - ----------------------------------------------------- */ - - 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 << 1)) != 0 && (mainData & (1 << 2)) != 0) - { - byteSignals += (1 << 1); - } - // manuale - if ((mainData & (1 << 3)) != 0) - { - byteSignals += (1 << 4); - } - // allarme - if ((mainData & (1 << 4)) != 0) - { - byteSignals += (1 << 3); - } - // emergenza - if ((mainData & (1 << 5)) != 0) - { - byteSignals += (1 << 5); - } - - // salvo! - B_input = byteSignals; - - // log opzionale! - if (verboseLog) - { - lgInfo($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}"); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -270,5 +191,84 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected int counterMes2Plc = 0; + protected int counterPlc2Mes = 0; + protected DateTime lastPLCWatchDog; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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 - Life bit + * - DBX0.1 – Macchina lavora + * - DBX0.2 – Macchina in ciclo + * - DBX0.3 – Macchina in manuale + * - DBX0.4 – Macchina in allarme + * - DBX0.5 – Macchina in emergenza + * + ----------------------------------------------------- */ + + 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 << 1)) != 0 && (mainData & (1 << 2)) != 0) + { + byteSignals += (1 << 1); + } + // manuale + if ((mainData & (1 << 3)) != 0) + { + byteSignals += (1 << 4); + } + // allarme + if ((mainData & (1 << 4)) != 0) + { + byteSignals += (1 << 3); + } + // emergenza + if ((mainData & (1 << 5)) != 0) + { + byteSignals += (1 << 5); + } + + // salvo! + B_input = byteSignals; + + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}"); + } + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensRobotService.cs b/IOB-WIN-NEXT/IobSiemensRobotService.cs index 325e40a6..38f5501e 100644 --- a/IOB-WIN-NEXT/IobSiemensRobotService.cs +++ b/IOB-WIN-NEXT/IobSiemensRobotService.cs @@ -2,8 +2,6 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; -using System.Linq; -using System.Threading; namespace IOB_WIN_NEXT { @@ -46,12 +44,6 @@ namespace IOB_WIN_NEXT * * -------------------------------------------------------------------------------- */ - #region Protected Fields - - protected bool EmergencyBypass = false; - - #endregion Protected Fields - #region Public Constructors /// @@ -72,61 +64,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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: MagOutPieno - * B6: MagInVuoto - * B7: Emergenza armata (1) - * - ----------------------------------------------------- */ - - byte mainData = RawInput[0]; - - // copio il primo byte - int byteSignals = RawInput[0]; - // bit 0 (poweron) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSignals |= (1 << 0); - } - else - { - byteSignals &= ~(1 << 0); - } - - // se bypass emergenza attivo --> forzo a ARMED... - if (EmergencyBypass) - { - byteSignals |= (1 << 7); - } - - // salvo! - B_input = byteSignals; - - // log opzionale! - if (verboseLog) - { - lgInfo($"Trasformazione dati: B0: {mainData} --> B_input: {B_input}"); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -275,5 +212,66 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected bool EmergencyBypass = false; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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: MagOutPieno + * B6: MagInVuoto + * B7: Emergenza armata (1) + * + ----------------------------------------------------- */ + + byte mainData = RawInput[0]; + + // copio il primo byte + int byteSignals = RawInput[0]; + // bit 0 (poweron) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSignals |= (1 << 0); + } + else + { + byteSignals &= ~(1 << 0); + } + + // se bypass emergenza attivo --> forzo a ARMED... + if (EmergencyBypass) + { + byteSignals |= (1 << 7); + } + + // salvo! + B_input = byteSignals; + + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione dati: B0: {mainData} --> B_input: {B_input}"); + } + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensSaet.cs b/IOB-WIN-NEXT/IobSiemensSaet.cs index a92c667f..d2b05b34 100644 --- a/IOB-WIN-NEXT/IobSiemensSaet.cs +++ b/IOB-WIN-NEXT/IobSiemensSaet.cs @@ -59,15 +59,6 @@ namespace IOB_WIN_NEXT * -------------------------------------------------------------------------------- */ - #region Protected Fields - - protected int counterMes2Plc = 0; - protected int counterPlc2Mes = 0; - protected int counterPlc2MesWrote = 0; - protected DateTime lastPLCWatchDog; - - #endregion Protected Fields - #region Public Constructors /// @@ -83,86 +74,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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: anomalia - * - * - * - BIT di stato - * - DBX2.0: macchina accesa - * - DBX2.1: CICLO AUTO = NON HO ANOMALIE/ALLARMI (0 --> allarme) - * - DBX2.2: contapezzi - * - DBX2.3: MACCHINA IN CICLO AUTO = LAVORA - * - DBX2.4: ERRORE tra part code MES/SAET (blu) - * - DBX2.5: Anomalia presente (rosso) - ----------------------------------------------------- */ - - byte mainData = RawInput[2]; - - int byteSignals = 0; - // bit 0 (poweron) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSignals += (1 << 0); - } - if ((mainData & (1 << 3)) != 0) - { - byteSignals += (1 << 1); - } - - // controllo il bit ALLARME - if ((mainData & (1 << 1)) == 0) - { - byteSignals += (1 << 3); - } - - // controllo il bit ANOMALIA - if ((mainData & (1 << 5)) != 0) - { - byteSignals += (1 << 3); - } - - // considero NON auto come manuale... - if ((mainData & (1 << 3)) == 0) - { - byteSignals += (1 << 4); - } - - // salvo! - B_input = byteSignals; - - // processo il watchdog! - counterPlc2Mes = S7.Net.Types.Int.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); - // ogni 60 registro... - if (Math.Abs(counterPlc2Mes - counterPlc2MesWrote) > 60) - { - lgInfo($"WatchDog da PLC: {counterPlc2Mes}"); - counterPlc2MesWrote = counterPlc2Mes; - } - // log opzionale! - if (verboseLog) - { - lgInfo($"Trasformazione dati: RawInput:{RawInput[3]} --> B_input: {B_input}"); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -338,5 +249,94 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected int counterMes2Plc = 0; + protected int counterPlc2Mes = 0; + protected int counterPlc2MesWrote = 0; + protected DateTime lastPLCWatchDog; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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: anomalia + * + * + * - BIT di stato + * - DBX2.0: macchina accesa + * - DBX2.1: CICLO AUTO = NON HO ANOMALIE/ALLARMI (0 --> allarme) + * - DBX2.2: contapezzi + * - DBX2.3: MACCHINA IN CICLO AUTO = LAVORA + * - DBX2.4: ERRORE tra part code MES/SAET (blu) + * - DBX2.5: Anomalia presente (rosso) + ----------------------------------------------------- */ + + byte mainData = RawInput[2]; + + int byteSignals = 0; + // bit 0 (poweron) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSignals += (1 << 0); + } + if ((mainData & (1 << 3)) != 0) + { + byteSignals += (1 << 1); + } + + // controllo il bit ALLARME + if ((mainData & (1 << 1)) == 0) + { + byteSignals += (1 << 3); + } + + // controllo il bit ANOMALIA + if ((mainData & (1 << 5)) != 0) + { + byteSignals += (1 << 3); + } + + // considero NON auto come manuale... + if ((mainData & (1 << 3)) == 0) + { + byteSignals += (1 << 4); + } + + // salvo! + B_input = byteSignals; + + // processo il watchdog! + counterPlc2Mes = S7.Net.Types.Int.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); + // ogni 60 registro... + if (Math.Abs(counterPlc2Mes - counterPlc2MesWrote) > 60) + { + lgInfo($"WatchDog da PLC: {counterPlc2Mes}"); + counterPlc2MesWrote = counterPlc2Mes; + } + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione dati: RawInput:{RawInput[3]} --> B_input: {B_input}"); + } + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensSimec.cs b/IOB-WIN-NEXT/IobSiemensSimec.cs index 5379caaf..a02df696 100644 --- a/IOB-WIN-NEXT/IobSiemensSimec.cs +++ b/IOB-WIN-NEXT/IobSiemensSimec.cs @@ -59,82 +59,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - 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 (1=attiva/premuta, 0=armed) - * - * - BIT di stato - * DB29 blocco dati letto dal MES Byte Bit - * CicloOn Bool 0 0 - * MacchOn Bool 0 1 - * ManualeOn Bool 0 2 - * AllarmiOn Bool 0 3 - * EmergenzaOn Bool 0 4 - * EmergenzaPremuta Bool 0 5 - * ContapezziAssoluto DInt 2 - * Comtapezzi parziale DInt 6 - * - ----------------------------------------------------- */ - - byte mainData = RawInput[0]; - - int byteSignals = 0; - // bit 0 (poweron) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSignals += (1 << 0); - } - - // lavora --> bit0 e bit1: cicloOn AND macchOn - if ((mainData & (1 << 0)) != 0 && (mainData & (1 << 1)) != 0) - { - byteSignals += (1 << 1); - } - - // controllo il bit ALARM - if ((mainData & (1 << 3)) != 0) - { - byteSignals += (1 << 3); - } - // controllo il bit emergenza dello status - if ((mainData & (1 << 5)) != 0) - { - byteSignals += (1 << 5); - } - - // check MANUALE ... - if ((mainData & (1 << 2)) != 0) - { - byteSignals += (1 << 4); - } - - // salvo! - B_input = byteSignals; - - // log opzionale! - if (verboseLog) - { - lgInfo($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}"); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -248,6 +172,7 @@ namespace IOB_WIN_NEXT } } break; + default: taskVal = "SKIPPED | NO EXEC"; break; @@ -264,5 +189,81 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + 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 (1=attiva/premuta, 0=armed) + * + * - BIT di stato + * DB29 blocco dati letto dal MES Byte Bit + * CicloOn Bool 0 0 + * MacchOn Bool 0 1 + * ManualeOn Bool 0 2 + * AllarmiOn Bool 0 3 + * EmergenzaOn Bool 0 4 + * EmergenzaPremuta Bool 0 5 + * ContapezziAssoluto DInt 2 + * Comtapezzi parziale DInt 6 + * + ----------------------------------------------------- */ + + byte mainData = RawInput[0]; + + int byteSignals = 0; + // bit 0 (poweron) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSignals += (1 << 0); + } + + // lavora --> bit0 e bit1: cicloOn AND macchOn + if ((mainData & (1 << 0)) != 0 && (mainData & (1 << 1)) != 0) + { + byteSignals += (1 << 1); + } + + // controllo il bit ALARM + if ((mainData & (1 << 3)) != 0) + { + byteSignals += (1 << 3); + } + // controllo il bit emergenza dello status + if ((mainData & (1 << 5)) != 0) + { + byteSignals += (1 << 5); + } + + // check MANUALE ... + if ((mainData & (1 << 2)) != 0) + { + byteSignals += (1 << 4); + } + + // salvo! + B_input = byteSignals; + + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}"); + } + } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSiemensTorri.cs b/IOB-WIN-NEXT/IobSiemensTorri.cs index e5b1390f..763f935f 100644 --- a/IOB-WIN-NEXT/IobSiemensTorri.cs +++ b/IOB-WIN-NEXT/IobSiemensTorri.cs @@ -17,12 +17,6 @@ namespace IOB_WIN_NEXT * mod: 2019.04.06: aggiunta indicazione (IOB--> PLC) di stato setup su DB701.B0.4 * -------------------------------------------------------------------------------- */ - #region Protected Fields - - protected Dictionary lastReadAlarms = new Dictionary(); - - #endregion Protected Fields - #region Public Constructors /// @@ -38,228 +32,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Methods - - private int checkAlarmBank(string memAddrAlarms) - { - int trovato = 0; - uint valDW = 0; - var MemBlockPZ = new byte[4]; - bool fatto = S7ReadBB(ref MemBlockPZ, memAddrAlarms, 4); - //if (fatto) - //{ - valDW = S7.Net.Types.DWord.FromByteArray(MemBlockPZ.ToArray()); - // se <> 0 --> log e accodo a dynData - if (valDW != 0) - { - string key = $"MTH_ALARM_{memAddrAlarms}_{valDW}"; - var biteVal = baseUtils.binaryForm(valDW); - lgInfo($"Stato allarmi rilevati: {key} | {valDW} | {biteVal}"); - // accodo a dictionary - string almMsg = $"{DateTime.Now} | val {valDW} | {biteVal}"; - // se non ci fosse aggiungo - if (!lastReadAlarms.ContainsKey(key)) - { - lastReadAlarms.Add(key, almMsg); - } - trovato++; - } - //} - return trovato; - } - - private void checkAlarms() - { - // leggo i banchi allarmi : cablato D700.DBDW2 --> D700 DBDW14, sono 4 banchi a 32 bit da verificare - - int trovati = 0; - // ciclo nei 4 banchi... - trovati += checkAlarmBank("DB700.DBDW2"); - trovati += checkAlarmBank("DB700.DBDW6"); - trovati += checkAlarmBank("DB700.DBDW10"); - trovati += checkAlarmBank("DB700.DBDW14"); - } - - #endregion Private Methods - - #region Protected Methods - - /// - /// Decodifica il resto dell'area TORRI x i dati accessori (allarmi, ...) - /// - protected override void decodeOtherData() - { - if (verboseLog) - { - } - } - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - protected override void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - // TORRI: leggo i primi 8 bit hard coded... - int byteSem = RawInput[0]; - - // azzero powerOn... - byteSem &= ~(1 << 0); - // bit 0 (powerOn) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSem += (1 << 0); - } - - // azzero i bit NON gestiti (2-5-6-7) - byteSem &= ~(1 << 2); - byteSem &= ~(1 << 5); - byteSem &= ~(1 << 6); - byteSem &= ~(1 << 7); - // leggo bit DB700.B1.4 e lo porto al bit 5 --> ciclo test/accensione/spegnimento - if ((RawInput[1] & (1 << 4)) != 0) //se RawInput[1] & 16-- > 5° bit-- > TEST - { - byteSem += (1 << 5); - } - // salvo infine variabile bit x invio - B_input = byteSem; - - // se ho il bit di allarme - if ((RawInput[0] & (1 << 3)) != 0) - { - checkAlarms(); - } - - // procedo SOLO SE è enabled IOB - if (IobOnline) - { - try - { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrEmpty(currODL) || currODL == "0") - { - if (periodicLog) - { - lgInfo($"SiemensTorri | Lettura ODL andata a vuoto: currODL: {currODL}"); - } - } - else - { - // se variato o scaduto timeout log... - if (periodicLog || (currIdxODL.ToString() != currODL)) - { - lgInfo($"SiemensTorri | Lettura ODL, currODL: {currODL} --> currIdxODL prec: {currIdxODL}"); - } - // provo a salvare nuovo ODL - int.TryParse(currODL, out currIdxODL); - } - } - catch (Exception exc) - { - if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) - { - lgError(exc, $"Errore in fase di chiamata URL x ODL corrente | URL chiamato: {urlGetCurrODL}"); - lastWarnODL = DateTime.Now; - } - } - } - else - { - // imposto currODL a vuoto! - currODL = ""; - if (periodicLog) - { - lgInfo($"Fanuc | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); - } - } - if (!string.IsNullOrEmpty(currODL) && currODL != "0") - { - // ora processo il contapezzi... - string retVal = ""; - // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - // Salvo il contapezzi della macchina - retVal = utils.callUrlNow(urlSetPzCountMAC + contapezziPLC.ToString()); - // verifica se tutto OK, ovvero conferma i pezzi inviati - if (retVal != contapezziPLC.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio Contapezzi PLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB} | Valore tornato: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - - // se sono differenti MOSTRO... - if (contapezziPLC != contapezziIOB) - { - // registro contapezzi - lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); - } - if ((contapezziPLC > contapezziIOB)) - { - // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio - contapezziIOB++; - needRefreshPzCount = true; - // salvo in semaforo! - B_input += 1 << 2; - // registro contapezzi - lgInfo($"contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - - // Salvo il contapezzi della macchina - retVal = utils.callUrlNow(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK, ovvero conferma i pezzi inviati - if (retVal != contapezziIOB.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB} | Valore tornato: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - - // verifico se variato contapezzi... e se passato ritardo minimo... - if ((contapezziPLC - contapezziIOB) > minSendPzCountBlock) - { - trySendPzCountBlock(); - } - - // invio a server contapezzi (aggiornato) - retVal = utils.callUrlNow(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK - if (retVal != contapezziIOB.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio Contapezzi SIEMENS-TORRI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - else - { - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - - // log opzionale! - if (verboseLog) - { - lgInfo("Trasformazione B_input: {B_input}"); - } - } - - #endregion Protected Methods - #region Public Methods /// @@ -409,7 +181,8 @@ namespace IOB_WIN_NEXT outVal.Add("FEED_OVER", RawInput[19].ToString()); outVal.Add("RAPID_OVER", RawInput[20].ToString()); outVal.Add("CURR_MODE", decodeCurrMode(RawInput[21])); - // recupero RPM pezzo/mola !!!FARE!!! cambio nome da config, qui sono 01:conduttrice e 02:operatrice (3013), mentre sono pezzo/mola nella V100 + // recupero RPM pezzo/mola !!!FARE!!! cambio nome da config, qui sono 01:conduttrice e + // 02:operatrice (3013), mentre sono pezzo/mola nella V100 valDW = S7.Net.Types.DWord.FromByteArray(RawInput.Skip(24).Take(4).ToArray()); outVal.Add("RPM_01", valDW.ToString()); valDW = S7.Net.Types.DWord.FromByteArray(RawInput.Skip(28).Take(4).ToArray()); @@ -510,5 +283,235 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected Dictionary lastReadAlarms = new Dictionary(); + + #endregion Protected Fields + + #region Protected Methods + + /// + /// Decodifica il resto dell'area TORRI x i dati accessori (allarmi, ...) + /// + protected override void decodeOtherData() + { + if (verboseLog) + { + } + } + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + protected override void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + // TORRI: leggo i primi 8 bit hard coded... + int byteSem = RawInput[0]; + + // azzero powerOn... + byteSem &= ~(1 << 0); + // bit 0 (powerOn) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSem += (1 << 0); + } + + // azzero i bit NON gestiti (2-5-6-7) + byteSem &= ~(1 << 2); + byteSem &= ~(1 << 5); + byteSem &= ~(1 << 6); + byteSem &= ~(1 << 7); + // leggo bit DB700.B1.4 e lo porto al bit 5 --> ciclo test/accensione/spegnimento + if ((RawInput[1] & (1 << 4)) != 0) //se RawInput[1] & 16-- > 5° bit-- > TEST + { + byteSem += (1 << 5); + } + // salvo infine variabile bit x invio + B_input = byteSem; + + // se ho il bit di allarme + if ((RawInput[0] & (1 << 3)) != 0) + { + checkAlarms(); + } + + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo($"SiemensTorri | Lettura ODL andata a vuoto: currODL: {currODL}"); + } + } + else + { + // se variato o scaduto timeout log... + if (periodicLog || (currIdxODL.ToString() != currODL)) + { + lgInfo($"SiemensTorri | Lettura ODL, currODL: {currODL} --> currIdxODL prec: {currIdxODL}"); + } + // provo a salvare nuovo ODL + int.TryParse(currODL, out currIdxODL); + } + } + catch (Exception exc) + { + if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) + { + lgError(exc, $"Errore in fase di chiamata URL x ODL corrente | URL chiamato: {urlGetCurrODL}"); + lastWarnODL = DateTime.Now; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"Fanuc | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + if (!string.IsNullOrEmpty(currODL) && currODL != "0") + { + // ora processo il contapezzi... + string retVal = ""; + // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x + // distanziare invio e ridurre letture + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + // Salvo il contapezzi della macchina + retVal = utils.callUrlNow(urlSetPzCountMAC + contapezziPLC.ToString()); + // verifica se tutto OK, ovvero conferma i pezzi inviati + if (retVal != contapezziPLC.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi PLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB} | Valore tornato: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + + // se sono differenti MOSTRO... + if (contapezziPLC != contapezziIOB) + { + // registro contapezzi + lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); + } + if ((contapezziPLC > contapezziIOB)) + { + // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio + contapezziIOB++; + needRefreshPzCount = true; + // salvo in semaforo! + B_input += 1 << 2; + // registro contapezzi + lgInfo($"contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + + // Salvo il contapezzi della macchina + retVal = utils.callUrlNow(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK, ovvero conferma i pezzi inviati + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB} | Valore tornato: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + + // verifico se variato contapezzi... e se passato ritardo minimo... + if ((contapezziPLC - contapezziIOB) > minSendPzCountBlock) + { + trySendPzCountBlock(); + } + + // invio a server contapezzi (aggiornato) + retVal = utils.callUrlNow(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi SIEMENS-TORRI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + + // log opzionale! + if (verboseLog) + { + lgInfo("Trasformazione B_input: {B_input}"); + } + } + + #endregion Protected Methods + + #region Private Methods + + private int checkAlarmBank(string memAddrAlarms) + { + int trovato = 0; + uint valDW = 0; + var MemBlockPZ = new byte[4]; + bool fatto = S7ReadBB(ref MemBlockPZ, memAddrAlarms, 4); + //if (fatto) + //{ + valDW = S7.Net.Types.DWord.FromByteArray(MemBlockPZ.ToArray()); + // se <> 0 --> log e accodo a dynData + if (valDW != 0) + { + string key = $"MTH_ALARM_{memAddrAlarms}_{valDW}"; + var biteVal = baseUtils.binaryForm(valDW); + lgInfo($"Stato allarmi rilevati: {key} | {valDW} | {biteVal}"); + // accodo a dictionary + string almMsg = $"{DateTime.Now} | val {valDW} | {biteVal}"; + // se non ci fosse aggiungo + if (!lastReadAlarms.ContainsKey(key)) + { + lastReadAlarms.Add(key, almMsg); + } + trovato++; + } + //} + return trovato; + } + + private void checkAlarms() + { + // leggo i banchi allarmi : cablato D700.DBDW2 --> D700 DBDW14, sono 4 banchi a 32 bit + // da verificare + + int trovati = 0; + // ciclo nei 4 banchi... + trovati += checkAlarmBank("DB700.DBDW2"); + trovati += checkAlarmBank("DB700.DBDW6"); + trovati += checkAlarmBank("DB700.DBDW10"); + trovati += checkAlarmBank("DB700.DBDW14"); + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobWPS.cs b/IOB-WIN-NEXT/IobWPS.cs index e4d26e4f..57b23d63 100644 --- a/IOB-WIN-NEXT/IobWPS.cs +++ b/IOB-WIN-NEXT/IobWPS.cs @@ -9,13 +9,13 @@ using System.Collections.Generic; using System.IO; using System.Net.NetworkInformation; using System.Threading; -using System.Threading.Tasks; using System.Windows.Forms; namespace IOB_WIN_NEXT { /// - /// Generica classe per implementare WebPageScraping (scaricamento web pages anche js-based x recupero informazioni) + /// Generica classe per implementare WebPageScraping (scaricamento web pages anche js-based x + /// recupero informazioni) /// public class IobWPS : IobGeneric, IDisposable { @@ -27,40 +27,6 @@ namespace IOB_WIN_NEXT * * -------------------------------------------------------------------------------- */ - #region Protected Fields - - /// - /// Pagina web da scaricare - /// - protected string baseUri = "http://127.0.0.1"; - - /// - /// Array di configurazione degli oggetti da cercare x decodifica e recupero info - /// - protected Dictionary dataLocatorLUT; - - /// - /// Driver per gestione chiamate crawling/scraping - /// - protected IWebDriver driver; - - /// - /// Elementi da recuperare nella apgina web - /// - protected IWebElement element; - - /// - /// Vettore della frequenza di ogni status trovato... invio ogni 100 rilevazioni (modulo 100, resto == 1) - /// - protected Dictionary freqUnknStatus = new Dictionary(); - - /// - /// Oggetti decodificati da pagina - /// - protected MonitoredItemsConf monitoredItems; - - #endregion Protected Fields - #region Public Constructors /// @@ -76,115 +42,6 @@ namespace IOB_WIN_NEXT #endregion Public Constructors - #region Private Methods - - /// - /// Processo stati unknown... - /// - /// - private void processUnknStatus(string cKey) - { - // cerco se avevo già una key nella dictionary... - if (freqUnknStatus.ContainsKey(cKey)) - { - freqUnknStatus[cKey]++; - // se è 1 ogni 100 (%100, resto ==1) --> loggo... - if (freqUnknStatus[cKey] % 100 == 1) - { - lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey} | freq: {freqUnknStatus[cKey]}"); - // accodo come invio di tipo FLOG... - string sVal = string.Format("[UnknStatus] {0}, freq: {1}", cKey, freqUnknStatus); - // chiamo accodamento... - accodaFLog(sVal, qEncodeFLog("UnknStatus", sVal)); - } - } - else - { - // creo chiave con freq = 1 - freqUnknStatus.Add(cKey, 1); - // log iniziale - lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey}"); - } - } - - /// - /// Ricarica conf adapter... - /// - private void reloadAdapterConf() - { - // init obj display - newDisplayData currDispData = new newDisplayData(); - lgInfo("BEGIN reloadAdapterConf"); - // inizializzo LUT decodifica - string jsonConf = getOptPar("LUT_CONF"); - if (!string.IsNullOrEmpty(jsonConf)) - { - string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{jsonConf}"; - lgInfo($"Apertura file {jsonFullPath}"); - StreamReader reader = new StreamReader(jsonFullPath); - string jsonData = reader.ReadToEnd(); - if (!string.IsNullOrEmpty(jsonData)) - { - try - { - monitoredItems = JsonConvert.DeserializeObject(jsonData); - // salvo baseUri - baseUri = monitoredItems.SrvData.baseUri; - lgInfo($"baseUri = {baseUri}"); - // imposto a zero la bitmap x riavvio! - B_input = 0; - // FORZO invio dati... - accodaSigIN(ref currDispData); - // loggo! - lgInfo($"init input bitmap to zero: {B_input}"); - } - catch (Exception exc) - { - lgError(exc, "Eccezione in decodifica conf json"); - } - } - reader.Dispose(); - } - lgInfo("DONE reloadAdapterConf"); - raiseRefresh(currDispData); - } - - /// - /// Avvio del WebDriver - /// - private void startDriver() - { - if (monitoredItems.SrvData.driverName == "CHROME") - { - lgInfo("Starting CHROME Driver"); - // preparo opzione headless x CHROME - var o = new ChromeOptions(); - o.AddArgument("headless"); - ChromeDriverService service = ChromeDriverService.CreateDefaultService(Application.StartupPath); - service.HideCommandPromptWindow = true; - driver = new ChromeDriver(service, o); - } - else - { - lgInfo("Starting FIREFOX Driver"); - // preparo opzione headless x FIREFOX - var o = new FirefoxOptions(); - o.AddArgument("-headless"); - o.SetPreference("app.update.auto", false); - o.SetPreference("app.update.enabled", false); - FirefoxDriverService service = FirefoxDriverService.CreateDefaultService(Application.StartupPath); - service.HideCommandPromptWindow = true; - driver = new FirefoxDriver(service, o); - } - // aggiungo timeout x JScripts - driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20); - driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(20); - // imposto pagina di acquisizione - driver.Navigate().GoToUrl(baseUri); - } - - #endregion Private Methods - #region Public Methods public void Dispose() @@ -387,5 +244,149 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + /// + /// Pagina web da scaricare + /// + protected string baseUri = "http://127.0.0.1"; + + /// + /// Array di configurazione degli oggetti da cercare x decodifica e recupero info + /// + protected Dictionary dataLocatorLUT; + + /// + /// Driver per gestione chiamate crawling/scraping + /// + protected IWebDriver driver; + + /// + /// Elementi da recuperare nella apgina web + /// + protected IWebElement element; + + /// + /// Vettore della frequenza di ogni status trovato... invio ogni 100 rilevazioni (modulo + /// 100, resto == 1) + /// + protected Dictionary freqUnknStatus = new Dictionary(); + + /// + /// Oggetti decodificati da pagina + /// + protected MonitoredItemsConf monitoredItems; + + #endregion Protected Fields + + #region Private Methods + + /// + /// Processo stati unknown... + /// + /// + private void processUnknStatus(string cKey) + { + // cerco se avevo già una key nella dictionary... + if (freqUnknStatus.ContainsKey(cKey)) + { + freqUnknStatus[cKey]++; + // se è 1 ogni 100 (%100, resto ==1) --> loggo... + if (freqUnknStatus[cKey] % 100 == 1) + { + lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey} | freq: {freqUnknStatus[cKey]}"); + // accodo come invio di tipo FLOG... + string sVal = string.Format("[UnknStatus] {0}, freq: {1}", cKey, freqUnknStatus); + // chiamo accodamento... + accodaFLog(sVal, qEncodeFLog("UnknStatus", sVal)); + } + } + else + { + // creo chiave con freq = 1 + freqUnknStatus.Add(cKey, 1); + // log iniziale + lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey}"); + } + } + + /// + /// Ricarica conf adapter... + /// + private void reloadAdapterConf() + { + // init obj display + newDisplayData currDispData = new newDisplayData(); + lgInfo("BEGIN reloadAdapterConf"); + // inizializzo LUT decodifica + string jsonConf = getOptPar("LUT_CONF"); + if (!string.IsNullOrEmpty(jsonConf)) + { + string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{jsonConf}"; + lgInfo($"Apertura file {jsonFullPath}"); + StreamReader reader = new StreamReader(jsonFullPath); + string jsonData = reader.ReadToEnd(); + if (!string.IsNullOrEmpty(jsonData)) + { + try + { + monitoredItems = JsonConvert.DeserializeObject(jsonData); + // salvo baseUri + baseUri = monitoredItems.SrvData.baseUri; + lgInfo($"baseUri = {baseUri}"); + // imposto a zero la bitmap x riavvio! + B_input = 0; + // FORZO invio dati... + accodaSigIN(ref currDispData); + // loggo! + lgInfo($"init input bitmap to zero: {B_input}"); + } + catch (Exception exc) + { + lgError(exc, "Eccezione in decodifica conf json"); + } + } + reader.Dispose(); + } + lgInfo("DONE reloadAdapterConf"); + raiseRefresh(currDispData); + } + + /// + /// Avvio del WebDriver + /// + private void startDriver() + { + if (monitoredItems.SrvData.driverName == "CHROME") + { + lgInfo("Starting CHROME Driver"); + // preparo opzione headless x CHROME + var o = new ChromeOptions(); + o.AddArgument("headless"); + ChromeDriverService service = ChromeDriverService.CreateDefaultService(Application.StartupPath); + service.HideCommandPromptWindow = true; + driver = new ChromeDriver(service, o); + } + else + { + lgInfo("Starting FIREFOX Driver"); + // preparo opzione headless x FIREFOX + var o = new FirefoxOptions(); + o.AddArgument("-headless"); + o.SetPreference("app.update.auto", false); + o.SetPreference("app.update.enabled", false); + FirefoxDriverService service = FirefoxDriverService.CreateDefaultService(Application.StartupPath); + service.HideCommandPromptWindow = true; + driver = new FirefoxDriver(service, o); + } + // aggiungo timeout x JScripts + driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20); + driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(20); + // imposto pagina di acquisizione + driver.Navigate().GoToUrl(baseUri); + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/Objects.cs b/IOB-WIN-NEXT/Objects.cs index 5304b21f..f7a47577 100644 --- a/IOB-WIN-NEXT/Objects.cs +++ b/IOB-WIN-NEXT/Objects.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace IOB_WIN_NEXT { @@ -81,6 +78,11 @@ namespace IOB_WIN_NEXT /// public string nodeId { get; set; } = ""; + /// + /// Valore Registrato in formato byte array + /// + public byte[] rawByte { get; set; } = new byte[1]; + /// /// Valore (in sec) del periodo di downsampling (0 --> NON usato) /// @@ -101,11 +103,6 @@ namespace IOB_WIN_NEXT /// public string value { get; set; } = ""; - /// - /// Valore Registrato in formato byte array - /// - public byte[] rawByte { get; set; } = new byte[1]; - /// /// Timestamp data-ora evento registrato /// diff --git a/IOB-WIN-NEXT/Output.cs b/IOB-WIN-NEXT/Output.cs index b78c7e1b..e4a251e3 100644 --- a/IOB-WIN-NEXT/Output.cs +++ b/IOB-WIN-NEXT/Output.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { diff --git a/IOB-WIN-NEXT/TcAdsClient.cs b/IOB-WIN-NEXT/TcAdsClient.cs index 6e056c57..39b0c239 100644 --- a/IOB-WIN-NEXT/TcAdsClient.cs +++ b/IOB-WIN-NEXT/TcAdsClient.cs @@ -1,16 +1,10 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Net.NetworkInformation; using System.Threading; -using TwinCAT; +using System.Threading.Tasks; using TwinCAT.Ads; using TwinCAT.Ads.TypeSystem; -using System.IO; -using System.Text; -using System.Linq; -using System.Threading.Tasks; -using TwinCAT.TypeSystem; namespace IOB_WIN_NEXT { @@ -20,48 +14,6 @@ namespace IOB_WIN_NEXT public class TcAdsClient { - #region Private Fields - - /// - /// elenco delle variabili monitorate x change event - /// - private List _MonitVars = new List(); - - private int _status; - - private List addedSignalationList = new List(); - - /// - /// Dizionario di conversione da indice a index group e index offset - /// - private Dictionary> addressList; - - private TwinCAT.Ads.TcAdsClient adsClient; - - private CancellationTokenSource cts; - - private System.Threading.Tasks.Task dispatchertask; - -#if false - //private Action dispatcher; - private int eventHandle; - - private int SegnalazioniADSEventHandle, StatusChangedEventHandle, MessageQueuedEventHandle; - - private int notifyposition; -#endif - private AdsStream notifyStream; - - private object lockobj = new object(); - - private AdsStream newNotificationStream; - - - - private Symbol StatoMacchina; - - #endregion Private Fields - #region Public Fields public System.Collections.Concurrent.ConcurrentQueue CodaComandi; @@ -84,9 +36,13 @@ namespace IOB_WIN_NEXT /// /// Inizializza un oggetto ADS x gestione classe comunicazione con TwinCat /// - /// Lista dei nomi delle variabili da gestire ad eventChange (es stato macchina) + /// + /// Lista dei nomi delle variabili da gestire ad eventChange (es stato macchina) + /// /// indirizzo tipo AmsNetId - /// Porta comunicazione: Connect to local PLC - Runtime 1 - TwinCAT2 Port=801, TwinCAT3 Port=851 + /// + /// Porta comunicazione: Connect to local PLC - Runtime 1 - TwinCAT2 Port=801, TwinCAT3 Port=851 + /// public TcAdsClient(List MonitVars, string indirizzo = "local", int porta = 851) { _MonitVars = MonitVars; @@ -139,7 +95,7 @@ namespace IOB_WIN_NEXT StatoMacchina.ValueChanged += StatoMacchina_ValueChanged; #if false - notifyposition = 0; + notifyposition = 0; #endif cts = new CancellationTokenSource(); @@ -213,6 +169,128 @@ namespace IOB_WIN_NEXT #endregion Public Properties + #region Public Methods + + public void dispose() + { + adsClient.Dispose(); + } + + public TcAdsSymbolInfo GetSymbolInfo(string nome) + { + try + { + var symbol = InfoLoader.FindSymbol(nome); + return symbol; + } + catch (Exception) + { + throw; + } + } + + public object ReadVariabile(ref TcAdsSymbolInfo variabile) + { + var comando = new ComandiADS { ComandoScrittua = false, Symbol = variabile }; + return ReadVariabile(comando); + } + + public object ReadVariabile(string symbolName, Type type = null) + { + var comando = new ComandiADS { ComandoScrittua = false, SymbolName = symbolName }; + return ReadVariabile(comando); + } + + public bool WriteVariabile(string symbolName, object value, bool syncronous = false) + { + var comando = new ComandiADS { Value = value, ComandoScrittua = true, SymbolName = symbolName }; + return WriteVariabile(comando, syncronous); + } + + public bool WriteVariabile(TcAdsSymbolInfo symbol, object value, bool syncronous = false) + { + var comando = new ComandiADS { Value = value, ComandoScrittua = true, Symbol = symbol }; + return WriteVariabile(comando, syncronous); + } + + #endregion Public Methods + + #region Public Classes + + public class ComandiADS + { + #region Public Fields + + public bool ComandoScrittua; + public bool Error; + public TcAdsSymbolInfo Symbol; + public string SymbolName; + public ManualResetEventSlim Updating; + public object Value; + + #endregion Public Fields + + #region Public Constructors + + public ComandiADS() + { + Updating = new ManualResetEventSlim(false); + } + + public ComandiADS(string name) + { + SymbolName = name; + Updating = new ManualResetEventSlim(false); + } + + public ComandiADS(TcAdsSymbolInfo info) + { + Symbol = info; + Updating = new ManualResetEventSlim(false); + } + + #endregion Public Constructors + } + + #endregion Public Classes + + #region Private Fields + + /// + /// elenco delle variabili monitorate x change event + /// + private List _MonitVars = new List(); + + private int _status; + + private List addedSignalationList = new List(); + + /// + /// Dizionario di conversione da indice a index group e index offset + /// + private Dictionary> addressList; + + private TwinCAT.Ads.TcAdsClient adsClient; + + private CancellationTokenSource cts; + + private System.Threading.Tasks.Task dispatchertask; + +#if false + //private Action dispatcher; + private int eventHandle; + + private int SegnalazioniADSEventHandle, StatusChangedEventHandle, MessageQueuedEventHandle; + + private int notifyposition; +#endif + private object lockobj = new object(); + private AdsStream newNotificationStream; + private AdsStream notifyStream; + private Symbol StatoMacchina; + + #endregion Private Fields + #region Private Methods private void commandDispatcher(object tk) @@ -327,90 +405,5 @@ namespace IOB_WIN_NEXT } #endregion Private Methods - - #region Public Methods - - public void dispose() - { - adsClient.Dispose(); - } - - public TcAdsSymbolInfo GetSymbolInfo(string nome) - { - try - { - var symbol = InfoLoader.FindSymbol(nome); - return symbol; - } - catch (Exception) - { - throw; - } - } - - public object ReadVariabile(ref TcAdsSymbolInfo variabile) - { - var comando = new ComandiADS { ComandoScrittua = false, Symbol = variabile }; - return ReadVariabile(comando); - } - - public object ReadVariabile(string symbolName, Type type = null) - { - var comando = new ComandiADS { ComandoScrittua = false, SymbolName = symbolName }; - return ReadVariabile(comando); - } - - public bool WriteVariabile(string symbolName, object value, bool syncronous = false) - { - var comando = new ComandiADS { Value = value, ComandoScrittua = true, SymbolName = symbolName }; - return WriteVariabile(comando, syncronous); - } - - public bool WriteVariabile(TcAdsSymbolInfo symbol, object value, bool syncronous = false) - { - var comando = new ComandiADS { Value = value, ComandoScrittua = true, Symbol = symbol }; - return WriteVariabile(comando, syncronous); - } - - #endregion Public Methods - - #region Public Classes - - public class ComandiADS - { - #region Public Fields - - public bool ComandoScrittua; - public bool Error; - public TcAdsSymbolInfo Symbol; - public string SymbolName; - public ManualResetEventSlim Updating; - public object Value; - - #endregion Public Fields - - #region Public Constructors - - public ComandiADS() - { - Updating = new ManualResetEventSlim(false); - } - - public ComandiADS(string name) - { - SymbolName = name; - Updating = new ManualResetEventSlim(false); - } - - public ComandiADS(TcAdsSymbolInfo info) - { - Symbol = info; - Updating = new ManualResetEventSlim(false); - } - - #endregion Public Constructors - } - - #endregion Public Classes } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/UAClient.cs b/IOB-WIN-NEXT/UAClient.cs index b10c9abb..25ae33be 100644 --- a/IOB-WIN-NEXT/UAClient.cs +++ b/IOB-WIN-NEXT/UAClient.cs @@ -1,12 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Collections; +using NLog; using Opc.Ua; using Opc.Ua.Client; -using NLog; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading.Tasks; namespace IOB_WIN_NEXT { @@ -15,20 +13,6 @@ namespace IOB_WIN_NEXT /// public class opcUaMonitItemChange : EventArgs { - #region Private Fields - - /// - /// Monitored Item da notificare - /// - private readonly MonitoredItem _monitoredItem; - - /// - /// Valore notifica - /// - private readonly MonitoredItemNotification _notification; - - #endregion Private Fields - #region Public Constructors /// @@ -62,6 +46,20 @@ namespace IOB_WIN_NEXT } #endregion Public Properties + + #region Private Fields + + /// + /// Monitored Item da notificare + /// + private readonly MonitoredItem _monitoredItem; + + /// + /// Valore notifica + /// + private readonly MonitoredItemNotification _notification; + + #endregion Private Fields } /// @@ -69,28 +67,6 @@ namespace IOB_WIN_NEXT /// public class UAClient { - #region Private Fields - - private readonly string currIob; - private readonly Action m_validateResponse; - private ApplicationConfiguration m_configuration; - private Session m_session; - - #endregion Private Fields - - #region Protected Fields - - protected static Logger lg; - protected static bool isLogVerbose = false; - - - /// - /// The user identity to use when creating the session. - /// - public IUserIdentity CurrUserIdentity { get; set; } = new UserIdentity(); - - #endregion Protected Fields - #region Public Constructors /// @@ -127,6 +103,11 @@ namespace IOB_WIN_NEXT #region Public Properties + /// + /// The user identity to use when creating the session. + /// + public IUserIdentity CurrUserIdentity { get; set; } = new UserIdentity(); + /// /// Gets or sets the server URL. /// @@ -139,105 +120,6 @@ namespace IOB_WIN_NEXT #endregion Public Properties - #region Private Methods - - /// - /// Handles the certificate validation event. - /// This event is triggered every time an untrusted certificate is received from the server. - /// - private void CertificateValidation(CertificateValidator sender, CertificateValidationEventArgs e) - { - bool certificateAccepted = true; - - // **** - // Implement a custom logic to decide if the certificate should be - // accepted or not and set certificateAccepted flag accordingly. - // The certificate can be retrieved from the e.Certificate field - // *** - - ServiceResult error = e.Error; - while (error != null) - { - lgError($"{error.StatusCode} | {error.Code} | {error.LocalizedText}"); - error = error.InnerResult; - } - - if (certificateAccepted) - { - lgInfo($"Untrusted Certificate accepted. SubjectName = {e.Certificate.SubjectName}"); - } - - e.AcceptAll = certificateAccepted; - } - - /// - /// Handle DataChange notifications from Server - /// - private void OnMonitoredItemNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) - { - try - { - // Log MonitoredItem Notification event - MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification; - - // sollevo evento notifica vaziazione MonitoredItem - if (eh_MonItChange != null) - { - eh_MonItChange(this, new opcUaMonitItemChange(monitoredItem, notification)); - } - lgTrace($"Notification Received | Variable: {monitoredItem.DisplayName} | Value: {notification.Value}"); - } - catch (Exception ex) - { - lgError($"OnMonitoredItemNotification error: {ex.Message}"); - } - } - - #endregion Private Methods - - #region Protected Methods - - /// - /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere... - /// - /// - protected void lgError(string message) - { - lg.Factory.Configuration.Variables["codIOB"] = currIob; - lg.Error(message); - } - - /// - /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere... - /// - /// - protected void lgInfo(string message) - { - lg.Factory.Configuration.Variables["codIOB"] = currIob; - lg.Info(message); - } - - /// - /// Effettua logging DEBUG corretto impostanto anche la variabile IOB prima di scrivere... - /// - /// - protected void lgDebug(string message) - { - lg.Factory.Configuration.Variables["codIOB"] = currIob; - lg.Info(message); - } - /// - /// Effettua logging TRACE corretto impostanto anche la variabile IOB prima di scrivere... - /// - /// - protected void lgTrace(string message) - { - lg.Factory.Configuration.Variables["codIOB"] = currIob; - lg.Trace(message); - } - - #endregion Protected Methods - #region Public Methods /// @@ -385,14 +267,11 @@ namespace IOB_WIN_NEXT try { - // Define the UA Method to call - // Parent node - Objects\CTT\Methods - // Method node - Objects\CTT\Methods\Add + // Define the UA Method to call Parent node - Objects\CTT\Methods Method node - Objects\CTT\Methods\Add NodeId objectId = new NodeId("ns=2;s=Methods"); NodeId methodId = new NodeId("ns=2;s=Methods_Add"); - // Define the method parameters - // Input argument requires a Float and an UInt32 value + // Define the method parameters Input argument requires a Float and an UInt32 value object[] inputArguments = new object[] { (float)10.5, (uint)10 }; IList outputArguments = null; @@ -429,8 +308,8 @@ namespace IOB_WIN_NEXT { lgInfo("Connecting..."); - // Get the endpoint by connecting to server's discovery endpoint. - // Try to find the first endopint without security. + // Get the endpoint by connecting to server's discovery endpoint. Try to find + // the first endopint without security. EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(ServerUrl, false); EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration); @@ -573,7 +452,6 @@ namespace IOB_WIN_NEXT return answ; } - /// /// Read a SINGLE of nodes value (RAW) from Server /// @@ -590,7 +468,6 @@ namespace IOB_WIN_NEXT try { - #region Read the Value attribute of a node by calling the Session.ReadValue method try @@ -614,8 +491,6 @@ namespace IOB_WIN_NEXT return answ; } - - /// /// Read a list of nodes from Server /// @@ -813,8 +688,7 @@ namespace IOB_WIN_NEXT return monItList; } - /// Write a list of nodes to the Server - /// + /// Write a list of nodes to the Server public void WriteNodes(List node2Write) { if (m_session == null || m_session.Connected == false) @@ -1002,5 +876,119 @@ namespace IOB_WIN_NEXT } #endregion Public Methods + + #region Protected Fields + + protected static bool isLogVerbose = false; + protected static Logger lg; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// Effettua logging DEBUG corretto impostanto anche la variabile IOB prima di scrivere... + /// + /// + protected void lgDebug(string message) + { + lg.Factory.Configuration.Variables["codIOB"] = currIob; + lg.Info(message); + } + + /// + /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere... + /// + /// + protected void lgError(string message) + { + lg.Factory.Configuration.Variables["codIOB"] = currIob; + lg.Error(message); + } + + /// + /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere... + /// + /// + protected void lgInfo(string message) + { + lg.Factory.Configuration.Variables["codIOB"] = currIob; + lg.Info(message); + } + + /// + /// Effettua logging TRACE corretto impostanto anche la variabile IOB prima di scrivere... + /// + /// + protected void lgTrace(string message) + { + lg.Factory.Configuration.Variables["codIOB"] = currIob; + lg.Trace(message); + } + + #endregion Protected Methods + + #region Private Fields + + private readonly string currIob; + private readonly Action m_validateResponse; + private ApplicationConfiguration m_configuration; + private Session m_session; + + #endregion Private Fields + + #region Private Methods + + /// + /// Handles the certificate validation event. This event is triggered every time an + /// untrusted certificate is received from the server. + /// + private void CertificateValidation(CertificateValidator sender, CertificateValidationEventArgs e) + { + bool certificateAccepted = true; + + // **** Implement a custom logic to decide if the certificate should be accepted or not + // and set certificateAccepted flag accordingly. The certificate can be retrieved from + // the e.Certificate field *** + + ServiceResult error = e.Error; + while (error != null) + { + lgError($"{error.StatusCode} | {error.Code} | {error.LocalizedText}"); + error = error.InnerResult; + } + + if (certificateAccepted) + { + lgInfo($"Untrusted Certificate accepted. SubjectName = {e.Certificate.SubjectName}"); + } + + e.AcceptAll = certificateAccepted; + } + + /// + /// Handle DataChange notifications from Server + /// + private void OnMonitoredItemNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) + { + try + { + // Log MonitoredItem Notification event + MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification; + + // sollevo evento notifica vaziazione MonitoredItem + if (eh_MonItChange != null) + { + eh_MonItChange(this, new opcUaMonitItemChange(monitoredItem, notification)); + } + lgTrace($"Notification Received | Variable: {monitoredItem.DisplayName} | Value: {notification.Value}"); + } + catch (Exception ex) + { + lgError($"OnMonitoredItemNotification error: {ex.Message}"); + } + } + + #endregion Private Methods } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/memAddress.cs b/IOB-WIN-NEXT/memAddress.cs index 307787c0..59f2627e 100644 --- a/IOB-WIN-NEXT/memAddress.cs +++ b/IOB-WIN-NEXT/memAddress.cs @@ -1,9 +1,4 @@ using EgwProxy.MultiCncLib.CNC; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace IOB_WIN_NEXT { diff --git a/IOB-WIN-NEXT/postBuildTgt.bat b/IOB-WIN-NEXT/postBuildTgt.bat index a7faeeb5..9e174781 100644 --- a/IOB-WIN-NEXT/postBuildTgt.bat +++ b/IOB-WIN-NEXT/postBuildTgt.bat @@ -54,12 +54,12 @@ goto END :RemoteDebug REM copia script verso server remoto -echo Debug remoto: effettuo robocopy sync (verificare remote per cliente) +REM echo Debug remoto: effettuo robocopy sync (verificare remote per cliente) REM FINASSI -ROBOCOPY . \\10.150.0.1\Steamware\IOB-WIN-NEXT-DEB /MIR +REM ROBOCOPY . \\10.150.0.1\Steamware\IOB-WIN-NEXT-DEB /MIR REM Baglietto -REM ROBOCOPY . \\192.168.60.15\Steamware\IOB-WIN-NEXT-DEB /MIR +ROBOCOPY . \\192.168.60.15\Steamware\IOB-WIN-NEXT-DEB /MIR goto END diff --git a/IOB-WIN-NEXT/specialConfig.cs b/IOB-WIN-NEXT/specialConfig.cs index 3c01cfad..5ee7c56e 100644 --- a/IOB-WIN-NEXT/specialConfig.cs +++ b/IOB-WIN-NEXT/specialConfig.cs @@ -10,6 +10,11 @@ namespace IOB_WIN_NEXT { #region Public Fields + /// + /// Indirizzo di base degli Holding Register + /// + public int holdRegBaseAddr = 40001; + /// /// Indirizzo IP del PLC /// @@ -40,11 +45,6 @@ namespace IOB_WIN_NEXT /// public int pingMsTimeout = 250; - /// - /// Indirizzo di base degli Holding Register - /// - public int holdRegBaseAddr= 40001; - /// /// Porta di comunicazione /// @@ -54,8 +54,8 @@ namespace IOB_WIN_NEXT } /// - /// Implementazione classe connessione SIEMENS con S7.net, - /// comprensiva dei parametri delle aree di memoria + /// Implementazione classe connessione SIEMENS con S7.net, comprensiva dei parametri delle aree + /// di memoria /// public class connParamS7 {