diff --git a/IOB-UT/IOB-UT.csproj b/IOB-UT/IOB-UT.csproj index 77657eee..965bc47f 100644 --- a/IOB-UT/IOB-UT.csproj +++ b/IOB-UT/IOB-UT.csproj @@ -72,17 +72,8 @@ ..\packages\NLog.4.6.8\lib\net40-client\NLog.dll - - ..\packages\ServiceStack.Common.4.0.62\lib\net40\ServiceStack.Common.dll - - - ..\packages\ServiceStack.Interfaces.4.0.62\lib\portable-wp80+sl5+net40+win8+wpa81+monotouch+monoandroid+xamarin.ios10\ServiceStack.Interfaces.dll - - - ..\packages\ServiceStack.Redis.4.0.62\lib\net40\ServiceStack.Redis.dll - - - ..\packages\ServiceStack.Text.4.0.62\lib\net40\ServiceStack.Text.dll + + ..\packages\StackExchange.Redis.1.2.0\lib\net40\StackExchange.Redis.dll diff --git a/IOB-UT/Objects.cs b/IOB-UT/Objects.cs index 5f004136..8af05708 100644 --- a/IOB-UT/Objects.cs +++ b/IOB-UT/Objects.cs @@ -471,21 +471,17 @@ namespace IOB_UT public class ServerMpStatus { /// - /// ID univoco + /// IP server /// - public long Id { get; set; } + public string IP { get; set; } /// /// Status del server /// public bool online { get; set; } = false; /// - /// DataOra veto invio chaimate a server + /// DataOra ultima comunicazione OUT (con MP Server) /// - public DateTime dtVetoPing { get; set; } = DateTime.Now.AddDays(-1); - /// - /// DataOra veto invio chaimate a server - /// - public DateTime dtVetoCall { get; set; } = DateTime.Now.AddDays(-1); + public DateTime lastUpdate { get; set; } = DateTime.Now.AddDays(-1); } /// /// Rappresentazione dello stato corrente dell'IOB @@ -495,15 +491,16 @@ namespace IOB_UT /// /// ID univoco /// - public long Id { get; set; } - /// - /// ID univoco - /// - public string IdxMacchina { get; set; } = "000"; + public string CodIob { get; set; } = "0"; /// /// Status del SINGOLO IOB /// public bool online { get; set; } = false; +#if false + /// + /// Indica se sia correntemente in setup + /// + public bool inSetup { get; set; } = false; /// /// Semaforo IN (IOB-PLC) /// @@ -511,7 +508,8 @@ namespace IOB_UT /// /// Semaforo OUT (IOB-MPserver) /// - public Semaforo SemOut { get; set; } = Semaforo.ND; + public Semaforo SemOut { get; set; } = Semaforo.ND; +#endif /// /// Contatore IOB /// @@ -527,7 +525,7 @@ namespace IOB_UT /// /// Lunghezza coda FluxLog in uscita /// - public int queueFLogLen { get; set; } = 0; + public int queueFlLen { get; set; } = 0; /// /// Lungh coda ALLARMI in uscita /// @@ -535,7 +533,8 @@ namespace IOB_UT /// /// Lungh coda MESSAGGI in uscita /// - public int queueMsgLen { get; set; } = 0; + public int queueMsLen { get; set; } = 0; +#if false /// /// DataOra ultima comunicazione IN (con PLC) /// @@ -547,7 +546,12 @@ namespace IOB_UT /// /// Ultimo stato noto dei parametri in memoria letti da PLC /// - public Dictionary currParams { get; set; } = null; + public Dictionary currParams { get; set; } = null; +#endif + /// + /// DataOra ultima comunicazione OUT (con MP Server) + /// + public DateTime lastUpdate { get; set; } = DateTime.Now.AddDays(-1); } } diff --git a/IOB-UT/RedisMan.cs b/IOB-UT/RedisMan.cs index 6ce8870c..de47d35f 100644 --- a/IOB-UT/RedisMan.cs +++ b/IOB-UT/RedisMan.cs @@ -1,5 +1,5 @@ -using ServiceStack.Redis; -using ServiceStack.Redis.Generic; +using Newtonsoft.Json; +using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; @@ -7,57 +7,912 @@ using System.Text; namespace IOB_UT { - public class RedisCache + public class RedisIobCache { + #region gestione valori in RedisCache + /// - /// Pool manager + /// Restituisce un pò di info sul server redis connesso /// - protected RedisManagerPool redisManPool; - /// - /// Client corrente - /// - protected IRedisClient redisClient; - /// - /// Oggetto descrizione stato SERVER MP-IO - /// - protected IRedisTypedClient redServerStatus; - /// - /// Oggetto descrizione stato CLIENT IOB - /// - protected IRedisTypedClient redIobStatus; - /// - /// init classe - /// - public RedisCache() + /// + public string getRedisInfoData() { - // init oggetti connessione - redisManPool = new RedisManagerPool(baseUtils.CRS("redisConf")); - redisClient = redisManPool.GetClient(); - // init oggetto server - redServerStatus = redisClient.As(); - var newSrvStatus = new ServerMpStatus() + string answ = ""; + StringBuilder sb = new StringBuilder(); + try { - Id = 1, - online = false, - dtVetoCall = DateTime.Now.AddMinutes(-1) - }; - redServerStatus.Store(newSrvStatus); - // init oggetto IOB - redIobStatus = redisClient.As(); - var newIobStatus = new IobWinStatus() - { - Id = 1, - online = false, - IdxMacchina="000" - }; - redIobStatus.Store(newIobStatus); + sb.AppendLine($"Configuration: {connRedis.Configuration}"); + sb.AppendLine($"Connected: {connRedis.IsConnected}"); + sb.AppendLine($"ClientName: {connRedis.ClientName}"); + sb.AppendLine($"Total Ops: {connRedis.OperationCount}"); + sb.AppendLine($"Status: {connRedis.GetStatus()}"); + answ = sb.ToString(); + } + catch + { } + return answ; } -#if false /// - /// Singleton gestione RedisCache + /// Oggetto currentDb locale /// - public static RedisCache man = new RedisCache(); -#endif + private IDatabase _currDB { get; set; } + /// + /// Oggetto DB REDIS corrente + /// + public IDatabase cache //currDB + { + get + { + IDatabase answ; + // se già valorizzato uso oggetto private... + if (_currDB != null) + { + answ = _currDB; + } + else + { + // init DB (sullo 0) + answ = connRedis.GetDatabase(); + // gestione override... + if (baseUtils.CRI("redisDb") >= 0) + { + // in questo caso uso il DB configurato in app.config... + answ = connRedis.GetDatabase(baseUtils.CRI("redisDb")); + } + _currDB = answ; + } + // restituisco oggetto DB + return answ; + } + } + /// + /// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da funzionalita' DbConfig) + keyName richiesto... + /// + public string redHash(string keyName) + { + keyName = keyName.Replace("\\", "_"); + string answ = keyName; + try + { + answ = string.Format($"{baseUtils.CRS("appName")}:{keyName}"); + } + catch + { } + return answ; + } + /// + /// Serializzazione di un oggetto generico + /// + /// + /// + public string serializeVal(object origVal) + { + string answ = ""; + try + { + answ = JsonConvert.SerializeObject(origVal); + } + catch { } + return answ; + } + /// + /// Deserializzazione di un valore string in oggetto generico + /// + /// + /// + public object deserializeVal(string serVal) + { + object answ = ""; + try + { + answ = JsonConvert.DeserializeObject(serVal); + } + catch { } + return answ; + } + /// + /// 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); + }); + /// + /// Oggetto statico connessione redis + /// + public ConnectionMultiplexer connRedis + { + get + { + return lazyConnection.Value; + } + } + /// + /// Oggetto statico connessione redis + /// + public ConnectionMultiplexer connRedisAdmin + { + get + { + return lazyConnectionAdmin.Value; + } + } + /// + /// Restituisce info dei server connessi... + /// + /// + public IServer[] redServInfo() + { + IServer[] answ = new IServer[1]; + try + { + answ = new IServer[connRedisAdmin.GetEndPoints().Length]; + int i = 0; + foreach (var ep in connRedisAdmin.GetEndPoints()) + { + var server = connRedisAdmin.GetServer(ep); + answ[i] = server; + i++; + } + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("{0}", exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Restituisce una chiave salvata in RedisCache + /// + /// + /// + public string getRSV(string chiave) + { + string answ = ""; + try + { + answ = cache.StringGet(chiave); + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in getRSV:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Salva una chiave in RedisCache + /// + /// + /// + /// + public bool setRSV(string chiave, string valore) + { + bool answ = false; + try + { + cache.StringSet(chiave, valore); + answ = true; + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in setRSV:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Salva una chiave in RedisCache + /// + /// + /// + /// in secondi + /// + public bool setRSV(string chiave, string valore, int TTL_sec) + { + bool answ = false; + try + { + TimeSpan expT = new TimeSpan(0, 0, TTL_sec); + // salvo con expyry... + cache.StringSet(chiave, valore, expT); + answ = true; + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in setRSV:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Incrementa un contatore in Redis + /// + /// + /// + public long setRCntI(string chiave) + { + long answ = 0; + try + { + answ = cache.StringIncrement(chiave, 1); + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in setRCI:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Decrementa un contatore in Redis + /// + /// + /// + public long setRCntD(string chiave) + { + long answ = 0; + try + { + answ = cache.StringDecrement(chiave, 1); + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in setRCD:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Restituisce una chiave COUNTER in RedisCache + /// + /// + /// + public int getRCnt(string chiave) + { + int answInt = 0; + string answ = ""; + try + { + answ = cache.StringGet(chiave); + answInt = Convert.ToInt32(answ); + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in getRSV:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); + } + return answInt; + } + /// + /// Resetta (elimina) un contatore in Redis + /// + /// + /// + public bool resetRCnt(string chiave) + { + bool answ = false; + try + { + answ = cache.KeyDelete(chiave); + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in resetRCnt:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Restituisce un set KVP (Key Value Pair) salvati in RedisCache + /// + /// + /// + public RedisValue[] getRKeys(RedisKey[] chiavi) + { + RedisValue[] answ = null; + try + { + answ = cache.StringGet(chiavi); + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in getRKeys:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Salva un set KVP (Key Value Pair) in RedisCache + /// + /// Set KVP chiave-valore da salvare + /// + public bool setRKeys(KeyValuePair[] valori) + { + bool answ = false; + try + { + cache.StringSet(valori); + answ = true; + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in setRKeys:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Verifica se ci siano valori nella KEY indicata... + /// + /// + /// + public bool redKeyPresent(RedisKey key) + { + bool answ = false; + // cerco se ci sia valore in redis... + try + { + answ = cache.KeyExists(key); + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in redKeyPresent per la key {2}:{0}{1}", Environment.NewLine, exc, key), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Verifica se ci siano valori nella KEY indicata (string) + /// + /// + /// + public bool redKeyPresentSz(string key) + { + bool answ = false; + try + { + RedisKey chiave = key; + answ = redKeyPresent(chiave); + } + catch + { } + return answ; + } + /// + /// Verifica se ci siano valori nella hash indicata... + /// + /// + /// + public bool redHashPresent(RedisKey key) + { + bool answ = false; + // cerco se ci sia valore in redis... + try + { + answ = cache.HashGetAll(key).Length > 0; + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("Errore in redHashPresent per la key {2}{0}{1}", Environment.NewLine, exc, key), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Verifica se ci siano valori nella hash indicata (string) + /// + /// + /// + public bool redHashPresentSz(string key) + { + bool answ = false; + try + { + RedisKey chiave = key; + answ = redHashPresent(chiave); + } + catch + { } + return answ; + } + /// + /// Recupera tutti i valori dalla hash + /// + /// + /// + public KeyValuePair[] redGetHash(string hashKey) + { + KeyValuePair[] answ = new KeyValuePair[1]; + // cerco se ci sia valore in redis... + try + { + RedisKey chiave = hashKey; + HashEntry[] valori = cache.HashGetAll(chiave); + answ = new KeyValuePair[valori.Length]; + int i = 0; + foreach (HashEntry item in valori) + { + answ[i] = new KeyValuePair(item.Name, item.Value); + i++; + } + } + catch + { } + return answ; + } + /// + /// Recupera tutti i valori dalla hash in formato Dictionary + /// + /// + /// + public Dictionary redGetHashDict(string hashKey) + { + Dictionary answ = new Dictionary(); + // cerco se ci sia valore in redis... + try + { + RedisKey chiave = hashKey; + HashEntry[] valori = cache.HashGetAll(chiave); + foreach (HashEntry item in valori) + { + answ.Add(item.Name, item.Value); + } + } + catch + { } + return answ; + } + /// + /// Recupera UN SINGOLO VALORE dalla hash per un dato field + /// + /// + /// + /// + public string redGetHashField(string hashKey, string hashField) + { + string answ = ""; + // cerco se ci sia valore in redis... + try + { + RedisKey chiave = hashKey; + RedisValue campo = hashField; + RedisValue valOut = cache.HashGet(chiave, campo); + answ = valOut.ToString(); + } + catch + { } + return answ; + } + /// + /// Salvataggio di una hash di valori + /// + /// chiave + /// valori + /// + public bool redSaveHash(string hashKey, KeyValuePair[] hashFields) + { + bool answ = false; + // cerco se ci sia valore in redis... + try + { + RedisKey chiave = hashKey; + HashEntry[] valori = new HashEntry[hashFields.Length]; + int i = 0; + foreach (KeyValuePair kvp in hashFields) + { + valori[i] = new HashEntry(kvp.Key, kvp.Value); + i++; + } + cache.HashSet(chiave, valori); + answ = true; + } + catch + { } + return answ; + } + /// + /// Salvataggio di una hash di valori in formato Dictionary + /// + /// chiave + /// valori + /// + public bool redSaveHashDict(string hashKey, Dictionary hashFields) + { + bool answ = false; + // cerco se ci sia valore in redis... + try + { + RedisKey chiave = hashKey; + HashEntry[] valori = new HashEntry[hashFields.Count]; + int i = 0; + foreach (KeyValuePair kvp in hashFields) + { + valori[i] = new HashEntry(kvp.Key, kvp.Value); + i++; + } + cache.HashSet(chiave, valori); + answ = true; + } + catch + { } + return answ; + } + + /// + /// Salvataggio di una hash di valori + /// + /// chiave + /// valori come lista KVP + /// + public bool redSaveHashList(string hashKey, List> hashListKVP) + { + bool answ = false; + if (connRedis.IsConnected) + { + // cerco se ci sia valore in redis... + IDatabase cache = connRedis.GetDatabase(); + try + { + RedisKey chiave = hashKey; + HashEntry[] valori = new HashEntry[hashListKVP.Count]; + int i = 0; + foreach (KeyValuePair kvp in hashListKVP) + { + valori[i] = new HashEntry(kvp.Key, kvp.Value); + i++; + } + cache.HashSet(chiave, valori); + answ = true; + } + catch + { } + } + return answ; + } + /// + /// Salvataggio di una hash di valori + /// + /// chiave + /// valori + /// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade) + /// + public bool redSaveHash(string hashKey, KeyValuePair[] hashFields, double expireSeconds = -1) + { + bool answ = false; + // cerco se ci sia valore in redis... + try + { + RedisKey chiave = hashKey; + answ = redSaveHash(hashKey, hashFields); + if (expireSeconds > 0) + { + cache.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds)); + } + //answ = true; + } + catch + { } + return answ; + } + /// + /// Salvataggio di una hash di valori in formato Dictionary + /// + /// chiave + /// valori + /// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade) + /// + public bool redSaveHashDict(string hashKey, Dictionary hashFields, double expireSeconds = -1) + { + bool answ = false; + // cerco se ci sia valore in redis... + try + { + RedisKey chiave = hashKey; + answ = redSaveHashDict(hashKey, hashFields); + if (expireSeconds > 0) + { + cache.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds)); + } + //answ = true; + } + catch + { } + return answ; + } + /// + /// Elimina una key (hash, string) + /// + /// + /// + public bool redDelKey(string key) + { + bool answ = false; + // cerco se ci sia valore in redis... + try + { + RedisKey chiave = key; + cache.KeyDelete(chiave); + answ = true; + } + catch + { } + return answ; + } + /// + /// Flush completo cache redis + /// + /// ** = tutti + /// + public bool redFlushKey(string keyPattern) + { + bool answ = false; + // cerco se ci sia valore in redis... + // se vuoto = ALL... + keyPattern = string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern; + try + { + foreach (var ep in connRedis.GetEndPoints()) + { + var server = connRedis.GetServer(ep); + var keys = server.Keys(database: baseUtils.CRI("redisDb"), pattern: $"{keyPattern}*"); + foreach (var key in keys) + { + cache.KeyDelete(key); + } + } + answ = true; + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("{0}", exc), tipoLog.EXCEPTION); + } + return answ; + } + /// + /// Conta num oggetti cache redis che rispondono a pattern + /// + /// ** = tutti + /// + public int redCountKey(string keyPattern) + { + int answ = 0; + // cerco se ci sia valore in redis... + // se vuoto = ALL... + keyPattern = string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern; + try + { + foreach (var ep in connRedis.GetEndPoints()) + { + var server = connRedis.GetServer(ep); + foreach (var key in server.Keys(pattern: keyPattern)) + { + answ++; + } + } + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("{0}", exc), tipoLog.EXCEPTION); + } + return answ; + } + + /// + /// Restituisce numero record in Redis DB + /// + public long numRecRedis + { + get + { + long answ = 0; + try + { + foreach (var ep in connRedis.GetEndPoints()) + { + var server = connRedis.GetServer(ep); + answ += server.DatabaseSize(); + } + } + catch + { } + return answ; + } + } + /// + /// Restituisce oggetti cache redis che rispondono a pattern + /// + /// ** = tutti + /// Tipo di ordinamento per kvp + /// + public List> redGetCounterByKey(string keyPattern, kvpOrderBy orderBy) + { + int numAnsw = redCountKey(keyPattern); + RedisKey[] chiavi = new RedisKey[numAnsw]; + List> answ = new List>(); + // se vuoto = ALL... + keyPattern = string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern; + + // recupero in primis elenco chiavi + try + { + int i = 0; + foreach (var ep in connRedis.GetEndPoints()) + { + var server = connRedis.GetServer(ep); + foreach (var key in server.Keys(pattern: keyPattern)) + { + chiavi[i] = key; + i++; + } + } + } + catch (Exception exc) + { + //logger.lg.scriviLog(string.Format("{0}", exc), tipoLog.EXCEPTION); + } + // ora recupero valori! + var valori = getRKeys(chiavi); + int currVal = 0; + // popolo rispsota + try + { + for (int i = 0; i < numAnsw; i++) + { + Int32.TryParse(valori[i], out currVal); + answ.Add(new KeyValuePair(chiavi[i], currVal)); + } + } + catch + { } + // se richiesto riordino... + switch (orderBy) + { + case kvpOrderBy.KeyAsc: + answ.Sort(CompareKey); + break; + case kvpOrderBy.KeyDesc: + answ.Sort(CompareKeyDesc); + break; + case kvpOrderBy.ValAsc: + answ.Sort(CompareVal); + break; + case kvpOrderBy.ValDesc: + answ.Sort(CompareValDesc); + break; + default: + break; + } + return answ; + } + /// + /// Effettua comaprazione x CHIAVE in KVP ASC + /// + /// + /// + /// + private int CompareKey(KeyValuePair x, KeyValuePair y) + { + return x.Key.CompareTo(y.Key); + } + /// + /// Effettua comaprazione x VALORE in KVP ASC + /// + /// + /// + /// + public int CompareVal(KeyValuePair x, KeyValuePair y) + { + return x.Value.CompareTo(y.Value); + } + /// + /// Effettua comaprazione x CHIAVE in KVP DESC + /// + /// + /// + /// + private int CompareKeyDesc(KeyValuePair x, KeyValuePair y) + { + return y.Key.CompareTo(x.Key); + } + /// + /// Effettua comaprazione x VALORE in KVP DESC + /// + /// + /// + /// + public int CompareValDesc(KeyValuePair x, KeyValuePair y) + { + return y.Value.CompareTo(x.Value); + } + + /// + /// Tipologia di ordinamento x liste KVP + /// + public enum kvpOrderBy + { + /// + /// Ordinamento ASCending per KEY + /// + KeyAsc, + /// + /// Ordinamento DESCending per KEY + /// + KeyDesc, + /// + /// Ordinamento ASCending per VAL + /// + ValAsc, + /// + /// Ordinamento DESCending per VAL + /// + ValDesc + } + + + + #endregion + + #region gestione redis specifica + + /// + /// Cod IOB + /// + protected string CodIob = "000"; + /// + /// Hash redis x dati server + /// + protected string redServKey = ""; + /// + /// Hash redis x dati IOB + /// + protected string redIobKey = ""; + /// + /// init classe "implicita" + /// + /// + /// + public RedisIobCache() + { + // init dati di base... + redServKey = redHash($"MP"); + redIobKey = redHash($"IOB:{CodIob}"); + } + /// + /// init classe gestione dati IOB su Redis + /// + /// + /// + public RedisIobCache(string codServer, string codIob) + { + // init dati di base... + CodIob = codIob; + redServKey = redHash($"MP"); + redIobKey = redHash($"IOB:{CodIob}"); + // init oggetti gestiti + ServerMpStatus newSrvStatus = new ServerMpStatus() + { + IP = codServer, + online = false + }; + // init oggetto IOB + IobWinStatus newIobStatus = new IobWinStatus() + { + CodIob = CodIob, + online = false + }; + // salvo in area REDIS + servStatus = newSrvStatus; + iobStatus = newIobStatus; + } /// /// Accesso all'oggetto stato server da esterno /// @@ -65,11 +920,31 @@ namespace IOB_UT { get { - return redServerStatus.GetById(1); + ServerMpStatus answ = null; + // cerco in REDIS + string rawData = getRSV(redServKey); + // se non ci fosse creo e salvo + if (string.IsNullOrEmpty(rawData)) + { + answ = new ServerMpStatus() + { + online = false + }; + // salvo serializzando... + rawData = JsonConvert.SerializeObject(answ); + setRSV(redServKey, rawData); + } + else + { + // deserializzo + answ = JsonConvert.DeserializeObject(rawData); + } + return answ; } set { - redServerStatus.Store(value); + string rawData = JsonConvert.SerializeObject(value); + setRSV(redServKey, rawData); } } /// @@ -79,12 +954,70 @@ namespace IOB_UT { get { - return redIobStatus.GetById(1); + IobWinStatus answ = null; + // cerco in REDIS + string rawData = getRSV(redIobKey); + // se non ci fosse creo e salvo + if (string.IsNullOrEmpty(rawData)) + { + answ = new IobWinStatus() + { + CodIob = CodIob, + online = false + }; + // salvo serializzando... + rawData = JsonConvert.SerializeObject(answ); + setRSV(redIobKey, rawData); + } + else + { + // deserializzo + answ = JsonConvert.DeserializeObject(rawData); + } + return answ; } set { - redIobStatus.Store(value); + string rawData = JsonConvert.SerializeObject(value); + setRSV(redIobKey, rawData); } } + /// + /// Variabile in cui viene salvato lo stato ONLINE del server MP-IO + /// + public bool MPIO_Online + { + get + { + return servStatus.online; + } + set + { + var currData = servStatus; + currData.online = value; + currData.lastUpdate = DateTime.Now; + servStatus = currData; + } + } + /// + /// Variabile in cui viene salvato lo stato ONLINE dell'IOB + /// + public bool IOB_Online + { + get + { + return iobStatus.online; + } + set + { + var currData = iobStatus; + currData.online = value; + currData.lastUpdate = DateTime.Now; + iobStatus = currData; + } + } + + + #endregion } } diff --git a/IOB-UT/baseUtils.cs b/IOB-UT/baseUtils.cs index 03d18445..8ce69b0c 100644 --- a/IOB-UT/baseUtils.cs +++ b/IOB-UT/baseUtils.cs @@ -47,33 +47,50 @@ namespace IOB_UT { /// - /// Oggetto gestione persistenza su REDIS (statico) + /// Oggetto connessione REDIS /// - public static RedisCache redManager = new RedisCache(); - /// - /// Variabile in cui viene salvato lo stato del server MP-IO - /// - public static bool MPIO_Online - { - get - { - return redManager.servStatus.online; - } - set - { - var currData = redManager.servStatus; - currData.online = value; - redManager.servStatus = currData; - } - } + public static RedisIobCache redisMan = new RedisIobCache(); /// /// Indicazione VETO PING a server sino alla data-ora indicata /// public static DateTime dtVetoPing = DateTime.Now; +#if false + { + get + { + return redisMan.servStatus.dtVetoPing; + } + set + { + var currData = redisMan.servStatus; + currData.dtVetoPing = value; + redisMan.servStatus = currData; + } + } +#endif /// /// Indicazione VETO invio a server sino alla data-ora indicata /// public static DateTime dtVetoSend = DateTime.Now; +#if false + { + get + { + return redisMan.servStatus.dtVetoSend; + } + set + { + var currData = redisMan.servStatus; + currData.dtVetoSend = value; + redisMan.servStatus = currData; + } + } +#endif + /// + /// Status MP_IO + /// + public static bool MPIO_Online = false; + /// /// Calcola una pausa con errore casuale x il prossimo send programmato verso SERVER /// @@ -91,10 +108,6 @@ namespace IOB_UT } } /// - /// oggetto static x gestione baseUtils - /// - public static baseUtils mgr = new baseUtils(); - /// /// Classe logger /// public static Logger lg = LogManager.GetCurrentClassLogger(); diff --git a/IOB-UT/packages.config b/IOB-UT/packages.config index 7e6fba6a..78d59d0a 100644 --- a/IOB-UT/packages.config +++ b/IOB-UT/packages.config @@ -6,9 +6,6 @@ - - - - + \ No newline at end of file diff --git a/IOB-WIN/AdapterForm.cs b/IOB-WIN/AdapterForm.cs index 7a266ee8..a1220b41 100644 --- a/IOB-WIN/AdapterForm.cs +++ b/IOB-WIN/AdapterForm.cs @@ -464,6 +464,16 @@ namespace IOB_WIN // aggiorno labels counters... counterIob = $"pz iob {iobObj.contapezzi}"; counterMac = $"pz mac {iobObj.lastCountCNC}"; + // salvo ANCHE in redis... + var currIobStatus = iobObj.redisMan.iobStatus; + currIobStatus.queueEvLen = evQueueLen; + currIobStatus.queueFlLen = flQueueLen; + currIobStatus.queueAlLen = alQueueLen; + currIobStatus.queueMsLen = msQueueLen; + currIobStatus.counterIOB = iobObj.contapezzi; + currIobStatus.counterMAC = iobObj.lastCountCNC; + currIobStatus.lastUpdate = DateTime.Now; + iobObj.redisMan.iobStatus = currIobStatus; } private void gather_Tick(object sender, EventArgs e) { diff --git a/IOB-WIN/App.config b/IOB-WIN/App.config index dcc75e67..b5ce548d 100644 --- a/IOB-WIN/App.config +++ b/IOB-WIN/App.config @@ -38,13 +38,16 @@ - + - + + + + diff --git a/IOB-WIN/DATA/CONF/MAIN.ini b/IOB-WIN/DATA/CONF/MAIN.ini index 7a474602..748b548c 100644 --- a/IOB-WIN/DATA/CONF/MAIN.ini +++ b/IOB-WIN/DATA/CONF/MAIN.ini @@ -7,12 +7,13 @@ NAME=master ;MPIP=192.168.1.7 ; server VALVITAL ;MPIP=192.168.214.4 -; Server Steamware -;MPIP=10.74.82.218 ; server interclays -MPIP=10.0.0.233 +;MPIP=10.0.0.233 ; server REMOSA -MPIP=192.168.0.110 +;MPIP=192.168.0.110 + +; Server Steamware +MPIP=10.74.82.218 MPURL=/MP/IO CMDREBO=/IOB/sendRebootGateway?GWIP= CMDIOB2CALL=/IOB/getIob2call?GWIP= diff --git a/IOB-WIN/IobFanuc.cs b/IOB-WIN/IobFanuc.cs index 65a3ce97..0ec13149 100644 --- a/IOB-WIN/IobFanuc.cs +++ b/IOB-WIN/IobFanuc.cs @@ -203,13 +203,13 @@ namespace IOB_WIN // aggiungo referenza obj FANUC FANUC_ref = (FANUC)Runtime.NC; - if (isVerboseLog) + if (isVerboseLog) { lgInfo("FANUC_ref da CncLib"); } // disconnetto e connetto... - if (isVerboseLog) + if (isVerboseLog) { lgInfo("FANUC: tryDisconnect"); } @@ -361,7 +361,7 @@ namespace IOB_WIN { memAddressFanuc areaCounter = new memAddressFanuc(memAddr); - if (isVerboseLog) + if (isVerboseLog) { lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); } @@ -936,14 +936,16 @@ namespace IOB_WIN } // salvo ultimo conteggio rilevato - Int32.TryParse(outputVal.ToString(), out lastCountCNC); + int newVal = -1; + Int32.TryParse(outputVal.ToString(), out newVal); + lastCountCNC = newVal > -1 ? newVal : lastCountCNC; } // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW else { memAddressFanuc areaCounter = new memAddressFanuc(memAddr); - if (isVerboseLog) + if (isVerboseLog) { lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); } @@ -966,13 +968,13 @@ namespace IOB_WIN case "DW": uint valDW = 0; FANUC_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); - if (isVerboseLog) + if (isVerboseLog) { lgInfo("[1] valDW contapezzi: {0}", valDW); } outputVal = valDW; - if (isVerboseLog) + if (isVerboseLog) { lgInfo("[2] outputVal contapezzi: {0}", outputVal); } @@ -987,8 +989,10 @@ namespace IOB_WIN } // salvo... - Int32.TryParse(outputVal.ToString(), out lastCountCNC); - if (isVerboseLog) + int newVal = -1; + Int32.TryParse(outputVal.ToString(), out newVal); + lastCountCNC = newVal > -1 ? newVal : lastCountCNC; + if (isVerboseLog) { lgInfo("[3] lastCountCNC contapezzi: {0}", lastCountCNC); } @@ -1091,7 +1095,7 @@ namespace IOB_WIN { memAddressFanuc areaCounter = new memAddressFanuc(memAddr); - if (isVerboseLog) + if (isVerboseLog) { lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); } @@ -1114,13 +1118,13 @@ namespace IOB_WIN case "DW": uint valDW = 0; FANUC_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); - if (isVerboseLog) + if (isVerboseLog) { lgInfo("[1] valDW PAR: {0}", valDW); } outputVal = valDW; - if (isVerboseLog) + if (isVerboseLog) { lgInfo("[2] outputVal PAR: {0}", outputVal); } @@ -1136,7 +1140,7 @@ namespace IOB_WIN // salvo... answ = outputVal.ToString(); - if (isVerboseLog) + if (isVerboseLog) { lgInfo("[3] PAR letto: {0} | {1}", varName, answ); } diff --git a/IOB-WIN/IobGeneric.cs b/IOB-WIN/IobGeneric.cs index aea815ca..e67ccca2 100644 --- a/IOB-WIN/IobGeneric.cs +++ b/IOB-WIN/IobGeneric.cs @@ -46,7 +46,44 @@ namespace IOB_WIN } public class IobGeneric - { + { + #region variabili serializzate in REDIS + + /// + /// Oggetto connessione REDIS + /// + public RedisIobCache redisMan; + + /// + /// stato Online/Offline della IOB + /// + public bool IobOnline + { + get + { + return redisMan.IOB_Online; + } + set + { + redisMan.IOB_Online = value; + } + } + /// + /// stato Online/Offline del server MP IO (su REDIS) + /// + public bool MPOnline + { + get + { + return redisMan.MPIO_Online; + } + set + { + redisMan.MPIO_Online = value; + } + } + #endregion + #region variabili ed oggetti base /// @@ -57,10 +94,6 @@ namespace IOB_WIN /// TImeout x ping al server /// protected int pingServerMsTimeout = utils.CRI("pingMsTimeout"); - /// - /// Indica impianto IN SETUP (fino a quando SMETTE di esserlo...) - /// - protected bool inSetup = false; /// /// Log verboso da configurazione (SOLO CHAIVE "verbose"... /// @@ -68,33 +101,51 @@ namespace IOB_WIN /// /// Coda massima ammessa per FLog (se <=0 disattivata...) /// - protected int maxQueueFLog { get; set; } = utils.CRI("maxQueueFLog"); + protected int maxQueueFLog { get; set; } = utils.CRI("maxQueueFLog"); + /// + /// Indica impianto IN SETUP (fino a quando SMETTE di esserlo...) + /// + protected bool inSetup = false; + /// + /// Indicazione VETO PING a server sino alla data-ora indicata + /// + public DateTime dtVetoPing + { + get + { + return utils.dtVetoPing; + } + set + { + utils.dtVetoPing = value; + } + } /// /// Indicazione VETO invio a server sino alla data-ora indicata /// - public static DateTime dtVetoPing + public DateTime dtVetoSend { get - { - return utils.dtVetoPing; + { + return utils.dtVetoSend; } set - { - utils.dtVetoPing = value; + { + utils.dtVetoSend = value; } } /// /// Indicazione VETO check status IOB x evitare loop troppo stretti... /// - public DateTime dtVetoCheckIOB = DateTime.Now; + public DateTime dtVetoCheckIOB = DateTime.Now.AddDays(-1); /// /// Contapezzi attuale /// - public Int32 contapezzi; + public Int32 contapezzi = 0; /// /// Ultima lettura variabile contapezzi da CNC /// - public Int32 lastCountCNC; + public Int32 lastCountCNC = 0; /// /// ODL attualmente sulla macchina /// @@ -439,24 +490,7 @@ namespace IOB_WIN /// Conteggio ATTUALE ore macchina IN LAVORO /// public double contOreMaccLav; - /// - /// stato Online/Offline della IOB - /// - public bool IobOnline; - /// - /// stato Online/Offline del server MP IO (su utils condiviso) - /// - public bool MPOnline - { - get - { - return utils.MPIO_Online; - } - set - { - utils.MPIO_Online = value; - } - } + /// /// Data/ora ultima volta che IOB è stato dichairato online /// @@ -472,10 +506,11 @@ namespace IOB_WIN /// /// Dizionario di VARIABILI da trattare come eventi (da inviare quando cambiano oppure a scadenza periodo...) /// - protected Dictionary VarArray = new Dictionary(); - + protected Dictionary VarArray = new Dictionary(); + #endregion + /// /// Form chiamante /// @@ -519,6 +554,9 @@ namespace IOB_WIN /// public IobGeneric(AdapterForm caller, IobConfiguration IOBConf) { + // init oggetto redis... + redisMan = new RedisIobCache(IOBConf.serverData.MPIP, IOBConf.codIOB); + // salvo il form chiamante parentForm = caller; // configurazione... @@ -1003,8 +1041,10 @@ namespace IOB_WIN { // se "-1" resto a ultimo... if (currServerCount != "-1") - { - int.TryParse(currServerCount, out contapezzi); + { + int newVal = -1; + Int32.TryParse(currServerCount, out newVal); + contapezzi = newVal > -1 ? newVal : contapezzi; lgInfo("Ricevuta conferma da server di {0} pezzi registrati per ODL", currServerCount); } else @@ -1307,8 +1347,17 @@ namespace IOB_WIN // verifico se risponde il server... if (checkServerAlive) { - // verifico SE posso inviare dati - if (checkIobEnabled) + bool iobOk = false; + if (utils.CRB("sendDataByThread")) + { + Task taskCheck = TaskEx.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) @@ -2838,12 +2887,12 @@ namespace IOB_WIN answ = (callResp == "OK"); // attesa casuale se necessario var rand = new Random(); - // primi 3 test - int maxTry = 3; + // primi 2 test + int maxTry = 2; while (maxTry > 0 && !answ) { - Thread.Sleep(rand.Next(150, 500)); - callResp = callUrl(urlIobEnabled, false); + Thread.Sleep(rand.Next(250, 500)); + callResp = callUrl(urlIobEnabled, true); answ = (callResp == "OK"); maxTry--; } @@ -2851,32 +2900,27 @@ namespace IOB_WIN if (!answ) { resetwebClients(); - Thread.Sleep(rand.Next(500, 1000)); + Thread.Sleep(rand.Next(250, 1000)); callResp = callUrl(urlIobEnabled, false); answ = (callResp == "OK"); - } - // altri 3 - maxTry = 3; + } + // altri 2 + maxTry = 2; while (maxTry > 0 && !answ) { - Thread.Sleep(rand.Next(150, 500)); + Thread.Sleep(rand.Next(250, 500)); callResp = callUrl(urlIobEnabled, false); answ = (callResp == "OK"); maxTry--; - } - // salvo status... + } + // salvo status... IobOnline = answ; - // se offline imposto veto check a 5 x tempo reinvio... - if (!answ) + // se online imposto veto check a 5 x tempo reinvio... + if (answ) { - dtVetoCheckIOB = DateTime.Now.AddMilliseconds(baseUtils.nextPauseSendMSec * 10); - } - else - { - // non controllo x meno... - dtVetoCheckIOB = DateTime.Now.AddMilliseconds(baseUtils.nextPauseSendMSec * 5); lastIobOnline = DateTime.Now; - } + } + dtVetoCheckIOB = DateTime.Now.AddMilliseconds(baseUtils.nextPauseSendMSec * 5); } catch { } @@ -4265,15 +4309,6 @@ namespace IOB_WIN accodaSignaInlData(newString); #endif } -#if false - /// - /// Mostra cosa ha/avrebbe inviato - /// - public void displayOutData() - { - accodaUrlData(lastUrl); - } -#endif /// /// Mostra cosa ha/avrebbe inviato /// @@ -4283,28 +4318,6 @@ namespace IOB_WIN // mostro update... accodaOtherData(newData); } -#if false - /// - /// Accoda (visualizzando in cima allo stack) la nuova stringa di output per area OTHER DATA - /// - /// - public void accodaSignaInlData(string newLine) - { - // inserisco in cima allo stack, trimmo e aggiorno display - parentForm.dataMonitor_1 = limitLine2show(string.Format("{0}{1}{2}", newLine, Environment.NewLine, parentForm.dataMonitor_1)); - } -#endif -#if false - /// - /// Accoda (visualizzando in cima allo stack) la nuova stringa di output per area OTHER DATA - /// - /// - public void accodaUrlData(string newLine) - { - // inserisco in cima allo stack, trimmo e aggiorno display - parentForm.dataMonitor_2 = limitLine2show(string.Format("{0}{1}{2}", newLine, Environment.NewLine, parentForm.dataMonitor_2)); - } -#endif /// /// Accoda (visualizzando in cima allo stack) la nuova stringa di output per area OTHER DATA /// diff --git a/IOB-WIN/IobMTC.cs b/IOB-WIN/IobMTC.cs index 18939a16..f9725df7 100644 --- a/IOB-WIN/IobMTC.cs +++ b/IOB-WIN/IobMTC.cs @@ -912,7 +912,9 @@ namespace IOB_WIN // se ho un contapezzi... processo... if (!string.IsNullOrEmpty(currPzCount)) { - int.TryParse(currPzCount, out lastCountCNC); + int newVal = -1; + Int32.TryParse(currPzCount, out newVal); + lastCountCNC = newVal > -1 ? newVal : lastCountCNC; } } } diff --git a/IOB-WIN/IobSiemens.cs b/IOB-WIN/IobSiemens.cs index 708b6a68..c4945a33 100644 --- a/IOB-WIN/IobSiemens.cs +++ b/IOB-WIN/IobSiemens.cs @@ -1106,7 +1106,9 @@ namespace IOB_WIN break; } // salvo... - Int32.TryParse(outputVal.ToString(), out lastCountCNC); + int newVal = -1; + Int32.TryParse(outputVal.ToString(), out newVal); + lastCountCNC = newVal > -1 ? newVal : lastCountCNC; if (isVerboseLog) { lgInfo("[2] outputVal contapezzi: {0}", outputVal); diff --git a/IOB-WIN/MainForm.cs b/IOB-WIN/MainForm.cs index a70057a0..a1f7dcb9 100644 --- a/IOB-WIN/MainForm.cs +++ b/IOB-WIN/MainForm.cs @@ -22,6 +22,10 @@ namespace IOB_WIN { #region variabili globali, utils ed helpers + /// + /// Oggetto connessioen REDIS + /// + public RedisIobCache redisMan; /// /// Parametri (opzionali) di avvio /// @@ -362,6 +366,7 @@ namespace IOB_WIN protected void myInit() { + DateTime adesso = DateTime.Now; resetProgBar = 0; formStartTime = adesso; @@ -541,6 +546,15 @@ namespace IOB_WIN IOB2START.Add("NONE"); } } + + + // init redis... + string firstIob = "00"; + if (IOB2START.Count > 0) + { + firstIob = IOB2START[0]; + } + redisMan = new RedisIobCache(MPIP, firstIob); } #endregion @@ -624,7 +638,7 @@ namespace IOB_WIN lgError($"Errore in checkServerAlive:{Environment.NewLine}{exc}"); } // verifico SE è variato stato online/offline... - if (utils.MPIO_Online != answ) + if (redisMan.MPIO_Online != answ) { // se ORA sono online riporto... if (answ) @@ -637,7 +651,7 @@ namespace IOB_WIN lgInfo("SERVER OFFLINE in MainForm:testServer"); } // salvo nuovo status... - utils.MPIO_Online = answ; + redisMan.MPIO_Online = answ; } else { @@ -648,7 +662,7 @@ namespace IOB_WIN else { lgInfo($"SERVER NOT RESPONDING (PING at {MPIP})"); - utils.MPIO_Online = false; + redisMan.MPIO_Online = false; updateComStats(0, 0, false); // imposto veto a 10 volte reinvio dati standard... utils.dtVetoPing = DateTime.Now.AddMilliseconds(baseUtils.nextPauseSendMSec * 10); @@ -658,7 +672,7 @@ namespace IOB_WIN else { // altrimenti passo ultimo valore noto... - answ = utils.MPIO_Online; + answ = redisMan.MPIO_Online; } } return answ; diff --git a/Jenkinsfile b/Jenkinsfile index 1ee20332..fa7bce1b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -16,7 +16,7 @@ pipeline { /* calcolo numero versione... diverso x branch MASTER/DEVELOP */ script { - withEnv(['NEXT_BUILD_NUMBER=638']) { + withEnv(['NEXT_BUILD_NUMBER=641']) { // env.versionNumber = VersionNumber(versionNumberString : '3.0.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true) env.versionNumber = VersionNumber(versionNumberString : '3.0.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true, overrideBuildsAllTime: '${NEXT_BUILD_NUMBER}') env.APP_NAME = 'MAPO-IOB-WIN'