diff --git a/EgwProxy.Icoel.DataLayer/Controllers/DbController.cs b/EgwProxy.Icoel.DataLayer/Controllers/DbController.cs
index 0727fdb5..98ab5ffd 100644
--- a/EgwProxy.Icoel.DataLayer/Controllers/DbController.cs
+++ b/EgwProxy.Icoel.DataLayer/Controllers/DbController.cs
@@ -2,8 +2,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
/*------------------------------------------------
* Aggiunto fix come da link seguente:
@@ -14,6 +12,7 @@ using System.Threading.Tasks;
* using SqlProviderServices= System.Data.Entity.SqlServer.SqlProviderServices;
*
*/
+
namespace EgwProxy.Icoel.DataLayer.Controllers
{
///
@@ -26,29 +25,9 @@ namespace EgwProxy.Icoel.DataLayer.Controllers
private static ExportDbContext dbExportCtx;
private static TrackerDbContext dbTrackerCtx;
#endif
- private static SyncStateDbContext dbSyncStateCtx;
- private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
-#if false
- ///
- /// Avvio dell'oggetto gestione DB con le 3 stringhe di connessione specifiche
- ///
- /// Connesisone Db frontiera Entrata Merce
- /// Connessione DB Tracker
- /// Connessione DB IcoelExport
- /// Connessione DB locale di SYNC
- public DbController(string connEntrata, string connTracker, string connExport, string connSyncState)
- {
- dbEntrataCtx = new EntrataDbContext(connEntrata);
- Log.Info("Avviata classe EntrataDbContext");
- dbExportCtx = new ExportDbContext(connExport);
- Log.Info("Avviata classe ExportDbContext");
- dbTrackerCtx = new TrackerDbContext(connTracker);
- Log.Info("Avviata classe dbTrackerCtx");
- dbSyncStateCtx = new SyncStateDbContext(connSyncState);
- Log.Info("Avviata classe dbSyncStateCtx");
- }
-#endif
+ #region Public Constructors
+
///
/// Avvio dell'oggetto gestione DB con stringa di connessione specifica
///
@@ -59,6 +38,25 @@ namespace EgwProxy.Icoel.DataLayer.Controllers
Log.Info("Avviata classe dbSyncStateCtx");
}
+ #endregion Public Constructors
+
+ #region Public Methods
+
+ ///
+ /// Recupera la tab di CurrData corrente
+ ///
+ ///
+ public List CurrDataGetAll()
+ {
+ List dbResult = new List();
+
+ dbResult = dbSyncStateCtx
+ .DbSetCurrData
+ .ToList();
+
+ return dbResult;
+ }
+
///
/// Dispose classe
///
@@ -73,94 +71,6 @@ namespace EgwProxy.Icoel.DataLayer.Controllers
dbSyncStateCtx.Dispose();
}
-#if false
- ///
- /// Elenco record Entrata Merce (Frontiera)
- ///
- /// idx da cui partire a recuperare
- ///
- public List EntrateGetFromIdx(int minIdx = 0)
- {
- List dbResult = new List();
- dbResult = dbEntrataCtx
- .DbSetEntrataMerce
- .Where(x => (x.ID_CHIAVE >= minIdx))
- .OrderBy(x => x.ID_CHIAVE)
- .ToList();
-
- return dbResult;
- }
-
- ///
- /// Elenco ultimi record Entrata Merce (Frontiera)
- ///
- /// numero records da recuperare
- ///
- public List EntrateGetLast(int numRec = 100)
- {
- List dbResult = new List();
- dbResult = dbEntrataCtx
- .DbSetEntrataMerce
- .OrderByDescending(x => x.ID_CHIAVE)
- .Take(numRec)
- .ToList();
-
- return dbResult;
- }
-
- ///
- /// Elenco record ProductsTotal (da Icoel Export Products)
- ///
- /// idx da cui partire a recuperare
- ///
- public List ExportProductsGetFromIdx(int minIdx = 0)
- {
- List dbResult = new List();
- dbResult = dbExportCtx
- .DbSetProductsTotals
- .Where(x => (x.SizerBatchId >= minIdx))
- .OrderBy(x => x.SizerBatchId)
- .ToList();
-
- return dbResult;
- }
-
- ///
- /// Elenco ultimi record ProductsTotal (da Icoel Export Products)
- ///
- /// numero records da recuperare
- ///
- public List ExportProductsGetLast(int numRec = 0)
- {
- List dbResult = new List();
- dbResult = dbExportCtx
- .DbSetProductsTotals
- .OrderByDescending(x => x.SizerBatchId)
- .ThenByDescending(x => x.Index)
- .Take(numRec)
- .ToList();
-
- return dbResult;
- }
-#endif
-
- ///
- /// Esegue una volta la stored di ImportAll (x recupero dati da DB esterni) e poi
- /// restitusice in output la tab di SyncState x verificare lo stato
- ///
- ///
- public List SyncStateDoImportAll()
- {
- List dbResult = new List();
-
- dbResult = dbSyncStateCtx
- .Database
- .SqlQuery("EXEC stp_ImportAll")
- .ToList();
-
- return dbResult;
- }
-
///
/// Esegue una volta la stored di ImportAll (x recupero dati da DB esterni) e poi
/// restitusice in output la tab di SyncState x verificare lo stato
@@ -178,6 +88,23 @@ namespace EgwProxy.Icoel.DataLayer.Controllers
return dbResult;
}
+ ///
+ /// Esegue una volta la stored di ImportAll (x recupero dati da DB esterni) e poi
+ /// restitusice in output la tab di SyncState x verificare lo stato
+ ///
+ ///
+ public List SyncStateDoImportAll()
+ {
+ List dbResult = new List();
+
+ dbResult = dbSyncStateCtx
+ .Database
+ .SqlQuery("EXEC stp_ImportAll")
+ .ToList();
+
+ return dbResult;
+ }
+
///
/// recupera la tab di SyncState corrente
///
@@ -193,60 +120,13 @@ namespace EgwProxy.Icoel.DataLayer.Controllers
return dbResult;
}
-#if false
- ///
- /// Elenco record DettConfezioni (da Icoel TrackerLotti)
- ///
- /// idx da cui partire a recuperare
- ///
- public List TrackConfezioniGetFromIdx(int minIdx = 0)
- {
- List dbResult = new List();
- dbResult = dbTrackerCtx
- .DbSetConfezioni
- .Where(x => (x.Pack_Id >= minIdx))
- .OrderBy(x => x.Pack_Id)
- .ToList();
+ #endregion Public Methods
- return dbResult;
- }
+ #region Private Fields
- ///
- /// Elenco ultimi record DettaglioConfezioni (da Icoel TrackerLotti)
- ///
- /// numero records da recuperare
- ///
- public List TrackConfezioniGetLast(int numRec = 0)
- {
- List dbResult = new List();
- dbResult = dbTrackerCtx
- .DbSetConfezioni
- .OrderByDescending(x => x.Pack_Id)
- .Take(numRec)
- .ToList();
+ private static SyncStateDbContext dbSyncStateCtx;
+ private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
- return dbResult;
- }
-
- ///
- /// Elenco dettaglio conferimento x PackId (da Icoel TrackerLotti)
- /// ATTENZIONE: in caso di mancata associazione lotto ingresso con lavorazione corrente la
- /// vista restituisce nuovo (possibile lavorare senza lotto ingresso e senza tracking)
- ///
- /// idx da cui partire a recuperare
- ///
- public List TrackPackConfDetailByIdx(long packId = 0)
- {
- List dbResult = new List();
- dbResult = dbTrackerCtx
- .DbSetConferimento
- .Where(x => (x.PackId == packId))
- .OrderBy(x => x.NUMERO_LOTTO)
- .ThenByDescending(x => x.QUANTITA_ENTRATA)
- .ToList();
-
- return dbResult;
- }
-#endif
+ #endregion Private Fields
}
}
\ No newline at end of file
diff --git a/EgwProxy.Icoel.DataLayer/DatabaseModels/CurrDataModel.cs b/EgwProxy.Icoel.DataLayer/DatabaseModels/CurrDataModel.cs
new file mode 100644
index 00000000..f6fb6573
--- /dev/null
+++ b/EgwProxy.Icoel.DataLayer/DatabaseModels/CurrDataModel.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Data.Entity.Spatial;
+
+namespace EgwProxy.Icoel.DataLayer.DatabaseModels
+{
+
+ [Table("CurrData")]
+ public partial class CurrDataModel
+ {
+ [Key]
+ [StringLength(50)]
+ public string Topic { get; set; }
+
+ public decimal CurrVal { get; set; } = 0;
+ }
+}
diff --git a/EgwProxy.Icoel.DataLayer/DatabaseModels/SyncStateModel.cs b/EgwProxy.Icoel.DataLayer/DatabaseModels/SyncStateModel.cs
index 477c3fc5..b37fa326 100644
--- a/EgwProxy.Icoel.DataLayer/DatabaseModels/SyncStateModel.cs
+++ b/EgwProxy.Icoel.DataLayer/DatabaseModels/SyncStateModel.cs
@@ -25,5 +25,7 @@ namespace EgwProxy.Icoel.DataLayer.DatabaseModels
public long NumRecIn { get; set; }
public long NumRecOut { get; set; }
+
+ public DateTime LastUpdate { get; set; } = DateTime.Today;
}
}
diff --git a/EgwProxy.Icoel.DataLayer/EgwProxy.Icoel.DataLayer.csproj b/EgwProxy.Icoel.DataLayer/EgwProxy.Icoel.DataLayer.csproj
index c1aaa5c3..ffb54d76 100644
--- a/EgwProxy.Icoel.DataLayer/EgwProxy.Icoel.DataLayer.csproj
+++ b/EgwProxy.Icoel.DataLayer/EgwProxy.Icoel.DataLayer.csproj
@@ -65,6 +65,7 @@
+
diff --git a/EgwProxy.Icoel.DataLayer/SyncStateDbContext.cs b/EgwProxy.Icoel.DataLayer/SyncStateDbContext.cs
index 1e811380..fd401841 100644
--- a/EgwProxy.Icoel.DataLayer/SyncStateDbContext.cs
+++ b/EgwProxy.Icoel.DataLayer/SyncStateDbContext.cs
@@ -32,10 +32,15 @@ namespace EgwProxy.Icoel.DataLayer
}
///
- /// DbSet dai dati stato sync DB esterni <--> locale
+ /// DbSet dei dati stato sync DB esterni <--> locale
///
public virtual DbSet DbSetSyncState { get; set; }
+ ///
+ /// DbSet CurrData
+ ///
+ public virtual DbSet DbSetCurrData { get; set; }
+
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
diff --git a/EgwProxy.Icoel/Compac/ComClient.cs b/EgwProxy.Icoel/Compac/ComClient.cs
index 587f5dd6..3f5ee6e6 100644
--- a/EgwProxy.Icoel/Compac/ComClient.cs
+++ b/EgwProxy.Icoel/Compac/ComClient.cs
@@ -182,18 +182,20 @@ namespace EgwProxy.Icoel.Compac
internal Dictionary GetPerfMeters()
{
Dictionary answ = new Dictionary();
- // indicata in tonnOra
+ // velocità processo indicata in tonnellate /oOra
double velTonnOra = SSClient.GetMachineTonnesPH();
// velocità espressa in frutti/minuto
double velFruttiMinuto = SSClient.GetMachineTotalFPM();
// percentuale riempimento carrellini
double percRiemp = SSClient.GetMachineCupfill();
- //// indicata in carrelli/minuto
- //int[] velCarrMinuto = SSClient.GetMachineRodsPM();
+ // Numero confezioni/ora
+ double numPackOra = SSClient.GetMachinePacksPH();
+
// accodo i valori ricavati
- answ.Add("VelTonnOra", velTonnOra);
- answ.Add("VelFruttiMinuto", velFruttiMinuto);
+ answ.Add("NumPacksOra", numPackOra);
answ.Add("PercRiemp", percRiemp);
+ answ.Add("VelFruttiMinuto", velFruttiMinuto);
+ answ.Add("VelTonnOra", velTonnOra);
return answ;
}
diff --git a/IOB-UT-NEXT/BinaryFormatter.cs b/IOB-UT-NEXT/BinaryFormatter.cs
index a91b074e..0619bf95 100644
--- a/IOB-UT-NEXT/BinaryFormatter.cs
+++ b/IOB-UT-NEXT/BinaryFormatter.cs
@@ -6,20 +6,6 @@ namespace IOB_UT_NEXT
{
public class BinaryUtils : IFormatProvider, ICustomFormatter
{
- #region Private Methods
-
- private string HandleOtherFormats(string format, object arg)
- {
- if (arg is IFormattable)
- return ((IFormattable)arg).ToString(format, CultureInfo.CurrentCulture);
- else if (arg != null)
- return arg.ToString();
- else
- return String.Empty;
- }
-
- #endregion Private Methods
-
#region Public Methods
// Format number in binary (B), octal (O), or hexadecimal (H).
@@ -29,8 +15,7 @@ namespace IOB_UT_NEXT
int baseNumber;
// Handle null or empty format string, string with precision specifier.
string thisFmt = String.Empty;
- // Extract first character of format string (precision specifiers
- // are not supported).
+ // Extract first character of format string (precision specifiers are not supported).
if (!String.IsNullOrEmpty(format))
thisFmt = format.Length > 1 ? format.Substring(0, 1) : format;
@@ -140,5 +125,19 @@ namespace IOB_UT_NEXT
}
#endregion Public Methods
+
+ #region Private Methods
+
+ private string HandleOtherFormats(string format, object arg)
+ {
+ if (arg is IFormattable)
+ return ((IFormattable)arg).ToString(format, CultureInfo.CurrentCulture);
+ else if (arg != null)
+ return arg.ToString();
+ else
+ return String.Empty;
+ }
+
+ #endregion Private Methods
}
}
\ No newline at end of file
diff --git a/IOB-UT-NEXT/Enums.cs b/IOB-UT-NEXT/Enums.cs
index 8a07e576..63f0993c 100644
--- a/IOB-UT-NEXT/Enums.cs
+++ b/IOB-UT-NEXT/Enums.cs
@@ -1,6 +1,4 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Converters;
-using System;
+using System;
namespace IOB_UT_NEXT
{
@@ -470,35 +468,6 @@ namespace IOB_UT_NEXT
WPS
}
-#if false
- ///
- /// Enumerazione tipi di semaforo
- ///
- public enum Semaforo
- {
- ///
- /// Stato non definito
- ///
- ND,
- ///
- /// Verde
- ///
- SV,
- ///
- /// Giallo
- ///
- SG,
- ///
- /// Rosso
- ///
- SR,
- ///
- /// Grigio/Spento
- ///
- SS
- }
-#endif
-
///
/// Enumerazione tipi di tipi di URL x invio
///
@@ -524,27 +493,4 @@ namespace IOB_UT_NEXT
///
ULog
}
-
-#if false
- ///
- /// Tipologia dato Raw Transfer (derivare da MapoSdk e togliere qui)
- ///
- /// serializzazione Native
- /// [JsonConverter(typeof(JsonStringEnumConverter))]
- /// serializzazione Newtonsoft json
- /// [JsonConverter(typeof(StringEnumConverter))]
- [JsonConverter(typeof(StringEnumConverter))]
- public enum rawTransfType
- {
- ND = 0,
- ///
- /// Icoel: Batch info
- ///
- IcoelBatch,
- ///
- /// Icoel: Variety + layout info relative
- ///
- IcoelVarInfo
- }
-#endif
}
\ No newline at end of file
diff --git a/IOB-UT-NEXT/Eurom63.cs b/IOB-UT-NEXT/Eurom63.cs
index d601eabe..0ffba8c9 100644
--- a/IOB-UT-NEXT/Eurom63.cs
+++ b/IOB-UT-NEXT/Eurom63.cs
@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
namespace IOB_UT_NEXT
{
@@ -39,7 +36,8 @@ namespace IOB_UT_NEXT
TimeSet,
///
- /// Verificato il canale di comunicazione è OK, fatta pulizia con AbortAll, NON ci sono report attivi
+ /// Verificato il canale di comunicazione è OK, fatta pulizia con AbortAll, NON ci sono
+ /// report attivi
///
ChannelOk,
@@ -135,7 +133,8 @@ namespace IOB_UT_NEXT
public int PzPallet { get; set; } = 1;
///
- /// Indica se sia possibile impostare i pezzi pallet dal server, ed in tal caso moltiplica i pezzi letti dalla macchina per il valore pzPallet (vedi sopra)
+ /// Indica se sia possibile impostare i pezzi pallet dal server, ed in tal caso
+ /// moltiplica i pezzi letti dalla macchina per il valore pzPallet (vedi sopra)
///
public bool SetPzPalletFromSrv { get; set; } = false;
@@ -170,7 +169,8 @@ namespace IOB_UT_NEXT
public List FileList { get; set; } = new List();
///
- /// Numero MAX di esecuzioni da mantenere in HIST prima di eliminare i + vecchi (fare folder HIST\SESSnnnn)
+ /// Numero MAX di esecuzioni da mantenere in HIST prima di eliminare i + vecchi (fare
+ /// folder HIST\SESSnnnn)
///
public int Max2Keep { get; set; } = 50;
@@ -190,7 +190,7 @@ namespace IOB_UT_NEXT
public string RespOk { get; set; } = "PROCESSED";
///
- /// Seconds before do a new retry (default = 0 --> no veto)
+ /// Seconds before do a new retry (default = 0 --> no veto)
///
public double RetrySec { get; set; } = 0;
diff --git a/IOB-UT-NEXT/IOB-UT-NEXT.csproj b/IOB-UT-NEXT/IOB-UT-NEXT.csproj
index 8dbe51fe..14903e11 100644
--- a/IOB-UT-NEXT/IOB-UT-NEXT.csproj
+++ b/IOB-UT-NEXT/IOB-UT-NEXT.csproj
@@ -59,8 +59,8 @@
..\packages\SharpZipLib.1.3.1\lib\net45\ICSharpCode.SharpZipLib.dll
-
- ..\packages\MapoSDK.6.14.2204.2616\lib\MapoSDK.dll
+
+ ..\packages\MapoSDK.6.14.2205.2808\lib\MapoSDK.dll
..\packages\Microsoft.Bcl.AsyncInterfaces.6.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
@@ -134,7 +134,6 @@
-
diff --git a/IOB-UT-NEXT/IniFile.cs b/IOB-UT-NEXT/IniFile.cs
index 1ea22447..a23f2453 100644
--- a/IOB-UT-NEXT/IniFile.cs
+++ b/IOB-UT-NEXT/IniFile.cs
@@ -1,7 +1,7 @@
using System;
+using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
-using System.Globalization;
namespace IOB_UT_NEXT
{
@@ -16,9 +16,6 @@ namespace IOB_UT_NEXT
#endregion Public Fields
- // INI filename
-
- // import windows dll functions
#region Public Constructors
@@ -33,25 +30,6 @@ namespace IOB_UT_NEXT
#endregion Public Constructors
- #region Private Methods
-
- [DllImport("kernel32")]
- private static extern int GetPrivateProfileInt(string section, string key, int def, string filePath);
-
- [DllImport("kernel32")]
- private static extern int GetPrivateProfileSection(string section, IntPtr retVal, uint size, string filePath);
-
- [DllImport("kernel32")]
- private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
-
- [DllImport("kernel32")]
- private static extern bool WritePrivateProfileSection(string section, string value, string filePath);
-
- [DllImport("kernel32", CharSet = CharSet.Auto, BestFitMapping = false)]
- private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
-
- #endregion Private Methods
-
#region Public Methods
///
@@ -149,7 +127,9 @@ namespace IOB_UT_NEXT
///
///
/// Section name
- /// restituisce delle stringhe keys=values da suddividere appunto come key/val successivamente
+ ///
+ /// restituisce delle stringhe keys=values da suddividere appunto come key/val successivamente
+ ///
public string[] ReadSection(string Section)
{
const int bufferSize = 2048; // max is 32767
@@ -270,5 +250,68 @@ namespace IOB_UT_NEXT
}
#endregion Public Methods
+
+ #region Private Methods
+
+
+ // INI filename
+
+ ///
+ /// GetPrivateProfileInt: import windows dll functions
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("kernel32")]
+ private static extern int GetPrivateProfileInt(string section, string key, int def, string filePath);
+
+ ///
+ /// GetPrivateProfileSection: import windows dll functions
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("kernel32")]
+ private static extern int GetPrivateProfileSection(string section, IntPtr retVal, uint size, string filePath);
+
+ ///
+ /// GetPrivateProfileString: import windows dll functions
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("kernel32")]
+ private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
+
+ ///
+ /// WritePrivateProfileSection: import windows dll functions
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("kernel32")]
+ private static extern bool WritePrivateProfileSection(string section, string value, string filePath);
+
+ ///
+ /// WritePrivateProfileString: import windows dll functions
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("kernel32", CharSet = CharSet.Auto, BestFitMapping = false)]
+ private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
+
+ #endregion Private Methods
}
}
\ No newline at end of file
diff --git a/IOB-UT-NEXT/Logging.cs b/IOB-UT-NEXT/Logging.cs
index ab425119..795dfd44 100644
--- a/IOB-UT-NEXT/Logging.cs
+++ b/IOB-UT-NEXT/Logging.cs
@@ -1,15 +1,10 @@
using NLog;
using NLog.Config;
using NLog.Targets;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace IOB_UT_NEXT
{///
- /// Classe helper x LOG basata su NLog
- ///
+ /// Classe helper x LOG basata su NLog
public static class Logging
{
#region Public Constructors
diff --git a/IOB-UT-NEXT/Objects.cs b/IOB-UT-NEXT/Objects.cs
index 7ee9ae69..5b893604 100644
--- a/IOB-UT-NEXT/Objects.cs
+++ b/IOB-UT-NEXT/Objects.cs
@@ -117,70 +117,6 @@ namespace IOB_UT_NEXT
#endregion Public Methods
}
-#if false
- ///
- /// Classe di base per trasferimento informazioni di tipo RawTransfer
- /// FixMe Todo Fare !!!: elimnare usando SDK MAPO
- ///
- public class BaseRawTransf
- {
- #region Public Properties
-
- ///
- /// Data-Ora riferimento (x ordinamento fifo)
- ///
- public DateTime dataRif { get; set; } = DateTime.Now;
-
- ///
- /// Messaggio in modalità raw/stringa
- ///
- public object mesContent { get; set; } = "";
-
- ///
- /// Tipo di messaggio trasmesso
- ///
- public rawTransfType mesType { get; set; } = rawTransfType.ND;
-
- ///
- /// Costruttore senza parametri
- ///
- public BaseRawTransf()
- {
- this.dataRif = DateTime.Now;
- this.mesContent = "";
- this.mesType = rawTransfType.ND;
- }
-
- ///
- /// Costruttore oggetto
- ///
- ///
- ///
- ///
- public BaseRawTransf(DateTime dataRif, object mesContent, rawTransfType mesType)
- {
- this.dataRif = dataRif;
- this.mesContent = mesContent;
- this.mesType = mesType;
- }
-
- #endregion Public Properties
- }
-
- ///
- /// Array valori tipo BaseRawTransf inviati come JSon
- /// FixMe Todo Fare !!!: elimnare usando SDK MAPO
- ///
- public class rawTransfJsonPayload
- {
- #region Public Properties
-
- public List rawTransfData { get; set; }
-
- #endregion Public Properties
- }
-#endif
-
///
/// Cache a tempo valori INT
///
@@ -343,6 +279,8 @@ namespace IOB_UT_NEXT
#endregion Public Properties
+ #region Public Methods
+
///
/// Override metodo di equality
///
@@ -371,7 +309,7 @@ namespace IOB_UT_NEXT
return false;
if (queueRawTransfLen != item.queueRawTransfLen)
return false;
- if (queueUlLen!= item.queueUlLen)
+ if (queueUlLen != item.queueUlLen)
return false;
return true;
@@ -381,6 +319,8 @@ namespace IOB_UT_NEXT
{
return base.GetHashCode();
}
+
+ #endregion Public Methods
}
///
diff --git a/IOB-UT-NEXT/RedisMan.cs b/IOB-UT-NEXT/RedisMan.cs
index 5bda2a2e..73f0cb7a 100644
--- a/IOB-UT-NEXT/RedisMan.cs
+++ b/IOB-UT-NEXT/RedisMan.cs
@@ -2,68 +2,12 @@
using StackExchange.Redis;
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Text;
namespace IOB_UT_NEXT
{
public class RedisIobCache
{
- #region Private Fields
-
- ///
- /// Connessione lazy a redis...
- ///
- private Lazy lazyConnection = new Lazy(() =>
- {
- string RedisConn = baseUtils.CRS("RedisConn");
- if (string.IsNullOrEmpty(RedisConn))
- {
- RedisConn = "localhost,abortConnect=false,ssl=false";
- }
-
- return ConnectionMultiplexer.Connect(RedisConn);
- });
-
- ///
- /// Connessione lazy a redis...
- ///
- private Lazy lazyConnectionAdmin = new Lazy(() =>
- {
- string RedisConnAdmin = baseUtils.CRS("RedisConnAdmin");
- if (string.IsNullOrEmpty(RedisConnAdmin))
- {
- RedisConnAdmin = "localhost,abortConnect=false,ssl=false,allowAdmin=true";
- }
-
- return ConnectionMultiplexer.Connect(RedisConnAdmin);
- });
-
- #endregion Private Fields
-
- #region Protected Fields
-
- ///
- /// Cod IOB
- ///
- protected string currCodIob = "000";
- ///
- /// Tipo IOB
- ///
- protected string currIobType = "ND";
-
- ///
- /// Hash redis x dati IOB
- ///
- protected string redIobKey = "";
-
- ///
- /// Hash redis x dati server
- ///
- protected string redServKey = "";
-
- #endregion Protected Fields
-
#region Public Constructors
///
@@ -97,7 +41,7 @@ namespace IOB_UT_NEXT
IobWinStatus newIobStatus = new IobWinStatus()
{
CodIob = currCodIob,
- IobType= currIobType,
+ IobType = currIobType,
online = false
};
// salvo in area REDIS
@@ -137,15 +81,6 @@ namespace IOB_UT_NEXT
#endregion Public Enums
- #region Private Properties
-
- ///
- /// Oggetto currentDb locale
- ///
- private IDatabase _currDB { get; set; }
-
- #endregion Private Properties
-
#region Public Properties
///
@@ -216,7 +151,7 @@ namespace IOB_UT_NEXT
answ = new IobWinStatus()
{
CodIob = currCodIob,
- IobType=currIobType,
+ IobType = currIobType,
online = false
};
// salvo serializzando...
@@ -298,39 +233,6 @@ namespace IOB_UT_NEXT
#endregion Public Properties
- #region Private Methods
-
- ///
- /// Effettua comaprazione x CHIAVE in KVP ASC
- ///
- ///
- ///
- ///
- private int CompareKey(KeyValuePair x, KeyValuePair y)
- {
- return x.Key.CompareTo(y.Key);
- }
-
- ///
- /// Effettua comaprazione x CHIAVE in KVP DESC
- ///
- ///
- ///
- ///
- private int CompareKeyDesc(KeyValuePair x, KeyValuePair y)
- {
- return y.Key.CompareTo(x.Key);
- }
-
- private void initHashKeys()
- {
- // init dati di base...
- redServKey = redHash($"MP");
- redIobKey = redHash($"IOB:{currCodIob}");
- }
-
- #endregion Private Methods
-
#region Public Methods
///
@@ -477,8 +379,7 @@ namespace IOB_UT_NEXT
public int redCountKey(string keyPattern)
{
int answ = 0;
- // cerco se ci sia valore in redis...
- // se vuoto = ALL...
+ // cerco se ci sia valore in redis... se vuoto = ALL...
keyPattern = string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern;
try
{
@@ -528,8 +429,7 @@ namespace IOB_UT_NEXT
public bool redFlushKey(string keyPattern)
{
bool answ = false;
- // cerco se ci sia valore in redis...
- // se vuoto = ALL...
+ // cerco se ci sia valore in redis... se vuoto = ALL...
keyPattern = string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern;
try
{
@@ -702,7 +602,8 @@ namespace IOB_UT_NEXT
}
///
- /// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da funzionalita' DbConfig) + keyName richiesto...
+ /// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da
+ /// funzionalita' DbConfig) + keyName richiesto...
///
public string redHash(string keyName)
{
@@ -834,7 +735,9 @@ namespace IOB_UT_NEXT
///
/// chiave
/// valori
- /// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade)
+ ///
+ /// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade)
+ ///
///
public bool redSaveHash(string hashKey, KeyValuePair[] hashFields, double expireSeconds = -1)
{
@@ -891,7 +794,9 @@ namespace IOB_UT_NEXT
///
/// chiave
/// valori
- /// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade)
+ ///
+ /// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade)
+ ///
///
public bool redSaveHashDict(string hashKey, Dictionary hashFields, double expireSeconds = -1)
{
@@ -1058,7 +963,7 @@ namespace IOB_UT_NEXT
}
///
- /// Salva un set KVP (Key Value Pair) in RedisCache
+ /// Salva un set KVP (Key Value Pair) in RedisCache
///
/// Set KVP chiave-valore da salvare
///
@@ -1123,5 +1028,103 @@ namespace IOB_UT_NEXT
}
#endregion Public Methods
+
+ #region Protected Fields
+
+ ///
+ /// Cod IOB
+ ///
+ protected string currCodIob = "000";
+
+ ///
+ /// Tipo IOB
+ ///
+ protected string currIobType = "ND";
+
+ ///
+ /// Hash redis x dati IOB
+ ///
+ protected string redIobKey = "";
+
+ ///
+ /// Hash redis x dati server
+ ///
+ protected string redServKey = "";
+
+ #endregion Protected Fields
+
+ #region Private Fields
+
+ ///
+ /// Connessione lazy a redis...
+ ///
+ private Lazy lazyConnection = new Lazy(() =>
+ {
+ string RedisConn = baseUtils.CRS("RedisConn");
+ if (string.IsNullOrEmpty(RedisConn))
+ {
+ RedisConn = "localhost,abortConnect=false,ssl=false";
+ }
+
+ return ConnectionMultiplexer.Connect(RedisConn);
+ });
+
+ ///
+ /// Connessione lazy a redis...
+ ///
+ private Lazy lazyConnectionAdmin = new Lazy(() =>
+ {
+ string RedisConnAdmin = baseUtils.CRS("RedisConnAdmin");
+ if (string.IsNullOrEmpty(RedisConnAdmin))
+ {
+ RedisConnAdmin = "localhost,abortConnect=false,ssl=false,allowAdmin=true";
+ }
+
+ return ConnectionMultiplexer.Connect(RedisConnAdmin);
+ });
+
+ #endregion Private Fields
+
+ #region Private Properties
+
+ ///
+ /// Oggetto currentDb locale
+ ///
+ private IDatabase _currDB { get; set; }
+
+ #endregion Private Properties
+
+ #region Private Methods
+
+ ///
+ /// Effettua comaprazione x CHIAVE in KVP ASC
+ ///
+ ///
+ ///
+ ///
+ private int CompareKey(KeyValuePair x, KeyValuePair y)
+ {
+ return x.Key.CompareTo(y.Key);
+ }
+
+ ///
+ /// Effettua comaprazione x CHIAVE in KVP DESC
+ ///
+ ///
+ ///
+ ///
+ private int CompareKeyDesc(KeyValuePair x, KeyValuePair y)
+ {
+ return y.Key.CompareTo(x.Key);
+ }
+
+ private void initHashKeys()
+ {
+ // init dati di base...
+ redServKey = redHash($"MP");
+ redIobKey = redHash($"IOB:{currCodIob}");
+ }
+
+ #endregion Private Methods
}
}
\ No newline at end of file
diff --git a/IOB-UT-NEXT/TCMan.cs b/IOB-UT-NEXT/TCMan.cs
index 0a8c1937..c513a8c0 100644
--- a/IOB-UT-NEXT/TCMan.cs
+++ b/IOB-UT-NEXT/TCMan.cs
@@ -1,7 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace IOB_UT_NEXT
{
@@ -27,50 +24,6 @@ namespace IOB_UT_NEXT
#endregion Public Constructors
- #region Protected Properties
-
- ///
- /// Fattore lambda (innovazione) per calcolo EWMA valore TCiclo corrente
- ///
- protected double _lambda { get; set; } = 0.4;
-
- ///
- /// Ultimo TCiclo osservato in SECONDI
- ///
- protected double _lastTC { get; set; } = 0;
-
- ///
- /// ULTIMO Contapezzi IOB VALIDO
- ///
- protected int _lastValidPzCountIOB { get; set; } = 0;
-
- ///
- /// ULTIMO Contapezzi PLC VALIDO
- ///
- protected int _lastValidPzCountPLC { get; set; } = 0;
-
- ///
- /// Fattore massimo ammesso di delay x il TCiclo
- ///
- protected double _maxDelayFactor { get; set; } = 1.2;
-
- ///
- /// Incremento amssimo pezzi per cui fare calcolo del tempociclo attuale
- ///
- protected double _maxIncrPz { get; set; } = 2;
-
- ///
- /// Contapezzi IOB
- ///
- protected int _pzCountIOB { get; set; } = 0;
-
- ///
- /// Contapezzi PLC
- ///
- protected int _pzCountPLC { get; set; } = 0;
-
- #endregion Protected Properties
-
#region Public Properties
///
@@ -171,5 +124,49 @@ namespace IOB_UT_NEXT
}
#endregion Public Properties
+
+ #region Protected Properties
+
+ ///
+ /// Fattore lambda (innovazione) per calcolo EWMA valore TCiclo corrente
+ ///
+ protected double _lambda { get; set; } = 0.4;
+
+ ///
+ /// Ultimo TCiclo osservato in SECONDI
+ ///
+ protected double _lastTC { get; set; } = 0;
+
+ ///
+ /// ULTIMO Contapezzi IOB VALIDO
+ ///
+ protected int _lastValidPzCountIOB { get; set; } = 0;
+
+ ///
+ /// ULTIMO Contapezzi PLC VALIDO
+ ///
+ protected int _lastValidPzCountPLC { get; set; } = 0;
+
+ ///
+ /// Fattore massimo ammesso di delay x il TCiclo
+ ///
+ protected double _maxDelayFactor { get; set; } = 1.2;
+
+ ///
+ /// Incremento amssimo pezzi per cui fare calcolo del tempociclo attuale
+ ///
+ protected double _maxIncrPz { get; set; } = 2;
+
+ ///
+ /// Contapezzi IOB
+ ///
+ protected int _pzCountIOB { get; set; } = 0;
+
+ ///
+ /// Contapezzi PLC
+ ///
+ protected int _pzCountPLC { get; set; } = 0;
+
+ #endregion Protected Properties
}
}
\ No newline at end of file
diff --git a/IOB-UT-NEXT/ToMapo.cs b/IOB-UT-NEXT/ToMapo.cs
index f91154da..56a1011b 100644
--- a/IOB-UT-NEXT/ToMapo.cs
+++ b/IOB-UT-NEXT/ToMapo.cs
@@ -1,11 +1,7 @@
using MapoSDK;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
-using System;
-using System.Collections;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace IOB_UT_NEXT
{
@@ -14,7 +10,23 @@ namespace IOB_UT_NEXT
///
public class BaseAlarmConf
{
- #region Public Fields
+ #region Public Properties
+
+ ///
+ /// Elenco dei contatori blink x gestione caso fronte salita/discesa segnale che blinka
+ ///
+ public int[] alarmsBlinkCounter { get; set; }
+
+ ///
+ /// BitMask 16bit (1 = valido, 0 = filtro) degli allarmi silenziati/disabilitati (se
+ /// iniziano per ##) come valore da sottrarre x check
+ ///
+ public uint[] alarmsMask { get; set; }
+
+ ///
+ /// Array dei valori allarme correnti
+ ///
+ public uint[] alarmsState { get; set; }
///
/// valore di partenza x un segnale di blink in caso di fine variazione (fronte discesa)
@@ -26,25 +38,6 @@ namespace IOB_UT_NEXT
///
public int blinkUpVal { get; set; } = 3;
- #endregion Public Fields
-
- #region Public Properties
-
- ///
- /// Elenco dei contatori blink x gestione caso fronte salita/discesa segnale che blinka
- ///
- public int[] alarmsBlinkCounter { get; set; }
-
- ///
- /// BitMask 16bit (1 = valido, 0 = filtro) degli allarmi silenziati/disabilitati (se iniziano per ##) come valore da sottrarre x check
- ///
- public uint[] alarmsMask { get; set; }
-
- ///
- /// Array dei valori allarme correnti
- ///
- public uint[] alarmsState { get; set; }
-
///
/// Descrizione area allarmi
///
@@ -177,7 +170,8 @@ namespace IOB_UT_NEXT
alarmsState = new uint[size / 2];
alarmsMask = new uint[size / 2];
- // una volta inizializzata la classe di base sistemo vettori allarmi disabilitati ed il contatore blink dei fronti di discesa
+ // una volta inizializzata la classe di base sistemo vettori allarmi disabilitati ed il
+ // contatore blink dei fronti di discesa
alarmsBlinkCounter = new int[messages.Count];
int idx = 0;
int bank = 0;
@@ -217,7 +211,8 @@ namespace IOB_UT_NEXT
}
///
- /// Classe gestione configurazione parametri di base x configuraizone estesa (es MTConnect, OPC-UA, ...)
+ /// Classe gestione configurazione parametri di base x configuraizone estesa (es MTConnect,
+ /// OPC-UA, ...)
///
public class BaseParamConf
{
@@ -229,14 +224,13 @@ namespace IOB_UT_NEXT
public List condWork { get; set; } = new List();
///
- /// Indica se l'emergenza armata va riportata verso Mapo come bit a TRUE
- /// True --> armata = 1 / triggered = 0
- /// False --> triggered = 1 / armata = 0
+ /// Indica se l'emergenza armata va riportata verso Mapo come bit a TRUE True --> armata
+ /// = 1 / triggered = 0 False --> triggered = 1 / armata = 0
///
public bool emergencyArmedTrue { get; set; } = true;
///
- /// Elenco items FILTRATI da invio come dynData --> FluxLog (events o samples)
+ /// Elenco items FILTRATI da invio come dynData --> FluxLog (events o samples)
///
public List fluxLogVeto { get; set; } = new List();
@@ -309,7 +303,8 @@ namespace IOB_UT_NEXT
}
///
- /// Classe per rappresentare una lista di oggetti chiave/valore target x controlo condizioni multiple + indicazione modalità di controllo (AND/OR/...)
+ /// Classe per rappresentare una lista di oggetti chiave/valore target x controlo condizioni
+ /// multiple + indicazione modalità di controllo (AND/OR/...)
///
public class diCheckCondSetup
{
@@ -326,13 +321,75 @@ namespace IOB_UT_NEXT
public boolCheckMode checkMode { get; set; } = boolCheckMode.AND;
///
- /// indica se il check vada NEGATO (esempio se cerco la condizione opposta, esempio num allarmi 0 --> se true NEGO la condizione HO ALLARMI)
+ /// indica se il check vada NEGATO (esempio se cerco la condizione opposta, esempio num
+ /// allarmi 0 --> se true NEGO la condizione HO ALLARMI)
///
public bool negateValue { get; set; } = false;
#endregion Public Properties
}
+ ///
+ /// Classe x definizione delle azioni in fase di setup macchina
+ ///
+ public class MachineSetupAction
+ {
+ #region Public Properties
+
+ ///
+ /// Indica se vada disabilitato il contapezzi quando la condizione NotEqual sia soddisfatta
+ ///
+ public bool DisablePzCountNotEqual { get; set; } = false;
+
+ ///
+ /// Parametro target dell'azione
+ ///
+ public string TargetParam { get; set; } = "";
+
+ ///
+ /// parametro da impostare SE il check da esito EQUAL
+ ///
+ public int TargetValEqual { get; set; } = 0;
+
+ ///
+ /// parametro da impostare SE il check da esito NOT EQUAL
+ ///
+ public int TargetValNotEqual { get; set; } = 1;
+
+ #endregion Public Properties
+ }
+
+ ///
+ /// Definizione parametri di setup incrociato...
+ ///
+ public class MachineSetupConf
+ {
+ #region Public Properties
+
+ ///
+ /// Dizionario dei parametri di corrispondenza tra variabili MES e variabili Macchina MES =
+ /// scritte dal MES Macchina = scritte da macchina
+ ///
+ public Dictionary checkParList { get; set; } = new Dictionary();
+
+ ///
+ /// Abilitazione gestione Setup Avanzato (= scrittura)
+ ///
+ public bool EnableAdvSetup { get; set; } = false;
+
+ ///
+ /// Modalità gestione setup
+ ///
+ public MachineSetupMode SetupMode { get; set; } = MachineSetupMode.ND;
+
+ /// Dizionario dei parametri da scrivere quando si rilevano differenze tra i
+ /// parametri MES/Macchina string (key) --> memoria da scrivere tuple --> valori da scrivere quando uguali o diversi
+ public List writeParAction { get; set; } = new List();
+
+ #endregion Public Properties
+ }
+
///
/// COnfigurazione blocchi x accesso memoria ottimizzato
///
@@ -360,84 +417,6 @@ namespace IOB_UT_NEXT
#endregion Public Properties
}
- ///
- /// Definizione parametri watchdog
- ///
- public class WatchDogConf
- {
- ///
- /// Abilitazione WatchDog
- ///
- public bool IsEnabled { get; set; } = false;
- ///
- /// Conf memoria x lettura WatchDog (ToMes), se !="" è gestito
- ///
- public string MemConfRead { get; set; } = "";
- ///
- /// Conf memoria x scrittura WatchDog (FromMes), se !="" è gestito
- ///
- public string MemConfWrite { get; set; } = "";
- ///
- /// Valore max contatore prima di resettare
- ///
- public int MaxVal { get; set; } = 9999;
- }
-
- ///
- /// Definizione parametri di setup incrociato...
- ///
- public class MachineSetupConf
- {
- ///
- /// Modalità gestione setup
- ///
- public MachineSetupMode SetupMode { get; set; } = MachineSetupMode.ND;
-
- ///
- /// Abilitazione gestione Setup Avanzato (= scrittura)
- ///
- public bool EnableAdvSetup { get; set; } = false;
-
- ///
- /// Dizionario dei parametri di corrispondenza tra variabili MES e variabili Macchina
- /// MES = scritte dal MES
- /// Macchina = scritte da macchina
- ///
- public Dictionary checkParList { get; set; } = new Dictionary();
-
- ///
- /// Dizionario dei parametri da scrivere quando si rilevano differenze tra i parametri MES/Macchina
- /// string (key) --> memoria da scrivere
- /// tuple --> valori da scrivere quando uguali o diversi
- ///
- public List writeParAction { get; set; } = new List();
- }
-
- ///
- /// Classe x definizione delle azioni in fase di setup macchina
- ///
- public class MachineSetupAction
- {
- ///
- /// Parametro target dell'azione
- ///
- public string TargetParam { get; set; } = "";
-
- ///
- /// parametro da impostare SE il check da esito EQUAL
- ///
- public int TargetValEqual { get; set; } = 0;
- ///
- /// parametro da impostare SE il check da esito NOT EQUAL
- ///
- public int TargetValNotEqual { get; set; } = 1;
-
- ///
- /// Indica se vada disabilitato il contapezzi quando la condizione NotEqual sia soddisfatta
- ///
- public bool DisablePzCountNotEqual { get; set; } = false;
- }
-
///
/// Classe gestione configurazione parametri specifici OPC-UA da BaseParamConf
///
@@ -470,12 +449,6 @@ namespace IOB_UT_NEXT
///
public diCheckCondSetup condError { get; set; } = new diCheckCondSetup();
-
- ///
- /// Struttura dati x check condizione Errore
- ///
- public diCheckCondSetup condWorkOpc { get; set; } = new diCheckCondSetup();
-
///
/// Struttura dati x check condizione Emergenza
///
@@ -496,6 +469,11 @@ namespace IOB_UT_NEXT
///
public diCheckCondSetup condReady { get; set; } = new diCheckCondSetup();
+ ///
+ /// Struttura dati x check condizione Setup
+ ///
+ public diCheckCondSetup condSetup { get; set; } = new diCheckCondSetup();
+
///
/// Struttura dati x check condizione WarmUp - CoolDown
///
@@ -505,16 +483,19 @@ namespace IOB_UT_NEXT
/// Struttura dati x check condizione Warning
///
public diCheckCondSetup condWarning { get; set; } = new diCheckCondSetup();
+
///
- /// Struttura dati x check condizione Setup
+ /// Struttura dati x check condizione Errore
///
- public diCheckCondSetup condSetup { get; set; } = new diCheckCondSetup();
+ public diCheckCondSetup condWorkOpc { get; set; } = new diCheckCondSetup();
///
/// Elenco dei NodeId da ignorare intesi come interi rami (se vuoto NON filtro)
///
public List filterItemsNodeId { get; set; } = new List();
+ public UserIdent Identity { get; set; } = new UserIdent();
+
///
/// Aree di memoria lettura
///
@@ -525,34 +506,66 @@ namespace IOB_UT_NEXT
///
public Dictionary mMapWrite { get; set; } = new Dictionary();
- ///
- /// Elenco dei SOLI item sottoscritti (se vuoto TUTTI)
- ///
- public List subscribedItems { get; set; } = new List();
-
///
/// Elenco item RAW sottoscritti e relative configurazioni di decodifica da byte[]
///
public Dictionary rawSubscribedItemsConf { get; set; } = new Dictionary();
- ///
- /// Conf Gestione WatchDog
- ///
- public WatchDogConf WatchDog { get; set; } = new WatchDogConf();
-
///
/// Conf gestione setup macchina
///
public MachineSetupConf SetupConf { get; set; } = new MachineSetupConf();
- public UserIdent Identity { get; set; } = new UserIdent();
+ ///
+ /// Elenco dei SOLI item sottoscritti (se vuoto TUTTI)
+ ///
+ public List subscribedItems { get; set; } = new List();
+
+ ///
+ /// Conf Gestione WatchDog
+ ///
+ public WatchDogConf WatchDog { get; set; } = new WatchDogConf();
#endregion Public Properties
}
public class UserIdent
{
- public string UserName { get; set; } = "";
+ #region Public Properties
+
public string Passwd { get; set; } = "";
+ public string UserName { get; set; } = "";
+
+ #endregion Public Properties
+ }
+
+ ///
+ /// Definizione parametri watchdog
+ ///
+ public class WatchDogConf
+ {
+ #region Public Properties
+
+ ///
+ /// Abilitazione WatchDog
+ ///
+ public bool IsEnabled { get; set; } = false;
+
+ ///
+ /// Valore max contatore prima di resettare
+ ///
+ public int MaxVal { get; set; } = 9999;
+
+ ///
+ /// Conf memoria x lettura WatchDog (ToMes), se !="" è gestito
+ ///
+ public string MemConfRead { get; set; } = "";
+
+ ///
+ /// Conf memoria x scrittura WatchDog (FromMes), se !="" è gestito
+ ///
+ public string MemConfWrite { get; set; } = "";
+
+ #endregion Public Properties
}
}
\ No newline at end of file
diff --git a/IOB-UT-NEXT/baseUtils.cs b/IOB-UT-NEXT/baseUtils.cs
index 7f074349..1dc6a419 100644
--- a/IOB-UT-NEXT/baseUtils.cs
+++ b/IOB-UT-NEXT/baseUtils.cs
@@ -1,4 +1,3 @@
-using MapoSDK;
using NLog;
using System;
using System.Collections;
@@ -49,35 +48,6 @@ namespace IOB_UT_NEXT
#endregion Public Fields
-#if false
- {
- get
- {
- return redisMan.servStatus.dtVetoPing;
- }
- set
- {
- var currData = redisMan.servStatus;
- currData.dtVetoPing = value;
- redisMan.servStatus = currData;
- }
- }
-#endif
-
- #region Protected Properties
-
- ///
- /// Oggetto WebClient BASE da riutilizzare
- ///
- protected static WebClientWT client { get; set; }
-
- ///
- /// Oggetto WebClient con PAYLOAD da riutilizzare
- ///
- protected static WebClientWT clientPayload { get; set; }
-
- #endregion Protected Properties
-
#region Public Properties
///
@@ -117,6 +87,7 @@ namespace IOB_UT_NEXT
{ }
return answ;
}
+
///
/// formatta un numero in forma binaria 0/1
///
@@ -409,7 +380,9 @@ namespace IOB_UT_NEXT
/// number will be formatted as a 32-character binary number in two's compliment.
///
/// self-explanatory
- /// if binary number contains fewer characters leading zeros are added
+ ///
+ /// if binary number contains fewer characters leading zeros are added
+ ///
/// string as described above
public static string IntToBinStr(int theNumber, int minimumDigits)
{
@@ -420,7 +393,9 @@ namespace IOB_UT_NEXT
/// verifica se un dato bit sia alzato (come flag di strobe)
///
/// valore da testare
- /// valore cercato, può essere un singolo valore o un insieme in modalità AND
+ ///
+ /// valore cercato, può essere un singolo valore o un insieme in modalità AND
+ ///
///
public static bool IsSetAll(StFlag32 value, StFlag32 flag)
{
@@ -431,7 +406,9 @@ namespace IOB_UT_NEXT
/// verifica se un dato bit sia alzato (come flag di strobe)
///
/// valore da testare
- /// valore cercato, può essere un singolo valore o un insieme in modalità OR
+ ///
+ /// valore cercato, può essere un singolo valore o un insieme in modalità OR
+ ///
///
public static bool IsSetAny(StFlag32 value, StFlag32 flag)
{
@@ -586,7 +563,8 @@ namespace IOB_UT_NEXT
}
///
- /// provvede a verificare la dim della cartella dei log e cancella i + vecchi fino a restare a dim inferiori a _logMaxMb
+ /// provvede a verificare la dim della cartella dei log e cancella i + vecchi fino a restare
+ /// a dim inferiori a _logMaxMb
///
public static void shrinkDir(string dirPath)
{
@@ -616,7 +594,8 @@ namespace IOB_UT_NEXT
// inizio con eliminare file + vecchi della data indicata...
int maxLogDays = CRI("maxLogDays");
fileMover.obj.deleteOlderThan(maxLogDays);
- // ora controllo SE sia superata la dim max della directory --> in tal caso cancello dal + vecchio...
+ // ora controllo SE sia superata la dim max della directory --> in tal caso cancello dal
+ // + vecchio...
dirSizeMb = fileMover.obj.totalMb();
int maxLogDirSize = CRI("maxLogDirSize");
int maxTry = 100;
@@ -723,6 +702,20 @@ namespace IOB_UT_NEXT
}
#endregion Public Methods
+
+ #region Protected Properties
+
+ ///
+ /// Oggetto WebClient BASE da riutilizzare
+ ///
+ protected static WebClientWT client { get; set; }
+
+ ///
+ /// Oggetto WebClient con PAYLOAD da riutilizzare
+ ///
+ protected static WebClientWT clientPayload { get; set; }
+
+ #endregion Protected Properties
}
///
diff --git a/IOB-UT-NEXT/packages.config b/IOB-UT-NEXT/packages.config
index 70e045e6..26591de3 100644
--- a/IOB-UT-NEXT/packages.config
+++ b/IOB-UT-NEXT/packages.config
@@ -1,6 +1,6 @@
-
+
diff --git a/IOB-UT-NEXT/val.cs b/IOB-UT-NEXT/val.cs
deleted file mode 100644
index 94029a5c..00000000
--- a/IOB-UT-NEXT/val.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace IOB_UT_NEXT
-{
- internal class val
- {
- }
-}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/App.config b/IOB-WIN-NEXT/App.config
index a3743cb8..3985bdbf 100644
--- a/IOB-WIN-NEXT/App.config
+++ b/IOB-WIN-NEXT/App.config
@@ -1,165 +1,174 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/DATA/CONF/GIACO_ICOEL_002.ini b/IOB-WIN-NEXT/DATA/CONF/GIACO_ICOEL_002.ini
index 92c2eae4..5f2471f1 100644
--- a/IOB-WIN-NEXT/DATA/CONF/GIACO_ICOEL_002.ini
+++ b/IOB-WIN-NEXT/DATA/CONF/GIACO_ICOEL_002.ini
@@ -63,10 +63,12 @@ MIN_SEND_PZC_BLOCK=0
MAX_SEND_PZC_BLOCK=100
ENABLE_DYN_DATA=TRUE
FORCE_DYN_DATA=TRUE
+DEM_FACT_DYN_DATA=3
ENABLE_DATA_FILTER=TRUE
ENABLE_CLI_RESTART=TRUE
-VETO_SIG_IN=TRUE
+; clock base (da 10ms)
+timerIntMs=50
; conf parametri memoria READ/WRITE
PARAM_CONF=GIACO_ICOEL_002.json
diff --git a/IOB-WIN-NEXT/DATA/CONF/GIACO_ICOEL_003.ini b/IOB-WIN-NEXT/DATA/CONF/GIACO_ICOEL_003.ini
index decae0b2..470b6385 100644
--- a/IOB-WIN-NEXT/DATA/CONF/GIACO_ICOEL_003.ini
+++ b/IOB-WIN-NEXT/DATA/CONF/GIACO_ICOEL_003.ini
@@ -10,8 +10,8 @@ VENDOR=ICOEL
MODEL=Impianto Ciliegie Turi
[CNC]
-IP=192.168.137.50
-PORT=8001
+IP=192.168.137.11
+PORT=1443
GETPRGNAME=false
[SERVER]
@@ -63,9 +63,12 @@ MIN_SEND_PZC_BLOCK=0
MAX_SEND_PZC_BLOCK=100
ENABLE_DYN_DATA=TRUE
FORCE_DYN_DATA=TRUE
+DEM_FACT_DYN_DATA=5
ENABLE_DATA_FILTER=TRUE
ENABLE_CLI_RESTART=TRUE
-VETO_SIG_IN=TRUE
+SyncStateDb=localhost\sqlexpress
+SyncStateUser=egalware
+SyncStatePwd=egalware2022
; clock base (da 10ms)
timerIntMs=10
diff --git a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini
index cb0aa7c3..9722b51a 100644
--- a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini
+++ b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini
@@ -79,6 +79,7 @@ CLI_INST=SteamWareSim
;STARTLIST=VL25
;STARTLIST=SIMUL_03
;STARTLIST=GIACO_CEDAX_01
-STARTLIST=GIACO_ICOEL_002
+;STARTLIST=GIACO_ICOEL_002
+STARTLIST=GIACO_ICOEL_003
MAXCNC=10
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
index 60a702f1..1be1e006 100644
--- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
+++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
@@ -1,5 +1,6 @@
+
@@ -87,10 +88,10 @@
..\packages\EasyModbusTCP.5.6.0\lib\net40\EasyModbus.dll
- ..\packages\EgwProxy.Icoel.3.6.2205.2617\lib\EgwProxy.Icoel.dll
+ ..\packages\EgwProxy.Icoel.3.6.2205.2812\lib\EgwProxy.Icoel.dll
- ..\packages\EgwProxy.Icoel.3.6.2205.2617\lib\EgwProxy.Icoel.DataLayer.dll
+ ..\packages\EgwProxy.Icoel.3.6.2205.2812\lib\EgwProxy.Icoel.DataLayer.dll
..\packages\EgwProxy.MultiCncLib.3.6.2205.2319\lib\EgwProxy.MultiCncLib.dll
@@ -101,12 +102,18 @@
..\packages\EgwProxy.OsaiCncLib.3.6.2205.2015\lib\EgwProxy.OsaiCncLib.XmlSerializers.dll
+
+ ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll
+
+
+ ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll
+
False
ExtLib\krcc.dll
-
- ..\packages\MapoSDK.6.14.2205.2808\lib\MapoSDK.dll
+
+ ..\packages\MapoSDK.6.14.2205.3011\lib\MapoSDK.dll
..\packages\MathNet.Numerics.4.15.0\lib\net461\MathNet.Numerics.dll
@@ -147,6 +154,7 @@
..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
@@ -316,6 +324,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
Always
@@ -917,9 +931,12 @@
+
+
+
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/IobGeneric.cs b/IOB-WIN-NEXT/IobGeneric.cs
index 6a63763d..66840aeb 100644
--- a/IOB-WIN-NEXT/IobGeneric.cs
+++ b/IOB-WIN-NEXT/IobGeneric.cs
@@ -22,173 +22,6 @@ namespace IOB_WIN_NEXT
{
public class IobGeneric
{
- #region Protected Fields
-
- ///
- /// wrapper di log
- ///
- protected static Logger lg;
-
- protected bool _connOk = false;
-
- ///
- /// valore booleano di check se sia in fase di COMUNICAZIONE ATTIVA con il PLC/NC
- ///
- protected bool adpCommAct;
-
- ///
- /// porta x adapter (x restart)
- ///
- protected int adpPortNum;
-
- ///
- /// DataOra ultimo avvio adapter x watchdog
- ///
- protected DateTime adpStartRun;
-
- ///
- /// Vettore 32 BIT valori in ingresso al filtro
- ///
- protected int B_input;
-
- ///
- /// Vettore 32 BIT valori in uscita dal filtro
- ///
- protected int B_output;
-
- ///
- /// Vettore 32 BIT valori precedenti
- ///
- protected int B_previous;
-
- ///
- /// Num errori check alive
- ///
- protected int currAliveErrors = 0;
-
- ///
- /// Variabile numero errori vari (in lettura) --> se supera soglia maxErroriCheck --> disconnette
- ///
- protected int numErroriCheck = 0;
-
- ///
- /// Soglia massima errori priam di disconnesisone automatica
- ///
- protected int maxErroriCheck = 100;
-
- ///
- /// Dizionario valori impostati x produzione
- ///
- protected Dictionary currProdData = new Dictionary();
-
- ///
- /// num corrente errori read PLC
- ///
- protected int currReadErrors = 0;
-
- ///
- /// num errori send
- ///
- protected int currSendErrors = 0;
-
- ///
- /// Periodo wathdog di default (2 sec se non specificato)
- ///
- protected int watchDogPeriod = 2;
-
- ///
- /// Array dei contatori x segnali blinking
- ///
- protected int[] i_counters;
-
- ///
- /// Indica impianto IN SETUP (fino a quando SMETTE di esserlo...)
- ///
- protected bool inSetup = false;
-
- ///
- /// ultimo tentativo connessione...
- ///
- protected DateTime lastConnectTry;
-
- ///
- /// Dizionario ULTIMI valori impostati x produzione
- ///
- protected Dictionary lastProdData = new Dictionary();
-
- ///
- /// Ultimo invio contapezzi (x invio delayed)
- ///
- protected DateTime lastPzCountSend;
-
-
- ///
- /// Ultimo LOG registrazione avvio (x ridurre log notturni...)
- ///
- protected DateTime lastLogStartup = DateTime.Today.AddHours(-1);
-
- ///
- /// Veto per registrazione completa log di startup (minuti)
- ///
- protected int vetoLogStartupDuration = 60;
-
- ///
- /// Dizionario ultimi valori (double) delle TSVC
- ///
- protected Dictionary LastTSVC = new Dictionary();
-
- ///
- /// Ultima registrazione warning x ODL mancante (x scrivere solo ogni 15 secondi)
- ///
- protected DateTime lastWarnODL;
-
- ///
- /// Num massimo di errori in funzionalità check alive
- ///
- protected int maxAliveErrors = utils.CRI("maxAliveErrors");
-
- ///
- /// Num massimo di errori di rete read (dal PLC)
- ///
- protected int maxReadErrors = utils.CRI("maxReadErrors");
-
- ///
- /// Num massimodi errori di rete send al server
- ///
- protected int maxSendErrors = utils.CRI("maxSendErrors");
-
- ///
- /// indica se serva refresh parametri e quindi PLC...
- ///
- protected bool needRefresh = true;
-
- ///
- /// Form chiamante
- ///
- protected AdapterForm parentForm;
-
- ///
- /// Timeout x ping al server
- ///
- protected int pingServerMsTimeout = utils.CRI("pingMsTimeout");
-
- ///
- /// Ritardo minimo x invio contapezzi
- ///
- protected int pzCountDelay;
-
- ///
- /// Dizionario di VC da trattare come TimeSeries (con conf decodificata + processing successivo...)
- ///
- protected Dictionary TSVC_Data = new Dictionary();
-
- ///
- /// Dizionario di VARIABILI da trattare come eventi (da inviare quando cambiano oppure a scadenza periodo...)
- ///
- protected Dictionary VarArray = new Dictionary();
-
- #endregion Protected Fields
-
#region Public Fields
///
@@ -196,11 +29,6 @@ namespace IOB_WIN_NEXT
///
public bool adpRunning = false;
- ///
- /// Valore di attesa (random) dopo ogni invio x evitare congestione send...
- ///
- protected static int urlRandWait = 0;
-
///
/// valore booleano di check se l'adapter STIA SALVANDO
///
@@ -362,7 +190,8 @@ namespace IOB_WIN_NEXT
public Dictionary persistenceLayer;
///
- /// Determina se utilizzare blocchi di memoria IOT contigui (e quindi processing "monoblocco" semplificato"=
+ /// Determina se utilizzare blocchi di memoria IOT contigui (e quindi processing
+ /// "monoblocco" semplificato"=
///
public bool procIotMem = false;
@@ -387,7 +216,7 @@ namespace IOB_WIN_NEXT
public ConcurrentQueue QueueMessages = new ConcurrentQueue();
///
- /// Oggetto della coda degli elementi di tipo RawTransf (e non ancora trasmessi)
+ /// Oggetto della coda degli elementi di tipo RawTransf (e non ancora trasmessi)
/// NB: sono salvati serializzati come stringhe
///
public ConcurrentQueue QueueRawTransf = new ConcurrentQueue();
@@ -497,387 +326,6 @@ namespace IOB_WIN_NEXT
#endregion Public Events
- #region Private Properties
-
- ///
- /// Verifica se la IOB sia ENABLED (da server o Demo)
- ///
- private bool checkIobEnabled
- {
- get
- {
- bool answ = false;
- // controllo se ho veto al check...
- if (dtVetoCheckIOB < DateTime.Now)
- {
- if (DemoOut)
- {
- answ = (QueueIN.Count + QueueFLog.Count >= nMaxSend);
- IobOnline = answ;
- }
- else
- {
- try
- {
- // chiamo URL, se restituisce "OK" è enabled!
- string callResp = callUrl(urlIobEnabled, true);
- answ = (callResp == "OK");
- // attesa casuale se necessario
- var rand = new Random();
- // primi 2 test
- int maxTry = 2;
- while (maxTry > 0 && !answ)
- {
- Thread.Sleep(rand.Next(250, 500));
- callResp = callUrl(urlIobEnabled, true);
- answ = (callResp == "OK");
- maxTry--;
- }
- // se NON OK riprovo ANCORA 1 volta...
- if (!answ)
- {
- resetWebClients();
- Thread.Sleep(rand.Next(250, 1000));
- callResp = callUrl(urlIobEnabled, false);
- answ = (callResp == "OK");
- }
- // altri 2
- maxTry = 2;
- while (maxTry > 0 && !answ)
- {
- Thread.Sleep(rand.Next(250, 500));
- callResp = callUrl(urlIobEnabled, false);
- answ = (callResp == "OK");
- maxTry--;
- }
- // salvo status...
- IobOnline = answ;
- // se online imposto veto check a 5 x tempo reinvio...
- if (answ)
- {
- lastIobOnline = DateTime.Now;
- }
- dtVetoCheckIOB = DateTime.Now.AddMilliseconds(baseUtils.nextPauseSendMSec * 5);
- }
- catch
- { }
- }
- // verifico SE è variato stato online/offline...
- if (IobOnline != answ)
- {
- // se ORA sono online riporto...
- if (answ)
- {
- lgInfo("IOB ONLINE for server MP/IO");
- }
- else
- {
- lgInfo("IOB OFFLINE for server MP/IO");
- }
- }
- // fix colore
- if (answ)
- {
- parentForm.commSrvActive = 2;
- }
- else
- {
- parentForm.commSrvActive = 1;
- }
- }
- else
- {
- // altrimenti passo ultimo valore noto
- answ = IobOnline;
- }
- return answ;
- }
- }
-
- ///
- /// test ping all'indirizzo impostato nei parametri
- ///
- ///
- private IPStatus testPingServer
- {
- get
- {
- IPStatus answ = IPStatus.Unknown;
- // se disabilitato salto...
- if (pingDisabled)
- {
- answ = IPStatus.Success;
- }
- else
- {
- IPAddress address;
- PingReply reply;
- var rand = new Random();
- int pingTOut = 500;
- using (Ping pingSender = new Ping())
- {
- address = IPAddress.Loopback;
- int maxRetry = maxPingRetry + 1;
- int numRetry = 1;
- string ipAddr = cIobConf.serverData.MPIP.Replace($"{cIobConf.serverData.TRANSP}://", "");
- // fix se fosse ip + porta...
- if (ipAddr.IndexOf(":") >= 0)
- {
- ipAddr = ipAddr.Substring(0, ipAddr.IndexOf(":"));
- }
- IPAddress.TryParse(ipAddr, out address);
- // se null --> provo DNS...
- if (address == null)
- {
- var rawAddresses = Dns.GetHostAddresses(ipAddr);
- if (rawAddresses.Length > 0)
- {
- address = rawAddresses[0];
- }
- }
- try
- {
- // se != null --> uso address...
- if (address != null)
- {
- pingTOut = rand.Next(200, 400);
- reply = pingSender.Send(address, pingTOut);
- }
- else
- {
- pingTOut = rand.Next(300, 600);
- reply = pingSender.Send(cIobConf.cncIpAddr, pingTOut);
- }
- }
- catch (Exception exc)
- {
- pingTOut = rand.Next(100, 200);
- reply = pingSender.Send(IPAddress.Loopback, pingTOut);
- lgError($"ping to loopback addres per eccezione:{Environment.NewLine}{exc}");
- }
- // se ho timeout riprovo...
- while (reply.Status != IPStatus.Success && numRetry < maxRetry)
- {
- Thread.Sleep(rand.Next(50, 200));
- pingTOut = pingServerMsTimeout * numRetry / 2;
- reply = pingSender.Send(address, pingTOut);
- numRetry++;
- if (reply.Status == IPStatus.Success)
- {
- lgInfo("Server PING OK!");
- break;
- }
- else
- {
- lgInfo($"Server Ping KO | reply: {reply.Status} --> retry | TimeOut: {pingTOut}");
- }
- }
- }
- answ = reply.Status;
- }
- return answ;
- }
- }
-
- #endregion Private Properties
-
- #region Protected Properties
-
- ///
- /// Valore del num max invii consecutivi da coda...
- ///
- protected static int nMaxSend
- {
- get
- {
- int answ = 5;
- try
- {
- answ = utils.CRI("nMaxSend");
- }
- catch
- { }
- return answ;
- }
- }
-
- ///
- /// Indica il counter della key richiesta attiva
- /// - gestito tramite Redis
- /// - a scadenza 25h
- /// - incrementato ogni invio di auto ODL
- ///
- protected int countKeyRichiesta
- {
- get
- {
- // calcolo key odierna
- int answ = redisMan.getKReqCount(dailyKey);
- return answ;
- }
- set
- {
- // calcolo key odierna
- redisMan.setKReqCount(dailyKey, value);
- }
- }
-
- protected string dailyKey
- {
- get
- {
- return DateTime.Today.ToString("yyMMdd");
- }
- }
-
- ///
- /// Variabile di appoggio GLOBALE x indicare che si può forzare reset contapezzi con macchina in RUN
- ///
- protected bool forceResetInRun { get; set; } = false;
-
- ///
- /// Variabile di appoggio GLOBALE x indicare macchina RUN (es x gestione su reset pezzi)
- ///
- protected bool isRunning { get; set; } = false;
-
- ///
- /// Valore limite MASSIMO di invio di dati come array Json
- ///
- protected int maxJsonData { get; set; } = utils.CRI("maxJsonData");
-
- ///
- /// Valore limite MASSIMO di invio di dati come array Json x EVENTI
- ///
- protected int maxJsonDataEv { get; set; } = utils.CRI("maxJsonDataEv");
-
- ///
- /// Max tentativi ping permessi (default: 5)
- ///
- protected int maxPingRetry { get; set; } = 5;
-
- ///
- /// Coda massima ammessa per FLog (se <=0 disattivata...)
- ///
- protected int maxQueueFLog { get; set; } = utils.CRI("maxQueueFLog");
- ///
- /// Coda massima ammessa per FLog (se <=0 disattivata...)
- ///
- protected int maxQueueRawTransf { get; set; } = utils.CRI("maxQueueRawTransf");
-
- ///
- /// Valore MINIMO limite x decidere invio di dati come array Json
- ///
- protected int minJsonData { get; set; } = utils.CRI("minJsonData");
-
- protected string nextKeyRich
- {
- get
- {
- return $"{dailyKey}{countKeyRichiesta:00}";
- }
- }
-
- ///
- /// Numero letture IN da avvio
- ///
- protected int nReadFilt { get; set; }
-
- ///
- /// Numero letture IN da avvio
- ///
- protected int nReadIN { get; set; }
-
- ///
- /// Numero invii OUT (svuotamento coda)
- ///
- protected int nSendOut { get; set; }
-
- ///
- /// Numero simulazioni ammesse...
- ///
- protected int numSim { get; set; }
-
- ///
- /// Indica se sia stato resettato un contapezzi
- ///
- protected bool pzCountResetted { get; set; } = false;
-
- ///
- /// Fornisce il valore letto da BITMAP in formato valido x messa in coda nel formato dtEve#value#cont
- ///
- protected string qEncodeIN
- {
- get
- {
- string answ = "";
- try
- {
- answ = string.Format("{0:yyyyMMddHHmmssfff}#{1:X2}#{2}", DateTime.Now, B_output, counterSigIN);
- }
- catch
- { }
- return answ;
- }
- }
-
- ///
- /// Indica se vada inviata la key richiesta con lo split/autoODL
- ///
- protected bool sendKeyRichiesta { get; set; } = false;
-
- ///
- /// test ping all'indirizzo PLC/CNC impostato nei parametri
- ///
- ///
- protected IPStatus testPingMachine
- {
- get
- {
- IPStatus answ = IPStatus.Unknown;
- // se disabilitato salto...
- if (pingDisabled)
- {
- answ = IPStatus.Success;
- }
- else
- {
- IPAddress address;
- PingReply reply;
- using (Ping pingSender = new Ping())
- {
- address = IPAddress.Loopback;
- int pingMsTimeout = cIobConf.pingMsTimeout;
- IPAddress.TryParse(cIobConf.cncIpAddr, out address);
- try
- {
- // se != null --> uso address...
- if (address != null)
- {
- reply = pingSender.Send(address, pingMsTimeout);
- }
- else
- {
- reply = pingSender.Send(cIobConf.cncIpAddr, pingMsTimeout);
- }
- }
- catch
- {
- reply = pingSender.Send(IPAddress.Loopback, pingMsTimeout);
- }
- answ = reply.Status;
- }
- }
- return answ;
- }
- }
-
- ///
- /// Secondi standard x veto check status e log
- ///
- protected int vetoSeconds { get; set; } = utils.CRI("vetoSeconds");
-
- #endregion Protected Properties
-
#region Public Properties
///
@@ -1112,23 +560,23 @@ namespace IOB_WIN_NEXT
///
public int counterFLog { get; set; }
- ///
- /// Contatore x invio dati SignalIN
- ///
- public int counterSigIN { get; set; }
-
///
/// Contatore x invio dati RawTransf
///
public int counterRawTransf { get; set; }
+ ///
+ /// Contatore x invio dati SignalIN
+ ///
+ public int counterSigIN { get; set; }
+
///
/// Contatore x invio dati UserLog
///
public int counterULog { get; set; }
///
- /// Verifica se sia in modalità DEMO --> da tipo IOB SIMULA...
+ /// Verifica se sia in modalità DEMO --> da tipo IOB SIMULA...
///
public bool DemoIn
{
@@ -1227,7 +675,8 @@ namespace IOB_WIN_NEXT
public string lastUrl { get; set; }
///
- /// Valore massimo accettato x incremento pezzi letti dal PLC (valore moltiplicato per 100... 200% --> 200)
+ /// Valore massimo accettato x incremento pezzi letti dal PLC (valore moltiplicato per
+ /// 100... 200% --> 200)
///
public int maxPzDeltaPerc
{
@@ -1722,813 +1171,2839 @@ namespace IOB_WIN_NEXT
#endregion Public Properties
- #region Private Methods
+ #region Public Methods
///
- /// Verifica e se necessario comprime directory log...
+ /// Effettua chiamata URL e restituisce risultato
///
- private void checkShrinkDir()
+ ///
+ /// invio in modalità async (NON GARANTITO ordine...)
+ ///
+ public static string callUrl(string URL, bool doAsync)
{
- string path = string.Format("{0}logs\\{1}", AppDomain.CurrentDomain.BaseDirectory, cIobConf.codIOB);
- baseUtils.shrinkDir(path);
- }
-
- ///
- /// Mostra i dati grezzi letti in esadecimale
- /// Parametri da aggiornare x display in form
- ///
- private void displayRawData(ref newDisplayData currDispData)
- {
- // mostro update...
- string newString = string.Format("{0:X}", B_input);
- currDispData.newInData = newString;
- }
-
- ///
- /// Esegue filtraggio dati x bit blinking!!!
- ///
- private void filterData()
- {
- // effettuo filtraggio dei valori letti... inizializzo OUT!
- B_output = 0;
- // in primis verifico SE ci siano bit blinkng... se non ci sono OUT=IN...
- if (cIobConf.BLINK_FILT == 0)
+ string answ = "";
+ // Chiamata ASINCRONA
+ if (doAsync)
{
- B_output = B_input;
+ //Task resp = utils.callUrlAsync(URL);
+ //answ = resp.Result;
+ answ = utils.callUrlAsync(URL);
+ if (urlRandWait > 0)
+ {
+ Random rnd = new Random();
+ Thread.Sleep(rnd.Next(urlRandWait / 10, urlRandWait));
+ }
+ }
+ // chiamata SOLO NORMALE SINCRONA...
+ else
+ {
+ answ = utils.callUrl(URL);
+ if (urlRandWait > 0)
+ {
+ Random rnd = new Random();
+ Thread.Sleep(rnd.Next(urlRandWait / 10, urlRandWait));
+ }
+ }
+ return answ;
+ }
+
+ ///
+ /// Effettua chiamata URL e restituisce risultato
+ ///
+ ///
+ ///
+ /// invio in modalità async (NON GARANTITO ordine...)
+ ///
+ public static string callUrlWithPayload(string URL, string payload, bool doAsync)
+ {
+ string answ = "";
+ // Chiamata ASINCRONA
+ if (doAsync)
+ {
+ answ = utils.callUrlAsync(URL, payload);
+ if (urlRandWait > 0)
+ {
+ Random rnd = new Random();
+ Thread.Sleep(rnd.Next(urlRandWait / 10, urlRandWait));
+ }
+ }
+ // chiamata SOLO NORMALE SINCRONA...
+ else
+ {
+ answ = utils.callUrl(URL, payload);
+ if (urlRandWait > 0)
+ {
+ Random rnd = new Random();
+ Thread.Sleep(rnd.Next(urlRandWait / 10, urlRandWait));
+ }
+ }
+ return answ;
+ }
+
+ ///
+ /// processa dataLayer e se necessario salva/mostra
+ ///
+ public static void checkSavePersDataLayer()
+ {
+ }
+
+ public static string GetMACAddress()
+ {
+ NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
+ String sMacAddress = string.Empty;
+ foreach (NetworkInterface adapter in nics)
+ {
+ if (string.IsNullOrEmpty(sMacAddress))// only return MAC Address from first card
+ {
+ IPInterfaceProperties properties = adapter.GetIPProperties();
+ //sMacAddress = adapter.GetPhysicalAddress().ToString();
+ sMacAddress = string.Join(":", (from z in adapter.GetPhysicalAddress().GetAddressBytes() select z.ToString("X2")).ToArray());
+ }
+ }
+ return sMacAddress;
+ }
+
+ public static void resetDebugConsole()
+ {
+ }
+
+ ///
+ /// Reset dei webclients
+ ///
+ public static void resetWebClients()
+ {
+ utils.resetWebClients();
+ }
+
+ ///
+ /// Accumula in coda i valori ALARM e logga...
+ ///
+ /// VALORE RAW (x display)
+ /// VALORE già processato con qEncodeFLog(...)
+ public void accodaAlarmLog(string val, string encodedVal)
+ {
+ // mostro dati variati letti...
+ displayOtherData(val);
+ // accodo IN PRIMIS al FluxLog --> accodo (valore già formattato)!
+ QueueFLog.Enqueue(encodedVal);
+ // accodo ANCHE alla coda allarmi che trasmetterò SOLO SE a scadenza impostata (10 sec?)
+ // ho allarmi perdurati...
+
+ // loggo!
+ lgInfo(string.Format("[QUEUE-ALARM-LOG] {0}", encodedVal));
+ counterFLog++;
+ if (counterFLog > 9999)
+ {
+ counterFLog = 0;
+ }
+ }
+
+ ///
+ /// Accumula in coda i valori Flux Log e logga...
+ ///
+ /// VALORE RAW (x display)
+ /// VALORE già processato con qEncodeFLog(...)
+ public void accodaFLog(string val, string encodedVal)
+ {
+ // mostro dati variati letti...
+ displayOtherData(val);
+ // --> accodo (valore già formattato)!
+ QueueFLog.Enqueue(encodedVal);
+ // se abilitato controllo coda FLog (superiore a 0...)
+ if (maxQueueFLog > 0)
+ {
+ // se ho una coda superiore a max ammesso
+ if (QueueFLog.Count > maxQueueFLog)
+ {
+ // elimino valori iniziali fino a tornare al max ammesso...
+ while (QueueFLog.Count > maxQueueFLog)
+ {
+ string currVal = "";
+ QueueFLog.TryDequeue(out currVal);
+ lgInfo($"Eliminazione da coda FLog per superamento maxLengh: {currVal}");
+ }
+ }
+ }
+ // loggo!
+ lgTrace(string.Format("[QUEUE-FLOG] {0}", encodedVal));
+ counterFLog++;
+ if (counterFLog > 9999)
+ {
+ counterFLog = 0;
+ }
+ }
+
+ ///
+ /// Accoda (visualizzando in cima allo stack) la nuova stringa di output per area OTHER DATA
+ ///
+ ///
+ public void accodaOtherData(string newLine)
+ {
+ // inserisco in cima allo stack, trimmo e aggiorno display
+ string strOtherData = limitLine2show(string.Format("{0}{1}{2}", newLine, Environment.NewLine, parentForm.dataMonitor_3));
+ //parentForm.dataMonitor_3 = strOtherData;
+ parentForm.WriteTextSafe(strOtherData);
+ }
+
+ ///
+ /// Accumula in coda i valori RawData + log
+ ///
+ ///
+ ///
+ public void accodaRawData(rawTransfType mesType, object mesContent)
+ {
+ /*--------------------------------
+ * nuova gestione coda dictionary
+ * fixme todo da fare !!!
+ *
+ * - conterrà una lista di oggetti baseRawTransf
+ * - i dati vanno poi "scodati" dal + vecchio ed inviati a MP/IO
+ * - mostra un sunto delle info da inviare
+ * - accodamento vero e proprio
+ * - verifica (opzionale) coda massima x gestire roundRobin ultimi eventi
+ * - trace della coda
+ * - counter invio??? valutare se c'è dataora e poi sono da salvare su MongoDb / Redis
+ *
+ * */
+
+ // serializzo il valore...
+ BaseRawTransf newVal = new BaseRawTransf(DateTime.Now, mesContent, mesType);
+ string encodedVal = JsonConvert.SerializeObject(newVal);
+ // --> accodo (valore già formattato)!
+ QueueRawTransf.Enqueue(encodedVal);
+ // se abilitato controllo coda Max (superiore a 0...)
+ if (maxQueueRawTransf > 0)
+ {
+ // se ho una coda superiore a max ammesso
+ if (QueueRawTransf.Count > maxQueueRawTransf)
+ {
+ // elimino valori iniziali fino a tornare al max ammesso...
+ while (QueueRawTransf.Count > maxQueueRawTransf)
+ {
+ string currVal = "";
+ QueueRawTransf.TryDequeue(out currVal);
+ lgInfo($"Eliminazione da coda RawTransf per superamento maxLengh: {currVal}");
+ }
+ }
+ }
+ // loggo!
+ lgTrace(string.Format("[QUEUE-RTRANSF] {0}", encodedVal));
+ counterRawTransf++;
+ if (counterRawTransf > 9999)
+ {
+ counterRawTransf = 0;
+ }
+ }
+
+ ///
+ /// Accumula in coda i valori Signal IN e logga... Parametri
+ /// da aggiornare x display in form
+ ///
+ public void accodaSigIN(ref newDisplayData currDispData)
+ {
+ // mostro dati variati letti...
+ displayInData(ref currDispData);
+ // verifico veto a invio status macchina
+ string keyName = "VETO_SIG_IN";
+ if (getOptPar(keyName).ToUpper() == "TRUE")
+ {
+ lgTrace($"Filtrato accodamento valore da conf IOB | {keyName} | [QUEUE-IN] {qEncodeIN}");
}
else
{
- // incomincio con i valori NON blinking: questi "passano invariati", inizio a sommare nel valore OUT...
- B_output = B_input & ~cIobConf.BLINK_FILT;
- // calcolo il valore dei BIT che "passano la maschera"
- int iBlink = B_input & cIobConf.BLINK_FILT;
- // ...aggiungo i "bit che passano"
- B_output += iBlink;
+ // --> accodo (valore già formattato)!
+ QueueIN.Enqueue(qEncodeIN);
+ // loggo!
+ lgTrace(string.Format("[QUEUE-IN] {0}", qEncodeIN));
+ }
+ // aggiorno counters ed eventuale reset
+ nReadFilt++;
+ if (nReadFilt > int.MaxValue - 1)
+ {
+ nReadFilt = 0; // per evitare buffer overflow...
+ }
- // calcolo QUALI valori (tra quelli blink) siano PASSATI da 0 a 1 --> init counters...
- BitArray bBlinkStart = new BitArray(new byte[] { Convert.ToByte(iBlink) });
- int[] bitsUp = bBlinkStart.Cast().Select(bit => bit ? 1 : 0).ToArray();
- for (int i = 0; i < bitsUp.Length; i++)
+ counterSigIN++;
+ if (counterSigIN > 9999)
+ {
+ counterSigIN = 0;
+ }
+ }
+
+ ///
+ /// Accumula in coda i valori USER LOG e logga...
+ ///
+ /// VALORE RAW (x display)
+ /// VALORE già processato con qEncodeULog(...)
+ public void accodaUserLog(string val, string encodedVal)
+ {
+ // mostro dati variati letti...
+ displayOtherData(val);
+ // accodo IN PRIMIS al FluxLog --> accodo (valore già formattato)!
+ QueueULog.Enqueue(encodedVal);
+
+ // loggo!
+ lgInfo(string.Format("[QUEUE-USER-LOG] {0}", encodedVal));
+ counterULog++;
+ if (counterULog > 9999)
+ {
+ counterFLog = 0;
+ }
+ }
+
+ ///
+ /// Update visualizzaizone BIT in ingresso Parametri da
+ /// aggiornare x display in form
+ ///
+ public void displayInData(ref newDisplayData currDispData)
+ {
+ if (currDispData != null)
+ {
+ // mostro update...
+ string newString = string.Format("{0:0000}|{1}", counterSigIN, utils.IntToBinStr(B_output, 8));
+ currDispData.newSignalData = newString;
+ }
+ }
+
+ ///
+ /// Mostra cosa ha/avrebbe inviato
+ ///
+ ///
+ public void displayOtherData(string newData)
+ {
+ // mostro update...
+ accodaOtherData(newData);
+ }
+
+ ///
+ /// Esecuzione dei task richiesti e pulizia coda richieste eseguite
+ ///
+ ///
+ public virtual Dictionary executeTasks(Dictionary task2exe)
+ {
+ // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti...
+ Dictionary taskDone = new Dictionary();
+ if (task2exe != null)
+ {
+ // controllo se memMap != null...
+ if (memMap != null)
{
- // SE 1... impostiamo contatori al MAX
- if (bitsUp[i] == 1)
+ bool taskOk = false;
+ string taskVal = "";
+ // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4
+ foreach (var item in task2exe)
{
- // se era zero indico START blink...
- if (i_counters[i] == 0)
+ taskOk = false;
+ taskVal = "";
+ // converto richiesta in enum...
+ taskType tName = taskType.nihil;
+ Enum.TryParse(item.Key, out tName);
+ // controllo sulla KEY...
+ switch (tName)
{
- lgTrace("START BLINK: B{0}", i);
+ case taskType.setArt:
+ case taskType.setComm:
+ case taskType.setProg:
+ case taskType.setPzComm:
+ // recupero dati da memMap...
+ if (memMap != null && memMap.mMapWrite != null)
+ {
+ if (memMap.mMapWrite.ContainsKey(item.Key))
+ {
+ dataConf currMem = memMap.mMapWrite[item.Key];
+ string addr = currMem.memAddr;
+ taskVal = $"SET task: {item.Key} --> {item.Value} | mem: {currMem.memAddr} - {currMem.size} byte";
+ // salvo il nuovo valore nella memoria... così prox invio lo trasmetterà
+ memMap.mMapWrite[item.Key].value = item.Value;
+ }
+ else
+ {
+ taskVal = $"NO DATA MEM, SET task: {item.Key} --> {item.Value}";
+ }
+ }
+ else
+ {
+ taskVal = $"NO MemMap found, SET task: {item.Key} --> {item.Value}";
+ }
+ // salvo in currProd..
+ saveProdData(new KeyValuePair(item.Key, item.Value));
+
+ break;
+
+ case taskType.forceResetPzCount:
+ // reset contapezzi inizio setup
+ taskOk = resetcontapezziPLC();
+ taskVal = taskOk ? "RESET PZ COUNT OK" : "PZ RESET DISABLED | NO EXEC";
+ lgInfo($"Chiamata forceResetPzCount: 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;
+
+ case taskType.setParameter:
+ // richiedo da URL i parametri WRITE da popolare
+ lgInfo("Chiamata setParameter --> processMemWriteRequests");
+ taskVal = processMemWriteRequests();
+ // se restituiscce "" faccio altra prova...
+ if (string.IsNullOrEmpty(taskVal))
+ {
+ // i parametri me li aspetto come stringa composta paramName|paramvalue
+ if (item.Value.Contains("|"))
+ {
+ string[] paramsJob = item.Value.Split('|');
+ taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}";
+ }
+ else
+ {
+ taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value";
+ }
+ }
+ break;
+
+ default:
+ taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
+ lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
+ break;
}
- // imposto comunque contatore al cambio fronte...
- i_counters[i] = cIobConf.MAX_COUNTER_BLINK;
+ // aggiungo task!
+ taskDone.Add(item.Key, taskVal);
}
}
-
- // quelli che sono zero... LI RECUPERO E LI PROCESSO...
- int iZero = ~B_input & cIobConf.BLINK_FILT;
- BitArray bBlinkEnd = new BitArray(new byte[] { Convert.ToByte(iZero) });
- int[] bitsDown = bBlinkEnd.Cast().Select(bit => bit ? 1 : 0).ToArray();
- for (int i = 0; i < bitsDown.Length; i++)
+ else
{
- // se era a zero (invertito...)
- if (bitsDown[i] == 1)
+ lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!");
+ }
+ }
+
+ return taskDone;
+ }
+
+ ///
+ /// Effettua verifica delle memorie WRITE, se ci siano variazioni da riportare verso il PLC
+ /// Da impiegare ad esempio in caso di chiamate complesse (ad 2 aree di memoria condivise
+ /// sul PLC; coem commessa + articolo EWON)
+ ///
+ ///
+ /// Cerca parametri opzionali in modalità "like" del nome
+ ///
+ ///
+ ///
+ public Dictionary findOptPar(string keyStartSearch = "")
+ {
+ Dictionary answ = new Dictionary();
+ // controllo SE keySearch !=""
+ if (!string.IsNullOrWhiteSpace(keyStartSearch))
+ {
+ if (cIobConf.optPar.Count > 0)
+ {
+ // ciclo su tutti e cerco occorrenze che INIZINO...
+ foreach (var item in cIobConf.optPar)
{
- // SE è in corso il conteggio...
- if (i_counters[i] > 0)
+ if (item.Key.StartsWith(keyStartSearch))
{
- // decremento!
- i_counters[i] -= 1;
- // se è zero NON faccio nulla, altrimenti SOMMO...
- if (i_counters[i] > 0)
- {
- B_output += 1 << i;
- }
- else
- {
- lgTrace("END BLINK: B{0}", i);
- }
+ answ.Add(item.Key, item.Value);
}
}
}
}
+ return answ;
}
///
- /// Imposta eventuali altri valori default
+ /// forza reset ODL
///
- private void fixDefaultPar()
+ public void forceResetOdl()
{
- // parametro max tentativi PING...
- string s_maxPingRetry = getOptPar("MAX_PING_RETRY");
- if (!string.IsNullOrEmpty(s_maxPingRetry))
- {
- int numRetry = 5;
- int.TryParse(s_maxPingRetry, out numRetry);
- maxPingRetry = numRetry;
- }
-
- string s_maxErrCheck = getOptPar("MAX_ERR_CHECK");
- if (!string.IsNullOrEmpty(s_maxErrCheck))
- {
- int numErr = 50;
- int.TryParse(s_maxErrCheck, out numErr);
- maxErroriCheck = numErr;
- }
-
- string s_watchDogPer = getOptPar("WATCHDOG_PERIOD");
- if (!string.IsNullOrEmpty(s_watchDogPer))
- {
- int numPer = 3;
- int.TryParse(s_watchDogPer, out numPer);
- watchDogPeriod = numPer;
- }
+ lgInfo("Registrato richiesta forzatura reset ODL");
+ pzCountResetted = true;
}
///
- /// recupera valore salvato in persistence layer (se non c'è crea...)
+ /// Effettua chiamata x split ODL
///
- ///
///
- private string getStoredVal(string keyVal)
+ public bool forceSplitOdl()
{
- string value = "";
- try
+ bool fatto = false;
+ if (vetoSplit < DateTime.Now)
{
- if (persistenceLayer != null)
+ lgInfo("Richiesto forceSplitOdl");
+ // imposto veto x 1 minuto ad altre chiamate...
+ vetoSplit = DateTime.Now.AddMinutes(1);
+ // eseguo SOLO SE sono online...
+ if (MPOnline && IobOnline)
{
- if (!persistenceLayer.TryGetValue(keyVal, out value))
+ string fullUrl = "";
+ string rawSplit = "";
+ string IOB_MULTI_CNAME = "";
+ string[] elencoMulti = null;
+
+ try
{
- persistenceLayer.Add(keyVal, "0");
+ /***************************************************
+ * Descrizione procedura (OK X SIMULATORI...)
+ *
+ * - chiamata su MP/IO
+ * - verifica che su DB sia abilitato AUTO ODL
+ * - il server inserisce un evento fine prod HW 1 minuto prima e inizio setup HW
+ * - viene duplicato e chiuso ODL corrente
+ * - viene fatto partire ODL nuovo ADESSO
+ * - num pezzi come ODL precedente (o da media 3 ODL precedenti)
+ * - conferme pezzi & co... gestione NULL (NON SERVONO si tratta di impianti SENZA gestione vera ODL)
+ * - reset contapezzi PLC locale...
+ *
+ *
+ *
+ * DA VALUTARE (x macchine tipo linea con + impianti... es valvital) SE
+ * - creare una gestione ALTERNATIVA sul server che preveda impianto LEADER e impianti follower (RIGIDAMENTE CONFIGURATI)
+ * - ogni volta che si fa setup LEADER --> si ripete su impianti FOLLOWER (eventi!!!)
+ * - viene fatto reset contapezzi sui follower (+ altre operazioni opzionali, ES imposstazione nome commessa, quantità, articolo...)
+ * - viene fatto reset + nuovo ODL (con stessi articoli e quantità) su follower, SENZA avere gestione x ODL di un codice esterno (quindi registra TUTTO ma NON RITORNERA' dati non avendo link verso esterno)
+ * - serve NUOVA TABELLA delle macchine LEADER | FOLLOWER (1:n) e gestione da MP/IO
+ *
+ * ***************************************************/
+
+ if (isMulti)
+ {
+ // devo chiamare cambio ODL x OGNI tavola: mi servono i parametri opzionali...
+ IOB_MULTI_CNAME = getOptPar("IOB_MULTI_CNAME");
+ elencoMulti = IOB_MULTI_CNAME.Split(',');
+ }
+ // se normale splitto!
+ if (!isMulti)
+ {
+ // invio chiamata URL x reset ODL su macchina
+ rawSplit = callUrl(urlForceSplit, false);
+ fatto = (rawSplit != "KO") ? true : false;
+ }
+ // se multi gestisco il bit delle tavole...
+ else
+ {
+ foreach (string item in elencoMulti)
+ {
+ // invio chiamata URL x reset ODL su macchina, ATTENZIONE scriviamo
+ // | al posto di "#" che in URL sarebbe filtrato...
+ fullUrl = $"{urlForceSplit}&multi={item}";
+ rawSplit = callUrl(fullUrl, false);
+ lgDebug($"Esecuzione forceSplit | URL: {fullUrl} | esito: {rawSplit}");
+ }
+ fatto = (rawSplit == "OK") ? true : false;
+ }
+ }
+ catch (Exception exc)
+ {
+ lgError($"Eccezione in forceSplitOdl{Environment.NewLine}{exc}");
+ }
+ // se fatto --> resetto contapezzi!!!
+ if (fatto)
+ {
+ contapezziPLC = 0;
+ contapezziIOB = 0;
}
}
+ else
+ {
+ lgError("Richiesto forceSplitOdl ma MP/IOB offline --> NON eseguito");
+ }
}
- catch (Exception exc)
+ else
{
- lgError(string.Format("Eccezione in getStoredVal: {0}{1}", Environment.NewLine, exc));
+ lgError("Richiesto forceSplitOdl ma veto attivo --> NON eseguito");
}
- return value;
+ return fatto;
}
///
- /// recupera valore salvato in persistence layer (se non c'è crea...) come double
+ /// effettua recupero dati ed invio valori modificati...
///
- ///
- ///
- private double getStoredValDouble(string keyVal)
- {
- double answ = 0;
- try
- {
- answ = Convert.ToDouble(getStoredVal(keyVal));
- }
- catch (Exception exc)
- {
- lgError(string.Format("Eccezione in getStoredValDouble: {0}{1}", Environment.NewLine, exc));
- }
- answ = (answ < (double.MaxValue / 10 * 9)) ? answ : 0;
- return answ;
- }
-
- ///
- /// recupera valore salvato in persistence layer (se non c'è crea...) come INT
- ///
- ///
- ///
- private long getStoredValLong(string keyVal)
- {
- long answ = 0;
- try
- {
- answ = Convert.ToInt64(getStoredVal(keyVal));
- }
- catch
- { }
- // verifico che il valore sia minore di 9/10 del valore massimo...
- answ = (answ < (long.MaxValue / 10 * 9)) ? answ : 0;
- return answ;
- }
-
- ///
- /// recupera valore salvato in persistence layer (se non c'è crea...) come UINT
- ///
- ///
- ///
- private uint getStoredValUInt(string keyVal)
- {
- uint answ = 0;
- try
- {
- answ = Convert.ToUInt32(getStoredVal(keyVal));
- }
- catch (Exception exc)
- {
- lgError(string.Format("Eccezione in getStoredValUInt: {0}{1}", Environment.NewLine, exc));
- }
- // verifico che il valore sia minore di 9/10 del valore massimo...
- answ = (answ < (uint.MaxValue / 10 * 9)) ? answ : 0;
- return answ;
- }
-
- ///
- /// Classe fittizia in caso di processing GLOBALE di tutto in 1 solo colpo...
- ///
- private void processAllMemory()
+ ///
+ public void getAndSend(gatherCycle ciclo)
{
// init obj display
newDisplayData currDispData = new newDisplayData();
- // in primis SALVO valori previous/precedenti
- B_previous = B_output;
- // poi faccio lettura NUOVI valori
- readAllData(ref currDispData);
- // eseguo il filtering dei valori (per i bit "blinking")
- filterData();
- // effettuo confronto valori vecchi/nuovi... SE trovo variazione OPPURE se è passato + di un timeout di controllo...
- if (B_output != B_previous)
+ // IN OGNI CASO a prima di tutto EFFETTUO GESTIONE INVII dati da code!!!
+ try
{
- accodaSigIN(ref currDispData);
+ trySendValues();
+ }
+ catch (Exception exc)
+ {
+ lgError(exc, "Errore in gestione svuotamento/invio preliminare code memoria");
+ currDispData.semOut = Semaforo.SR;
+ }
+ // controllo connessione/connettività
+ if (connectionOk)
+ {
+ // controllo non sia già in esecuzione...
+ if (!adpCommAct)
+ {
+ // provo ad avviare
+ try
+ {
+ // imposto flag adapter running..
+ adpCommAct = true;
+ adpStartRun = DateTime.Now;
+ }
+ catch (Exception exc)
+ {
+ string errore = $"Adapter NOT STARTED!!!{Environment.NewLine}{exc}";
+ adpCommAct = false;
+ adpStartRun = DateTime.Now;
+ currDispData.newLiveLogData = errore;
+ }
+ if (adpCommAct)
+ {
+ // try / catch generale altrimenti segno che è disconnesso...
+ try
+ {
+ bool showDebugData = false;
+ if (ciclo == gatherCycle.VHF)
+ {
+ processVHF();
+ }
+ // processing dati memoria (lettura, filtraggio, enqueque)
+ else if (ciclo == gatherCycle.HF)
+ {
+ processWhatchDog();
+ processAllMemory();
+ processMode();
+ }
+ else if (ciclo == gatherCycle.MF)
+ {
+ processServerRequests();
+ processOverride();
+ processContapezzi();
+ processCncAlarms();
+ processDynData();
+ processMem2Write();
+ }
+ else if (ciclo == gatherCycle.LF)
+ {
+ processCustomTaskLF();
+ processOtherCounters();
+ processProgram();
+ // verifico se devo gestire cambio ODL in modo automatico
+ processAutoOdl();
+ }
+ else if (ciclo == gatherCycle.VLF)
+ {
+ if (utils.CRB("enableContapezzi"))
+ {
+ // rilettura contapezzi da server...
+ lgTrace("Ciclo VLF: pzCntReload(true)");
+ if (!isMulti)
+ {
+ pzCntReload(true);
+ }
+ // refresh associazione Macchina - IOB
+ sendM2IOB();
+ }
+ // recupero dati SETUP (sysinfo) e li invio/mostro se variati...
+ processSysInfo();
+ // checkLogDir x shrink!
+ checkShrinkDir();
+ // eventuale log!
+ if (utils.CRB("recTime"))
+ {
+ logTimeResults();
+ }
+ }
+ // mostra eventuali altri dati di processo...
+ reportDataProc();
+ if (showDebugData)
+ {
+ // verifica se debba salvare e mostrare dati
+ checkSavePersDataLayer();
+ }
+ }
+ catch (Exception exc)
+ {
+ // segnalo eccezione e indico disconnesso...
+ lgError(exc, string.Format("Errore in gestione ciclo principale ADP, fermo adapter{0}{1}", Environment.NewLine, exc));
+ parentForm.fermaAdapter(true, false, true);
+ }
+ // tolgo flag running
+ adpCommAct = false;
+ }
+ else
+ {
+ if (periodicLog)
+ {
+ lgDebug("ADP not running...");
+ }
+ }
+ }
+ else
+ {
+ // log ADP running
+ lgError("Non eseguo chiamata: ADP ancora in running");
+ // se è bloccato da oltre maxSec lo sblocco...
+ if (DateTime.Now.Subtract(adpStartRun).TotalSeconds > utils.CRI("maxAdapterLockSec"))
+ {
+ // tolgo flag running
+ adpCommAct = false;
+ adpStartRun = DateTime.Now;
+ }
+ }
+ }
+ else
+ {
+ // provo a riconnettere SE abilitato tryRestart...
+ if (adpTryRestart && !connectionOk)
+ {
+ // controllo se sia scaduto periodi di veto al tryConnect...
+ int waitRecMSec = utils.CRI("waitRecMSec") * 2;
+ DateTime dtVeto = lastConnectTry.AddMilliseconds(waitRecMSec);
+ if (DateTime.Now > dtVeto)
+ {
+ lgInfo($"Veto Time Elapsed | lastConnectTry: {lastConnectTry} | waitRecMSec {waitRecMSec} ms) | NOW tryConnect");
+ lastConnectTry = DateTime.Now;
+ tryConnect();
+ }
+ }
+ currDispData.semIn = Semaforo.SR;
+ processDisconnectedTask();
}
raiseRefresh(currDispData);
}
- private void processMem2Write()
+ ///
+ /// Recupera eventuali allarmi CNC...
+ ///
+ public virtual Dictionary getCncAlarms()
{
- List updatedPar = new List();
- // ciclo tutti gli oggetti write x vedere se modificati...
- foreach (var item in currProdData)
+ Dictionary outVal = new Dictionary();
+ return outVal;
+ }
+
+ ///
+ /// Restituisce info DINAMICHE
+ ///
+ ///
+ public virtual Dictionary getDynData()
+ {
+ Dictionary outVal = new Dictionary();
+ return outVal;
+ }
+
+ ///
+ /// Cerca se esiste il parametro opzionale e lo restituisce
+ ///
+ ///
+ ///
+ public string getOptPar(string key)
+ {
+ string answ = "";
+ if (cIobConf.optPar.Count > 0)
{
- bool needWrite = false;
- // li cerco su last... se non ci sono o modificati --> salvo da scrivere e copio
- if (lastProdData.ContainsKey(item.Key))
+ // controllo SE HO il parametro
+ if (cIobConf.optPar.ContainsKey(key))
{
- // verifico se variato...
- if (!item.Value.Equals(lastProdData[item.Key]))
- {
- needWrite = true;
- lastProdData[item.Key] = item.Value;
- }
- }
- // aggiungo
- else
- {
- needWrite = true;
- lastProdData.Add(item.Key, item.Value);
- }
- // se devo scrivere --> riporto
- if (needWrite)
- {
- if (memMap.mMapWrite.ContainsKey(item.Key))
- {
- // preparo obj da scrivere
- objItem newWrite = new objItem()
- {
- uid = item.Key,
- name = item.Key,
- reqValue = memMap.mMapWrite[item.Key].value,
- lastRequest = DateTime.Now,
- writable = true
- };
- updatedPar.Add(newWrite);
- }
+ answ = cIobConf.optPar[key];
}
}
- // se ho da scrivere... scrivo TUTTI!
- if (updatedPar.Count > 0)
+ return answ;
+ }
+
+ ///
+ /// Restituisce info OVERRIDES
+ ///
+ ///
+ public virtual Dictionary getOverrides()
+ {
+ Dictionary outVal = new Dictionary();
+ return outVal;
+ }
+
+ ///
+ /// Restituisce programma in esecuzione
+ ///
+ public virtual string getPrgName()
+ {
+ return "";
+ }
+
+ ///
+ /// Restituisce info sistema
+ ///
+ ///
+ public virtual Dictionary getSysInfo()
+ {
+ Dictionary outVal = new Dictionary();
+ return outVal;
+ }
+
+ ///
+ /// Recupera la VC x TS, svuotando lista e resettando periodo partenza
+ ///
+ /// Nome della VC
+ /// Reimposta e resetta array VC
+ ///
+ public double getVal_TSVC(string VCName, bool doReset)
+ {
+ double answ = -999999;
+ // cerco VC...
+ if (TSVC_Data.ContainsKey(VCName))
{
- // scrivo valore!
- lgInfo("Chiamata di plcWriteParams da processMem2Write");
- plcWriteParams(ref updatedPar);
- // invio su cloud parametri!
- string rawData = JsonConvert.SerializeObject(updatedPar);
- utils.callUrl($"{urlUpdateWriteParams}", rawData);
- lgInfo($"Notificato a server scrittura {updatedPar.Count} parametri");
+ try
+ {
+ switch (TSVC_Data[VCName].Funzione)
+ {
+ case VC_func.POINT:
+ // prendo PRIMO
+ answ = TSVC_Data[VCName].dataArray.FirstOrDefault();
+ break;
+
+ case VC_func.AVG:
+ answ = TSVC_Data[VCName].dataArray.Average();
+ break;
+
+ case VC_func.MEDIAN:
+ answ = TSVC_Data[VCName].dataArray.Median();
+ break;
+
+ case VC_func.MIN:
+ answ = TSVC_Data[VCName].dataArray.Min();
+ break;
+
+ case VC_func.MAX:
+ default:
+ answ = TSVC_Data[VCName].dataArray.Max();
+ break;
+ }
+ }
+ catch
+ { }
+ // ora resetto... SE richiesto...
+ if (doReset)
+ {
+ TSVC_Data[VCName].dataArray = new List();
+ TSVC_Data[VCName].DTStart = DateTime.Now;
+ }
+ }
+ return answ;
+ }
+
+ ///
+ /// Recupera la VC x TS, svuotando lista e resettando periodo partenza
+ ///
+ /// Nome della VC
+ /// Reimposta e resetta array VC
+ ///
+ public int getVal_TSVC_int(string VCName, bool doReset)
+ {
+ int answ = 0;
+ // cerco VC...
+ if (TSVC_Data.ContainsKey(VCName))
+ {
+ // !!!FARE!!! vero calcolo... x ora FIX a MAX...
+ foreach (var item in TSVC_Data[VCName].dataArray)
+ {
+ answ = (int)item > answ ? (int)item : answ;
+ }
+ // ora resetto... SE richiesto..
+ if (doReset)
+ {
+ TSVC_Data[VCName].dataArray = new List();
+ TSVC_Data[VCName].DTStart = DateTime.Now;
+ }
+ }
+ return answ;
+ }
+
+ ///
+ /// Restituisce un payload in formato json della lista di valori ricevuta
+ ///
+ /// Tipo di URL (eventi / FLog)
+ /// elenco di valori da coda string salvata
+ ///
+ public string jsonPayload(urlType tipoUrl, List elencoValori)
+ {
+ string answ = "";
+ if (elencoValori != null)
+ {
+ string[] valori;
+ int counter = 0;
+ DateTime dtEve = DateTime.Now;
+ switch (tipoUrl)
+ {
+ case urlType.FLog:
+ flogData currFlData = new flogData();
+ flogJsonPayload fullFlObj = new flogJsonPayload();
+ fullFlObj.fluxData = new List();
+ // inizio processando ogni valore
+ foreach (var item in elencoValori)
+ {
+ valori = qDecodeIN(item);
+ CultureInfo provider = CultureInfo.InvariantCulture;
+ DateTime.TryParseExact(valori[0], "yyyyMMddHHmmssfff", provider, DateTimeStyles.AssumeLocal, out dtEve);
+ int.TryParse(valori[3], out counter);
+ currFlData = new flogData()
+ {
+ flux = valori[1],
+ valore = valori[2],
+ dtEve = dtEve,
+ dtCurr = DateTime.Now,
+ cnt = counter
+ };
+ fullFlObj.fluxData.Add(currFlData);
+ }
+ // conversione finale
+ try
+ {
+ answ = JsonConvert.SerializeObject(fullFlObj);
+ }
+ catch (Exception exc)
+ {
+ lgError($"FLog Errore in costruzione jsonPayload:{Environment.NewLine}{exc}");
+ }
+ break;
+
+ case urlType.SignIN:
+ evData currSigData = new evData();
+ evJsonPayload fullEvObj = new evJsonPayload();
+ fullEvObj.eventList = new List();
+ // inizio processando ogni valore
+ foreach (var item in elencoValori)
+ {
+ valori = qDecodeIN(item);
+ CultureInfo provider = CultureInfo.InvariantCulture;
+ DateTime.TryParseExact(valori[0], "yyyyMMddHHmmssfff", provider, DateTimeStyles.AssumeLocal, out dtEve);
+ int.TryParse(valori[2], out counter);
+ currSigData = new evData()
+ {
+ valore = valori[1],
+ dtEve = dtEve,
+ dtCurr = DateTime.Now,
+ cnt = counter
+ };
+ fullEvObj.eventList.Add(currSigData);
+ }
+ // conversione finale
+ try
+ {
+ answ = JsonConvert.SerializeObject(fullEvObj);
+ }
+ catch (Exception exc)
+ {
+ lgError($"SignIN Errore in costruzione jsonPayload:{Environment.NewLine}{exc}");
+ }
+ break;
+
+ case urlType.RawTransf:
+ BaseRawTransf currRTData = new BaseRawTransf();
+#if false
+ rawTransfJsonPayload fullRTObj = new rawTransfJsonPayload();
+ fullRTObj.rawTransfData = new List();
+ // inizio processando ogni valore
+ foreach (var item in elencoValori)
+ {
+ try
+ {
+ currRTData = JsonConvert.DeserializeObject(item);
+ }
+ catch (Exception exc)
+ {
+ lgError($"Eccezione in deserializzazione BaseRawTransf:{Environment.NewLine}{exc}");
+ }
+ fullRTObj.rawTransfData.Add(currRTData);
+ }
+ // conversione finale
+ try
+ {
+ answ = JsonConvert.SerializeObject(fullRTObj);
+ }
+ catch (Exception exc)
+ {
+ lgError($"RawTransf Errore in costruzione jsonPayload:{Environment.NewLine}{exc}");
+ }
+#endif
+
+ // provo una serializzazione "brutale", ovvero aggiungo alla stringa il
+ // valore di testa...
+ string rawResult = "";
+ foreach (var item in elencoValori)
+ {
+ rawResult += $"{item},";
+ }
+ if (rawResult.Length > 0)
+ {
+ rawResult = rawResult.Substring(0, rawResult.Length - 1);
+ }
+ answ = "{" + $"\"rawTransfData\":[{rawResult}]" + "}";
+
+ break;
+
+ case urlType.ULog:
+ int numVal = 0;
+ int matrOp = 0;
+ ulogData currUlData = new ulogData();
+ ulogJsonPayload fullUlObj = new ulogJsonPayload();
+ fullUlObj.fluxData = new List();
+ // inizio processando ogni valore
+ foreach (var item in elencoValori)
+ {
+ valori = qDecodeIN(item);
+ CultureInfo provider = CultureInfo.InvariantCulture;
+ DateTime.TryParseExact(valori[0], "yyyyMMddHHmmssfff", provider, DateTimeStyles.AssumeLocal, out dtEve);
+ int.TryParse(valori[3], out matrOp);
+ int.TryParse(valori[5], out numVal);
+ int.TryParse(valori[6], out counter);
+ currUlData = new ulogData()
+ {
+ flux = valori[1],
+ valore = valori[2],
+ dtEve = dtEve,
+ dtCurr = DateTime.Now,
+ cnt = counter,
+ matrOpr = matrOp,
+ label = valori[4],
+ valNum = numVal
+ };
+ fullUlObj.fluxData.Add(currUlData);
+ }
+ // conversione finale
+ try
+ {
+ answ = JsonConvert.SerializeObject(fullUlObj);
+ }
+ catch (Exception exc)
+ {
+ lgError($"ULog Errore in costruzione jsonPayload:{Environment.NewLine}{exc}");
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ return answ;
+ }
+
+ ///
+ /// Effettua un trim della stringa al numero max di linee da mostrare a video
+ ///
+ ///
+ ///
+ public string limitLine2show(string newString)
+ {
+ // se num righe superiore a limite trimmo...
+ if (newString.Split('\n').Length > parentForm.nLine2show)
+ {
+ //int idx = newString.LastIndexOf('\r');
+ int idx = newString.LastIndexOf(Environment.NewLine);
+ newString = newString.Substring(0, idx);
+ }
+ return newString;
+ }
+
+ ///
+ /// riporta il log di tutti i dati di results temporali registrati
+ ///
+ public void logTimeResults()
+ {
+ if (TimingData.results.Count > 0)
+ {
+ lgInfo("{0}--------------- START TIMING DATA ---------------", Environment.NewLine);
+ int globNumCall = 0;
+ TimeSpan globAvgMsec = new TimeSpan(0);
+ foreach (TimeRec item in TimingData.results)
+ {
+ // loggo SOLO se del mio IOB corrente...
+ if (item.classCall == cIobConf.codIOB)
+ {
+ lgInfo("{4}|Chiamate {0}: effettuate {1}, tempo medio {2:N2} msec | impegno canale {3:P3}", item.codCall, item.numCall, item.avgMsec, item.totMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds, cIobConf.codIOB);
+ globNumCall += item.numCall;
+ globAvgMsec += item.totMsec;
+ }
+ }
+ // riporto conteggio medio al secondo...
+ lgInfo("{4}|Chiamate GLOBALI: {0}, periodo: {1:N2} minuti.cent, tempo medio {2:N2} msec | impegno canale {3:P3}", globNumCall, DateTime.Now.Subtract(dtAvvioAdp).TotalMinutes, globAvgMsec.TotalMilliseconds / globNumCall, globAvgMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds, cIobConf.codIOB);
+ lgInfo("{0}--------------- STOP TIMING DATA ---------------{0}", Environment.NewLine);
+ // mostro in form statistiche globali!
+ parentForm.updateComStats(string.Format("Periodo: {0:N2}min | {1} x {2:N2}ms | canale {3:P3}", DateTime.Now.Subtract(dtAvvioAdp).TotalMinutes, globNumCall, globAvgMsec.TotalMilliseconds / globNumCall, globAvgMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds));
}
}
///
- /// Effettua gestioen programma: legge e mostra su display...
+ /// Processa un monitoredItem, e ritorna boolean SE richiede invio (cambio o scadenza)
///
- private void processProgram()
+ ///
+ ///
+ ///
+ public bool monItem2Send(string newVal, DynDataItem item)
{
- string currPrgName = "";
- // se abilitata lettura prgName
- if (enablePrgName)
+ bool answ = false;
+ if (item != null)
{
- if (connectionOk)
+ // controllo in base al tipo di function...
+ switch (item.func)
{
- currPrgName = getPrgName();
+ case "SAMPLE":
+ // controllo se scaduto sample period...
+ if (item.DTScad < DateTime.Now)
+ {
+ answ = true;
+ }
+ break;
+
+ case "CHANGE":
+ default:
+ // controllo se scaduto o se variato...
+ if (newVal != item.actVal || item.DTScad < DateTime.Now)
+ {
+ // aggiorno scadenza e che vada inviato
+ answ = true;
+ }
+ break;
+ }
+ }
+ return answ;
+ }
+
+ ///
+ /// Verifica e processing x gestione ODL automatica
+ ///
+ public void processAutoOdl()
+ {
+ bool fatto = false;
+ if (!string.IsNullOrEmpty(getOptPar("AUTO_CHANGE_ODL")))
+ {
+ lgTrace("Richiesta processAutoOdl");
+ string IOB_MULTI_CNAME = "";
+ string[] elencoMulti = null;
+ string fullUrl = "";
+ if (isMulti)
+ {
+ // devo chiamare cambio ODL x OGNI tavola: mi servono i parametri opzionali...
+ IOB_MULTI_CNAME = getOptPar("IOB_MULTI_CNAME");
+ elencoMulti = IOB_MULTI_CNAME.Split(',');
+ }
+ // controllo SIA abilitato...
+ bool doProc = false;
+ DateTime adesso = DateTime.Now;
+ bool.TryParse(getOptPar("AUTO_CHANGE_ODL"), out doProc);
+ if (doProc)
+ {
+ lgTrace("AUTO_CHANGE_ODL abilitato");
+ bool callChangeODL = false;
+ // modalità change ODL
+ string CHANGE_ODL_MODE = "TIME";
+ if (!string.IsNullOrEmpty(getOptPar("CHANGE_ODL_MODE")))
+ {
+ CHANGE_ODL_MODE = getOptPar("CHANGE_ODL_MODE");
+ }
+ if (CHANGE_ODL_MODE == "PZCOUNT_RESET")
+ {
+ /* verifico se sia "armato" il reset cambio ODL, DEVO essere :
+ * - NON in produzione
+ * - contapezzi ACT < contapezzi LAST
+ * */
+ lgTrace("processAutoOdl: caso PZCOUNT_RESET");
+ if ((!isRunning || forceResetInRun) && pzCountResetted)
+ {
+ callChangeODL = true;
+ lgInfo("Attivato cambio ODL da PZCOUNT_RESET");
+ }
+ else
+ {
+ lgInfo($"isRunning: {isRunning} | pzCountResetted: {pzCountResetted} | forceResetInRun: {forceResetInRun} | contapezziIOB: {contapezziIOB} | contapezziPLC: {contapezziPLC}");
+ }
+ }
+ else if (CHANGE_ODL_MODE == "TIME")
+ {
+ // carico i parametri di configurazione x reset ODL...
+ string CHANGE_ODL_HOURS = getOptPar("CHANGE_ODL_HOURS");
+ string CHANGE_ODL_IDLE_MIN = getOptPar("CHANGE_ODL_IDLE_MIN");
+ if (!string.IsNullOrEmpty(CHANGE_ODL_HOURS) && !string.IsNullOrEmpty(CHANGE_ODL_IDLE_MIN))
+ {
+ int minOdlDurHours = -1;
+ int minPlcIdelMin = -1;
+ int.TryParse(CHANGE_ODL_HOURS, out minOdlDurHours);
+ int.TryParse(CHANGE_ODL_IDLE_MIN, out minPlcIdelMin);
+ // controllo parametri validi
+ if (minOdlDurHours > 0 && minPlcIdelMin >= 0)
+ {
+ // leggo da server inizio ODL... se non multi 1 solo...
+ DateTime inizioOdl = DateTime.Now;
+ string rawDataInizio = "";
+ if (!isMulti)
+ {
+ rawDataInizio = callUrl(urlInizioOdlIob, false);
+ DateTime.TryParse(rawDataInizio, out inizioOdl);
+ }
+ else
+ {
+ DateTime tmpData = DateTime.Now;
+ // prendo il + vecchio...
+ foreach (var item in elencoMulti)
+ {
+ fullUrl = $"{urlInizioOdlIob}|{item}";
+ rawDataInizio = callUrl(fullUrl, false);
+ DateTime.TryParse(rawDataInizio, out tmpData);
+ inizioOdl = (tmpData < inizioOdl) ? tmpData : inizioOdl;
+ }
+ }
+ // verifico se sia scaduto...
+ if (inizioOdl.AddHours(minOdlDurHours) < adesso)
+ {
+ string rawIdle = "";
+ int idlePeriod = 0;
+ if (!isMulti)
+ {
+ // controllo SE sono fermo (spento o in manuale) per il
+ // periodo minimo richiesto...
+ rawIdle = callUrl(urlIdleTime, false);
+ int.TryParse(rawIdle, out idlePeriod);
+ }
+ else
+ {
+ int tmpIdle = 0;
+ // prendo il + grande...
+ foreach (var item in elencoMulti)
+ {
+ fullUrl = $"{urlIdleTime}|{item}";
+ rawIdle = callUrl(fullUrl, false);
+ int.TryParse(rawIdle, out tmpIdle);
+ idlePeriod = tmpIdle > idlePeriod ? tmpIdle : idlePeriod;
+ }
+ }
+ if (idlePeriod >= minPlcIdelMin)
+ {
+ callChangeODL = true;
+ }
+ }
+ }
+ }
+ }
+
+ // vero processing...
+ if (callChangeODL)
+ {
+ lgTrace("Chiamata: processAutoOdl --> forceSplitODL");
+ fatto = forceSplitOdl();
+ pzCountResetted = false;
+ lgInfo("Esecuzione processAutoOdl completata --> pzCountResetted = false");
+ }
}
else
{
- lgError("Errore connessione mancante x getPrgName");
+ lgTrace("AUTO_CHANGE_ODL DISABILITATO");
+ }
+ }
+ // loggo se fatto
+ if (fatto)
+ {
+ lgTrace("Effettuato processAutoOdl");
+ }
+ }
+
+ ///
+ /// Effettua processing degli allarmi CNC SE disponibili
+ ///
+ public void processCncAlarms()
+ {
+ if (utils.CRB("enableAlarms"))
+ {
+ Dictionary currAlarms = new Dictionary();
+ if (connectionOk)
+ {
+ currAlarms = getCncAlarms();
+ }
+ else
+ {
+ lgError("Errore connessione mancante x getCncAlarms");
+ }
+ // verifico SE sia cambiato il programma...
+ if (currAlarms.Count > 0)
+ {
+ try
+ {
+ string sVal = "";
+ if (lastAlarm != currAlarms["CNC_ALARM"])
+ {
+ // salvo!
+ lastAlarm = currAlarms["CNC_ALARM"];
+ // per ogni valore del dizionario mostro ed accodo!
+ foreach (var item in currAlarms)
+ {
+ sVal = string.Format("[CNC_ALARM]{0}|{1}", item.Key, item.Value);
+ // chiamo accodamento...
+ accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
+ }
+ }
+ // accodo ALTRI allarmi NON CNC...
+ foreach (var item in currAlarms.Where(X => X.Key != "CNC_ALARM"))
+ {
+ sVal = $"{item.Key} | {item.Value}";
+ accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
+ }
+ }
+ catch (Exception exc)
+ {
+ lgError("Eccezione in processCncAlarms{0}{1}", Environment.NewLine, exc);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Effettua processing contapezzi (ed eventualmente alza il bit di contapezzo...)
+ ///
+ public virtual void processContapezzi()
+ { }
+
+ ///
+ /// Effettua processing CUSTOM x l'IOB corrente (ed invia ad IO) (task svolto tipicamente
+ /// ogni 5 sec se base timer 10ms, vedere app.config)
+ ///
+ public virtual void processCustomTaskLF()
+ { }
+
+ ///
+ /// Task periodici SE disconnesso
+ ///
+ public virtual void processDisconnectedTask()
+ {
+ }
+
+ ///
+ /// Effettua processing del recupero dei valori dinamici:
+ /// es: speed (RPM, feedrate) degli assi, valori pressioni, temeprature
+ ///
+ public void processDynData()
+ {
+ bool enableByApp = utils.CRB("enableDynData");
+ bool enableByIob = (getOptPar("ENABLE_DYN_DATA") == "TRUE");
+ bool forceSendByIob = (getOptPar("FORCE_DYN_DATA") == "TRUE");
+ Dictionary currDynData = new Dictionary();
+
+ if (enableByApp || enableByIob)
+ {
+ // verifico se ho fattore demoltiplica...
+ if (demFactDynData > 1)
+ {
+ lgTrace($"Non eseguo processDynData: fatt veto {demFactDynData}");
+ // ricudo...
+ demFactDynData--;
+ }
+ else
+ {
+ lgInfo("Inizio processDynData");
+ // sistemo il valore di demoltiplica a default
+ fixDemFactDynData();
+ // proseguo
+ if (connectionOk)
+ {
+ currDynData = getDynData();
+ try
+ {
+ string sVal = "";
+ // se richiesto send diretto...
+ if (forceSendByIob)
+ {
+ // per ogni valore del dizionario mostro ed accodo!
+ foreach (var item in currDynData)
+ {
+ sVal = string.Format("[DYNDATA]{0}|{1}", item.Key, item.Value);
+ // chiamo accodamento...
+ accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
+ }
+ }
+ // altrimenti verifico SE sia cambiato il valore dei DynData...
+ else if (lastDynDataCtrlVal != currDynData["DYNDATA"])
+ {
+ // salvo!
+ lastDynDataCtrlVal = currDynData["DYNDATA"];
+ // per ogni valore del dizionario mostro ed accodo!
+ foreach (var item in currDynData)
+ {
+ sVal = string.Format("[DYNDATA]{0}|{1}", item.Key, item.Value);
+ // chiamo accodamento...
+ accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
+ }
+ }
+ // salvo array...
+ lastDynData = currDynData;
+ }
+ catch (Exception exc)
+ {
+ lgError(exc, "Eccezione in processDynData");
+ }
+ }
+ else
+ {
+ lgError("Errore connessione mancante x getDynData");
+ }
+ }
+ }
+ }
+
+ ///
+ /// Processa gestione memoria x invio dati QUANDO IOB è disconnesso da CNC...
+ ///
+ public void processMemoryDiscon()
+ {
+ // init obj display
+ newDisplayData currDispData = new newDisplayData();
+ // controllo contatore invio "keepalive"... invio solo a scadenza
+ if (DateTime.Now.Subtract(lastDisconnCheck).TotalSeconds > utils.CRI("disconMaxSec"))
+ {
+ // resetto tutti i vlaori BYTE IN/PREV/OUT... così invio macchina spenta...
+ B_input = 0;
+ B_output = 0;
+ B_previous = 0;
+ accodaSigIN(ref currDispData);
+ // update controllo
+ lastDisconnCheck = DateTime.Now;
+ }
+ raiseRefresh(currDispData);
+ }
+
+ ///
+ /// Effettua processing mode/status (EDIT/MDI/...)
+ ///
+ public virtual void processMode()
+ { }
+
+ ///
+ /// Effettua processing ALTRI contatori/parametri (ed invia ad IO)
+ ///
+ public virtual void processOtherCounters()
+ { }
+
+ ///
+ /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid)
+ ///
+ public virtual void processOverride()
+ {
+ bool enableByApp = utils.CRB("enableOverrides");
+ bool enableByIob = (getOptPar("ENABLE_OVERRIDES") == "TRUE");
+ Dictionary currOverride = new Dictionary();
+ if (enableByApp || enableByIob)
+ {
+ lgInfo("Inizio processOverride");
+ if (connectionOk)
+ {
+ currOverride = getOverrides();
+ }
+ else
+ {
+ lgError("Errore connessione mancante x getOverrides");
+ }
+
+ // SE sono connesso...
+ if (connectionOk)
+ {
+ // se HO dei valori override...
+ if (currOverride.Count > 0)
+ {
+ // verifico SE sia cambiato il programma...
+ if (lastOverrideFS != currOverride["FEED_OVER"] || lastOverrideRapid != currOverride["RAPID_OVER"])
+ {
+ // salvo!
+ lastOverrideFS = currOverride["FEED_OVER"];
+ lastOverrideRapid = currOverride["RAPID_OVER"];
+ // per ogni valore del dizionario mostro ed accodo!
+ string sVal = "";
+ foreach (var item in currOverride)
+ {
+ sVal = string.Format("[OVERRIDES]{0}|{1}", item.Key, item.Value);
+ // chiamo accodamento...
+ accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Effettua ciclo controllo richieste server
+ ///
+ public void processServerRequests()
+ {
+ Dictionary task2exe = new Dictionary();
+ Dictionary taskDone = new Dictionary();
+ // recupero elenco delle cose da fare
+ string resp = getTask2exe();
+ if (!string.IsNullOrEmpty(resp))
+ {
+ try
+ {
+ task2exe = JsonConvert.DeserializeObject>(resp);
+ // se ho da fare chiamo esecuzione..
+ if (task2exe.Count > 0)
+ {
+ taskDone = processTask(task2exe);
+ }
+ }
+ catch (Exception exc)
+ {
+ lgError($"Eccezione in processServerRequests:{Environment.NewLine}{exc}");
+ }
+ }
+ }
+
+ public Dictionary processTask(Dictionary task2exe)
+ {
+ Dictionary taskDone = new Dictionary();
+ if (task2exe != null)
+ {
+ lgInfo($"Task2Exe S01: {task2exe.Count} task ricevuti:");
+ int idTask = 0;
+ foreach (var item in task2exe)
+ {
+ idTask++;
+ lgInfo($"[{idTask:00}] - {item.Key} --> {item.Value}");
+ }
+ // chiamo procedura esecutiva (diversa x ogni IOB)
+ taskDone = executeTasks(task2exe);
+ lgInfo($"Task2Exe S02: eseguiti {taskDone.Count} task");
+ // loggo tutti i task done...
+ foreach (var item in taskDone)
+ {
+ sendToTaskWatch(item.Key, item.Value);
+ }
+ // ora chiamo la cancellazione dei task eseguiti...
+ foreach (var item in taskDone)
+ {
+ remTask2exe(item.Key, item.Value);
+ }
+ }
+ return taskDone;
+ }
+
+ ///
+ /// Classe fittizia in caso di processing task in VHF
+ ///
+ public virtual void processVHF()
+ {
+ }
+
+ ///
+ /// Classe fittizia in caso di processing watchdog data
+ ///
+ public virtual void processWhatchDog()
+ {
+ }
+
+ ///
+ /// Effettua rilettura del contapezzi dal server MP/IO
+ ///
+ /// Forza rilettura da DB tempi ciclo rilevati
+ public void pzCntReload(bool forceCountRec)
+ {
+ // legge da IO server ULTIMO valore CONTPEZZI al riavvio...
+ string currServerCount = "";
+ string lastIdxODL = "";
+ if (checkServerAlive)
+ {
+ // leggo PRIMA ODL ....
+ lastIdxODL = utils.callUrl(urlGetCurrODL);
+ lgTrace("Lettura ODL dall'url {0} --> {1}", urlGetCurrODL, lastIdxODL);
+ // se ho valori in coda da trasmettere uso dati REDIS
+ if (forceCountRec)
+ {
+ // uso dati da TCiclo registrati...
+ currServerCount = utils.callUrl(urlGetPzCountRec);
+ lgInfo("Lettura contapezzi da TCiclo dall'url {0} --> num pz: {1}", urlGetPzCountRec, currServerCount);
+ }
+ else
+ {
+ // uso il contapezzi dichiarato dall'IOB stesso
+ currServerCount = utils.callUrl(urlGetPzCount);
+ lgInfo("Lettura contapezzi dall'url {0}", urlGetPzCount);
+ }
+ // controllo: SE NON HO ODL...
+ if (string.IsNullOrEmpty(lastIdxODL) || lastIdxODL == "0")
+ {
+ // NON AGGIORNO
+ contapezziIOB = contapezziPLC;
+ lgError($"Errore lettura ODL (vuoto) resta tutto invariato contapezzi: {contapezziIOB} | contapezziPLC {contapezziPLC}");
+ }
+ else
+ {
+ if (!string.IsNullOrEmpty(currServerCount))
+ {
+ // se "-1" resto a ultimo...
+ if (currServerCount != "-1")
+ {
+ int newVal = -1;
+ Int32.TryParse(currServerCount, out newVal);
+ contapezziIOB = newVal > -1 ? newVal : contapezziIOB;
+ lgInfo("Ricevuta conferma da server di {0} pezzi registrati per ODL", currServerCount);
+ }
+ else
+ {
+ // NON AGGIORNO
+ contapezziIOB = contapezziPLC;
+ lgError($"Errore lettura contapezzi (-1) - uso contapezziPLC --> {contapezziPLC}");
+ }
+ }
+ else
+ {
+ // registro che ho UN NUOVO ODL
+ lgInfo($"Lettura ODL in pzCntReload, currIdxODL {currIdxODL} --> lastIdxODL {lastIdxODL}");
+ // se ODL differente e NUOVO è zero --> resetto!
+ if (currIdxODL.ToString() != lastIdxODL && lastIdxODL == "0")
+ {
+ // cambiato ODL quindi reset...
+ contapezziIOB = 0;
+ lgInfo("Nuovo ODL==0, RESET contapezzi (-->ZERO)");
+ }
+ // provo a salvare nuovo ODL
+ int.TryParse(lastIdxODL, out currIdxODL);
+ }
}
}
else
{
- currPrgName = lastPrgName;
- }
- // verifico SE sia cambiato il programma...
- if (lastPrgName != currPrgName)
- {
- // salvo!
- lastPrgName = currPrgName;
- string sVal = string.Format("[PROG]{0}", currPrgName);
-
- // chiamo accodamento...
- accodaFLog(sVal, qEncodeFLog("PROG", currPrgName));
+ // se server NON pronto...
+ contapezziIOB = contapezziPLC;
+ lgError("Errore server NON pronto in pzCntReload");
}
}
///
- /// Processo lettura dati sysinfo
+ /// Fornisce il valore di flusso e valore in formato valido x messa in coda nel formato
+ /// dtEve#flusso#valore#cont Flusso datiValore da salvare
///
- private void processSysInfo()
+ public string qEncodeFLog(string flusso, string valore)
{
- if (utils.CRB("enableSysInfo"))
+ string answ = "";
+ try
{
- Dictionary currSysInfo = new Dictionary();
+ answ = $"{DateTime.Now:yyyyMMddHHmmssfff}#{flusso}#{valore}#{counterULog}";
+ }
+ catch
+ { }
+ return answ;
+ }
+ ///
+ /// Fornisce il valore di flusso e valore in formato valido x messa in coda nel formato
+ /// dtEve#flux#value#cont DataOra evento
+ /// registratoFlusso datiValore da salvare
+ ///
+ public string qEncodeFLog(DateTime eventDT, string flusso, string valore)
+ {
+ string answ = "";
+ try
+ {
+ answ = $"{eventDT:yyyyMMddHHmmssfff}#{flusso}#{valore}#{counterFLog}";
+ }
+ catch
+ { }
+ return answ;
+ }
+
+ ///
+ /// Fornisce il valore di UserLog e valore in formato valido x messa in coda nel formato:
+ /// dtEve#flusso#value#cont#matrOpr#label#valNum Flusso dati
+ /// (RC/RS/DI)Valore da inviare
+ /// (valStringMatricola operatoreValore etichetta: causale scarto / tagCodeValore numerico: esitoOk (0/1) / nuo scarti
+ ///
+ public string qEncodeULog(string flusso, string valore, int matrOpr, string label, int valNum)
+ {
+ string answ = "";
+ try
+ {
+ answ = $"{DateTime.Now:yyyyMMddHHmmssfff}#{flusso}#{valore}#{matrOpr}#{label}#{valNum}#{counterULog}";
+ }
+ catch
+ { }
+ return answ;
+ }
+
+ ///
+ /// Effettua lettura dati Parametri da aggiornare x display in form
+ ///
+ public virtual void readAllData(ref newDisplayData currDispData)
+ {
+ if (currDispData == null)
+ {
+ currDispData = new newDisplayData();
+ }
+ try
+ {
+ if (DemoIn)
+ {
+ // segnalo che sono in Demo
+ currDispData.semIn = Semaforo.SV;
+ }
if (connectionOk)
{
- currSysInfo = getSysInfo();
+ readSemafori(ref currDispData);
}
else
{
- lgError("Errore connessione mancante x getSysInfo");
+ lgError("Errore connessione mancante x readSemafori");
}
- // verifico SE sia cambiato il programma...
- if (lastSysInfo != currSysInfo["SYSINFO"])
- {
- // salvo!
- lastSysInfo = currSysInfo["SYSINFO"];
- // per ogni valore del dizionario mostro ed accodo!
- string sVal = "";
- foreach (var item in currSysInfo)
- {
- sVal = string.Format("[SYSINFO]{0}|{1}", item.Key, item.Value);
- // chiamo accodamento...
- accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
- }
- }
- }
- }
- private void reportDataProc()
- {
- // update valori visualizzazione...
- parentForm.dataProcLabel = string.Format("RAW: {0} --> IN: {1} --> OUT: {2}", nReadIN, nReadFilt, nSendOut);
+ nReadIN++;
+ // aggiorno valore mostrato...
+ displayRawData(ref currDispData);
+ }
+ catch
+ {
+ currDispData.semIn = Semaforo.SR;
+ }
+ raiseRefresh(currDispData);
}
///
- /// Imposto alcuni valori di default
+ /// Effettua lettura semafori principale Parametri da
+ /// aggiornare x display in form
///
- /// indica se sia richeisto di SVUOTARE le code delel info
- private void setDefaults(bool resetQueue)
+ public virtual void readSemafori(ref newDisplayData currDispData)
{
- numSim = utils.CRI("numSim");
- lastPrgName = "";
- nReadIN = 0;
- nReadFilt = 0;
- nSendOut = 0;
- currMode = 0;
- lastAlarm = "";
- doStartMemDump = utils.CRB("doStartMemDump");
- doSampleMemory = utils.CRB("doSampleMemory");
- // fix url wait random...
- urlRandWait = utils.CRI("urlRandWait");
-
- // svuoto code se richiesto
- if (resetQueue)
- {
- QueueAlarm = new ConcurrentQueue();
- QueueIN = new ConcurrentQueue();
- QueueFLog = new ConcurrentQueue();
- QueueMessages = new ConcurrentQueue();
- QueueRawTransf = new ConcurrentQueue();
- QueueULog = new ConcurrentQueue();
- }
- // imposto contatori blink a zero...
- i_counters = new int[32];
- lastPeriodicLog = DateTime.Now;
- // fix parametri generali...
- enablePrgName = true;
+ lastReadPLC = DateTime.Now;
}
- private void svuotaCodaContapezzi()
+ ///
+ /// Aggiunge ai dati da inviare alla parentform i valori di RawInput rilevati (32bit)
+ /// 2021.08.27: filtrati secondo i valori setup start/size RawDataInput
+ ///
+ public virtual void reportRawInput(ref newDisplayData currDispData)
{
- // permetto al max 2 tentativi infruttuosi...
- int maxTry = 2;
- int oldContapezzi = contapezziIOB;
- // se ho contapezzi OLTRE limite...
- while ((MPOnline) && (contapezziPLC > contapezziIOB + minSendPzCountBlock))
+ // processo eventualmente aggiungendo ad elementi esistenti...
+ if (currDispData == null)
{
- lgInfo($"Ciclo svuotaCodaContapezzi --> contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}");
- if (!isMulti)
+ currDispData = new newDisplayData();
+ }
+ try
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append($"B_input --> {(short)B_input}{Environment.NewLine}");
+ sb.Append($"{baseUtils.binaryForm(B_input)}{Environment.NewLine}");
+ sb.Append($"{Environment.NewLine}");
+ sb.Append($"----------- RAW Data Memory -----------{Environment.NewLine}");
+ // Do x scontato siano VALIDI i valori di RawDataInputStart / size --> filtro...
+ var filtRawData = new byte[RawDataInputSize];
+ Array.Copy(RawInput, RawDataInputStart, filtRawData, 0, RawDataInputSize);
+ int i = RawDataInputStart;
+ foreach (var item in filtRawData)
{
- pzCntReload(true);
+ sb.Append($"B{i:00} --> {baseUtils.binaryForm(item)} = {(short)item}{Environment.NewLine}");
+ i++;
}
- // provo invio
- trySendPzCountBlock();
- // verifica per evitare loop infinito invio fallito
- if (oldContapezzi == contapezziIOB)
+ sb.Append("-------------------------------");
+ currDispData.currBitmap = sb.ToString();
+ }
+ catch
+ { }
+ }
+
+ ///
+ /// Metodo generico di reset contapezzi...
+ ///
+ ///
+ public virtual bool resetcontapezziPLC()
+ {
+ return false;
+ }
+
+ ///
+ /// metodo dummy x salvataggio aree memoria conf x CN
+ ///
+ /// tipo di DUMP
+ public virtual void saveMemDump(dumpType tipo)
+ {
+ }
+
+ ///
+ /// Salva valori indicati in prod data
+ ///
+ /// Item KVP di cui salvare i dati in currProdData come chiave/valore
+ ///
+ public void saveProdData(KeyValuePair item)
+ {
+ // imposto i valori...
+ if (currProdData.ContainsKey(item.Key))
+ {
+ currProdData[item.Key] = item.Value;
+ }
+ else
+ {
+ currProdData.Add(item.Key, item.Value);
+ }
+ }
+
+ ///
+ /// Effettua salvataggio in LUT del valore ricevuto
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual void saveValue(ref Dictionary outVal, double valore, string chiave)
+ {
+ //check obj preliminare
+ if (outVal == null)
+ {
+ outVal = new Dictionary();
+ }
+ bool scaduto = stackVal_TSVC(chiave, valore);
+ // recupero VC
+ valore = getVal_TSVC(chiave, scaduto);
+ if (scaduto)
+ {
+ // limite a 3 digit x valore float
+ outVal.Add(chiave, $"{valore:N3}");
+ }
+ LastTSVC[chiave] = valore;
+ }
+
+ ///
+ /// Invio la variazione dello stato allarmi (se avvenuta)
+ ///
+ /// COD memoria allarmi
+ /// Indice memoria allarmi
+ /// ultimo stato rilevato
+ /// stato corrente
+ /// Lista allarmi validi per l'area
+ ///
+ public bool sendAlarmVariations(string memAddr, int index, uint lastStatus, uint currStatus, List AlarmList)
+ {
+ bool fatto = false;
+ if (lastStatus != currStatus)
+ {
+ List ActiveAlarmList = new List();
+ // invio GET del MemoryAddress, del banco e del valore currStatus
+ lastUrl = $"{urlSendAlarm}?memAddr={memAddr}&index={index}&currStatus={currStatus}";
+ if (currStatus == 0)
{
- maxTry--;
+ ActiveAlarmList.Add("ALL OK");
}
else
{
- maxTry = 2;
- oldContapezzi = contapezziIOB;
+ // calcolo quali allarmi mostrare dato currStatus ed elenco allarmi
+ string bitMap = Convert.ToString(currStatus, 2);
+ int bitLen = bitMap.Length;
+ // ciclo x associare tutti gli allarmi
+ for (int i = 0; i < bitLen; i++)
+ {
+ // se è 1 --> aggiungo!
+ if (bitMap[bitLen - i - 1] == '1')
+ {
+ // se sono entro limiti
+ if (AlarmList.Count >= i)
+ {
+ ActiveAlarmList.Add($"{i:000}-{AlarmList.ElementAt(i)}");
+ }
+ //else
+ //{
+ // ActiveAlarmList.Add($"Unknown Bit.{i}");
+ //}
+ }
+ }
}
- // verifico maxTry: se li ho esauriti esco!
- if (maxTry <= 0)
+
+ string rawData = JsonConvert.SerializeObject(ActiveAlarmList);
+
+ //string resp = utils.callUrlNow(lastUrl, rawData);
+ string resp = utils.callUrlAsync(lastUrl, rawData);
+ if (!string.IsNullOrEmpty(resp))
{
- return;
+ if (resp.ToUpper() == "OK")
+ {
+ // segnalo fatto
+ fatto = true;
+ }
+ }
+ else
+ {
+ lgError($"Errore in invio richiesta registrazione allarme: URL: {lastUrl}{Environment.NewLine}Payload:{Environment.NewLine}{rawData}");
}
- // aspetto x dare tempo calcolo
- Thread.Sleep(400);
}
+ return fatto;
}
///
- /// Processo la coda FLog...
+ /// Invia una LISTA di valori
///
- private void svuotaCodaFLog()
+ ///
+ ///
+ public void sendDataBlock(urlType tipoUrl, List listQueueVal)
{
- // controllo se è passato oltre watchdog e non ho inviato nulla --> RE-INVIO (ultimo inviato)!!!!
- if (DateTime.Now.Subtract(lastWatchDog).TotalSeconds > utils.CRI("watchdogMaxSec"))
+ // init obj display
+ newDisplayData currDispData = new newDisplayData();
+ if (listQueueVal != null)
{
- string wdStatus = "elapsed";
- string sVal = string.Format("[WDST]{0}", wdStatus);
- // chiamo accodamento...
- accodaFLog(sVal, qEncodeFLog("WDST", wdStatus));
- lastWatchDog = DateTime.Now;
- }
- // verifico SE la coda abbia dei valori...
- if (QueueFLog.Count > 0)
- {
- // invio pacchetto di dati (max da conf)
- for (int i = 0; i < nMaxSend; i++)
+ try
{
- // SE ho qualcosa in coda...
- if (QueueFLog.Count > 0)
+ // recupero e formatto URL dati da coda...
+ lastUrl = urlDataBlock(tipoUrl);
+ // in base al tipo di dato compongo il payload Json da inviare
+ string payload = jsonPayload(tipoUrl, listQueueVal);
+ // async a true SE FLog
+ bool doAsync = tipoUrl == urlType.FLog ? true : false;
+ // se NON sono in demo effettuo invio!
+ if (!DemoOut)
{
- string currVal = "";
- if (MPOnline)
+ // SE server alive...
+ if (checkServerAlive)
{
- if (IobOnline)
+ // chiamo URL!
+ string answ = callUrlWithPayload(lastUrl, payload, doAsync);
+ // attesa opzionale se configurata
+
+ // loggo!
+ lgInfo($"[SEND payload] TipoURL: {tipoUrl} | {listQueueVal.Count} records --> {answ}");
+ // se "OK" verde, altrimenti errore --> ROSSO
+ if (answ.Contains("OK"))
{
- // se ho + di 2 elementi in coda --> uso invio JSON in blocco...
- if (QueueFLog.Count > 1)
+ currDispData.semOut = Semaforo.SV;
+ // se oltre 1 min NON era online --> check pezzi!
+ if (DateTime.Now.Subtract(lastIobOnline).TotalMinutes > 1 && !isMulti)
{
- List listaValori = new List();
- // se ho + di maxJsonData elementi --> invio un set di dati alla volta
- if (QueueFLog.Count > maxJsonData)
- {
- // prendoi primi maxJsonDataValori
- for (int j = 0; j < maxJsonData; j++)
- {
- QueueFLog.TryDequeue(out currVal);
- listaValori.Add(currVal);
- }
- sendDataBlock(urlType.FLog, listaValori);
- lastWatchDog = DateTime.Now;
- }
- else
- {
- // invio in blocco
- listaValori = QueueFLog.ToList();
- // invio
- sendDataBlock(urlType.FLog, listaValori);
- // svuoto!
- QueueFLog = new ConcurrentQueue();
- lastWatchDog = DateTime.Now;
- }
- }
- else
- {
- // INVIO SINGOLO...!!!
- QueueFLog.TryDequeue(out currVal);
- sendToMoonPro(urlType.FLog, currVal);
- lastWatchDog = DateTime.Now;
+ lgInfo($"sendDataBlock --> offline timeout ({lastIobOnline}) --> pzCntReload(true)");
+ pzCntReload(true);
}
+ lastIobOnline = DateTime.Now;
}
else
{
- break;
+ currDispData.semOut = Semaforo.SR;
}
}
else
{
- break;
+ lgInfo($"[SERVER KO] {listQueueVal.Count}");
}
}
else
{
- break;
+ currDispData.semOut = Semaforo.SV;
+ // loggo!
+ lgInfo($"{listQueueVal.Count} records --> [SIM]");
}
+ nSendOut += listQueueVal.Count;
+ // riporto cosa inviato
+ currDispData.newUrlCallData = lastUrl;
+ // aggiorno data ultimo watchdog...
+ lastWatchDog = DateTime.Now;
}
- }
- }
-
- ///
- /// Processo la coda RawTransf...
- ///
- private void svuotaCodaRawTransf()
- {
- // verifico SE la coda abbia dei valori...
- if (QueueRawTransf.Count > 0)
- {
- // invio pacchetto di dati (max da conf)
- for (int i = 0; i < nMaxSend; i++)
+ catch
{
- // SE ho qualcosa in coda...
- if (QueueRawTransf.Count > 0)
- {
- string currVal = "";
- if (MPOnline)
- {
- if (IobOnline)
- {
- List listaValori = new List();
- // se ho + di maxJsonData elementi --> invio un set di dati alla volta
- if (QueueRawTransf.Count > maxJsonData)
- {
- // prendoi primi maxJsonDataValori
- for (int j = 0; j < maxJsonData; j++)
- {
- QueueRawTransf.TryDequeue(out currVal);
- listaValori.Add(currVal);
- }
- sendDataBlock(urlType.RawTransf, listaValori);
- }
- else
- {
- // invio in blocco
- listaValori = QueueRawTransf.ToList();
- // invio
- sendDataBlock(urlType.RawTransf, listaValori);
- // svuoto!
- QueueRawTransf = new ConcurrentQueue();
- }
- }
- else
- {
- break;
- }
- }
- else
- {
- break;
- }
- }
- else
- {
- break;
- }
+ currDispData.semOut = Semaforo.SR;
}
}
+ raiseRefresh(currDispData);
}
///
- /// Processo la coda UserLog...
+ /// Effettua invio a MoonPro del valore richiesto
///
- private void svuotaCodaULog()
- {
- // verifico SE la coda abbia dei valori...
- if (QueueULog.Count > 0)
- {
- // invio pacchetto di dati (max da conf)
- for (int i = 0; i < nMaxSend; i++)
- {
- // SE ho qualcosa in coda...
- if (QueueULog.Count > 0)
- {
- string currVal = "";
- if (MPOnline)
- {
- if (IobOnline)
- {
- List listaValori = new List();
- // se ho + di maxJsonData elementi --> invio un set di dati alla volta
- if (QueueULog.Count > maxJsonData)
- {
- // prendoi primi maxJsonDataValori
- for (int j = 0; j < maxJsonData; j++)
- {
- QueueULog.TryDequeue(out currVal);
- listaValori.Add(currVal);
- }
- sendDataBlock(urlType.ULog, listaValori);
- }
- else
- {
- // invio in blocco
- listaValori = QueueULog.ToList();
- // invio
- sendDataBlock(urlType.ULog, listaValori);
- // svuoto!
- QueueULog = new ConcurrentQueue();
- }
- }
- else
- {
- break;
- }
- }
- else
- {
- break;
- }
- }
- else
- {
- break;
- }
- }
- }
- }
-
- ///
- /// Cerca di inviare su un altro thread i vari dati accumulati...
- ///
- private void trySendValues()
+ ///
+ ///
+ /// Valore da trasmettere: es
+ /// INPUT: lo status rilevato in HEX
+ /// FLog: il valore da trasmettere per il flusso indicato
+ ///
+ public void sendToMoonPro(urlType tipoUrl, string queueVal)
{
// init obj display
newDisplayData currDispData = new newDisplayData();
try
{
- // verifico se risponde il server...
- if (checkServerAlive)
+ // recupero e formatto URL dati da coda...
+ switch (tipoUrl)
{
- bool iobOk = false;
- if (utils.CRB("sendDataByThread"))
+ case urlType.FLog:
+ lastUrl = urlFLog(queueVal);
+ break;
+
+ case urlType.SignIN:
+ lastUrl = urlInput(queueVal);
+ break;
+
+ default:
+ lastUrl = "";
+ break;
+ }
+ // se NON sono in demo effettuo invio!
+ if (!DemoOut)
+ {
+ // SE server alive...
+ if (checkServerAlive)
{
- Task taskCheck = Task.Run(() => iobOk = checkIobEnabled);
- }
- else
- {
- iobOk = checkIobEnabled;
- }
- // verifico SE posso inviare dati
- if (iobOk)
- {
- currDispData.semOut = Semaforo.SV;
- // verificare come gestire il task secondario senza interferenza (chiamate update su FORM da thread secondari danno errori)
- if (utils.CRB("sendDataByThread"))
+ // chiamo URL!
+ string answ = callUrl(lastUrl, false);
+ // loggo!
+ lgDebug(string.Format("[SEND] {0} -> {1}", queueVal, answ));
+ // se oltre 1 min NON era online --> check pezzi!
+ if (DateTime.Now.Subtract(lastIobOnline).TotalMinutes > 1 && !isMulti)
{
- // invio con thread separato...
- Task taskSigIN = Task.Run(() => svuotaCodaSignIN());
- Task taskFLog = Task.Run(() => svuotaCodaFLog());
- Task taskRawTransf = Task.Run(() => svuotaCodaRawTransf());
- Task taskULog = Task.Run(() => svuotaCodaULog());
+ lgInfo($"sendToMoonPro --> offline timeout ({lastIobOnline}) --> pzCntReload(true)");
+ pzCntReload(true);
+ }
+ // se richiesto effettuo refresh contapezzi
+ if (needRefreshPzCount && !isMulti)
+ {
+ pzCntReload(true);
+ needRefreshPzCount = false;
+ }
+ lastIobOnline = DateTime.Now;
+ // se "OK" verde, altrimenti errore --> ROSSO
+ if (answ == "OK")
+ {
+ currDispData.semOut = Semaforo.SV;
}
else
{
- // gestione queue SignalIN (invio, display)
- svuotaCodaSignIN();
- currDispData.counter = contapezziIOB;
- raiseRefresh(currDispData);
- // provo a svuotare coda contapezzi
- svuotaCodaContapezzi();
- currDispData.counter = contapezziIOB;
- raiseRefresh(currDispData);
- // gestione queue FluxLog (invio, display)
- svuotaCodaFLog();
- // coda RawTransf
- svuotaCodaRawTransf();
- // coda UserLog
- svuotaCodaULog();
- // refresh
- raiseRefresh(currDispData);
+ currDispData.semOut = Semaforo.SR;
}
- // se arrivo è tutto ok...
- currSendErrors = 0;
}
else
{
- // mostro VETO-SEND x invio... GIALLO
- currDispData.semOut = Semaforo.SG;
- if (periodicLog)
- {
- lgInfo("IOB - VETO SEND");
- }
+ lgError(string.Format("[SERVER KO] {0}", queueVal));
}
}
else
{
- // mostro SERVER KO x invio... ROSSO
- currDispData.semOut = Semaforo.SR;
- if (periodicLog)
- {
- lgError("IOB - SERVER NOT READY");
- }
+ currDispData.semOut = Semaforo.SV;
+ // loggo!
+ lgDebug(string.Format("{0} -> [SIM]", queueVal));
}
+ nSendOut++;
+ currDispData.newUrlCallData = lastUrl;
+ // aggiorno data ultimo watchdog...
+ lastWatchDog = DateTime.Now;
}
- catch (Exception exc)
+ catch
{
- lgError($"Errore in fase trySendValues | currSendErrors: {currSendErrors}{Environment.NewLine}{exc}");
currDispData.semOut = Semaforo.SR;
}
raiseRefresh(currDispData);
}
///
- /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce
+ /// Metodo generico di IMPOSTAZIONE FORZATA del contapezzi...
///
- ///
- ///
- ///
- /// Nuovo valore incrementato
- private double updateValDoubleByIncr(int i, double delta, string searchString)
+ /// Pezzi richiesti
+ ///
+ public virtual bool setcontapezziPLC(int newPzCount)
{
- // stringa da cercare..
- string keyVal = string.Format(searchString, i + 1);
- // recupero valore precedente...
- double contAct = getStoredValDouble(keyVal);
- // nuovo valore...
- contAct += delta;
- // salvo in ram!
- persistenceLayer[keyVal] = contAct.ToString();
- // rendo il valore!
- return contAct;
+ return false;
}
///
- /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce
+ /// Processing di Variabili Campionarie x TimeSeries, accoda valori x la VC (se esiste) e
+ /// restituisce bool val se SCADUTO periodo controllo
///
- ///
- ///
- ///
- /// Nuovo valore incrementato
- private long updateValLongByIncr(int i, long delta, string searchString)
+ /// Nome della VC
+ /// Valore (nuovo) delal VC
+ ///
+ public bool stackVal_TSVC(string VCName, double VCVal)
{
- // stringa da cercare..
- string keyVal = string.Format(searchString, i + 1);
- // recupero valore precedente...
- long contAct = getStoredValLong(keyVal);
- // nuovo valore...
- contAct += delta;
- // salvo in ram!
- persistenceLayer[keyVal] = contAct.ToString();
- // rendo il valore!
- return contAct;
+ bool answ = false;
+ // cerco VC...
+ if (TSVC_Data.ContainsKey(VCName))
+ {
+ TSVC_Data[VCName].dataArray.Add(VCVal);
+ // ora verifico scadenza...
+ if (TSVC_Data[VCName].DTStart.AddSeconds(TSVC_Data[VCName].Period) < DateTime.Now)
+ {
+ answ = true;
+ }
+ }
+ return answ;
}
///
- /// Aggiorna un valore del dizionario in SOSTITUZIONE
+ /// Avvia l'adapter sulla porta richiesta
///
- ///
- ///
- ///
- /// Nuovo valore incrementato
- private void updateValString(int i, string newVal, string searchString)
+ /// indica se sia richeisto di SVUOTARE le code delel info
+ public virtual void startAdapter(bool resetQueue)
{
- // stringa da cercare..
- string keyVal = string.Format(searchString, i + 1);
- // salvo in ram!
- persistenceLayer[keyVal] = newVal;
+ DateTime adesso = DateTime.Now; ;
+ DateTime scaduto = adesso.AddMinutes(-10);
+ lgInfo("Starting adapter...");
+ maxJsonData = utils.CRI("maxJsonData");
+ maxJsonDataEv = utils.CRI("maxJsonDataEv");
+ parentForm.commPlcActive = false;
+ adpRunning = true;
+ dtAvvioAdp = adesso;
+ lastWatchDog = scaduto;
+ lastPING = scaduto;
+ lastReadPLC = scaduto;
+ lastDisconnCheck = scaduto;
+ TimingData.resetData();
+ // aggiungo altri defaults
+ setDefaults(resetQueue);
+ adpTryRestart = true;
+ lgDebug("startAdapter completed");
}
///
- /// Aggiorna un valore del dizionario in SOSTITUZIONE e lo restituisce
+ /// ferma l'adapter...
///
- ///
- ///
- ///
- /// Nuovo valore incrementato
- private void updateValUInt(int i, uint newVal, string searchString)
+ ///
+ /// indica se si debba tentare di riavviare l'adapter (con caduta connessione viene fermato
+ /// in automatico)
+ ///
+ /// indica se sia richeisto di SVUOTARE le code delel info
+ public virtual void stopAdapter(bool tryRestart, bool forceDequeue)
{
- // stringa da cercare..
- string keyVal = string.Format(searchString, i + 1);
- // salvo in ram!
- persistenceLayer[keyVal] = newVal.ToString();
+ if (forceDequeue)
+ {
+ // svuoto le code dei valori letti e non ancora trasmessi...
+ parentForm.displayTaskAndLog("[CLOSING] Svuotamento FORZATO coda segnali...");
+ while (QueueIN.Count > 0)
+ {
+ // INVIO COMUNQUE...!!!
+ string valore = "";
+ QueueIN.TryDequeue(out valore);
+ sendToMoonPro(urlType.SignIN, valore);
+ }
+ parentForm.displayTaskAndLog("[CLOSING] Svuotamento FORZATO coda FluxLOG...");
+ // se ho + di 2 elementi in coda --> uso invio JSON in blocco...
+ if (QueueFLog.Count > minJsonData)
+ {
+ while (QueueFLog.Count > 0)
+ {
+ List listaValori = new List();
+ // se ho + di maxJsonData elementi --> invio un set di dati alla volta
+ if (QueueFLog.Count > maxJsonData)
+ {
+ string currVal = "";
+ // prendoi primi maxJsonDataValori
+ for (int i = 0; i < maxJsonData; i++)
+ {
+ QueueFLog.TryDequeue(out currVal);
+ listaValori.Add(currVal);
+ }
+ sendDataBlock(urlType.FLog, listaValori);
+ }
+ else
+ {
+ // invio in blocco
+ listaValori = QueueFLog.ToList();
+ // invio
+ sendDataBlock(urlType.FLog, listaValori);
+ // svuoto!
+ QueueFLog = new ConcurrentQueue();
+ }
+ }
+ // HO FINITO invio di FLog...
+ }
+ else
+ {
+ string currVal = "";
+ while (QueueFLog.Count > 0)
+ {
+ // INVIO COMUNQUE...!!!
+ QueueFLog.TryDequeue(out currVal);
+ sendToMoonPro(urlType.FLog, currVal);
+ }
+ }
+
+ // svuoto coda ULog
+ while (QueueULog.Count > 0)
+ {
+ List listaValori = new List();
+ // se ho + di maxJsonData elementi --> invio un set di dati alla volta
+ if (QueueULog.Count > maxJsonData)
+ {
+ string currVal = "";
+ // prendoi primi maxJsonDataValori
+ for (int i = 0; i < maxJsonData; i++)
+ {
+ QueueULog.TryDequeue(out currVal);
+ listaValori.Add(currVal);
+ }
+ sendDataBlock(urlType.ULog, listaValori);
+ }
+ else
+ {
+ // invio in blocco
+ listaValori = QueueULog.ToList();
+ // invio
+ sendDataBlock(urlType.ULog, listaValori);
+ // svuoto!
+ QueueULog = new ConcurrentQueue();
+ }
+ }
+ }
+ parentForm.displayTaskAndLog("[STOP] Stopping adapter...");
+ adpTryRestart = false;
+
+ parentForm.displayTaskAndLog("[STOP] Stopping adapter - last periodic data read...");
+
+ // chiudo la connessione all'adapter...
+ tryDisconnect();
+ dtStopAdp = DateTime.Now;
+ adpTryRestart = tryRestart;
+ adpRunning = false;
+ // chiudo!
+ parentForm.displayTaskAndLog("Adapter Stopped.");
+ parentForm.commPlcActive = false;
}
///
- /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce
+ /// Processo la coda SignalIN...
///
- ///
- ///
- ///
- /// Nuovo valore incrementato
- private uint updateValUIntByIncr(int i, uint delta, string searchString)
+ public void svuotaCodaSignIN()
{
- // stringa da cercare..
- string keyVal = string.Format(searchString, i + 1);
- // recupero valore precedente...
- uint contAct = getStoredValUInt(keyVal);
- // nuovo valore...
- contAct += delta;
- // salvo in ram!
- persistenceLayer[keyVal] = contAct.ToString();
- // rendo il valore!
- return contAct;
+ // verifico SE la coda abbia dei valori...
+ if (QueueIN.Count > 0)
+ {
+ // invio pacchetto di dati (max da conf)
+ for (int i = 0; i < nMaxSend; i++)
+ {
+ if (QueueIN.Count > 0)
+ {
+ string currVal = "";
+ // se online provo
+ if (MPOnline)
+ {
+ if (IobOnline)
+ {
+ // se ho + di 2 elementi in coda --> uso invio JSON in blocco...
+ if (QueueIN.Count > 1)
+ {
+ List listaValori = new List();
+ // se ho + di maxJsonData elementi --> invio un set di dati alla volta
+ if (QueueIN.Count > maxJsonDataEv)
+ {
+ // prendoi primi maxJsonDataValori
+ for (int j = 0; j < maxJsonDataEv; j++)
+ {
+ QueueIN.TryDequeue(out currVal);
+ listaValori.Add(currVal);
+ }
+ sendDataBlock(urlType.SignIN, listaValori);
+ }
+ else
+ {
+ // invio in blocco
+ listaValori = QueueIN.ToList();
+ // invio
+ sendDataBlock(urlType.SignIN, listaValori);
+ // svuoto!
+ QueueIN = new ConcurrentQueue();
+ }
+ }
+ else
+ {
+ // INVIO SINGOLO...!!!
+ QueueIN.TryDequeue(out currVal);
+ sendToMoonPro(urlType.SignIN, currVal);
+ }
+ // salvo come last signal in il currVal ultimo... SE !=""
+ if (!string.IsNullOrEmpty(currVal))
+ {
+ lastSignInVal = currVal;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
}
- #endregion Private Methods
+ ///
+ /// Metodo base connessione...
+ ///
+ public virtual void tryConnect()
+ {
+ dtAvvioAdp = DateTime.Now;
+ }
+
+ ///
+ /// Metodo base disconnessione...
+ ///
+ public virtual void tryDisconnect()
+ {
+ }
+
+ ///
+ /// Effettua verifica se abilitato invio pezzi in blocco e nel caso
+ /// - invio in blocco pezzi
+ /// - aggiornamento del contapezzi (passato come ref) x nuovo valore post invio
+ ///
+ public void trySendPzCountBlock()
+ {
+ // in primis HA SENSO procedere SOLO SE server MP è Online...
+ if (MPOnline)
+ {
+ // SOLO SE online la macchina...
+ if (IobOnline)
+ {
+ int numIncr = 0;
+ int qtyAdded = 0;
+ // verifico se la funzione SIA abilitata
+ if (enableSendPzCountBlock)
+ {
+ int delta = contapezziPLC - contapezziIOB;
+ // se è abilitata verifico differenza: se ho DELTA > minSendPzCountBlock -->
+ // invio un blocco <= maxSendPzCountBlock
+ if (delta > minSendPzCountBlock)
+ {
+ // init obj display
+ newDisplayData currDispData = new newDisplayData();
+ // resta indietro di ALMENO minSendPzCountBlock pezzi x recuperare 1:1...
+ numIncr = delta > maxSendPzCountBlock + minSendPzCountBlock ? maxSendPzCountBlock : delta - minSendPzCountBlock;
+ // invio il num max di pezzi ammesso in blocco!
+ lastUrl = $"{urlAddPzCount}{numIncr}";
+ string resp = utils.callUrlNow(lastUrl);
+ if (!string.IsNullOrEmpty(resp))
+ {
+ // dalla risposta (come numero) capisco SE ha aggiunto i pezzi (e quanti)
+ int.TryParse(resp, out qtyAdded);
+ if (qtyAdded > 0)
+ {
+ // aggiorno IL MIO contapezzi...
+ contapezziIOB += qtyAdded;
+ lgInfo($"Inviato incremento contapezzi: send: {numIncr} | resp: {qtyAdded} | contapezziIOB: {contapezziIOB}");
+ // invio conferma contapezzi..
+ string retVal = utils.callUrl($"{urlSetPzCount}{contapezziIOB}");
+ // verifica se tutto OK
+ if (retVal != contapezziIOB.ToString())
+ {
+ // errore salvataggio contapezzi
+ lgError($"trySendPzCountBlock: errore salvataggio contapezzi: contapezziIOB {contapezziIOB} | risposta: {retVal}");
+ }
+ }
+ else
+ {
+ lgError($"Richiesto incremento {numIncr} ma NON registrato su server MP-IO");
+ }
+ }
+ currDispData.newUrlCallData = lastUrl;
+ currDispData.counter = contapezziIOB;
+ currDispData.semOut = Semaforo.SV;
+ raiseRefresh(currDispData);
+ }
+ }
+ }
+ else
+ {
+ lgError("Impossibile trySendPzCountBlock: IobOnline è false");
+ }
+ }
+ else
+ {
+ lgError("Impossibile trySendPzCountBlock: MPOnline è false");
+ }
+ }
+
+ ///
+ /// Inserimento/aggiornamento chiavi/valore in currProdData
+ ///
+ ///
+ ///
+ public void upsertKey(string chiave, string valore)
+ {
+ if (currProdData.ContainsKey(chiave))
+ {
+ currProdData[chiave] = valore;
+ }
+ else
+ {
+ currProdData.Add(chiave, valore);
+ }
+ }
+
+ ///
+ /// Formatta URL x invio in DataBlock Json dei dati FLog / eventi
+ ///
+ ///
+ ///
+ public string urlDataBlock(urlType tipoUrl)
+ {
+ // verifico la parte di link "tipoComando"
+ string tipoComando = "";
+ switch (tipoUrl)
+ {
+ case urlType.FLog:
+ tipoComando = cIobConf.serverData.CMDFLOG_JSON;
+ break;
+
+ case urlType.SignIN:
+ tipoComando = cIobConf.serverData.CMDBASE_JSON;
+ break;
+
+ case urlType.RawTransf:
+ tipoComando = cIobConf.serverData.CMDRAWTRANSF_JSON;
+ break;
+
+ case urlType.ULog:
+ tipoComando = cIobConf.serverData.CMDULOG_JSON;
+ break;
+
+ default:
+ break;
+ }
+ // URL base x input
+ string answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{tipoComando}{cIobConf.codIOB}";
+ return answ;
+ }
+
+ ///
+ /// Fornisce URL di tipo FluxLog
+ ///
+ /// valore salvato in coda nel formato dtEve#flux#valore#counter
+ ///
+ public string urlFLog(string queueVal)
+ {
+ // URL base x input
+ string answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDFLOG}";
+ // decodifica valore!
+ string[] valori = qDecodeIN(queueVal);
+ // aggiungo macchina e valore...
+ answ += string.Format(@"{0}?flux={1}&&valore={2}", cIobConf.codIOB, valori[1], valori[2]);
+ // aggiondo dataOra evento e corrente + contatore...
+ answ += string.Format(@"&&dtEve={0}&&dtCurr={1:yyyyMMddHHmmssfff}&&cnt={2}", valori[0], DateTime.Now, valori[3]);
+ return answ;
+ }
+
+ ///
+ /// Fornisce URL INPUT per i parametri richiesti
+ ///
+ /// valore salvato in coda formato dtEve#valore#counter
+ ///
+ public string urlInput(string queueVal)
+ {
+ // URL base x input
+ string answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDBASE}";
+ // decodifica valore!
+ string[] valori = qDecodeIN(queueVal);
+ // aggiungo macchina e valore...
+ answ += string.Format(@"{0}?valore={1}", cIobConf.codIOB, valori[1]);
+ // aggiondo dataOra evento e corrente + contatore...
+ answ += string.Format(@"&&dtEve={0}&&dtCurr={1:yyyyMMddHHmmssfff}&&cnt={2}", valori[0], DateTime.Now, valori[2]);
+ return answ;
+ }
+
+ ///
+ /// Fornisce URL di tipo UserLog
+ ///
+ /// valore salvato in coda nel formato dtEve#flux#valore#counter
+ ///
+ public string urlULog(string queueVal)
+ {
+ // URL base x input
+ string answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDULOG}";
+ // decodifica valore!
+ string[] valori = qDecodeIN(queueVal);
+ // aggiungo macchina e valore...
+ answ += string.Format(@"{0}?flux={1}&&valore={2}", cIobConf.codIOB, valori[1], valori[2]);
+ // aggiondo dataOra evento e corrente + contatore...
+ answ += string.Format(@"&&dtEve={0}&&dtCurr={1:yyyyMMddHHmmssfff}&&cnt={2}", valori[0], DateTime.Now, valori[3]);
+ return answ;
+ }
+
+ #endregion Public Methods
+
+ #region Protected Fields
+
+ ///
+ /// wrapper di log
+ ///
+ protected static Logger lg;
+
+ ///
+ /// Valore di attesa (random) dopo ogni invio x evitare congestione send...
+ ///
+ protected static int urlRandWait = 0;
+
+ protected bool _connOk = false;
+
+ ///
+ /// valore booleano di check se sia in fase di COMUNICAZIONE ATTIVA con il PLC/NC
+ ///
+ protected bool adpCommAct;
+
+ ///
+ /// porta x adapter (x restart)
+ ///
+ protected int adpPortNum;
+
+ ///
+ /// DataOra ultimo avvio adapter x watchdog
+ ///
+ protected DateTime adpStartRun;
+
+ ///
+ /// Vettore 32 BIT valori in ingresso al filtro
+ ///
+ protected int B_input;
+
+ ///
+ /// Vettore 32 BIT valori in uscita dal filtro
+ ///
+ protected int B_output;
+
+ ///
+ /// Vettore 32 BIT valori precedenti
+ ///
+ protected int B_previous;
+
+ ///
+ /// Num errori check alive
+ ///
+ protected int currAliveErrors = 0;
+
+ ///
+ /// Dizionario valori impostati x produzione
+ ///
+ protected Dictionary currProdData = new Dictionary();
+
+ ///
+ /// num corrente errori read PLC
+ ///
+ protected int currReadErrors = 0;
+
+ ///
+ /// num errori send
+ ///
+ protected int currSendErrors = 0;
+
+ ///
+ /// Fattore di demoltiplicazione dei DynData x ridurre campionamento
+ ///
+ protected int demFactDynData = 1;
+
+ ///
+ /// Array dei contatori x segnali blinking
+ ///
+ protected int[] i_counters;
+
+ ///
+ /// Indica impianto IN SETUP (fino a quando SMETTE di esserlo...)
+ ///
+ protected bool inSetup = false;
+
+ ///
+ /// ultimo tentativo connessione...
+ ///
+ protected DateTime lastConnectTry;
+
+ ///
+ /// Ultimo LOG registrazione avvio (x ridurre log notturni...)
+ ///
+ protected DateTime lastLogStartup = DateTime.Today.AddHours(-1);
+
+ ///
+ /// Dizionario ULTIMI valori impostati x produzione
+ ///
+ protected Dictionary lastProdData = new Dictionary();
+
+ ///
+ /// Ultimo invio contapezzi (x invio delayed)
+ ///
+ protected DateTime lastPzCountSend;
+
+ ///
+ /// Dizionario ultimi valori (double) delle TSVC
+ ///
+ protected Dictionary LastTSVC = new Dictionary();
+
+ ///
+ /// Ultima registrazione warning x ODL mancante (x scrivere solo ogni 15 secondi)
+ ///
+ protected DateTime lastWarnODL;
+
+ ///
+ /// Num massimo di errori in funzionalità check alive
+ ///
+ protected int maxAliveErrors = utils.CRI("maxAliveErrors");
+
+ ///
+ /// Soglia massima errori priam di disconnesisone automatica
+ ///
+ protected int maxErroriCheck = 100;
+
+ ///
+ /// Num massimo di errori di rete read (dal PLC)
+ ///
+ protected int maxReadErrors = utils.CRI("maxReadErrors");
+
+ ///
+ /// Num massimodi errori di rete send al server
+ ///
+ protected int maxSendErrors = utils.CRI("maxSendErrors");
+
+ ///
+ /// indica se serva refresh parametri e quindi PLC...
+ ///
+ protected bool needRefresh = true;
+
+ ///
+ /// Variabile numero errori vari (in lettura) --> se supera soglia maxErroriCheck --> disconnette
+ ///
+ protected int numErroriCheck = 0;
+
+ ///
+ /// Form chiamante
+ ///
+ protected AdapterForm parentForm;
+
+ ///
+ /// Timeout x ping al server
+ ///
+ protected int pingServerMsTimeout = utils.CRI("pingMsTimeout");
+
+ ///
+ /// Ritardo minimo x invio contapezzi
+ ///
+ protected int pzCountDelay;
+
+ ///
+ /// Dizionario di VC da trattare come TimeSeries (con conf decodificata + processing successivo...)
+ ///
+ protected Dictionary TSVC_Data = new Dictionary();
+
+ ///
+ /// Dizionario di VARIABILI da trattare come eventi (da inviare quando cambiano oppure a
+ /// scadenza periodo...)
+ ///
+ protected Dictionary VarArray = new Dictionary();
+
+ ///
+ /// Veto per registrazione completa log di startup (minuti)
+ ///
+ protected int vetoLogStartupDuration = 60;
+
+ ///
+ /// Periodo wathdog di default (2 sec se non specificato)
+ ///
+ protected int watchDogPeriod = 2;
+
+ #endregion Protected Fields
+
+ #region Protected Properties
+
+ ///
+ /// Valore del num max invii consecutivi da coda...
+ ///
+ protected static int nMaxSend
+ {
+ get
+ {
+ int answ = 5;
+ try
+ {
+ answ = utils.CRI("nMaxSend");
+ }
+ catch
+ { }
+ return answ;
+ }
+ }
+
+ ///
+ /// Indica il counter della key richiesta attiva
+ /// - gestito tramite Redis
+ /// - a scadenza 25h
+ /// - incrementato ogni invio di auto ODL
+ ///
+ protected int countKeyRichiesta
+ {
+ get
+ {
+ // calcolo key odierna
+ int answ = redisMan.getKReqCount(dailyKey);
+ return answ;
+ }
+ set
+ {
+ // calcolo key odierna
+ redisMan.setKReqCount(dailyKey, value);
+ }
+ }
+
+ protected string dailyKey
+ {
+ get
+ {
+ return DateTime.Today.ToString("yyMMdd");
+ }
+ }
+
+ ///
+ /// Variabile di appoggio GLOBALE x indicare che si può forzare reset contapezzi con
+ /// macchina in RUN
+ ///
+ protected bool forceResetInRun { get; set; } = false;
+
+ ///
+ /// Variabile di appoggio GLOBALE x indicare macchina RUN (es x gestione su reset pezzi)
+ ///
+ protected bool isRunning { get; set; } = false;
+
+ ///
+ /// Valore limite MASSIMO di invio di dati come array Json
+ ///
+ protected int maxJsonData { get; set; } = utils.CRI("maxJsonData");
+
+ ///
+ /// Valore limite MASSIMO di invio di dati come array Json x EVENTI
+ ///
+ protected int maxJsonDataEv { get; set; } = utils.CRI("maxJsonDataEv");
+
+ ///
+ /// Max tentativi ping permessi (default: 5)
+ ///
+ protected int maxPingRetry { get; set; } = 5;
+
+ /// Coda massima ammessa per FLog (se <=0 disattivata...)
+ protected int maxQueueFLog { get; set; } = utils.CRI("maxQueueFLog");
+
+ /// Coda massima ammessa per FLog (se <=0 disattivata...)
+ protected int maxQueueRawTransf { get; set; } = utils.CRI("maxQueueRawTransf");
+
+ ///
+ /// Valore MINIMO limite x decidere invio di dati come array Json
+ ///
+ protected int minJsonData { get; set; } = utils.CRI("minJsonData");
+
+ protected string nextKeyRich
+ {
+ get
+ {
+ return $"{dailyKey}{countKeyRichiesta:00}";
+ }
+ }
+
+ ///
+ /// Numero letture IN da avvio
+ ///
+ protected int nReadFilt { get; set; }
+
+ ///
+ /// Numero letture IN da avvio
+ ///
+ protected int nReadIN { get; set; }
+
+ ///
+ /// Numero invii OUT (svuotamento coda)
+ ///
+ protected int nSendOut { get; set; }
+
+ ///
+ /// Numero simulazioni ammesse...
+ ///
+ protected int numSim { get; set; }
+
+ ///
+ /// Indica se sia stato resettato un contapezzi
+ ///
+ protected bool pzCountResetted { get; set; } = false;
+
+ ///
+ /// Fornisce il valore letto da BITMAP in formato valido x messa in coda nel formato dtEve#value#cont
+ ///
+ protected string qEncodeIN
+ {
+ get
+ {
+ string answ = "";
+ try
+ {
+ answ = string.Format("{0:yyyyMMddHHmmssfff}#{1:X2}#{2}", DateTime.Now, B_output, counterSigIN);
+ }
+ catch
+ { }
+ return answ;
+ }
+ }
+
+ ///
+ /// Indica se vada inviata la key richiesta con lo split/autoODL
+ ///
+ protected bool sendKeyRichiesta { get; set; } = false;
+
+ ///
+ /// test ping all'indirizzo PLC/CNC impostato nei parametri
+ ///
+ ///
+ protected IPStatus testPingMachine
+ {
+ get
+ {
+ IPStatus answ = IPStatus.Unknown;
+ // se disabilitato salto...
+ if (pingDisabled)
+ {
+ answ = IPStatus.Success;
+ }
+ else
+ {
+ IPAddress address;
+ PingReply reply;
+ using (Ping pingSender = new Ping())
+ {
+ address = IPAddress.Loopback;
+ int pingMsTimeout = cIobConf.pingMsTimeout;
+ IPAddress.TryParse(cIobConf.cncIpAddr, out address);
+ try
+ {
+ // se != null --> uso address...
+ if (address != null)
+ {
+ reply = pingSender.Send(address, pingMsTimeout);
+ }
+ else
+ {
+ reply = pingSender.Send(cIobConf.cncIpAddr, pingMsTimeout);
+ }
+ }
+ catch
+ {
+ reply = pingSender.Send(IPAddress.Loopback, pingMsTimeout);
+ }
+ answ = reply.Status;
+ }
+ }
+ return answ;
+ }
+ }
+
+ ///
+ /// Secondi standard x veto check status e log
+ ///
+ protected int vetoSeconds { get; set; } = utils.CRI("vetoSeconds");
+
+ #endregion Protected Properties
#region Protected Methods
///
- /// Decodifica file MAP (caso .bit)
+ /// Decodifica file MAP (caso .bit)
///
///
///
@@ -2590,10 +4065,7 @@ namespace IOB_WIN_NEXT
}
///
- /// Decodifica valore della coda IN nel formato
- /// answ[0]=dtEve
- /// answ[1]=valore
- /// answ[2]=counter
+ /// Decodifica valore della coda IN nel formato answ[0]=dtEve answ[1]=valore answ[2]=counter
///
/// dtEve + '#' + value + '#' + cont
///
@@ -2638,8 +4110,8 @@ namespace IOB_WIN_NEXT
/// - formato Json
/// - array di KVP / Dictionary
/// - formato definito da API x MP/IO/:
- /// - KEY: task
- /// - VALUE: array JSon KVP
+ /// - KEY: task
+ /// - VALUE: array JSon KVP
///
protected string getTask2exe()
{
@@ -2779,6 +4251,19 @@ namespace IOB_WIN_NEXT
sendToLogWatch("INFO", message);
}
}
+
+ ///
+ /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere...
+ ///
+ ///
+ ///
+ protected void lgInfo(string message, params object[] args)
+ {
+ lg.Factory.Configuration.Variables["codIOB"] = cIobConf.codIOB;
+ lg.Info(message, args);
+ sendToLogWatch("INFO", message, args);
+ }
+
protected void lgInfoStartup(string message, bool sendToForm = true)
{
lg.Factory.Configuration.Variables["codIOB"] = cIobConf.codIOB;
@@ -2799,17 +4284,6 @@ namespace IOB_WIN_NEXT
}
}
- ///
- /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere...
- ///
- ///
- ///
- protected void lgInfo(string message, params object[] args)
- {
- lg.Factory.Configuration.Variables["codIOB"] = cIobConf.codIOB;
- lg.Info(message, args);
- sendToLogWatch("INFO", message, args);
- }
///
/// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere...
///
@@ -2934,8 +4408,7 @@ namespace IOB_WIN_NEXT
}
///
- /// Lettura memorie conf speciali (json)
- /// ...SE inserito in [OPTPAR] come PARAM_CONF=nome.json
+ /// Lettura memorie conf speciali (json) ...SE inserito in [OPTPAR] come PARAM_CONF=nome.json
///
protected virtual void loadMemConf()
{
@@ -3343,2236 +4816,696 @@ namespace IOB_WIN_NEXT
#endregion Protected Methods
- #region Public Methods
+ #region Private Properties
///
- /// Effettua chiamata URL e restituisce risultato
+ /// Verifica se la IOB sia ENABLED (da server o Demo)
///
- ///
- /// invio in modalità async (NON GARANTITO ordine...)
- ///
- public static string callUrl(string URL, bool doAsync)
+ private bool checkIobEnabled
{
- string answ = "";
- // Chiamata ASINCRONA
- if (doAsync)
+ get
{
- //Task resp = utils.callUrlAsync(URL);
- //answ = resp.Result;
- answ = utils.callUrlAsync(URL);
- if (urlRandWait > 0)
+ bool answ = false;
+ // controllo se ho veto al check...
+ if (dtVetoCheckIOB < DateTime.Now)
{
- Random rnd = new Random();
- Thread.Sleep(rnd.Next(urlRandWait / 10, urlRandWait));
- }
- }
- // chiamata SOLO NORMALE SINCRONA...
- else
- {
- answ = utils.callUrl(URL);
- if (urlRandWait > 0)
- {
- Random rnd = new Random();
- Thread.Sleep(rnd.Next(urlRandWait / 10, urlRandWait));
- }
- }
- return answ;
- }
-
- ///
- /// Effettua chiamata URL e restituisce risultato
- ///
- ///
- ///
- /// invio in modalità async (NON GARANTITO ordine...)
- ///
- public static string callUrlWithPayload(string URL, string payload, bool doAsync)
- {
- string answ = "";
- // Chiamata ASINCRONA
- if (doAsync)
- {
- answ = utils.callUrlAsync(URL, payload);
- if (urlRandWait > 0)
- {
- Random rnd = new Random();
- Thread.Sleep(rnd.Next(urlRandWait / 10, urlRandWait));
- }
- }
- // chiamata SOLO NORMALE SINCRONA...
- else
- {
- answ = utils.callUrl(URL, payload);
- if (urlRandWait > 0)
- {
- Random rnd = new Random();
- Thread.Sleep(rnd.Next(urlRandWait / 10, urlRandWait));
- }
- }
- return answ;
- }
-
- ///
- /// processa dataLayer e se necessario salva/mostra
- ///
- public static void checkSavePersDataLayer()
- {
- }
-
- public static string GetMACAddress()
- {
- NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
- String sMacAddress = string.Empty;
- foreach (NetworkInterface adapter in nics)
- {
- if (string.IsNullOrEmpty(sMacAddress))// only return MAC Address from first card
- {
- IPInterfaceProperties properties = adapter.GetIPProperties();
- //sMacAddress = adapter.GetPhysicalAddress().ToString();
- sMacAddress = string.Join(":", (from z in adapter.GetPhysicalAddress().GetAddressBytes() select z.ToString("X2")).ToArray());
- }
- }
- return sMacAddress;
- }
-
- public static void resetDebugConsole()
- {
- }
-
- ///
- /// Reset dei webclients
- ///
- public static void resetWebClients()
- {
- utils.resetWebClients();
- }
-
- ///
- /// Accumula in coda i valori ALARM e logga...
- ///
- /// VALORE RAW (x display)
- /// VALORE già processato con qEncodeFLog(...)
- public void accodaAlarmLog(string val, string encodedVal)
- {
- // mostro dati variati letti...
- displayOtherData(val);
- // accodo IN PRIMIS al FluxLog --> accodo (valore già formattato)!
- QueueFLog.Enqueue(encodedVal);
- // accodo ANCHE alla coda allarmi che trasmetterò SOLO SE a scadenza impostata (10 sec?) ho allarmi perdurati...
-
- // loggo!
- lgInfo(string.Format("[QUEUE-ALARM-LOG] {0}", encodedVal));
- counterFLog++;
- if (counterFLog > 9999)
- {
- counterFLog = 0;
- }
- }
-
- ///
- /// Accumula in coda i valori Flux Log e logga...
- ///
- /// VALORE RAW (x display)
- /// VALORE già processato con qEncodeFLog(...)
- public void accodaFLog(string val, string encodedVal)
- {
- // mostro dati variati letti...
- displayOtherData(val);
- // --> accodo (valore già formattato)!
- QueueFLog.Enqueue(encodedVal);
- // se abilitato controllo coda FLog (superiore a 0...)
- if (maxQueueFLog > 0)
- {
- // se ho una coda superiore a max ammesso
- if (QueueFLog.Count > maxQueueFLog)
- {
- // elimino valori iniziali fino a tornare al max ammesso...
- while (QueueFLog.Count > maxQueueFLog)
+ if (DemoOut)
{
- string currVal = "";
- QueueFLog.TryDequeue(out currVal);
- lgInfo($"Eliminazione da coda FLog per superamento maxLengh: {currVal}");
- }
- }
- }
- // loggo!
- lgTrace(string.Format("[QUEUE-FLOG] {0}", encodedVal));
- counterFLog++;
- if (counterFLog > 9999)
- {
- counterFLog = 0;
- }
- }
-
- ///
- /// Accumula in coda i valori RawData + log
- ///
- ///
- ///
- public void accodaRawData(IOB_UT_NEXT.rawTransfType mesType, object mesContent)
- {
- /*--------------------------------
- * nuova gestione coda dictionary
- * fixme todo da fare !!!
- *
- * - conterrà una lista di oggetti baseRawTransf
- * - i dati vanno poi "scodati" dal + vecchio ed inviati a MP/IO
- * - mostra un sunto delle info da inviare
- * - accodamento vero e proprio
- * - verifica (opzionale) coda massima x gestire roundRobin ultimi eventi
- * - trace della coda
- * - counter invio??? valutare se c'è dataora e poi sono da salvare su MongoDb / Redis
- *
- * */
-
- // serializzo il valore...
- BaseRawTransf newVal = new BaseRawTransf(DateTime.Now, mesContent, mesType);
- string encodedVal = JsonConvert.SerializeObject(newVal);
- // --> accodo (valore già formattato)!
- QueueRawTransf.Enqueue(encodedVal);
- // se abilitato controllo coda Max (superiore a 0...)
- if (maxQueueRawTransf > 0)
- {
- // se ho una coda superiore a max ammesso
- if (QueueRawTransf.Count > maxQueueRawTransf)
- {
- // elimino valori iniziali fino a tornare al max ammesso...
- while (QueueRawTransf.Count > maxQueueRawTransf)
- {
- string currVal = "";
- QueueRawTransf.TryDequeue(out currVal);
- lgInfo($"Eliminazione da coda RawTransf per superamento maxLengh: {currVal}");
- }
- }
- }
- // loggo!
- lgTrace(string.Format("[QUEUE-RTRANSF] {0}", encodedVal));
- counterRawTransf++;
- if (counterRawTransf > 9999)
- {
- counterRawTransf = 0;
- }
- }
-
- ///
- /// Accoda (visualizzando in cima allo stack) la nuova stringa di output per area OTHER DATA
- ///
- ///
- public void accodaOtherData(string newLine)
- {
- // inserisco in cima allo stack, trimmo e aggiorno display
- string strOtherData = limitLine2show(string.Format("{0}{1}{2}", newLine, Environment.NewLine, parentForm.dataMonitor_3));
- //parentForm.dataMonitor_3 = strOtherData;
- parentForm.WriteTextSafe(strOtherData);
- }
-
- ///
- /// Accumula in coda i valori Signal IN e logga...
- /// Parametri da aggiornare x display in form
- ///
- public void accodaSigIN(ref newDisplayData currDispData)
- {
- // mostro dati variati letti...
- displayInData(ref currDispData);
- // verifico veto a invio status macchina
- string keyName = "VETO_SIG_IN";
- if (getOptPar(keyName).ToUpper() == "TRUE")
- {
- lgTrace($"Filtrato accodamento valore da conf IOB | {keyName} | [QUEUE-IN] {qEncodeIN}");
- }
- else
- {
- // --> accodo (valore già formattato)!
- QueueIN.Enqueue(qEncodeIN);
- // loggo!
- lgTrace(string.Format("[QUEUE-IN] {0}", qEncodeIN));
- }
- // aggiorno counters ed eventuale reset
- nReadFilt++;
- if (nReadFilt > int.MaxValue - 1)
- {
- nReadFilt = 0; // per evitare buffer overflow...
- }
-
- counterSigIN++;
- if (counterSigIN > 9999)
- {
- counterSigIN = 0;
- }
- }
-
- ///
- /// Accumula in coda i valori USER LOG e logga...
- ///
- /// VALORE RAW (x display)
- /// VALORE già processato con qEncodeULog(...)
- public void accodaUserLog(string val, string encodedVal)
- {
- // mostro dati variati letti...
- displayOtherData(val);
- // accodo IN PRIMIS al FluxLog --> accodo (valore già formattato)!
- QueueULog.Enqueue(encodedVal);
-
- // loggo!
- lgInfo(string.Format("[QUEUE-USER-LOG] {0}", encodedVal));
- counterULog++;
- if (counterULog > 9999)
- {
- counterFLog = 0;
- }
- }
-
- ///
- /// Update visualizzaizone BIT in ingresso
- /// Parametri da aggiornare x display in form
- ///
- public void displayInData(ref newDisplayData currDispData)
- {
- if (currDispData != null)
- {
- // mostro update...
- string newString = string.Format("{0:0000}|{1}", counterSigIN, utils.IntToBinStr(B_output, 8));
- currDispData.newSignalData = newString;
- }
- }
-
- ///
- /// Mostra cosa ha/avrebbe inviato
- ///
- ///
- public void displayOtherData(string newData)
- {
- // mostro update...
- accodaOtherData(newData);
- }
-
- ///
- /// Esecuzione dei task richiesti e pulizia coda richieste eseguite
- ///
- ///
- public virtual Dictionary executeTasks(Dictionary task2exe)
- {
- // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti...
- Dictionary taskDone = new Dictionary();
- if (task2exe != null)
- {
- // controllo se memMap != null...
- if (memMap != 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);
- // controllo sulla KEY...
- switch (tName)
- {
- case taskType.nihil:
- case taskType.fixStopSetup:
- case taskType.forceSetPzCount:
- 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.setArt:
- case taskType.setComm:
- case taskType.setProg:
- case taskType.setPzComm:
- // recupero dati da memMap...
- if (memMap != null && memMap.mMapWrite != null)
- {
- if (memMap.mMapWrite.ContainsKey(item.Key))
- {
- dataConf currMem = memMap.mMapWrite[item.Key];
- string addr = currMem.memAddr;
- taskVal = $"SET task: {item.Key} --> {item.Value} | mem: {currMem.memAddr} - {currMem.size} byte";
- // salvo il nuovo valore nella memoria... così prox invio lo trasmetterà
- memMap.mMapWrite[item.Key].value = item.Value;
- }
- else
- {
- taskVal = $"NO DATA MEM, SET task: {item.Key} --> {item.Value}";
- }
- }
- else
- {
- taskVal = $"NO MemMap found, SET task: {item.Key} --> {item.Value}";
- }
- // salvo in currProd..
- saveProdData(new KeyValuePair(item.Key, item.Value));
-
- break;
-
- case taskType.forceResetPzCount:
- // reset contapezzi inizio setup
- taskOk = resetcontapezziPLC();
- taskVal = taskOk ? "RESET PZ COUNT OK" : "PZ RESET DISABLED | NO EXEC";
- lgInfo($"Chiamata forceResetPzCount: 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;
-
- case taskType.setParameter:
- // richiedo da URL i parametri WRITE da popolare
- lgInfo("Chiamata setParameter --> processMemWriteRequests");
- taskVal = processMemWriteRequests();
- // se restituiscce "" faccio altra prova...
- if (string.IsNullOrEmpty(taskVal))
- {
- // i parametri me li aspetto come stringa composta paramName|paramvalue
- if (item.Value.Contains("|"))
- {
- string[] paramsJob = item.Value.Split('|');
- taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}";
- }
- else
- {
- taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value";
- }
- }
- break;
-
- default:
- taskVal = "SKIPPED | NO EXEC";
- lgInfo($"Chiamata default senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
- break;
- }
- // aggiungo task!
- taskDone.Add(item.Key, taskVal);
- }
- }
- else
- {
- lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!");
- }
- }
-
- return taskDone;
- }
-
- ///
- /// Effettua verifica delle memorie WRITE, se ci siano variazioni da riportare verso il PLC
- /// Da impiegare ad esempio in caso di chiamate complesse (ad 2 aree di memoria condivise sul PLC; coem commessa + articolo EWON)
- ///
- ///
- /// Cerca parametri opzionali in modalità "like" del nome
- ///
- ///
- ///
- public Dictionary findOptPar(string keyStartSearch = "")
- {
- Dictionary answ = new Dictionary();
- // controllo SE keySearch !=""
- if (!string.IsNullOrWhiteSpace(keyStartSearch))
- {
- if (cIobConf.optPar.Count > 0)
- {
- // ciclo su tutti e cerco occorrenze che INIZINO...
- foreach (var item in cIobConf.optPar)
- {
- if (item.Key.StartsWith(keyStartSearch))
- {
- answ.Add(item.Key, item.Value);
- }
- }
- }
- }
- return answ;
- }
-
- ///
- /// forza reset ODL
- ///
- public void forceResetOdl()
- {
- lgInfo("Registrato richiesta forzatura reset ODL");
- pzCountResetted = true;
- }
-
- ///
- /// Effettua chiamata x split ODL
- ///
- ///
- public bool forceSplitOdl()
- {
- bool fatto = false;
- if (vetoSplit < DateTime.Now)
- {
- lgInfo("Richiesto forceSplitOdl");
- // imposto veto x 1 minuto ad altre chiamate...
- vetoSplit = DateTime.Now.AddMinutes(1);
- // eseguo SOLO SE sono online...
- if (MPOnline && IobOnline)
- {
- string fullUrl = "";
- string rawSplit = "";
- string IOB_MULTI_CNAME = "";
- string[] elencoMulti = null;
-
- try
- {
- /***************************************************
- * Descrizione procedura (OK X SIMULATORI...)
- *
- * - chiamata su MP/IO
- * - verifica che su DB sia abilitato AUTO ODL
- * - il server inserisce un evento fine prod HW 1 minuto prima e inizio setup HW
- * - viene duplicato e chiuso ODL corrente
- * - viene fatto partire ODL nuovo ADESSO
- * - num pezzi come ODL precedente (o da media 3 ODL precedenti)
- * - conferme pezzi & co... gestione NULL (NON SERVONO si tratta di impianti SENZA gestione vera ODL)
- * - reset contapezzi PLC locale...
- *
- *
- *
- * DA VALUTARE (x macchine tipo linea con + impianti... es valvital) SE
- * - creare una gestione ALTERNATIVA sul server che preveda impianto LEADER e impianti follower (RIGIDAMENTE CONFIGURATI)
- * - ogni volta che si fa setup LEADER --> si ripete su impianti FOLLOWER (eventi!!!)
- * - viene fatto reset contapezzi sui follower (+ altre operazioni opzionali, ES imposstazione nome commessa, quantità, articolo...)
- * - viene fatto reset + nuovo ODL (con stessi articoli e quantità) su follower, SENZA avere gestione x ODL di un codice esterno (quindi registra TUTTO ma NON RITORNERA' dati non avendo link verso esterno)
- * - serve NUOVA TABELLA delle macchine LEADER | FOLLOWER (1:n) e gestione da MP/IO
- *
- * ***************************************************/
-
- if (isMulti)
- {
- // devo chiamare cambio ODL x OGNI tavola: mi servono i parametri opzionali...
- IOB_MULTI_CNAME = getOptPar("IOB_MULTI_CNAME");
- elencoMulti = IOB_MULTI_CNAME.Split(',');
- }
- // se normale splitto!
- if (!isMulti)
- {
- // invio chiamata URL x reset ODL su macchina
- rawSplit = callUrl(urlForceSplit, false);
- fatto = (rawSplit != "KO") ? true : false;
- }
- // se multi gestisco il bit delle tavole...
- else
- {
- foreach (string item in elencoMulti)
- {
- // invio chiamata URL x reset ODL su macchina, ATTENZIONE scriviamo | al posto di "#" che in URL sarebbe filtrato...
- fullUrl = $"{urlForceSplit}&multi={item}";
- rawSplit = callUrl(fullUrl, false);
- lgDebug($"Esecuzione forceSplit | URL: {fullUrl} | esito: {rawSplit}");
- }
- fatto = (rawSplit == "OK") ? true : false;
- }
- }
- catch (Exception exc)
- {
- lgError($"Eccezione in forceSplitOdl{Environment.NewLine}{exc}");
- }
- // se fatto --> resetto contapezzi!!!
- if (fatto)
- {
- contapezziPLC = 0;
- contapezziIOB = 0;
- }
- }
- else
- {
- lgError("Richiesto forceSplitOdl ma MP/IOB offline --> NON eseguito");
- }
- }
- else
- {
- lgError("Richiesto forceSplitOdl ma veto attivo --> NON eseguito");
- }
- return fatto;
- }
-
- ///
- /// effettua recupero dati ed invio valori modificati...
- ///
- ///
- public void getAndSend(gatherCycle ciclo)
- {
- // init obj display
- newDisplayData currDispData = new newDisplayData();
- // IN OGNI CASO a prima di tutto EFFETTUO GESTIONE INVII dati da code!!!
- try
- {
- trySendValues();
- }
- catch (Exception exc)
- {
- lgError(exc, "Errore in gestione svuotamento/invio preliminare code memoria");
- currDispData.semOut = Semaforo.SR;
- }
- // controllo connessione/connettività
- if (connectionOk)
- {
- // controllo non sia già in esecuzione...
- if (!adpCommAct)
- {
- // provo ad avviare
- try
- {
- // imposto flag adapter running..
- adpCommAct = true;
- adpStartRun = DateTime.Now;
- }
- catch (Exception exc)
- {
- string errore = $"Adapter NOT STARTED!!!{Environment.NewLine}{exc}";
- adpCommAct = false;
- adpStartRun = DateTime.Now;
- currDispData.newLiveLogData = errore;
- }
- if (adpCommAct)
- {
- // try / catch generale altrimenti segno che è disconnesso...
- try
- {
- bool showDebugData = false;
- if (ciclo == gatherCycle.VHF)
- {
- processVHF();
- }
- // processing dati memoria (lettura, filtraggio, enqueque)
- else if (ciclo == gatherCycle.HF)
- {
- processWhatchDog();
- processAllMemory();
- processMode();
- }
- else if (ciclo == gatherCycle.MF)
- {
- processServerRequests();
- processOverride();
- processContapezzi();
- processCncAlarms();
- processDynData();
- processMem2Write();
- }
- else if (ciclo == gatherCycle.LF)
- {
- processCustomTaskLF();
- processOtherCounters();
- processProgram();
- // verifico se devo gestire cambio ODL in modo automatico
- processAutoOdl();
- }
- else if (ciclo == gatherCycle.VLF)
- {
- if (utils.CRB("enableContapezzi"))
- {
- // rilettura contapezzi da server...
- lgTrace("Ciclo VLF: pzCntReload(true)");
- if (!isMulti)
- {
- pzCntReload(true);
- }
- // refresh associazione Macchina - IOB
- sendM2IOB();
- }
- // recupero dati SETUP (sysinfo) e li invio/mostro se variati...
- processSysInfo();
- // checkLogDir x shrink!
- checkShrinkDir();
- // eventuale log!
- if (utils.CRB("recTime"))
- {
- logTimeResults();
- }
- }
- // mostra eventuali altri dati di processo...
- reportDataProc();
- if (showDebugData)
- {
- // verifica se debba salvare e mostrare dati
- checkSavePersDataLayer();
- }
- }
- catch (Exception exc)
- {
- // segnalo eccezione e indico disconnesso...
- lgError(exc, string.Format("Errore in gestione ciclo principale ADP, fermo adapter{0}{1}", Environment.NewLine, exc));
- parentForm.fermaAdapter(true, false, true);
- }
- // tolgo flag running
- adpCommAct = false;
+ answ = (QueueIN.Count + QueueFLog.Count >= nMaxSend);
+ IobOnline = answ;
}
else
{
- if (periodicLog)
- {
- lgDebug("ADP not running...");
- }
- }
- }
- else
- {
- // log ADP running
- lgError("Non eseguo chiamata: ADP ancora in running");
- // se è bloccato da oltre maxSec lo sblocco...
- if (DateTime.Now.Subtract(adpStartRun).TotalSeconds > utils.CRI("maxAdapterLockSec"))
- {
- // tolgo flag running
- adpCommAct = false;
- adpStartRun = DateTime.Now;
- }
- }
- }
- else
- {
- // provo a riconnettere SE abilitato tryRestart...
- if (adpTryRestart && !connectionOk)
- {
- // controllo se sia scaduto periodi di veto al tryConnect...
- int waitRecMSec = utils.CRI("waitRecMSec") * 2;
- DateTime dtVeto = lastConnectTry.AddMilliseconds(waitRecMSec);
- if (DateTime.Now > dtVeto)
- {
- lgInfo($"Veto Time Elapsed | lastConnectTry: {lastConnectTry} | waitRecMSec {waitRecMSec} ms) | NOW tryConnect");
- lastConnectTry = DateTime.Now;
- tryConnect();
- }
- }
- currDispData.semIn = Semaforo.SR;
- processDisconnectedTask();
- }
- raiseRefresh(currDispData);
- }
-
- ///
- /// Effettua processing CUSTOM x l'IOB corrente (ed invia ad IO)
- /// (task svolto tipicamente ogni 5 sec se base timer 10ms, vedere app.config)
- ///
- public virtual void processCustomTaskLF()
- { }
-
- ///
- /// Recupera eventuali allarmi CNC...
- ///
- public virtual Dictionary getCncAlarms()
- {
- Dictionary outVal = new Dictionary();
- return outVal;
- }
-
- ///
- /// Restituisce info DINAMICHE
- ///
- ///
- public virtual Dictionary getDynData()
- {
- Dictionary outVal = new Dictionary();
- return outVal;
- }
-
- ///
- /// Cerca se esiste il parametro opzionale e lo restituisce
- ///
- ///
- ///
- public string getOptPar(string key)
- {
- string answ = "";
- if (cIobConf.optPar.Count > 0)
- {
- // controllo SE HO il parametro
- if (cIobConf.optPar.ContainsKey(key))
- {
- answ = cIobConf.optPar[key];
- }
- }
- return answ;
- }
-
- ///
- /// Restituisce info OVERRIDES
- ///
- ///
- public virtual Dictionary getOverrides()
- {
- Dictionary outVal = new Dictionary();
- return outVal;
- }
-
- ///
- /// Restituisce programma in esecuzione
- ///
- public virtual string getPrgName()
- {
- return "";
- }
-
- ///
- /// Restituisce info sistema
- ///
- ///
- public virtual Dictionary getSysInfo()
- {
- Dictionary outVal = new Dictionary();
- return outVal;
- }
-
- ///
- /// Recupera la VC x TS, svuotando lista e resettando periodo partenza
- ///
- /// Nome della VC
- /// Reimposta e resetta array VC
- ///
- public double getVal_TSVC(string VCName, bool doReset)
- {
- double answ = -999999;
- // cerco VC...
- if (TSVC_Data.ContainsKey(VCName))
- {
- try
- {
- switch (TSVC_Data[VCName].Funzione)
- {
- case VC_func.POINT:
- // prendo PRIMO
- answ = TSVC_Data[VCName].dataArray.FirstOrDefault();
- break;
-
- case VC_func.AVG:
- answ = TSVC_Data[VCName].dataArray.Average();
- break;
-
- case VC_func.MEDIAN:
- answ = TSVC_Data[VCName].dataArray.Median();
- break;
-
- case VC_func.MIN:
- answ = TSVC_Data[VCName].dataArray.Min();
- break;
-
- case VC_func.MAX:
- default:
- answ = TSVC_Data[VCName].dataArray.Max();
- break;
- }
- }
- catch
- { }
- // ora resetto... SE richiesto...
- if (doReset)
- {
- TSVC_Data[VCName].dataArray = new List();
- TSVC_Data[VCName].DTStart = DateTime.Now;
- }
- }
- return answ;
- }
-
- ///
- /// Recupera la VC x TS, svuotando lista e resettando periodo partenza
- ///
- /// Nome della VC
- /// Reimposta e resetta array VC
- ///
- public int getVal_TSVC_int(string VCName, bool doReset)
- {
- int answ = 0;
- // cerco VC...
- if (TSVC_Data.ContainsKey(VCName))
- {
- // !!!FARE!!! vero calcolo... x ora FIX a MAX...
- foreach (var item in TSVC_Data[VCName].dataArray)
- {
- answ = (int)item > answ ? (int)item : answ;
- }
- // ora resetto... SE richiesto..
- if (doReset)
- {
- TSVC_Data[VCName].dataArray = new List();
- TSVC_Data[VCName].DTStart = DateTime.Now;
- }
- }
- return answ;
- }
-
- ///
- /// Restituisce un payload in formato json della lista di valori ricevuta
- ///
- /// Tipo di URL (eventi / FLog)
- /// elenco di valori da coda string salvata
- ///
- public string jsonPayload(urlType tipoUrl, List elencoValori)
- {
- string answ = "";
- if (elencoValori != null)
- {
- string[] valori;
- int counter = 0;
- DateTime dtEve = DateTime.Now;
- switch (tipoUrl)
- {
- case urlType.FLog:
- flogData currFlData = new flogData();
- flogJsonPayload fullFlObj = new flogJsonPayload();
- fullFlObj.fluxData = new List();
- // inizio processando ogni valore
- foreach (var item in elencoValori)
- {
- valori = qDecodeIN(item);
- CultureInfo provider = CultureInfo.InvariantCulture;
- DateTime.TryParseExact(valori[0], "yyyyMMddHHmmssfff", provider, DateTimeStyles.AssumeLocal, out dtEve);
- int.TryParse(valori[3], out counter);
- currFlData = new flogData()
- {
- flux = valori[1],
- valore = valori[2],
- dtEve = dtEve,
- dtCurr = DateTime.Now,
- cnt = counter
- };
- fullFlObj.fluxData.Add(currFlData);
- }
- // conversione finale
try
{
- answ = JsonConvert.SerializeObject(fullFlObj);
- }
- catch (Exception exc)
- {
- lgError($"FLog Errore in costruzione jsonPayload:{Environment.NewLine}{exc}");
- }
- break;
-
- case urlType.SignIN:
- evData currSigData = new evData();
- evJsonPayload fullEvObj = new evJsonPayload();
- fullEvObj.eventList = new List();
- // inizio processando ogni valore
- foreach (var item in elencoValori)
- {
- valori = qDecodeIN(item);
- CultureInfo provider = CultureInfo.InvariantCulture;
- DateTime.TryParseExact(valori[0], "yyyyMMddHHmmssfff", provider, DateTimeStyles.AssumeLocal, out dtEve);
- int.TryParse(valori[2], out counter);
- currSigData = new evData()
+ // chiamo URL, se restituisce "OK" è enabled!
+ string callResp = callUrl(urlIobEnabled, true);
+ answ = (callResp == "OK");
+ // attesa casuale se necessario
+ var rand = new Random();
+ // primi 2 test
+ int maxTry = 2;
+ while (maxTry > 0 && !answ)
{
- valore = valori[1],
- dtEve = dtEve,
- dtCurr = DateTime.Now,
- cnt = counter
- };
- fullEvObj.eventList.Add(currSigData);
- }
- // conversione finale
- try
- {
- answ = JsonConvert.SerializeObject(fullEvObj);
- }
- catch (Exception exc)
- {
- lgError($"SignIN Errore in costruzione jsonPayload:{Environment.NewLine}{exc}");
- }
- break;
-
- case urlType.RawTransf:
- BaseRawTransf currRTData = new BaseRawTransf();
-#if false
- rawTransfJsonPayload fullRTObj = new rawTransfJsonPayload();
- fullRTObj.rawTransfData = new List();
- // inizio processando ogni valore
- foreach (var item in elencoValori)
- {
- try
- {
- currRTData = JsonConvert.DeserializeObject(item);
+ Thread.Sleep(rand.Next(250, 500));
+ callResp = callUrl(urlIobEnabled, true);
+ answ = (callResp == "OK");
+ maxTry--;
}
- catch (Exception exc)
+ // se NON OK riprovo ANCORA 1 volta...
+ if (!answ)
{
- lgError($"Eccezione in deserializzazione BaseRawTransf:{Environment.NewLine}{exc}");
+ resetWebClients();
+ Thread.Sleep(rand.Next(250, 1000));
+ callResp = callUrl(urlIobEnabled, false);
+ answ = (callResp == "OK");
}
- fullRTObj.rawTransfData.Add(currRTData);
- }
- // conversione finale
- try
- {
- answ = JsonConvert.SerializeObject(fullRTObj);
- }
- catch (Exception exc)
- {
- lgError($"RawTransf Errore in costruzione jsonPayload:{Environment.NewLine}{exc}");
- }
-#endif
-
- // provo una serializzazione "brutale", ovvero aggiungo alla stringa il valore di testa...
- string rawResult = "";
- foreach (var item in elencoValori)
- {
- rawResult += $"{item},";
- }
- if (rawResult.Length > 0)
- {
- rawResult = rawResult.Substring(0, rawResult.Length - 1);
- }
- answ = "{" + $"\"rawTransfData\":[{rawResult}]" + "}";
-
- break;
-
- case urlType.ULog:
- int numVal = 0;
- int matrOp = 0;
- ulogData currUlData = new ulogData();
- ulogJsonPayload fullUlObj = new ulogJsonPayload();
- fullUlObj.fluxData = new List();
- // inizio processando ogni valore
- foreach (var item in elencoValori)
- {
- valori = qDecodeIN(item);
- CultureInfo provider = CultureInfo.InvariantCulture;
- DateTime.TryParseExact(valori[0], "yyyyMMddHHmmssfff", provider, DateTimeStyles.AssumeLocal, out dtEve);
- int.TryParse(valori[3], out matrOp);
- int.TryParse(valori[5], out numVal);
- int.TryParse(valori[6], out counter);
- currUlData = new ulogData()
+ // altri 2
+ maxTry = 2;
+ while (maxTry > 0 && !answ)
{
- flux = valori[1],
- valore = valori[2],
- dtEve = dtEve,
- dtCurr = DateTime.Now,
- cnt = counter,
- matrOpr = matrOp,
- label = valori[4],
- valNum = numVal
- };
- fullUlObj.fluxData.Add(currUlData);
- }
- // conversione finale
- try
- {
- answ = JsonConvert.SerializeObject(fullUlObj);
- }
- catch (Exception exc)
- {
- lgError($"ULog Errore in costruzione jsonPayload:{Environment.NewLine}{exc}");
- }
- break;
-
- default:
- break;
- }
- }
- return answ;
- }
-
- ///
- /// Effettua un trim della stringa al numero max di linee da mostrare a video
- ///
- ///
- ///
- public string limitLine2show(string newString)
- {
- // se num righe superiore a limite trimmo...
- if (newString.Split('\n').Length > parentForm.nLine2show)
- {
- //int idx = newString.LastIndexOf('\r');
- int idx = newString.LastIndexOf(Environment.NewLine);
- newString = newString.Substring(0, idx);
- }
- return newString;
- }
-
- ///
- /// riporta il log di tutti i dati di results temporali registrati
- ///
- public void logTimeResults()
- {
- if (TimingData.results.Count > 0)
- {
- lgInfo("{0}--------------- START TIMING DATA ---------------", Environment.NewLine);
- int globNumCall = 0;
- TimeSpan globAvgMsec = new TimeSpan(0);
- foreach (TimeRec item in TimingData.results)
- {
- // loggo SOLO se del mio IOB corrente...
- if (item.classCall == cIobConf.codIOB)
- {
- lgInfo("{4}|Chiamate {0}: effettuate {1}, tempo medio {2:N2} msec | impegno canale {3:P3}", item.codCall, item.numCall, item.avgMsec, item.totMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds, cIobConf.codIOB);
- globNumCall += item.numCall;
- globAvgMsec += item.totMsec;
- }
- }
- // riporto conteggio medio al secondo...
- lgInfo("{4}|Chiamate GLOBALI: {0}, periodo: {1:N2} minuti.cent, tempo medio {2:N2} msec | impegno canale {3:P3}", globNumCall, DateTime.Now.Subtract(dtAvvioAdp).TotalMinutes, globAvgMsec.TotalMilliseconds / globNumCall, globAvgMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds, cIobConf.codIOB);
- lgInfo("{0}--------------- STOP TIMING DATA ---------------{0}", Environment.NewLine);
- // mostro in form statistiche globali!
- parentForm.updateComStats(string.Format("Periodo: {0:N2}min | {1} x {2:N2}ms | canale {3:P3}", DateTime.Now.Subtract(dtAvvioAdp).TotalMinutes, globNumCall, globAvgMsec.TotalMilliseconds / globNumCall, globAvgMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds));
- }
- }
-
- ///
- /// Processa un monitoredItem, e ritorna boolean SE richiede invio (cambio o scadenza)
- ///
- ///
- ///
- ///
- public bool monItem2Send(string newVal, DynDataItem item)
- {
- bool answ = false;
- if (item != null)
- {
- // controllo in base al tipo di function...
- switch (item.func)
- {
- case "SAMPLE":
- // controllo se scaduto sample period...
- if (item.DTScad < DateTime.Now)
- {
- answ = true;
- }
- break;
-
- case "CHANGE":
- default:
- // controllo se scaduto o se variato...
- if (newVal != item.actVal || item.DTScad < DateTime.Now)
- {
- // aggiorno scadenza e che vada inviato
- answ = true;
- }
- break;
- }
- }
- return answ;
- }
-
- ///
- /// Verifica e processing x gestione ODL automatica
- ///
- public void processAutoOdl()
- {
- bool fatto = false;
- if (!string.IsNullOrEmpty(getOptPar("AUTO_CHANGE_ODL")))
- {
- lgTrace("Richiesta processAutoOdl");
- string IOB_MULTI_CNAME = "";
- string[] elencoMulti = null;
- string fullUrl = "";
- if (isMulti)
- {
- // devo chiamare cambio ODL x OGNI tavola: mi servono i parametri opzionali...
- IOB_MULTI_CNAME = getOptPar("IOB_MULTI_CNAME");
- elencoMulti = IOB_MULTI_CNAME.Split(',');
- }
- // controllo SIA abilitato...
- bool doProc = false;
- DateTime adesso = DateTime.Now;
- bool.TryParse(getOptPar("AUTO_CHANGE_ODL"), out doProc);
- if (doProc)
- {
- lgTrace("AUTO_CHANGE_ODL abilitato");
- bool callChangeODL = false;
- // modalità change ODL
- string CHANGE_ODL_MODE = "TIME";
- if (!string.IsNullOrEmpty(getOptPar("CHANGE_ODL_MODE")))
- {
- CHANGE_ODL_MODE = getOptPar("CHANGE_ODL_MODE");
- }
- if (CHANGE_ODL_MODE == "PZCOUNT_RESET")
- {
- /* verifico se sia "armato" il reset cambio ODL, DEVO essere :
- * - NON in produzione
- * - contapezzi ACT < contapezzi LAST
- * */
- lgTrace("processAutoOdl: caso PZCOUNT_RESET");
- if ((!isRunning || forceResetInRun) && pzCountResetted)
- {
- callChangeODL = true;
- lgInfo("Attivato cambio ODL da PZCOUNT_RESET");
- }
- else
- {
- lgInfo($"isRunning: {isRunning} | pzCountResetted: {pzCountResetted} | forceResetInRun: {forceResetInRun} | contapezziIOB: {contapezziIOB} | contapezziPLC: {contapezziPLC}");
- }
- }
- else if (CHANGE_ODL_MODE == "TIME")
- {
- // carico i parametri di configurazione x reset ODL...
- string CHANGE_ODL_HOURS = getOptPar("CHANGE_ODL_HOURS");
- string CHANGE_ODL_IDLE_MIN = getOptPar("CHANGE_ODL_IDLE_MIN");
- if (!string.IsNullOrEmpty(CHANGE_ODL_HOURS) && !string.IsNullOrEmpty(CHANGE_ODL_IDLE_MIN))
- {
- int minOdlDurHours = -1;
- int minPlcIdelMin = -1;
- int.TryParse(CHANGE_ODL_HOURS, out minOdlDurHours);
- int.TryParse(CHANGE_ODL_IDLE_MIN, out minPlcIdelMin);
- // controllo parametri validi
- if (minOdlDurHours > 0 && minPlcIdelMin >= 0)
- {
- // leggo da server inizio ODL... se non multi 1 solo...
- DateTime inizioOdl = DateTime.Now;
- string rawDataInizio = "";
- if (!isMulti)
- {
- rawDataInizio = callUrl(urlInizioOdlIob, false);
- DateTime.TryParse(rawDataInizio, out inizioOdl);
- }
- else
- {
- DateTime tmpData = DateTime.Now;
- // prendo il + vecchio...
- foreach (var item in elencoMulti)
- {
- fullUrl = $"{urlInizioOdlIob}|{item}";
- rawDataInizio = callUrl(fullUrl, false);
- DateTime.TryParse(rawDataInizio, out tmpData);
- inizioOdl = (tmpData < inizioOdl) ? tmpData : inizioOdl;
- }
- }
- // verifico se sia scaduto...
- if (inizioOdl.AddHours(minOdlDurHours) < adesso)
- {
- string rawIdle = "";
- int idlePeriod = 0;
- if (!isMulti)
- {
- // controllo SE sono fermo (spento o in manuale) per il periodo minimo richiesto...
- rawIdle = callUrl(urlIdleTime, false);
- int.TryParse(rawIdle, out idlePeriod);
- }
- else
- {
- int tmpIdle = 0;
- // prendo il + grande...
- foreach (var item in elencoMulti)
- {
- fullUrl = $"{urlIdleTime}|{item}";
- rawIdle = callUrl(fullUrl, false);
- int.TryParse(rawIdle, out tmpIdle);
- idlePeriod = tmpIdle > idlePeriod ? tmpIdle : idlePeriod;
- }
- }
- if (idlePeriod >= minPlcIdelMin)
- {
- callChangeODL = true;
- }
- }
+ Thread.Sleep(rand.Next(250, 500));
+ callResp = callUrl(urlIobEnabled, false);
+ answ = (callResp == "OK");
+ maxTry--;
}
- }
- }
-
- // vero processing...
- if (callChangeODL)
- {
- lgTrace("Chiamata: processAutoOdl --> forceSplitODL");
- fatto = forceSplitOdl();
- pzCountResetted = false;
- lgInfo("Esecuzione processAutoOdl completata --> pzCountResetted = false");
- }
- }
- else
- {
- lgTrace("AUTO_CHANGE_ODL DISABILITATO");
- }
- }
- // loggo se fatto
- if (fatto)
- {
- lgTrace("Effettuato processAutoOdl");
- }
- }
-
- ///
- /// Effettua processing degli allarmi CNC SE disponibili
- ///
- public void processCncAlarms()
- {
- if (utils.CRB("enableAlarms"))
- {
- Dictionary currAlarms = new Dictionary();
- if (connectionOk)
- {
- currAlarms = getCncAlarms();
- }
- else
- {
- lgError("Errore connessione mancante x getCncAlarms");
- }
- // verifico SE sia cambiato il programma...
- if (currAlarms.Count > 0)
- {
- try
- {
- string sVal = "";
- if (lastAlarm != currAlarms["CNC_ALARM"])
- {
- // salvo!
- lastAlarm = currAlarms["CNC_ALARM"];
- // per ogni valore del dizionario mostro ed accodo!
- foreach (var item in currAlarms)
+ // salvo status...
+ IobOnline = answ;
+ // se online imposto veto check a 5 x tempo reinvio...
+ if (answ)
{
- sVal = string.Format("[CNC_ALARM]{0}|{1}", item.Key, item.Value);
- // chiamo accodamento...
- accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
- }
- }
- // accodo ALTRI allarmi NON CNC...
- foreach (var item in currAlarms.Where(X => X.Key != "CNC_ALARM"))
- {
- sVal = $"{item.Key} | {item.Value}";
- accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
- }
- }
- catch (Exception exc)
- {
- lgError("Eccezione in processCncAlarms{0}{1}", Environment.NewLine, exc);
- }
- }
- }
- }
-
- ///
- /// Effettua processing contapezzi (ed eventualmente alza il bit di contapezzo...)
- ///
- public virtual void processContapezzi()
- { }
-
- ///
- /// Task periodici SE disconnesso
- ///
- public virtual void processDisconnectedTask()
- {
- }
-
- ///
- /// Effettua processing del recupero dei valori dinamici:
- /// es: speed (RPM, feedrate) degli assi, valori pressioni, temeprature
- ///
- public void processDynData()
- {
- bool enableByApp = utils.CRB("enableDynData");
- bool enableByIob = (getOptPar("ENABLE_DYN_DATA") == "TRUE");
- bool forceSendByIob = (getOptPar("FORCE_DYN_DATA") == "TRUE");
- Dictionary currDynData = new Dictionary();
-
- if (enableByApp || enableByIob)
- {
- lgInfo("Inizio processDynData");
- if (connectionOk)
- {
- currDynData = getDynData();
- try
- {
- string sVal = "";
- // se richiesto send diretto...
- if (forceSendByIob)
- {
- // per ogni valore del dizionario mostro ed accodo!
- foreach (var item in currDynData)
- {
- sVal = string.Format("[DYNDATA]{0}|{1}", item.Key, item.Value);
- // chiamo accodamento...
- accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
- }
- }
- // altrimenti verifico SE sia cambiato il valore dei DynData...
- else if (lastDynDataCtrlVal != currDynData["DYNDATA"])
- {
- // salvo!
- lastDynDataCtrlVal = currDynData["DYNDATA"];
- // per ogni valore del dizionario mostro ed accodo!
- foreach (var item in currDynData)
- {
- sVal = string.Format("[DYNDATA]{0}|{1}", item.Key, item.Value);
- // chiamo accodamento...
- accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
- }
- }
- // salvo array...
- lastDynData = currDynData;
- }
- catch (Exception exc)
- {
- lgError(exc, "Eccezione in processDynData");
- }
- }
- else
- {
- lgError("Errore connessione mancante x getDynData");
- }
- }
- }
-
- ///
- /// Processa gestione memoria x invio dati QUANDO IOB è disconnesso da CNC...
- ///
- public void processMemoryDiscon()
- {
- // init obj display
- newDisplayData currDispData = new newDisplayData();
- // controllo contatore invio "keepalive"... invio solo a scadenza
- if (DateTime.Now.Subtract(lastDisconnCheck).TotalSeconds > utils.CRI("disconMaxSec"))
- {
- // resetto tutti i vlaori BYTE IN/PREV/OUT... così invio macchina spenta...
- B_input = 0;
- B_output = 0;
- B_previous = 0;
- accodaSigIN(ref currDispData);
- // update controllo
- lastDisconnCheck = DateTime.Now;
- }
- raiseRefresh(currDispData);
- }
-
- ///
- /// Effettua processing mode/status (EDIT/MDI/...)
- ///
- public virtual void processMode()
- { }
-
- ///
- /// Effettua processing ALTRI contatori/parametri (ed invia ad IO)
- ///
- public virtual void processOtherCounters()
- { }
-
- ///
- /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid)
- ///
- public virtual void processOverride()
- {
- bool enableByApp = utils.CRB("enableOverrides");
- bool enableByIob = (getOptPar("ENABLE_OVERRIDES") == "TRUE");
- Dictionary currOverride = new Dictionary();
- if (enableByApp || enableByIob)
- {
- lgInfo("Inizio processOverride");
- if (connectionOk)
- {
- currOverride = getOverrides();
- }
- else
- {
- lgError("Errore connessione mancante x getOverrides");
- }
-
- // SE sono connesso...
- if (connectionOk)
- {
- // se HO dei valori override...
- if (currOverride.Count > 0)
- {
- // verifico SE sia cambiato il programma...
- if (lastOverrideFS != currOverride["FEED_OVER"] || lastOverrideRapid != currOverride["RAPID_OVER"])
- {
- // salvo!
- lastOverrideFS = currOverride["FEED_OVER"];
- lastOverrideRapid = currOverride["RAPID_OVER"];
- // per ogni valore del dizionario mostro ed accodo!
- string sVal = "";
- foreach (var item in currOverride)
- {
- sVal = string.Format("[OVERRIDES]{0}|{1}", item.Key, item.Value);
- // chiamo accodamento...
- accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
- }
- }
- }
- }
- }
- }
-
- ///
- /// Effettua ciclo controllo richieste server
- ///
- public void processServerRequests()
- {
- Dictionary task2exe = new Dictionary();
- Dictionary taskDone = new Dictionary();
- // recupero elenco delle cose da fare
- string resp = getTask2exe();
- if (!string.IsNullOrEmpty(resp))
- {
- try
- {
- task2exe = JsonConvert.DeserializeObject>(resp);
- // se ho da fare chiamo esecuzione..
- if (task2exe.Count > 0)
- {
- taskDone = processTask(task2exe);
- }
- }
- catch (Exception exc)
- {
- lgError($"Eccezione in processServerRequests:{Environment.NewLine}{exc}");
- }
- }
- }
-
- public Dictionary processTask(Dictionary task2exe)
- {
- Dictionary taskDone = new Dictionary();
- if (task2exe != null)
- {
- lgInfo($"Task2Exe S01: {task2exe.Count} task ricevuti:");
- int idTask = 0;
- foreach (var item in task2exe)
- {
- idTask++;
- lgInfo($"[{idTask:00}] - {item.Key} --> {item.Value}");
- }
- // chiamo procedura esecutiva (diversa x ogni IOB)
- taskDone = executeTasks(task2exe);
- lgInfo($"Task2Exe S02: eseguiti {taskDone.Count} task");
- // loggo tutti i task done...
- foreach (var item in taskDone)
- {
- sendToTaskWatch(item.Key, item.Value);
- }
- // ora chiamo la cancellazione dei task eseguiti...
- foreach (var item in taskDone)
- {
- remTask2exe(item.Key, item.Value);
- }
- }
- return taskDone;
- }
-
- ///
- /// Classe fittizia in caso di processing task in VHF
- ///
- public virtual void processVHF()
- {
- }
-
- ///
- /// Classe fittizia in caso di processing watchdog data
- ///
- public virtual void processWhatchDog()
- {
- }
-
- ///
- /// Effettua rilettura del contapezzi dal server MP/IO
- ///
- /// Forza rilettura da DB tempi ciclo rilevati
- public void pzCntReload(bool forceCountRec)
- {
- // legge da IO server ULTIMO valore CONTPEZZI al riavvio...
- string currServerCount = "";
- string lastIdxODL = "";
- if (checkServerAlive)
- {
- // leggo PRIMA ODL ....
- lastIdxODL = utils.callUrl(urlGetCurrODL);
- lgTrace("Lettura ODL dall'url {0} --> {1}", urlGetCurrODL, lastIdxODL);
- // se ho valori in coda da trasmettere uso dati REDIS
- if (forceCountRec)
- {
- // uso dati da TCiclo registrati...
- currServerCount = utils.callUrl(urlGetPzCountRec);
- lgInfo("Lettura contapezzi da TCiclo dall'url {0} --> num pz: {1}", urlGetPzCountRec, currServerCount);
- }
- else
- {
- // uso il contapezzi dichiarato dall'IOB stesso
- currServerCount = utils.callUrl(urlGetPzCount);
- lgInfo("Lettura contapezzi dall'url {0}", urlGetPzCount);
- }
- // controllo: SE NON HO ODL...
- if (string.IsNullOrEmpty(lastIdxODL) || lastIdxODL == "0")
- {
- // NON AGGIORNO
- contapezziIOB = contapezziPLC;
- lgError($"Errore lettura ODL (vuoto) resta tutto invariato contapezzi: {contapezziIOB} | contapezziPLC {contapezziPLC}");
- }
- else
- {
- if (!string.IsNullOrEmpty(currServerCount))
- {
- // se "-1" resto a ultimo...
- if (currServerCount != "-1")
- {
- int newVal = -1;
- Int32.TryParse(currServerCount, out newVal);
- contapezziIOB = newVal > -1 ? newVal : contapezziIOB;
- lgInfo("Ricevuta conferma da server di {0} pezzi registrati per ODL", currServerCount);
- }
- else
- {
- // NON AGGIORNO
- contapezziIOB = contapezziPLC;
- lgError($"Errore lettura contapezzi (-1) - uso contapezziPLC --> {contapezziPLC}");
- }
- }
- else
- {
- // registro che ho UN NUOVO ODL
- lgInfo($"Lettura ODL in pzCntReload, currIdxODL {currIdxODL} --> lastIdxODL {lastIdxODL}");
- // se ODL differente e NUOVO è zero --> resetto!
- if (currIdxODL.ToString() != lastIdxODL && lastIdxODL == "0")
- {
- // cambiato ODL quindi reset...
- contapezziIOB = 0;
- lgInfo("Nuovo ODL==0, RESET contapezzi (-->ZERO)");
- }
- // provo a salvare nuovo ODL
- int.TryParse(lastIdxODL, out currIdxODL);
- }
- }
- }
- else
- {
- // se server NON pronto...
- contapezziIOB = contapezziPLC;
- lgError("Errore server NON pronto in pzCntReload");
- }
- }
-
- ///
- /// Fornisce il valore di flusso e valore in formato valido x messa in coda nel formato
- /// dtEve#flusso#valore#cont
- /// Flusso dati
- /// Valore da salvare
- ///
- public string qEncodeFLog(string flusso, string valore)
- {
- string answ = "";
- try
- {
- answ = $"{DateTime.Now:yyyyMMddHHmmssfff}#{flusso}#{valore}#{counterULog}";
- }
- catch
- { }
- return answ;
- }
-
- ///
- /// Fornisce il valore di flusso e valore in formato valido x messa in coda nel formato dtEve#flux#value#cont
- /// DataOra evento registrato
- /// Flusso dati
- /// Valore da salvare
- ///
- public string qEncodeFLog(DateTime eventDT, string flusso, string valore)
- {
- string answ = "";
- try
- {
- answ = $"{eventDT:yyyyMMddHHmmssfff}#{flusso}#{valore}#{counterFLog}";
- }
- catch
- { }
- return answ;
- }
-
- ///
- /// Fornisce il valore di UserLog e valore in formato valido x messa in coda nel formato:
- /// dtEve#flusso#value#cont#matrOpr#label#valNum
- /// Flusso dati (RC/RS/DI)
- /// Valore da inviare (valString
- /// Matricola operatore
- /// Valore etichetta: causale scarto / tagCode
- /// Valore numerico: esitoOk (0/1) / nuo scarti
- ///
- public string qEncodeULog(string flusso, string valore, int matrOpr, string label, int valNum)
- {
- string answ = "";
- try
- {
- answ = $"{DateTime.Now:yyyyMMddHHmmssfff}#{flusso}#{valore}#{matrOpr}#{label}#{valNum}#{counterULog}";
- }
- catch
- { }
- return answ;
- }
-
- ///
- /// Effettua lettura dati
- /// Parametri da aggiornare x display in form
- ///
- public virtual void readAllData(ref newDisplayData currDispData)
- {
- if (currDispData == null)
- {
- currDispData = new newDisplayData();
- }
- try
- {
- if (DemoIn)
- {
- // segnalo che sono in Demo
- currDispData.semIn = Semaforo.SV;
- }
- if (connectionOk)
- {
- readSemafori(ref currDispData);
- }
- else
- {
- lgError("Errore connessione mancante x readSemafori");
- }
-
- nReadIN++;
- // aggiorno valore mostrato...
- displayRawData(ref currDispData);
- }
- catch
- {
- currDispData.semIn = Semaforo.SR;
- }
- raiseRefresh(currDispData);
- }
-
- ///
- /// Effettua lettura semafori principale
- /// Parametri da aggiornare x display in form
- ///
- public virtual void readSemafori(ref newDisplayData currDispData)
- {
- lastReadPLC = DateTime.Now;
- }
-
- ///
- /// Aggiunge ai dati da inviare alla parentform i valori di RawInput rilevati (32bit)
- /// 2021.08.27: filtrati secondo i valori setup start/size RawDataInput
- ///
- public virtual void reportRawInput(ref newDisplayData currDispData)
- {
- // processo eventualmente aggiungendo ad elementi esistenti...
- if (currDispData == null)
- {
- currDispData = new newDisplayData();
- }
- try
- {
- StringBuilder sb = new StringBuilder();
- sb.Append($"B_input --> {(short)B_input}{Environment.NewLine}");
- sb.Append($"{baseUtils.binaryForm(B_input)}{Environment.NewLine}");
- sb.Append($"{Environment.NewLine}");
- sb.Append($"----------- RAW Data Memory -----------{Environment.NewLine}");
- // Do x scontato siano VALIDI i valori di RawDataInputStart / size --> filtro...
- var filtRawData = new byte[RawDataInputSize];
- Array.Copy(RawInput, RawDataInputStart, filtRawData, 0, RawDataInputSize);
- int i = RawDataInputStart;
- foreach (var item in filtRawData)
- {
- sb.Append($"B{i:00} --> {baseUtils.binaryForm(item)} = {(short)item}{Environment.NewLine}");
- i++;
- }
- sb.Append("-------------------------------");
- currDispData.currBitmap = sb.ToString();
- }
- catch
- { }
- }
-
- ///
- /// Metodo generico di reset contapezzi...
- ///
- ///
- public virtual bool resetcontapezziPLC()
- {
- return false;
- }
-
- ///
- /// metodo dummy x salvataggio aree memoria conf x CN
- ///
- /// tipo di DUMP
- public virtual void saveMemDump(dumpType tipo)
- {
- }
-
- ///
- /// Salva valori indicati in prod data
- ///
- /// Item KVP di cui salvare i dati in currProdData come chiave/valore
- ///
- public void saveProdData(KeyValuePair item)
- {
- // imposto i valori...
- if (currProdData.ContainsKey(item.Key))
- {
- currProdData[item.Key] = item.Value;
- }
- else
- {
- currProdData.Add(item.Key, item.Value);
- }
- }
-
- ///
- /// Effettua salvataggio in LUT del valore ricevuto
- ///
- ///
- ///
- ///
- ///
- public virtual void saveValue(ref Dictionary outVal, double valore, string chiave)
- {
- //check obj preliminare
- if (outVal == null)
- {
- outVal = new Dictionary();
- }
- bool scaduto = stackVal_TSVC(chiave, valore);
- // recupero VC
- valore = getVal_TSVC(chiave, scaduto);
- if (scaduto)
- {
- // limite a 3 digit x valore float
- outVal.Add(chiave, $"{valore:N3}");
- }
- LastTSVC[chiave] = valore;
- }
-
- ///
- /// Invio la variazione dello stato allarmi (se avvenuta)
- ///
- /// COD memoria allarmi
- /// Indice memoria allarmi
- /// ultimo stato rilevato
- /// stato corrente
- /// Lista allarmi validi per l'area
- ///
- public bool sendAlarmVariations(string memAddr, int index, uint lastStatus, uint currStatus, List AlarmList)
- {
- bool fatto = false;
- if (lastStatus != currStatus)
- {
- List ActiveAlarmList = new List();
- // invio GET del MemoryAddress, del banco e del valore currStatus
- lastUrl = $"{urlSendAlarm}?memAddr={memAddr}&index={index}&currStatus={currStatus}";
- if (currStatus == 0)
- {
- ActiveAlarmList.Add("ALL OK");
- }
- else
- {
- // calcolo quali allarmi mostrare dato currStatus ed elenco allarmi
- string bitMap = Convert.ToString(currStatus, 2);
- int bitLen = bitMap.Length;
- // ciclo x associare tutti gli allarmi
- for (int i = 0; i < bitLen; i++)
- {
- // se è 1 --> aggiungo!
- if (bitMap[bitLen - i - 1] == '1')
- {
- // se sono entro limiti
- if (AlarmList.Count >= i)
- {
- ActiveAlarmList.Add($"{i:000}-{AlarmList.ElementAt(i)}");
- }
- //else
- //{
- // ActiveAlarmList.Add($"Unknown Bit.{i}");
- //}
- }
- }
- }
-
- string rawData = JsonConvert.SerializeObject(ActiveAlarmList);
-
- //string resp = utils.callUrlNow(lastUrl, rawData);
- string resp = utils.callUrlAsync(lastUrl, rawData);
- if (!string.IsNullOrEmpty(resp))
- {
- if (resp.ToUpper() == "OK")
- {
- // segnalo fatto
- fatto = true;
- }
- }
- else
- {
- lgError($"Errore in invio richiesta registrazione allarme: URL: {lastUrl}{Environment.NewLine}Payload:{Environment.NewLine}{rawData}");
- }
- }
- return fatto;
- }
-
- ///
- /// Invia una LISTA di valori
- ///
- ///
- ///
- public void sendDataBlock(urlType tipoUrl, List listQueueVal)
- {
- // init obj display
- newDisplayData currDispData = new newDisplayData();
- if (listQueueVal != null)
- {
- try
- {
- // recupero e formatto URL dati da coda...
- lastUrl = urlDataBlock(tipoUrl);
- // in base al tipo di dato compongo il payload Json da inviare
- string payload = jsonPayload(tipoUrl, listQueueVal);
- // async a true SE FLog
- bool doAsync = tipoUrl == urlType.FLog ? true : false;
- // se NON sono in demo effettuo invio!
- if (!DemoOut)
- {
- // SE server alive...
- if (checkServerAlive)
- {
- // chiamo URL!
- string answ = callUrlWithPayload(lastUrl, payload, doAsync);
- // attesa opzionale se configurata
-
- // loggo!
- lgInfo($"[SEND payload] TipoURL: {tipoUrl} | {listQueueVal.Count} records --> {answ}");
- // se "OK" verde, altrimenti errore --> ROSSO
- if (answ.Contains("OK"))
- {
- currDispData.semOut = Semaforo.SV;
- // se oltre 1 min NON era online --> check pezzi!
- if (DateTime.Now.Subtract(lastIobOnline).TotalMinutes > 1 && !isMulti)
- {
- lgInfo($"sendDataBlock --> offline timeout ({lastIobOnline}) --> pzCntReload(true)");
- pzCntReload(true);
- }
lastIobOnline = DateTime.Now;
}
+ dtVetoCheckIOB = DateTime.Now.AddMilliseconds(baseUtils.nextPauseSendMSec * 5);
+ }
+ catch
+ { }
+ }
+ // verifico SE è variato stato online/offline...
+ if (IobOnline != answ)
+ {
+ // se ORA sono online riporto...
+ if (answ)
+ {
+ lgInfo("IOB ONLINE for server MP/IO");
+ }
+ else
+ {
+ lgInfo("IOB OFFLINE for server MP/IO");
+ }
+ }
+ // fix colore
+ if (answ)
+ {
+ parentForm.commSrvActive = 2;
+ }
+ else
+ {
+ parentForm.commSrvActive = 1;
+ }
+ }
+ else
+ {
+ // altrimenti passo ultimo valore noto
+ answ = IobOnline;
+ }
+ return answ;
+ }
+ }
+
+ ///
+ /// test ping all'indirizzo impostato nei parametri
+ ///
+ ///
+ private IPStatus testPingServer
+ {
+ get
+ {
+ IPStatus answ = IPStatus.Unknown;
+ // se disabilitato salto...
+ if (pingDisabled)
+ {
+ answ = IPStatus.Success;
+ }
+ else
+ {
+ IPAddress address;
+ PingReply reply;
+ var rand = new Random();
+ int pingTOut = 500;
+ using (Ping pingSender = new Ping())
+ {
+ address = IPAddress.Loopback;
+ int maxRetry = maxPingRetry + 1;
+ int numRetry = 1;
+ string ipAddr = cIobConf.serverData.MPIP.Replace($"{cIobConf.serverData.TRANSP}://", "");
+ // fix se fosse ip + porta...
+ if (ipAddr.IndexOf(":") >= 0)
+ {
+ ipAddr = ipAddr.Substring(0, ipAddr.IndexOf(":"));
+ }
+ IPAddress.TryParse(ipAddr, out address);
+ // se null --> provo DNS...
+ if (address == null)
+ {
+ var rawAddresses = Dns.GetHostAddresses(ipAddr);
+ if (rawAddresses.Length > 0)
+ {
+ address = rawAddresses[0];
+ }
+ }
+ try
+ {
+ // se != null --> uso address...
+ if (address != null)
+ {
+ pingTOut = rand.Next(200, 400);
+ reply = pingSender.Send(address, pingTOut);
+ }
else
{
- currDispData.semOut = Semaforo.SR;
+ pingTOut = rand.Next(300, 600);
+ reply = pingSender.Send(cIobConf.cncIpAddr, pingTOut);
}
}
- else
+ catch (Exception exc)
{
- lgInfo($"[SERVER KO] {listQueueVal.Count}");
+ pingTOut = rand.Next(100, 200);
+ reply = pingSender.Send(IPAddress.Loopback, pingTOut);
+ lgError($"ping to loopback addres per eccezione:{Environment.NewLine}{exc}");
+ }
+ // se ho timeout riprovo...
+ while (reply.Status != IPStatus.Success && numRetry < maxRetry)
+ {
+ Thread.Sleep(rand.Next(50, 200));
+ pingTOut = pingServerMsTimeout * numRetry / 2;
+ reply = pingSender.Send(address, pingTOut);
+ numRetry++;
+ if (reply.Status == IPStatus.Success)
+ {
+ lgInfo("Server PING OK!");
+ break;
+ }
+ else
+ {
+ lgInfo($"Server Ping KO | reply: {reply.Status} --> retry | TimeOut: {pingTOut}");
+ }
}
}
- else
- {
- currDispData.semOut = Semaforo.SV;
- // loggo!
- lgInfo($"{listQueueVal.Count} records --> [SIM]");
- }
- nSendOut += listQueueVal.Count;
- // riporto cosa inviato
- currDispData.newUrlCallData = lastUrl;
- // aggiorno data ultimo watchdog...
- lastWatchDog = DateTime.Now;
- }
- catch
- {
- currDispData.semOut = Semaforo.SR;
+ answ = reply.Status;
}
+ return answ;
}
- raiseRefresh(currDispData);
+ }
+
+ #endregion Private Properties
+
+ #region Private Methods
+
+ ///
+ /// Verifica e se necessario comprime directory log...
+ ///
+ private void checkShrinkDir()
+ {
+ string path = string.Format("{0}logs\\{1}", AppDomain.CurrentDomain.BaseDirectory, cIobConf.codIOB);
+ baseUtils.shrinkDir(path);
}
///
- /// Effettua invio a MoonPro del valore richiesto
+ /// Mostra i dati grezzi letti in esadecimale Parametri da
+ /// aggiornare x display in form
///
- ///
- /// Valore da trasmettere: es
- /// INPUT: lo status rilevato in HEX
- /// FLog: il valore da trasmettere per il flusso indicato
- public void sendToMoonPro(urlType tipoUrl, string queueVal)
+ private void displayRawData(ref newDisplayData currDispData)
{
- // init obj display
- newDisplayData currDispData = new newDisplayData();
+ // mostro update...
+ string newString = string.Format("{0:X}", B_input);
+ currDispData.newInData = newString;
+ }
+
+ ///
+ /// Esegue filtraggio dati x bit blinking!!!
+ ///
+ private void filterData()
+ {
+ // effettuo filtraggio dei valori letti... inizializzo OUT!
+ B_output = 0;
+ // in primis verifico SE ci siano bit blinkng... se non ci sono OUT=IN...
+ if (cIobConf.BLINK_FILT == 0)
+ {
+ B_output = B_input;
+ }
+ else
+ {
+ // incomincio con i valori NON blinking: questi "passano invariati", inizio a
+ // sommare nel valore OUT...
+ B_output = B_input & ~cIobConf.BLINK_FILT;
+ // calcolo il valore dei BIT che "passano la maschera"
+ int iBlink = B_input & cIobConf.BLINK_FILT;
+ // ...aggiungo i "bit che passano"
+ B_output += iBlink;
+
+ // calcolo QUALI valori (tra quelli blink) siano PASSATI da 0 a 1 --> init counters...
+ BitArray bBlinkStart = new BitArray(new byte[] { Convert.ToByte(iBlink) });
+ int[] bitsUp = bBlinkStart.Cast().Select(bit => bit ? 1 : 0).ToArray();
+ for (int i = 0; i < bitsUp.Length; i++)
+ {
+ // SE 1... impostiamo contatori al MAX
+ if (bitsUp[i] == 1)
+ {
+ // se era zero indico START blink...
+ if (i_counters[i] == 0)
+ {
+ lgTrace("START BLINK: B{0}", i);
+ }
+ // imposto comunque contatore al cambio fronte...
+ i_counters[i] = cIobConf.MAX_COUNTER_BLINK;
+ }
+ }
+
+ // quelli che sono zero... LI RECUPERO E LI PROCESSO...
+ int iZero = ~B_input & cIobConf.BLINK_FILT;
+ BitArray bBlinkEnd = new BitArray(new byte[] { Convert.ToByte(iZero) });
+ int[] bitsDown = bBlinkEnd.Cast().Select(bit => bit ? 1 : 0).ToArray();
+ for (int i = 0; i < bitsDown.Length; i++)
+ {
+ // se era a zero (invertito...)
+ if (bitsDown[i] == 1)
+ {
+ // SE è in corso il conteggio...
+ if (i_counters[i] > 0)
+ {
+ // decremento!
+ i_counters[i] -= 1;
+ // se è zero NON faccio nulla, altrimenti SOMMO...
+ if (i_counters[i] > 0)
+ {
+ B_output += 1 << i;
+ }
+ else
+ {
+ lgTrace("END BLINK: B{0}", i);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Imposta eventuali altri valori default
+ ///
+ private void fixDefaultPar()
+ {
+ // parametro max tentativi PING...
+ string s_maxPingRetry = getOptPar("MAX_PING_RETRY");
+ if (!string.IsNullOrEmpty(s_maxPingRetry))
+ {
+ int numRetry = 5;
+ int.TryParse(s_maxPingRetry, out numRetry);
+ maxPingRetry = numRetry;
+ }
+
+ string s_maxErrCheck = getOptPar("MAX_ERR_CHECK");
+ if (!string.IsNullOrEmpty(s_maxErrCheck))
+ {
+ int numErr = 50;
+ int.TryParse(s_maxErrCheck, out numErr);
+ maxErroriCheck = numErr;
+ }
+
+ string s_watchDogPer = getOptPar("WATCHDOG_PERIOD");
+ if (!string.IsNullOrEmpty(s_watchDogPer))
+ {
+ int numPer = 3;
+ int.TryParse(s_watchDogPer, out numPer);
+ watchDogPeriod = numPer;
+ }
+ }
+
+ ///
+ /// Legge da conf il valore di demoltiplica lettura dynData (se presente) o ignora e pone a 1...
+ ///
+ private void fixDemFactDynData()
+ {
+ var rawDemFact = getOptPar("DEM_FACT_DYN_DATA");
+ if (string.IsNullOrEmpty(rawDemFact))
+ {
+ demFactDynData = 1;
+ }
+ else
+ {
+ int.TryParse(rawDemFact, out demFactDynData);
+ }
+ }
+
+ ///
+ /// recupera valore salvato in persistence layer (se non c'è crea...)
+ ///
+ ///
+ ///
+ private string getStoredVal(string keyVal)
+ {
+ string value = "";
try
{
- // recupero e formatto URL dati da coda...
- switch (tipoUrl)
+ if (persistenceLayer != null)
{
- case urlType.FLog:
- lastUrl = urlFLog(queueVal);
- break;
-
- case urlType.SignIN:
- lastUrl = urlInput(queueVal);
- break;
-
- default:
- lastUrl = "";
- break;
- }
- // se NON sono in demo effettuo invio!
- if (!DemoOut)
- {
- // SE server alive...
- if (checkServerAlive)
+ if (!persistenceLayer.TryGetValue(keyVal, out value))
{
- // chiamo URL!
- string answ = callUrl(lastUrl, false);
- // loggo!
- lgDebug(string.Format("[SEND] {0} -> {1}", queueVal, answ));
- // se oltre 1 min NON era online --> check pezzi!
- if (DateTime.Now.Subtract(lastIobOnline).TotalMinutes > 1 && !isMulti)
- {
- lgInfo($"sendToMoonPro --> offline timeout ({lastIobOnline}) --> pzCntReload(true)");
- pzCntReload(true);
- }
- // se richiesto effettuo refresh contapezzi
- if (needRefreshPzCount && !isMulti)
- {
- pzCntReload(true);
- needRefreshPzCount = false;
- }
- lastIobOnline = DateTime.Now;
- // se "OK" verde, altrimenti errore --> ROSSO
- if (answ == "OK")
- {
- currDispData.semOut = Semaforo.SV;
- }
- else
- {
- currDispData.semOut = Semaforo.SR;
- }
- }
- else
- {
- lgError(string.Format("[SERVER KO] {0}", queueVal));
+ persistenceLayer.Add(keyVal, "0");
}
}
- else
- {
- currDispData.semOut = Semaforo.SV;
- // loggo!
- lgDebug(string.Format("{0} -> [SIM]", queueVal));
- }
- nSendOut++;
- currDispData.newUrlCallData = lastUrl;
- // aggiorno data ultimo watchdog...
- lastWatchDog = DateTime.Now;
}
- catch
+ catch (Exception exc)
{
- currDispData.semOut = Semaforo.SR;
+ lgError(string.Format("Eccezione in getStoredVal: {0}{1}", Environment.NewLine, exc));
}
- raiseRefresh(currDispData);
+ return value;
}
///
- /// Metodo generico di IMPOSTAZIONE FORZATA del contapezzi...
+ /// recupera valore salvato in persistence layer (se non c'è crea...) come double
///
- /// Pezzi richiesti
+ ///
///
- public virtual bool setcontapezziPLC(int newPzCount)
+ private double getStoredValDouble(string keyVal)
{
- return false;
- }
-
- ///
- /// Processing di Variabili Campionarie x TimeSeries, accoda valori x la VC (se esiste) e restituisce bool val se SCADUTO periodo controllo
- ///
- /// Nome della VC
- /// Valore (nuovo) delal VC
- ///
- public bool stackVal_TSVC(string VCName, double VCVal)
- {
- bool answ = false;
- // cerco VC...
- if (TSVC_Data.ContainsKey(VCName))
+ double answ = 0;
+ try
{
- TSVC_Data[VCName].dataArray.Add(VCVal);
- // ora verifico scadenza...
- if (TSVC_Data[VCName].DTStart.AddSeconds(TSVC_Data[VCName].Period) < DateTime.Now)
- {
- answ = true;
- }
+ answ = Convert.ToDouble(getStoredVal(keyVal));
}
+ catch (Exception exc)
+ {
+ lgError(string.Format("Eccezione in getStoredValDouble: {0}{1}", Environment.NewLine, exc));
+ }
+ answ = (answ < (double.MaxValue / 10 * 9)) ? answ : 0;
return answ;
}
///
- /// Avvia l'adapter sulla porta richiesta
+ /// recupera valore salvato in persistence layer (se non c'è crea...) come INT
///
- /// indica se sia richeisto di SVUOTARE le code delel info
- public virtual void startAdapter(bool resetQueue)
+ ///
+ ///
+ private long getStoredValLong(string keyVal)
{
- DateTime adesso = DateTime.Now; ;
- DateTime scaduto = adesso.AddMinutes(-10);
- lgInfo("Starting adapter...");
- maxJsonData = utils.CRI("maxJsonData");
- maxJsonDataEv = utils.CRI("maxJsonDataEv");
- parentForm.commPlcActive = false;
- adpRunning = true;
- dtAvvioAdp = adesso;
- lastWatchDog = scaduto;
- lastPING = scaduto;
- lastReadPLC = scaduto;
- lastDisconnCheck = scaduto;
- TimingData.resetData();
- // aggiungo altri defaults
- setDefaults(resetQueue);
- adpTryRestart = true;
- lgDebug("startAdapter completed");
+ long answ = 0;
+ try
+ {
+ answ = Convert.ToInt64(getStoredVal(keyVal));
+ }
+ catch
+ { }
+ // verifico che il valore sia minore di 9/10 del valore massimo...
+ answ = (answ < (long.MaxValue / 10 * 9)) ? answ : 0;
+ return answ;
}
///
- /// ferma l'adapter...
+ /// recupera valore salvato in persistence layer (se non c'è crea...) come UINT
///
- /// indica se si debba tentare di riavviare l'adapter (con caduta connessione viene fermato in automatico)
- /// indica se sia richeisto di SVUOTARE le code delel info
- public virtual void stopAdapter(bool tryRestart, bool forceDequeue)
+ ///
+ ///
+ private uint getStoredValUInt(string keyVal)
{
- if (forceDequeue)
+ uint answ = 0;
+ try
{
- // svuoto le code dei valori letti e non ancora trasmessi...
- parentForm.displayTaskAndLog("[CLOSING] Svuotamento FORZATO coda segnali...");
- while (QueueIN.Count > 0)
+ answ = Convert.ToUInt32(getStoredVal(keyVal));
+ }
+ catch (Exception exc)
+ {
+ lgError(string.Format("Eccezione in getStoredValUInt: {0}{1}", Environment.NewLine, exc));
+ }
+ // verifico che il valore sia minore di 9/10 del valore massimo...
+ answ = (answ < (uint.MaxValue / 10 * 9)) ? answ : 0;
+ return answ;
+ }
+
+ ///
+ /// Classe fittizia in caso di processing GLOBALE di tutto in 1 solo colpo...
+ ///
+ private void processAllMemory()
+ {
+ // init obj display
+ newDisplayData currDispData = new newDisplayData();
+ // in primis SALVO valori previous/precedenti
+ B_previous = B_output;
+ // poi faccio lettura NUOVI valori
+ readAllData(ref currDispData);
+ // eseguo il filtering dei valori (per i bit "blinking")
+ filterData();
+ // effettuo confronto valori vecchi/nuovi... SE trovo variazione OPPURE se è passato +
+ // di un timeout di controllo...
+ if (B_output != B_previous)
+ {
+ accodaSigIN(ref currDispData);
+ }
+ raiseRefresh(currDispData);
+ }
+
+ private void processMem2Write()
+ {
+ List updatedPar = new List();
+ // ciclo tutti gli oggetti write x vedere se modificati...
+ foreach (var item in currProdData)
+ {
+ bool needWrite = false;
+ // li cerco su last... se non ci sono o modificati --> salvo da scrivere e copio
+ if (lastProdData.ContainsKey(item.Key))
{
- // INVIO COMUNQUE...!!!
- string valore = "";
- QueueIN.TryDequeue(out valore);
- sendToMoonPro(urlType.SignIN, valore);
- }
- parentForm.displayTaskAndLog("[CLOSING] Svuotamento FORZATO coda FluxLOG...");
- // se ho + di 2 elementi in coda --> uso invio JSON in blocco...
- if (QueueFLog.Count > minJsonData)
- {
- while (QueueFLog.Count > 0)
+ // verifico se variato...
+ if (!item.Value.Equals(lastProdData[item.Key]))
{
- List listaValori = new List();
- // se ho + di maxJsonData elementi --> invio un set di dati alla volta
- if (QueueFLog.Count > maxJsonData)
- {
- string currVal = "";
- // prendoi primi maxJsonDataValori
- for (int i = 0; i < maxJsonData; i++)
- {
- QueueFLog.TryDequeue(out currVal);
- listaValori.Add(currVal);
- }
- sendDataBlock(urlType.FLog, listaValori);
- }
- else
- {
- // invio in blocco
- listaValori = QueueFLog.ToList();
- // invio
- sendDataBlock(urlType.FLog, listaValori);
- // svuoto!
- QueueFLog = new ConcurrentQueue();
- }
+ needWrite = true;
+ lastProdData[item.Key] = item.Value;
}
- // HO FINITO invio di FLog...
}
+ // aggiungo
else
{
- string currVal = "";
- while (QueueFLog.Count > 0)
- {
- // INVIO COMUNQUE...!!!
- QueueFLog.TryDequeue(out currVal);
- sendToMoonPro(urlType.FLog, currVal);
- }
+ needWrite = true;
+ lastProdData.Add(item.Key, item.Value);
}
-
- // svuoto coda ULog
- while (QueueULog.Count > 0)
+ // se devo scrivere --> riporto
+ if (needWrite)
{
- List listaValori = new List();
- // se ho + di maxJsonData elementi --> invio un set di dati alla volta
- if (QueueULog.Count > maxJsonData)
+ if (memMap.mMapWrite.ContainsKey(item.Key))
{
- string currVal = "";
- // prendoi primi maxJsonDataValori
- for (int i = 0; i < maxJsonData; i++)
+ // preparo obj da scrivere
+ objItem newWrite = new objItem()
{
- QueueULog.TryDequeue(out currVal);
- listaValori.Add(currVal);
- }
- sendDataBlock(urlType.ULog, listaValori);
- }
- else
- {
- // invio in blocco
- listaValori = QueueULog.ToList();
- // invio
- sendDataBlock(urlType.ULog, listaValori);
- // svuoto!
- QueueULog = new ConcurrentQueue();
+ uid = item.Key,
+ name = item.Key,
+ reqValue = memMap.mMapWrite[item.Key].value,
+ lastRequest = DateTime.Now,
+ writable = true
+ };
+ updatedPar.Add(newWrite);
}
}
}
- parentForm.displayTaskAndLog("[STOP] Stopping adapter...");
- adpTryRestart = false;
-
- parentForm.displayTaskAndLog("[STOP] Stopping adapter - last periodic data read...");
-
- // chiudo la connessione all'adapter...
- tryDisconnect();
- dtStopAdp = DateTime.Now;
- adpTryRestart = tryRestart;
- adpRunning = false;
- // chiudo!
- parentForm.displayTaskAndLog("Adapter Stopped.");
- parentForm.commPlcActive = false;
+ // se ho da scrivere... scrivo TUTTI!
+ if (updatedPar.Count > 0)
+ {
+ // scrivo valore!
+ lgInfo("Chiamata di plcWriteParams da processMem2Write");
+ plcWriteParams(ref updatedPar);
+ // invio su cloud parametri!
+ string rawData = JsonConvert.SerializeObject(updatedPar);
+ utils.callUrl($"{urlUpdateWriteParams}", rawData);
+ lgInfo($"Notificato a server scrittura {updatedPar.Count} parametri");
+ }
}
///
- /// Processo la coda SignalIN...
+ /// Effettua gestioen programma: legge e mostra su display...
///
- public void svuotaCodaSignIN()
+ private void processProgram()
{
+ string currPrgName = "";
+ // se abilitata lettura prgName
+ if (enablePrgName)
+ {
+ if (connectionOk)
+ {
+ currPrgName = getPrgName();
+ }
+ else
+ {
+ lgError("Errore connessione mancante x getPrgName");
+ }
+ }
+ else
+ {
+ currPrgName = lastPrgName;
+ }
+ // verifico SE sia cambiato il programma...
+ if (lastPrgName != currPrgName)
+ {
+ // salvo!
+ lastPrgName = currPrgName;
+ string sVal = string.Format("[PROG]{0}", currPrgName);
+
+ // chiamo accodamento...
+ accodaFLog(sVal, qEncodeFLog("PROG", currPrgName));
+ }
+ }
+
+ ///
+ /// Processo lettura dati sysinfo
+ ///
+ private void processSysInfo()
+ {
+ if (utils.CRB("enableSysInfo"))
+ {
+ Dictionary currSysInfo = new Dictionary();
+
+ if (connectionOk)
+ {
+ currSysInfo = getSysInfo();
+ }
+ else
+ {
+ lgError("Errore connessione mancante x getSysInfo");
+ }
+ // verifico SE sia cambiato il programma...
+ if (lastSysInfo != currSysInfo["SYSINFO"])
+ {
+ // salvo!
+ lastSysInfo = currSysInfo["SYSINFO"];
+ // per ogni valore del dizionario mostro ed accodo!
+ string sVal = "";
+ foreach (var item in currSysInfo)
+ {
+ sVal = string.Format("[SYSINFO]{0}|{1}", item.Key, item.Value);
+ // chiamo accodamento...
+ accodaFLog(sVal, qEncodeFLog(item.Key, item.Value));
+ }
+ }
+ }
+ }
+
+ private void reportDataProc()
+ {
+ // update valori visualizzazione...
+ parentForm.dataProcLabel = string.Format("RAW: {0} --> IN: {1} --> OUT: {2}", nReadIN, nReadFilt, nSendOut);
+ }
+
+ ///
+ /// Imposto alcuni valori di default
+ ///
+ /// indica se sia richeisto di SVUOTARE le code delel info
+ private void setDefaults(bool resetQueue)
+ {
+ numSim = utils.CRI("numSim");
+ lastPrgName = "";
+ nReadIN = 0;
+ nReadFilt = 0;
+ nSendOut = 0;
+ currMode = 0;
+ lastAlarm = "";
+ doStartMemDump = utils.CRB("doStartMemDump");
+ doSampleMemory = utils.CRB("doSampleMemory");
+ // fix url wait random...
+ urlRandWait = utils.CRI("urlRandWait");
+ // fix fattore demoltiplica dynData
+ fixDemFactDynData();
+
+ // svuoto code se richiesto
+ if (resetQueue)
+ {
+ QueueAlarm = new ConcurrentQueue();
+ QueueIN = new ConcurrentQueue();
+ QueueFLog = new ConcurrentQueue();
+ QueueMessages = new ConcurrentQueue();
+ QueueRawTransf = new ConcurrentQueue();
+ QueueULog = new ConcurrentQueue();
+ }
+ // imposto contatori blink a zero...
+ i_counters = new int[32];
+ lastPeriodicLog = DateTime.Now;
+ // fix parametri generali...
+ enablePrgName = true;
+ }
+
+ private void svuotaCodaContapezzi()
+ {
+ // permetto al max 2 tentativi infruttuosi...
+ int maxTry = 2;
+ int oldContapezzi = contapezziIOB;
+ // se ho contapezzi OLTRE limite...
+ while ((MPOnline) && (contapezziPLC > contapezziIOB + minSendPzCountBlock))
+ {
+ lgInfo($"Ciclo svuotaCodaContapezzi --> contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}");
+ if (!isMulti)
+ {
+ pzCntReload(true);
+ }
+ // provo invio
+ trySendPzCountBlock();
+ // verifica per evitare loop infinito invio fallito
+ if (oldContapezzi == contapezziIOB)
+ {
+ maxTry--;
+ }
+ else
+ {
+ maxTry = 2;
+ oldContapezzi = contapezziIOB;
+ }
+ // verifico maxTry: se li ho esauriti esco!
+ if (maxTry <= 0)
+ {
+ return;
+ }
+ // aspetto x dare tempo calcolo
+ Thread.Sleep(400);
+ }
+ }
+
+ ///
+ /// Processo la coda FLog...
+ ///
+ private void svuotaCodaFLog()
+ {
+ // controllo se è passato oltre watchdog e non ho inviato nulla --> RE-INVIO (ultimo inviato)!!!!
+ if (DateTime.Now.Subtract(lastWatchDog).TotalSeconds > utils.CRI("watchdogMaxSec"))
+ {
+ string wdStatus = "elapsed";
+ string sVal = string.Format("[WDST]{0}", wdStatus);
+ // chiamo accodamento...
+ accodaFLog(sVal, qEncodeFLog("WDST", wdStatus));
+ lastWatchDog = DateTime.Now;
+ }
// verifico SE la coda abbia dei valori...
- if (QueueIN.Count > 0)
+ if (QueueFLog.Count > 0)
{
// invio pacchetto di dati (max da conf)
for (int i = 0; i < nMaxSend; i++)
{
- if (QueueIN.Count > 0)
+ // SE ho qualcosa in coda...
+ if (QueueFLog.Count > 0)
{
string currVal = "";
- // se online provo
if (MPOnline)
{
if (IobOnline)
{
// se ho + di 2 elementi in coda --> uso invio JSON in blocco...
- if (QueueIN.Count > 1)
+ if (QueueFLog.Count > 1)
{
List listaValori = new List();
// se ho + di maxJsonData elementi --> invio un set di dati alla volta
- if (QueueIN.Count > maxJsonDataEv)
+ if (QueueFLog.Count > maxJsonData)
{
// prendoi primi maxJsonDataValori
- for (int j = 0; j < maxJsonDataEv; j++)
+ for (int j = 0; j < maxJsonData; j++)
{
- QueueIN.TryDequeue(out currVal);
+ QueueFLog.TryDequeue(out currVal);
listaValori.Add(currVal);
}
- sendDataBlock(urlType.SignIN, listaValori);
+ sendDataBlock(urlType.FLog, listaValori);
+ lastWatchDog = DateTime.Now;
}
else
{
// invio in blocco
- listaValori = QueueIN.ToList();
+ listaValori = QueueFLog.ToList();
// invio
- sendDataBlock(urlType.SignIN, listaValori);
+ sendDataBlock(urlType.FLog, listaValori);
// svuoto!
- QueueIN = new ConcurrentQueue();
+ QueueFLog = new ConcurrentQueue();
+ lastWatchDog = DateTime.Now;
}
}
else
{
// INVIO SINGOLO...!!!
- QueueIN.TryDequeue(out currVal);
- sendToMoonPro(urlType.SignIN, currVal);
- }
- // salvo come last signal in il currVal ultimo... SE !=""
- if (!string.IsNullOrEmpty(currVal))
- {
- lastSignInVal = currVal;
+ QueueFLog.TryDequeue(out currVal);
+ sendToMoonPro(urlType.FLog, currVal);
+ lastWatchDog = DateTime.Now;
}
}
else
@@ -5594,197 +5527,302 @@ namespace IOB_WIN_NEXT
}
///
- /// Metodo base connessione...
+ /// Processo la coda RawTransf...
///
- public virtual void tryConnect()
+ private void svuotaCodaRawTransf()
{
- dtAvvioAdp = DateTime.Now;
- }
-
- ///
- /// Metodo base disconnessione...
- ///
- public virtual void tryDisconnect()
- {
- }
-
- ///
- /// Effettua verifica se abilitato invio pezzi in blocco e nel caso
- /// - invio in blocco pezzi
- /// - aggiornamento del contapezzi (passato come ref) x nuovo valore post invio
- ///
- public void trySendPzCountBlock()
- {
- // in primis HA SENSO procedere SOLO SE server MP è Online...
- if (MPOnline)
+ // verifico SE la coda abbia dei valori...
+ if (QueueRawTransf.Count > 0)
{
- // SOLO SE online la macchina...
- if (IobOnline)
+ // invio pacchetto di dati (max da conf)
+ for (int i = 0; i < nMaxSend; i++)
{
- int numIncr = 0;
- int qtyAdded = 0;
- // verifico se la funzione SIA abilitata
- if (enableSendPzCountBlock)
+ // SE ho qualcosa in coda...
+ if (QueueRawTransf.Count > 0)
{
- int delta = contapezziPLC - contapezziIOB;
- // se è abilitata verifico differenza: se ho DELTA > minSendPzCountBlock --> invio un blocco <= maxSendPzCountBlock
- if (delta > minSendPzCountBlock)
+ string currVal = "";
+ if (MPOnline)
{
- // init obj display
- newDisplayData currDispData = new newDisplayData();
- // resta indietro di ALMENO minSendPzCountBlock pezzi x recuperare 1:1...
- numIncr = delta > maxSendPzCountBlock + minSendPzCountBlock ? maxSendPzCountBlock : delta - minSendPzCountBlock;
- // invio il num max di pezzi ammesso in blocco!
- lastUrl = $"{urlAddPzCount}{numIncr}";
- string resp = utils.callUrlNow(lastUrl);
- if (!string.IsNullOrEmpty(resp))
+ if (IobOnline)
{
- // dalla risposta (come numero) capisco SE ha aggiunto i pezzi (e quanti)
- int.TryParse(resp, out qtyAdded);
- if (qtyAdded > 0)
+ List listaValori = new List();
+ // se ho + di maxJsonData elementi --> invio un set di dati alla volta
+ if (QueueRawTransf.Count > maxJsonData)
{
- // aggiorno IL MIO contapezzi...
- contapezziIOB += qtyAdded;
- lgInfo($"Inviato incremento contapezzi: send: {numIncr} | resp: {qtyAdded} | contapezziIOB: {contapezziIOB}");
- // invio conferma contapezzi..
- string retVal = utils.callUrl($"{urlSetPzCount}{contapezziIOB}");
- // verifica se tutto OK
- if (retVal != contapezziIOB.ToString())
+ // prendoi primi maxJsonDataValori
+ for (int j = 0; j < maxJsonData; j++)
{
- // errore salvataggio contapezzi
- lgError($"trySendPzCountBlock: errore salvataggio contapezzi: contapezziIOB {contapezziIOB} | risposta: {retVal}");
+ QueueRawTransf.TryDequeue(out currVal);
+ listaValori.Add(currVal);
}
+ sendDataBlock(urlType.RawTransf, listaValori);
}
else
{
- lgError($"Richiesto incremento {numIncr} ma NON registrato su server MP-IO");
+ // invio in blocco
+ listaValori = QueueRawTransf.ToList();
+ // invio
+ sendDataBlock(urlType.RawTransf, listaValori);
+ // svuoto!
+ QueueRawTransf = new ConcurrentQueue();
}
}
- currDispData.newUrlCallData = lastUrl;
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Processo la coda UserLog...
+ ///
+ private void svuotaCodaULog()
+ {
+ // verifico SE la coda abbia dei valori...
+ if (QueueULog.Count > 0)
+ {
+ // invio pacchetto di dati (max da conf)
+ for (int i = 0; i < nMaxSend; i++)
+ {
+ // SE ho qualcosa in coda...
+ if (QueueULog.Count > 0)
+ {
+ string currVal = "";
+ if (MPOnline)
+ {
+ if (IobOnline)
+ {
+ List listaValori = new List();
+ // se ho + di maxJsonData elementi --> invio un set di dati alla volta
+ if (QueueULog.Count > maxJsonData)
+ {
+ // prendoi primi maxJsonDataValori
+ for (int j = 0; j < maxJsonData; j++)
+ {
+ QueueULog.TryDequeue(out currVal);
+ listaValori.Add(currVal);
+ }
+ sendDataBlock(urlType.ULog, listaValori);
+ }
+ else
+ {
+ // invio in blocco
+ listaValori = QueueULog.ToList();
+ // invio
+ sendDataBlock(urlType.ULog, listaValori);
+ // svuoto!
+ QueueULog = new ConcurrentQueue();
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Cerca di inviare su un altro thread i vari dati accumulati...
+ ///
+ private void trySendValues()
+ {
+ // init obj display
+ newDisplayData currDispData = new newDisplayData();
+ try
+ {
+ // verifico se risponde il server...
+ if (checkServerAlive)
+ {
+ bool iobOk = false;
+ if (utils.CRB("sendDataByThread"))
+ {
+ Task taskCheck = Task.Run(() => iobOk = checkIobEnabled);
+ }
+ else
+ {
+ iobOk = checkIobEnabled;
+ }
+ // verifico SE posso inviare dati
+ if (iobOk)
+ {
+ currDispData.semOut = Semaforo.SV;
+ // verificare come gestire il task secondario senza interferenza (chiamate
+ // update su FORM da thread secondari danno errori)
+ if (utils.CRB("sendDataByThread"))
+ {
+ // invio con thread separato...
+ Task taskSigIN = Task.Run(() => svuotaCodaSignIN());
+ Task taskFLog = Task.Run(() => svuotaCodaFLog());
+ Task taskRawTransf = Task.Run(() => svuotaCodaRawTransf());
+ Task taskULog = Task.Run(() => svuotaCodaULog());
+ }
+ else
+ {
+ // gestione queue SignalIN (invio, display)
+ svuotaCodaSignIN();
currDispData.counter = contapezziIOB;
- currDispData.semOut = Semaforo.SV;
raiseRefresh(currDispData);
+ // provo a svuotare coda contapezzi
+ svuotaCodaContapezzi();
+ currDispData.counter = contapezziIOB;
+ raiseRefresh(currDispData);
+ // gestione queue FluxLog (invio, display)
+ svuotaCodaFLog();
+ // coda RawTransf
+ svuotaCodaRawTransf();
+ // coda UserLog
+ svuotaCodaULog();
+ // refresh
+ raiseRefresh(currDispData);
+ }
+ // se arrivo è tutto ok...
+ currSendErrors = 0;
+ }
+ else
+ {
+ // mostro VETO-SEND x invio... GIALLO
+ currDispData.semOut = Semaforo.SG;
+ if (periodicLog)
+ {
+ lgInfo("IOB - VETO SEND");
}
}
}
else
{
- lgError("Impossibile trySendPzCountBlock: IobOnline è false");
+ // mostro SERVER KO x invio... ROSSO
+ currDispData.semOut = Semaforo.SR;
+ if (periodicLog)
+ {
+ lgError("IOB - SERVER NOT READY");
+ }
}
}
- else
+ catch (Exception exc)
{
- lgError("Impossibile trySendPzCountBlock: MPOnline è false");
+ lgError($"Errore in fase trySendValues | currSendErrors: {currSendErrors}{Environment.NewLine}{exc}");
+ currDispData.semOut = Semaforo.SR;
}
+ raiseRefresh(currDispData);
}
///
- /// Inserimento/aggiornamento chiavi/valore in currProdData
+ /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce
///
- ///
- ///
- public void upsertKey(string chiave, string valore)
+ ///
+ ///
+ ///
+ /// Nuovo valore incrementato
+ private double updateValDoubleByIncr(int i, double delta, string searchString)
{
- if (currProdData.ContainsKey(chiave))
- {
- currProdData[chiave] = valore;
- }
- else
- {
- currProdData.Add(chiave, valore);
- }
+ // stringa da cercare..
+ string keyVal = string.Format(searchString, i + 1);
+ // recupero valore precedente...
+ double contAct = getStoredValDouble(keyVal);
+ // nuovo valore...
+ contAct += delta;
+ // salvo in ram!
+ persistenceLayer[keyVal] = contAct.ToString();
+ // rendo il valore!
+ return contAct;
}
///
- /// Formatta URL x invio in DataBlock Json dei dati FLog / eventi
+ /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce
///
- ///
- ///
- public string urlDataBlock(urlType tipoUrl)
+ ///
+ ///
+ ///
+ /// Nuovo valore incrementato
+ private long updateValLongByIncr(int i, long delta, string searchString)
{
- // verifico la parte di link "tipoComando"
- string tipoComando = "";
- switch (tipoUrl)
- {
- case urlType.FLog:
- tipoComando = cIobConf.serverData.CMDFLOG_JSON;
- break;
-
- case urlType.SignIN:
- tipoComando = cIobConf.serverData.CMDBASE_JSON;
- break;
-
- case urlType.RawTransf:
- tipoComando = cIobConf.serverData.CMDRAWTRANSF_JSON;
- break;
-
- case urlType.ULog:
- tipoComando = cIobConf.serverData.CMDULOG_JSON;
- break;
-
- default:
- break;
- }
- // URL base x input
- string answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{tipoComando}{cIobConf.codIOB}";
- return answ;
+ // stringa da cercare..
+ string keyVal = string.Format(searchString, i + 1);
+ // recupero valore precedente...
+ long contAct = getStoredValLong(keyVal);
+ // nuovo valore...
+ contAct += delta;
+ // salvo in ram!
+ persistenceLayer[keyVal] = contAct.ToString();
+ // rendo il valore!
+ return contAct;
}
///
- /// Fornisce URL di tipo FluxLog
+ /// Aggiorna un valore del dizionario in SOSTITUZIONE
///
- /// valore salvato in coda nel formato dtEve#flux#valore#counter
- ///
- public string urlFLog(string queueVal)
+ ///
+ ///
+ ///
+ /// Nuovo valore incrementato
+ private void updateValString(int i, string newVal, string searchString)
{
- // URL base x input
- string answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDFLOG}";
- // decodifica valore!
- string[] valori = qDecodeIN(queueVal);
- // aggiungo macchina e valore...
- answ += string.Format(@"{0}?flux={1}&&valore={2}", cIobConf.codIOB, valori[1], valori[2]);
- // aggiondo dataOra evento e corrente + contatore...
- answ += string.Format(@"&&dtEve={0}&&dtCurr={1:yyyyMMddHHmmssfff}&&cnt={2}", valori[0], DateTime.Now, valori[3]);
- return answ;
+ // stringa da cercare..
+ string keyVal = string.Format(searchString, i + 1);
+ // salvo in ram!
+ persistenceLayer[keyVal] = newVal;
}
///
- /// Fornisce URL INPUT per i parametri richiesti
+ /// Aggiorna un valore del dizionario in SOSTITUZIONE e lo restituisce
///
- /// valore salvato in coda formato dtEve#valore#counter
- ///
- public string urlInput(string queueVal)
+ ///
+ ///
+ ///
+ /// Nuovo valore incrementato
+ private void updateValUInt(int i, uint newVal, string searchString)
{
- // URL base x input
- string answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDBASE}";
- // decodifica valore!
- string[] valori = qDecodeIN(queueVal);
- // aggiungo macchina e valore...
- answ += string.Format(@"{0}?valore={1}", cIobConf.codIOB, valori[1]);
- // aggiondo dataOra evento e corrente + contatore...
- answ += string.Format(@"&&dtEve={0}&&dtCurr={1:yyyyMMddHHmmssfff}&&cnt={2}", valori[0], DateTime.Now, valori[2]);
- return answ;
+ // stringa da cercare..
+ string keyVal = string.Format(searchString, i + 1);
+ // salvo in ram!
+ persistenceLayer[keyVal] = newVal.ToString();
}
///
- /// Fornisce URL di tipo UserLog
+ /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce
///
- /// valore salvato in coda nel formato dtEve#flux#valore#counter
- ///
- public string urlULog(string queueVal)
+ ///
+ ///
+ ///
+ /// Nuovo valore incrementato
+ private uint updateValUIntByIncr(int i, uint delta, string searchString)
{
- // URL base x input
- string answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDULOG}";
- // decodifica valore!
- string[] valori = qDecodeIN(queueVal);
- // aggiungo macchina e valore...
- answ += string.Format(@"{0}?flux={1}&&valore={2}", cIobConf.codIOB, valori[1], valori[2]);
- // aggiondo dataOra evento e corrente + contatore...
- answ += string.Format(@"&&dtEve={0}&&dtCurr={1:yyyyMMddHHmmssfff}&&cnt={2}", valori[0], DateTime.Now, valori[3]);
- return answ;
+ // stringa da cercare..
+ string keyVal = string.Format(searchString, i + 1);
+ // recupero valore precedente...
+ uint contAct = getStoredValUInt(keyVal);
+ // nuovo valore...
+ contAct += delta;
+ // salvo in ram!
+ persistenceLayer[keyVal] = contAct.ToString();
+ // rendo il valore!
+ return contAct;
}
- #endregion Public Methods
+ #endregion Private Methods
}
///
@@ -5792,15 +5830,6 @@ namespace IOB_WIN_NEXT
///
public class iobRefreshedEventArgs : EventArgs
{
- #region Private Fields
-
- ///
- /// classe obj privata
- ///
- private readonly newDisplayData _newDisplayData;
-
- #endregion Private Fields
-
#region Public Constructors
///
@@ -5825,5 +5854,14 @@ namespace IOB_WIN_NEXT
}
#endregion Public Properties
+
+ #region Private Fields
+
+ ///
+ /// classe obj privata
+ ///
+ private readonly newDisplayData _newDisplayData;
+
+ #endregion Private Fields
}
}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/IobIcoelDb.cs b/IOB-WIN-NEXT/IobIcoelDb.cs
index 3da0998c..3bb11b86 100644
--- a/IOB-WIN-NEXT/IobIcoelDb.cs
+++ b/IOB-WIN-NEXT/IobIcoelDb.cs
@@ -3,21 +3,22 @@ using IOB_UT_NEXT;
using MapoSDK;
using System;
using System.Collections.Generic;
-using System.Linq;
+using System.Diagnostics;
using System.Net.NetworkInformation;
-using System.Text;
-using System.Threading.Tasks;
namespace IOB_WIN_NEXT
-{ ///
- /// Adapter specializzato per ICOEL e le chiamate tramite DB per i dati
- /// - accettazione lotti prodotto (frontiera / entrata ciliegie)
- /// - export (totale per prodotti)
- /// - tracciabilità (confezioni
- ///
+{
+ ///
+ /// Adapter specializzato per ICOEL e le chiamate tramite DB per i dati
+ /// - accettazione lotti prodotto (frontiera / entrata ciliegie)
+ /// - export (totale per prodotti)
+ /// - tracciabilità (confezioni
+ ///
public class IobIcoelDb : IobGeneric
{
+ #region Public Constructors
+
///
/// Costruttore dell'IOB Icoel DB
///
@@ -31,82 +32,19 @@ namespace IOB_WIN_NEXT
* - init obj comunicazione da conf e nuget
* - lanciare sync e verifica stato sync
*/
- string connEntrataFrontiera = utils.CRS("EntrataFrontiera");
- string connTrackerLotti = utils.CRS("TrackerLotti");
- string connExportIcoel = utils.CRS("ExportIcoel");
- string connSyncState = utils.CRS("SyncState");
- dbProxy = new DbProxy(connEntrataFrontiera, connTrackerLotti, connExportIcoel, connSyncState);
+ string SyncStateDb = getOptPar("SyncStateDb");
+ string SyncStateUser = getOptPar("SyncStateUser");
+ string SyncStatePwd = getOptPar("SyncStatePwd");
+
+ string connSyncState = $"data source={SyncStateDb};initial catalog=MoonPro_ISF;persist security info=True;user id={SyncStateUser};password={SyncStatePwd};MultipleActiveResultSets=True;App=IOB-WIN-NEXT";
+
+ // eccezione: NON TROVA EntityFramework 6.0.0 o successivo... why?!?
+ dbProxy = new DbProxy(connSyncState);
lastPING = DateTime.Now.AddHours(-1);
}
- #region Public Constructors
-
-
- ///
- /// Effettua lettura semafori principale
- /// Parametri da aggiornare x display in form
- ///
- public override void readSemafori(ref newDisplayData currDispData)
- {
- if (connectionOk)
- {
- B_input = 1;
- currDispData.semIn = Semaforo.SV;
-#if false
- if (currBatchList == null)
- {
- // se nullo --> provo a leggere!
-
- var currBatch = IcoelSizer.GetCurrentBatch();
- if (currBatch != null)
- {
- currBatchList = currBatch;
- // accodo invio!
- string rawBatch = JsonConvert.SerializeObject(currBatch);
- accodaRawData(IOB_UT_NEXT.rawTransfType.IcoelBatch, currBatch);
- }
- }
- else
- {
- // se ho batch NON chiusi (data = minValue) allora lavora
- if (currBatchList[1].EndTime == DateTime.MinValue || currBatchList[1].EndTime == DateTime.MinValue)
- {
- B_input = 3;
- }
- }
-#endif
- }
- else
- {
- B_input = 0;
- currDispData.semIn = Semaforo.SR;
- }
- }
-
- ///
- /// Recupero dati dinamici...
- ///
- public override Dictionary getDynData()
- {
- // valore non presente in vers default... se gestito fare override
- Dictionary outVal = new Dictionary();
-
- // mettere conteggio dei record trasferiti?!?
-#if false
- // recupero da libreria il dizionario dei performance parameters...
- var perfParamDict = IcoelSizer.GetPerfMeters();
- foreach (var item in perfParamDict)
- {
- saveValue(ref outVal, item.Value, item.Key);
- }
-
-#endif
- lastReadPLC = DateTime.Now;
- return outVal;
- }
-
#endregion Public Constructors
#region Public Methods
@@ -118,18 +56,63 @@ namespace IOB_WIN_NEXT
///
public override Dictionary executeTasks(Dictionary task2exe)
{
- /*---------------------------------------
- * fixme todo fare !!!
- * gestione execute task SPECIFICI x il sizer:
- * - recupero anagrafice variety/layout (attivi)
- * - recupero grower
- * - invio batch da accodare
- * - recupero dati da sizer (OVE disponibili)
- * - recupero batch corrente (modalità force/resync?)
- *
- *---------------------------------------*/
+ // unico task ammissibile: fare un SYNC forzato...
+ Dictionary taskDone = new Dictionary();
+ if (task2exe != null)
+ {
+ // controllo se memMap != null...
+ if (memMap != 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);
+ // controllo sulla KEY...
+ switch (tName)
+ {
+ case taskType.syncDbData:
+ lgInfo($"executeTasks --> syncDbData");
+ // effettua sync
+ refreshElencoStati();
- return base.executeTasks(task2exe);
+ break;
+
+ default:
+ taskVal = $"IobIcoelDb | taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
+ lgInfo($"IobIcoelDb | chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
+ break;
+ }
+ }
+ }
+ }
+ lastReadPLC = DateTime.Now;
+ return taskDone;
+ }
+
+ ///
+ /// Recupero dati dinamici...
+ ///
+ public override Dictionary getDynData()
+ {
+ // valore non presente in vers default... se gestito fare override
+ Dictionary outVal = new Dictionary();
+ // recupero da DB locale stato sync attuale
+ var elencoSyncStateCurr = dbProxy.DataController.SyncStateGetAll();
+ foreach (var item in elencoSyncStateCurr)
+ {
+ saveValue(ref outVal, item.NumRec, $"{item.TableName}_NumRec");
+ saveValue(ref outVal, item.NumRecIn, $"{item.TableName}_NumRecIn");
+ saveValue(ref outVal, item.LastIdx, $"{item.TableName}_LastIdx");
+ saveValue(ref outVal, item.LastIdxIn, $"{item.TableName}_LastIdxIn");
+ }
+ lastReadPLC = DateTime.Now;
+ return outVal;
}
///
@@ -140,76 +123,37 @@ namespace IOB_WIN_NEXT
public override void processCustomTaskLF()
{
lgInfo($"Richiesto processCustomTaskLF");
-
- // fare processing DB secondo il seguente scehma:
-
- /*
- *
- EgwProxy.Icoel.DbProxy dbProxy = new DbProxy(ReadSetting("EntrataFrontiera"), ReadSetting("TrackerLotti"), ReadSetting("ExportIcoel"), ReadSetting("SyncState"));
- Console.WriteLine();
- Console.WriteLine("--- SyncState ---");
- bool needRedo = true;
- var elencoSyncState = dbProxy.DataController.SyncStateGetAll();
- while (needRedo)
- {
- Console.WriteLine(" --- PRE --- ");
- if (elencoSyncState != null)
- {
- foreach (var item in elencoSyncState)
- {
- Console.WriteLine($"TAB: {item.TableName} | IdxIN / IdxLocal {item.LastIdxIn} / {item.LastIdx} | NumIn / NumLocal {item.NumRecIn} / {item.NumRec}");
- // verifico se serva redo..
- }
- }
- Console.WriteLine();
- Console.WriteLine("Premere un tasto x continuare...");
- Console.ReadKey();
- Stopwatch sw = new Stopwatch();
- sw.Start();
- elencoSyncState = dbProxy.DataController.SyncStateDoImportAll();
- sw.Stop();
- Console.WriteLine($" process time: {sw.ElapsedMilliseconds} ms ");
- Console.WriteLine(" --- POST --- ");
- if (elencoSyncState != null)
- {
- foreach (var item in elencoSyncState)
- {
- Console.WriteLine($"TAB: {item.TableName} | IdxIN / IdxLocal {item.LastIdxIn} / {item.LastIdx} | NumIn / NumLocal {item.NumRecIn} / {item.NumRec}");
- // verifico se serva redo..
- }
- }
- // processo
- needRedo = testNeedRedo(elencoSyncState);
- }
- *
- *
- * */
-
-#if false
- var currBatch = IcoelSizer.GetCurrentBatch();
- if (currBatch != null)
- {
- // verifico se i batch siano variati... e quindi da inviare...
- bool doSend = (currBatchList == null || currBatchList.Count == 0);
- if (currBatch.Count > 0 && !doSend)
- {
- foreach (var item in currBatch)
- {
- // se variato ID è cambiato
- doSend = doSend || (currBatchList[item.Key].Id != item.Value.Id);
- }
- }
- // se devo inviare impacchetto dati
- if (doSend)
- {
- accodaRawData(IOB_UT_NEXT.rawTransfType.IcoelBatch, currBatch);
- currBatchList = currBatch;
- }
- }
-#endif
+ // effettua sync
+ refreshElencoStati();
lastReadPLC = DateTime.Now;
}
+ ///
+ /// Effettua lettura semafori principale Parametri da
+ /// aggiornare x display in form
+ ///
+ public override void readSemafori(ref newDisplayData currDispData)
+ {
+ if (connectionOk)
+ {
+ B_input = 1;
+ currDispData.semIn = Semaforo.SV;
+
+ if (dbProxy != null && elencoSyncState != null && elencoSyncState.Count > 0)
+ {
+ B_input += (1 << 1);
+ }
+
+ // accodo NON emergenza
+ B_input += (1 << 7);
+ }
+ else
+ {
+ B_input = 0;
+ currDispData.semIn = Semaforo.SR;
+ }
+ }
+
///
/// Override connessione
///
@@ -234,16 +178,16 @@ namespace IOB_WIN_NEXT
{
// ora provo connessione...
parentForm.commPlcActive = true;
-#if false
- // recupero elenco batch... se != vuoto -_> connesso!
- var batchList = IcoelSizer.GetCurrentBatch();
- if (batchList != null && batchList.Count > 0)
+ if (dbProxy != null)
{
- lgInfo($"szStatusConnection IcoelSoap, recuperato elenco di {batchList.Count} batch");
- parentForm.commPlcActive = false;
- connectionOk = true;
- }
-#endif
+ elencoSyncState = dbProxy.DataController.SyncStateDoImportAll();
+
+ if (elencoSyncState != null && elencoSyncState.Count > 0)
+ {
+ parentForm.commPlcActive = false;
+ connectionOk = true;
+ }
+ }
// refresh stato connessione!!!
if (connectionOk)
{
@@ -291,40 +235,34 @@ namespace IOB_WIN_NEXT
#region Protected Properties
-#if false
- ///
- /// elenco dei BAtch correntemente caricati x testing variazione
- ///
- protected Dictionary currBatchList { get; set; }
-#endif
+ protected EgwProxy.Icoel.DbProxy dbProxy { get; set; } = null;
- protected EgwProxy.Icoel.DbProxy dbProxy { get; set; }
+ ///
+ /// Stato di sync delle tab gestite
+ ///
+ protected List elencoSyncState { get; set; } = new List();
#endregion Protected Properties
- #region Protected Methods
+ #region Private Methods
- ///
- /// recupera le variety ed i rispettivi layout e li invia al sistema MP/IO
- ///
- protected void refreshVarietyData()
+ private void refreshElencoStati()
{
-#if false
- ///determina se recuperare SOLO varietà attive o tutte
- bool soloAttive = false;
- var varList = IcoelSizer.GetVarietyList(soloAttive);
- if (varList != null && varList.Length > 0)
+ Stopwatch sw = new Stopwatch();
+ sw.Start();
+ elencoSyncState = dbProxy.DataController.SyncStateDoImportAll();
+ sw.Stop();
+ lgInfo($"DB: esecuzione task dbProxy.DataController.SyncStateGetAll() in {sw.ElapsedMilliseconds} ms");
+
+ if (elencoSyncState != null)
{
- var varietyData = IcoelSizer.GetLayoutForVarietyList(varList);
- // invio dai al server IO
-
- }
-#endif
-
- lastReadPLC = DateTime.Now;
+ foreach (var item in elencoSyncState)
+ {
+ lgTrace($"TAB: {item.TableName} | IdxIN / IdxLocal {item.LastIdxIn} / {item.LastIdx} | NumIn / NumLocal {item.NumRecIn} / {item.NumRec}");
+ }
+ }
}
- #endregion Protected Methods
-
+ #endregion Private Methods
}
-}
+}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/IobIcoelSoap.cs b/IOB-WIN-NEXT/IobIcoelSoap.cs
index ab5dedd1..19e35d1b 100644
--- a/IOB-WIN-NEXT/IobIcoelSoap.cs
+++ b/IOB-WIN-NEXT/IobIcoelSoap.cs
@@ -2,10 +2,8 @@
using EgwProxy.Icoel.SizerService;
using IOB_UT_NEXT;
using MapoSDK;
-using Newtonsoft.Json;
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Net.NetworkInformation;
namespace IOB_WIN_NEXT
@@ -44,65 +42,6 @@ namespace IOB_WIN_NEXT
lastPING = DateTime.Now.AddHours(-1);
}
- ///
- /// Effettua lettura semafori principale
- /// Parametri da aggiornare x display in form
- ///
- public override void readSemafori(ref newDisplayData currDispData)
- {
- if (connectionOk)
- {
- B_input = 1;
- currDispData.semIn = Semaforo.SV;
- if (currBatchList == null)
- {
- // se nullo --> provo a leggere!
-
- var currBatch = IcoelSizer.GetCurrentBatch();
- if (currBatch != null)
- {
- currBatchList = currBatch;
-#if false
- // accodo invio!
- string rawBatch = JsonConvert.SerializeObject(currBatch);
-#endif
- accodaRawData(IOB_UT_NEXT.rawTransfType.IcoelBatch, currBatch);
- }
- }
- else
- {
- // se ho batch NON chiusi (data = minValue) allora lavora
- if (currBatchList[1].EndTime == DateTime.MinValue || currBatchList[1].EndTime == DateTime.MinValue)
- {
- B_input = 3;
- }
- }
- }
- else
- {
- B_input = 0;
- currDispData.semIn = Semaforo.SR;
- }
- }
-
- ///
- /// Recupero dati dinamici...
- ///
- public override Dictionary getDynData()
- {
- // valore non presente in vers default... se gestito fare override
- Dictionary outVal = new Dictionary();
- // recupero da libreria il dizionario dei performance parameters...
- var perfParamDict = IcoelSizer.GetPerfMeters();
- foreach (var item in perfParamDict)
- {
- saveValue(ref outVal, item.Value, item.Key);
- }
-
- lastReadPLC = DateTime.Now;
- return outVal;
- }
-
#endregion Public Constructors
#region Public Methods
@@ -128,6 +67,30 @@ namespace IOB_WIN_NEXT
return base.executeTasks(task2exe);
}
+ ///
+ /// Dizionario parametri correnti
+ ///
+ protected Dictionary perfParamDict { get; set; } = new Dictionary();
+
+ ///
+ /// Recupero dati dinamici...
+ ///
+ public override Dictionary getDynData()
+ {
+ // valore non presente in vers default... se gestito fare override
+ Dictionary outVal = new Dictionary();
+ // recupero da libreria il dizionario dei performance parameters...
+ perfParamDict = IcoelSizer.GetPerfMeters();
+ lgTrace("SOAP: effettuata chiamata IcoelSizer.GetPerfMeters()");
+ foreach (var item in perfParamDict)
+ {
+ saveValue(ref outVal, item.Value, item.Key);
+ }
+
+ lastReadPLC = DateTime.Now;
+ return outVal;
+ }
+
///
/// Effettua processing CUSTOM x Icoel:
/// - recupera elenco batch delle 2 linee
@@ -137,6 +100,7 @@ namespace IOB_WIN_NEXT
{
lgInfo($"Richiesto processCustomTaskLF");
var currBatch = IcoelSizer.GetCurrentBatch();
+ lgTrace("SOAP: effettuata chiamata IcoelSizer.GetCurrentBatch()");
if (currBatch != null)
{
// verifico se i batch siano variati... e quindi da inviare...
@@ -152,12 +116,7 @@ namespace IOB_WIN_NEXT
// se devo inviare impacchetto dati
if (doSend)
{
-#if false
- // accodo per invio...
- string rawBatch = JsonConvert.SerializeObject(currBatch);
- accodaRawData(IOB_UT_NEXT.rawTransfType.IcoelBatch, rawBatch);
-#endif
- accodaRawData(IOB_UT_NEXT.rawTransfType.IcoelBatch, currBatch);
+ accodaRawData(rawTransfType.IcoelBatch, currBatch);
currBatchList = currBatch;
}
}
@@ -165,6 +124,65 @@ namespace IOB_WIN_NEXT
lastReadPLC = DateTime.Now;
}
+ ///
+ /// Effettua lettura semafori principale Parametri da
+ /// aggiornare x display in form
+ ///
+ public override void readSemafori(ref newDisplayData currDispData)
+ {
+ if (connectionOk)
+ {
+ B_input = 1;
+ currDispData.semIn = Semaforo.SV;
+ if (currBatchList == null)
+ {
+ // se nullo --> provo a leggere!
+ var currBatch = IcoelSizer.GetCurrentBatch();
+ lgTrace("SOAP: effettuata chiamata IcoelSizer.GetCurrentBatch()");
+ if (currBatch != null)
+ {
+ currBatchList = currBatch;
+ accodaRawData(rawTransfType.IcoelBatch, currBatch);
+ }
+ }
+ else
+ {
+ //se i perf parameters mi danno valire > 0 x quantità frutta...
+ if (perfParamDict != null && perfParamDict.Count > 0)
+ {
+ if (perfParamDict.ContainsKey("VelFruttiMinuto"))
+ {
+ if (perfParamDict["VelFruttiMinuto"] > 0)
+ {
+ B_input += (1 << 1);
+ }
+ // metto manuale
+ else
+ {
+ B_input += (1 << 4);
+ }
+ }
+ }
+
+ //usato altro criterio x stato verde da vel frutti minuto
+#if false
+ // se ho batch NON chiusi (data = minValue) allora lavora
+ if (currBatchList[1].EndTime == DateTime.MinValue || currBatchList[1].EndTime == DateTime.MinValue)
+ {
+ B_input = 3;
+ }
+#endif
+ }
+ // accodo NON emergenza
+ B_input += (1 << 7);
+ }
+ else
+ {
+ B_input = 0;
+ currDispData.semIn = Semaforo.SR;
+ }
+ }
+
///
/// Override connessione
///
@@ -191,6 +209,7 @@ namespace IOB_WIN_NEXT
parentForm.commPlcActive = true;
// recupero elenco batch... se != vuoto -_> connesso!
var batchList = IcoelSizer.GetCurrentBatch();
+ lgTrace("SOAP: effettuata chiamata IcoelSizer.GetCurrentBatch()");
if (batchList != null && batchList.Count > 0)
{
lgInfo($"szStatusConnection IcoelSoap, recuperato elenco di {batchList.Count} batch");
@@ -263,11 +282,11 @@ namespace IOB_WIN_NEXT
///determina se recuperare SOLO varietà attive o tutte
bool soloAttive = false;
var varList = IcoelSizer.GetVarietyList(soloAttive);
+ lgTrace("SOAP: effettuata chiamata IcoelSizer.GetVarietyList()");
if (varList != null && varList.Length > 0)
{
var varietyData = IcoelSizer.GetLayoutForVarietyList(varList);
- // invio dai al server IO
-
+ lgTrace("SOAP: effettuata chiamata IcoelSizer.GetLayoutForVarietyList()");
}
lastReadPLC = DateTime.Now;
diff --git a/IOB-WIN-NEXT/IobOpcUaOmronIcoel.cs b/IOB-WIN-NEXT/IobOpcUaOmronIcoel.cs
index 91803e95..bc31f488 100644
--- a/IOB-WIN-NEXT/IobOpcUaOmronIcoel.cs
+++ b/IOB-WIN-NEXT/IobOpcUaOmronIcoel.cs
@@ -415,7 +415,7 @@ namespace IOB_WIN_NEXT
B_input = powerOnOk ? 1 : 0;
// decodifico da currData
- if (currData.Varie.InEmergenza)
+ if (!currData.Varie.InEmergenza)
{
B_input += (1 << 7);
}
@@ -427,6 +427,7 @@ namespace IOB_WIN_NEXT
{
B_input += (1 << 3);
}
+
}
// controllo se sono poweroff e se non ho dati buoni da > 2 minuti --> disconnetto
diff --git a/IOB-WIN-NEXT/packages.config b/IOB-WIN-NEXT/packages.config
index e0471635..43bf02c1 100644
--- a/IOB-WIN-NEXT/packages.config
+++ b/IOB-WIN-NEXT/packages.config
@@ -2,10 +2,11 @@
-
+
-
+
+