Merge branch 'develop'

This commit is contained in:
2022-10-25 11:17:20 +02:00
25 changed files with 206 additions and 177 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>AnyCPU;x86;x64</Platforms>
<Version>1.2.2210.2420</Version>
<Version>1.2.2210.2510</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>MAPO-MONO</i>
<h4>Version: 1.2.2210.2420</h4>
<h4>Version: 1.2.2210.2510</h4>
<br /> Release Note:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
1.2.2210.2420
1.2.2210.2510
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>1.2.2210.2420</version>
<version>1.2.2210.2510</version>
<url>http://nexus.steamware.net/repository/SWS/MP.MONO.ANALYZER/stable/LAST/MP.Mon.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/MP.MONO.ANALYZER/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+1
View File
@@ -46,6 +46,7 @@ namespace MP.MONO.Core
public static readonly string ALARM_ACT_KEY = $"{BASE_HASH}:Current:AlarmsVal";
public static readonly string ALARM_BLINK_CURR_KEY = $"{BASE_HASH}:Current:AlarmsBlink";
public static readonly string ALARM_CURR_KEY = $"{BASE_HASH}:Current:Alarms";
public static readonly string ALARM_LOG_SAVED = $"{BASE_HASH}:Current:AlarmsLogSaved";
public static readonly string ALARM_RECEIV_KEY = $"{BASE_HASH}:Current:AlarmsReceived";
public static readonly string ALARM_PEND_KEY = $"{BASE_HASH}:Current:AlarmsPendingClose";
public static readonly string EVENT_LOG_CURR_KEY = $"{BASE_HASH}:Current:EventsLog";
+105 -141
View File
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Configuration;
using MP.MONO.Core;
using MP.MONO.Data;
using MP.MONO.Data.Controllers;
@@ -6,6 +7,7 @@ using MP.MONO.Data.DbModels;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Collections.Concurrent;
namespace MP.MONO.DECODER
{
@@ -54,30 +56,8 @@ namespace MP.MONO.DECODER
/// </summary>
public static List<string> alarmsActAck
{
get
{
List<string> answ = new List<string>();
if (useRedis)
{
answ = getAlarms("Current");
}
else
{
answ = _alarmsActAck;
}
return answ;
}
set
{
if (useRedis)
{
setAlarms("Current", value);
}
else
{
_alarmsActAck = value;
}
}
get => getAlarms(redisDb.StringGet(Constants.ALARM_CURR_KEY));
set => setAlarms(Constants.ALARM_CURR_KEY, value);
}
/// <summary>
@@ -85,30 +65,8 @@ namespace MP.MONO.DECODER
/// </summary>
public static List<string> alarmsLastRec
{
get
{
List<string> answ = new List<string>();
if (useRedis)
{
answ = getAlarms("LastReceived");
}
else
{
answ = _alarmsLastRec;
}
return answ;
}
set
{
if (useRedis)
{
setAlarms("LastReceived", value);
}
else
{
_alarmsLastRec = value;
}
}
get => getAlarms(redisDb.StringGet(Constants.ALARM_RECEIV_KEY));
set => setAlarms(Constants.ALARM_RECEIV_KEY, value);
}
/// <summary>
@@ -116,8 +74,8 @@ namespace MP.MONO.DECODER
/// </summary>
public static string alarmsLogSaved
{
get => _alarmsLogSaved;
set => _alarmsLogSaved = value;
get => redisDb.StringGet(Constants.ALARM_LOG_SAVED);
set => redisDb.StringSet(Constants.ALARM_LOG_SAVED, value);
}
public static List<string> alarmsPendingClose
@@ -127,27 +85,21 @@ namespace MP.MONO.DECODER
// rileggo da REDIS SE ci sono allarmi che sono pending close... in un area che dura poco (2 sec)
List<string> lista = new List<string>();
// in base al tipo leggo una chiave redis o l'altra...
if (redisDb != null)
string rawData = redisDb.StringGet(Constants.ALARM_PEND_KEY);
if (!string.IsNullOrEmpty(rawData))
{
string rawData = redisDb.StringGet(Constants.ALARM_PEND_KEY);
if (!string.IsNullOrEmpty(rawData))
var desList = JsonConvert.DeserializeObject<List<string>>(rawData);
if (desList != null)
{
var desList = JsonConvert.DeserializeObject<List<string>>(rawData);
if (desList != null)
{
lista = desList;
}
lista = desList;
}
}
return lista;
}
set
{
if (redisDb != null)
{
string rawData = JsonConvert.SerializeObject(value);
redisDb.StringSet(Constants.ALARM_PEND_KEY, rawData, TimeSpan.FromMilliseconds(3000));
}
string rawData = JsonConvert.SerializeObject(value);
redisDb.StringSet(Constants.ALARM_PEND_KEY, rawData, TimeSpan.FromMilliseconds(3000));
}
}
@@ -155,6 +107,61 @@ namespace MP.MONO.DECODER
#region Public Methods
public static bool isProcessing { get; set; } = false;
private static int ticketNum { get; set; } = 0;
private static ConcurrentQueue<int> reqList { get; set; } = new ConcurrentQueue<int>();
/// <summary>
/// Recupera un ticket di esecuzione x eseguire in ordine corretto gli insert...
/// </summary>
/// <returns></returns>
public static int getTicket()
{
// incremento contatore
ticketNum++;
// faccio coda 0...999
ticketNum = ticketNum > 99 ? 1 : ticketNum;
// accodo...
reqList.Enqueue(ticketNum);
// rendo ticket
return ticketNum;
}
/// <summary>
/// Indica il ticket attualmente in esecuzione
/// </summary>
/// <returns></returns>
public static int currTicket
{
get
{
int answ = -1;
reqList.TryPeek(out answ);
return answ;
}
}
/// <summary>
/// Verifico se il mio ticket sia quello corretto/prossimo
/// </summary>
/// <param name="ticket"></param>
/// <returns></returns>
public static bool checklTicket(int ticket)
{
bool fatto = false;
if (!isProcessing)
{
// verifico se quello richiesto sia il ticket giusto
if (ticket == currTicket)
{
isProcessing = true;
int usedTicket = 0;
fatto = reqList.TryDequeue(out usedTicket);
}
}
return fatto;
}
/// <summary>
/// restituisce elenco allarmi muted, eventualmente da cache redis ( 5 sec)
/// </summary>
@@ -166,39 +173,36 @@ namespace MP.MONO.DECODER
List<string> mutedAlarm = new List<string>();
string rawData = "";
// cerco in redis...
if (redisDb != null)
rawData = redisDb.StringGet(Constants.ALARMS_SETT_MUTED_KEY);
if (!string.IsNullOrEmpty(rawData))
{
rawData = redisDb.StringGet(Constants.ALARMS_SETT_MUTED_KEY);
var rawAlarm = JsonConvert.DeserializeObject<List<string>>(rawData);
if (rawAlarm != null)
{
mutedAlarm = rawAlarm;
}
}
else
{
// altrimenti da conf/DB... gestione allarmi muted
List<AlarmListModel>? alarmListSetup = new List<AlarmListModel>();
rawData = redisDb.StringGet(Constants.ALARMS_SETT_RLIST_KEY);
if (!string.IsNullOrEmpty(rawData))
{
var rawAlarm = JsonConvert.DeserializeObject<List<string>>(rawData);
if (rawAlarm != null)
{
mutedAlarm = rawAlarm;
}
alarmListSetup = JsonConvert.DeserializeObject<List<AlarmListModel>>(rawData);
}
else
if (alarmListSetup == null)
{
// altrimenti da conf/DB... gestione allarmi muted
List<AlarmListModel>? alarmListSetup = new List<AlarmListModel>();
rawData = redisDb.StringGet(Constants.ALARMS_SETT_RLIST_KEY);
if (!string.IsNullOrEmpty(rawData))
{
alarmListSetup = JsonConvert.DeserializeObject<List<AlarmListModel>>(rawData);
}
if (alarmListSetup == null)
{
alarmListSetup = dbController.AlarmListGetAll();
}
// calcolo come lista string...
if (alarmListSetup != null && alarmListSetup.Count > 0)
{
mutedAlarm = alarmListSetup.Where(x => x.Muted).Select(x => x.FullValue).ToList();
}
// salvo cache in redis x 1 minuto...
rawData = JsonConvert.SerializeObject(mutedAlarm);
redisDb.StringSet(Constants.ALARMS_SETT_MUTED_KEY, rawData, TimeSpan.FromSeconds(60));
alarmListSetup = dbController.AlarmListGetAll();
}
// calcolo come lista string...
if (alarmListSetup != null && alarmListSetup.Count > 0)
{
mutedAlarm = alarmListSetup.Where(x => x.Muted).Select(x => x.FullValue).ToList();
}
// salvo cache in redis x 1 minuto...
rawData = JsonConvert.SerializeObject(mutedAlarm);
redisDb.StringSet(Constants.ALARMS_SETT_MUTED_KEY, rawData, TimeSpan.FromSeconds(60));
}
return mutedAlarm;
}
@@ -317,9 +321,7 @@ namespace MP.MONO.DECODER
private static ConnectionMultiplexer? redisConn = null;
private static IDatabase? redisDb = null;
private static bool useRedis = true;
private static IDatabase redisDb = null!;
private static MpDbController dbController = null!;
@@ -327,76 +329,38 @@ namespace MP.MONO.DECODER
#region Private Properties
/// <summary>
/// Elenco allarmi attivi e acknowled ad es: subito i nuovi, con ritardo i cessati
/// </summary>
private static List<string> _alarmsActAck { get; set; } = new List<string>();
/// <summary>
/// Elenco ultimo set allarmi ricevuti
/// </summary>
private static List<string> _alarmsLastRec { get; set; } = new List<string>();
/// <summary>
/// Elenco allarmi registrati come LOG (=ultima variazione riconosciuta)
/// </summary>
private static string _alarmsLogSaved { get; set; } = "";
#endregion Private Properties
#region Private Methods
/// <summary>
/// Recupero da redis gli allarmi secondo tipo LastReceived / Current
/// Converto deserializzando lista allarmi
/// </summary>
private static List<string> getAlarms(string tipo)
private static List<string> getAlarms(string rawData)
{
// rileggo da REDIS la conf attuale allarmi già attivi da area ALARM_CURR_KEY
List<string> lastAlarms = new List<string>();
// in base al tipo leggo una chiave redis o l'altra...
string rawData = "";
if (redisDb != null)
{
if (tipo == "LastReceived")
{
rawData = redisDb.StringGet(Constants.ALARM_RECEIV_KEY);
}
else
{
rawData = redisDb.StringGet(Constants.ALARM_CURR_KEY);
}
}
// se trovati uso questi...
if (!string.IsNullOrEmpty(rawData))
{
var rawLastAlarms = JsonConvert.DeserializeObject<List<string>>(rawData);
lastAlarms = rawLastAlarms != null ? rawLastAlarms : new List<string>();
Log.Debug($"Lettura allarmi | tipo: {tipo} | num: {lastAlarms.Count}");
}
return lastAlarms;
}
/// <summary>
/// Salvo in redis gli allarmi secondo tipo LastReceived / Sent
/// Salvo in redis gli allarmi datala key
/// </summary>
private static bool setAlarms(string tipo, List<string> listAlarm)
/// <param name="keyName"></param>
/// <param name="listAlarm"></param>
/// <returns></returns>
private static bool setAlarms(string keyName, List<string> listAlarm)
{
bool fatto = false;
string rawData = JsonConvert.SerializeObject(listAlarm);
if (redisDb != null)
{
if (tipo == "LastReceived")
{
fatto = redisDb.StringSet(Constants.ALARM_RECEIV_KEY, rawData);
}
else
{
fatto = redisDb.StringSet(Constants.ALARM_CURR_KEY, rawData);
}
}
Log.Debug($"Scrittura allarmi | tipo: {tipo} | num: {listAlarm.Count}");
fatto = redisDb.StringSet(keyName, rawData);
Log.Debug($"Scrittura allarmi | key: {keyName} | num: {listAlarm.Count}");
return fatto;
}
+1 -1
View File
@@ -6,7 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>AnyCPU;x86;x64</Platforms>
<Version>1.2.2210.2420</Version>
<Version>1.2.2210.2511</Version>
</PropertyGroup>
<ItemGroup>
+2 -1
View File
@@ -51,7 +51,8 @@
<logger name="*" minlevel="Debug" writeTo="f" />
-->
<!--<logger name="Microsoft.*" maxlevel="Info" final="true" />-->
<!--<logger name="*" minlevel="Info" writeTo="consoleTarget" />-->
<!--<logger name="*" minlevel="Debug" writeTo="consoleTarget" />-->
<logger name="*" minlevel="Info" writeTo="consoleTarget" />
<logger name="*" minlevel="Info" writeTo="fileTarget" />
</rules>
</nlog>
+48 -8
View File
@@ -9,6 +9,7 @@ using MP.MONO.DECODER;
using Newtonsoft.Json;
using NLog;
using Org.BouncyCastle.Asn1.Pkcs;
using Pomelo.EntityFrameworkCore.MySql.Query.Internal;
using StackExchange.Redis;
using System.Diagnostics;
using System.Reflection;
@@ -379,6 +380,8 @@ async void AlarmsValPipe_EA_NewMessage(object? sender, EventArgs e)
List<AlarmRecModel> alarmRecList = new List<AlarmRecModel>();
List<AlarmLogModel> alarmLogList = new List<AlarmLogModel>();
Random rand = new Random();
if (alarmMode == AlarmReportingMode.RawList)
{
try
@@ -596,7 +599,14 @@ async void AlarmsValPipe_EA_NewMessage(object? sender, EventArgs e)
// salvo sul DB
if (alarmRecList.Count > 0)
{
_ = dbController.AlarmRecInsertMany(alarmRecList);
foreach (var item in alarmRecList)
{
_ = dbController.AlarmRecInsert(item);
await Task.Delay(10);
}
#if false
_ = dbController.AlarmRecInsertMany(alarmRecList);
#endif
}
if (alarmLogList.Count > 0)
{
@@ -611,11 +621,30 @@ async void AlarmsValPipe_EA_NewMessage(object? sender, EventArgs e)
}
else if (alarmMode == AlarmReportingMode.RawListBlink)
{
int numTry = 0;
int myTicket = 0;
Stopwatch stopWatch = new Stopwatch();
try
{
myTicket = AlarmsBlinkManager.getTicket();
// attendo che NON ci siano altri processi in coda...
while (!AlarmsBlinkManager.checklTicket(myTicket))
{
await Task.Delay(rand.Next(10, 30));
if (numTry % 10 == 0)
{
TimeSpan ts = DateTime.Now.Subtract(adesso);
Log.Info($"Ticket {myTicket} | total wait {ts.TotalMilliseconds:N3}ms");
}
numTry++;
}
stopWatch.Start();
Log.Debug($"---------- INIZIO ticket {myTicket} ---------- ");
// decodifico allarmi ricevuti
var alarmListRaw = JsonConvert.DeserializeObject<List<string>>(currArgs.newMessage);
var alarmListRcvd = alarmListRaw != null ? alarmListRaw : new List<string>();
var alarmListRcvd = alarmListRaw != null ? alarmListRaw : new List<string>();
// bonifico allarmi
var alarmiListClean = AlarmsBlinkManager.cleanAlarms(AlarmCleanPre, AlarmCleanPost, alarmListRcvd);
@@ -633,7 +662,7 @@ async void AlarmsValPipe_EA_NewMessage(object? sender, EventArgs e)
alarmsSendPipe.saveAndSendMessage(Constants.ALARM_CURR_KEY, serAlarms);
// se cambiato --> ultimo ricevuto != current...
string lastLogList = AlarmsBlinkManager.alarmsLogSaved;
string lastLogList = AlarmsBlinkManager.alarmsLogSaved != null ? AlarmsBlinkManager.alarmsLogSaved : "";
// calcolo nuova stringa...
string newLogString = string.Join(", ", alarmiListClean);
bool logChanged = !lastLogList.Equals(newLogString);
@@ -677,6 +706,12 @@ async void AlarmsValPipe_EA_NewMessage(object? sender, EventArgs e)
}
}
// salvo sul DB
#if false
foreach (var item in alarmRecList)
{
_ = dbController.AlarmRecInsert(item);
}
#endif
_ = dbController.AlarmRecInsertMany(alarmRecList);
Log.Debug($"Inseriti {alarmRecList.Count} Records AlarmRecModel");
}
@@ -685,18 +720,23 @@ async void AlarmsValPipe_EA_NewMessage(object? sender, EventArgs e)
// chiamo task x verifica chiusura ritardata
foreach (var item in ceasedAlarms)
{
await Task.Run(async () =>
await Task.Run(() =>
{
await checkCeasedAlarm(item);
checkCeasedAlarm(item);
});
await Task.Delay(10);
}
// Loggo quanto fatto
Log.Debug($"Chiamato controllo differito per {ceasedAlarms.Count} allarmi cessati");
}
}
catch
{ }
catch (Exception exc)
{
Log.Error($"Eccezione:{Environment.NewLine}{exc}");
}
AlarmsBlinkManager.isProcessing = false;
stopWatch.Stop();
Log.Debug($"---------- Fine ticket {myTicket} | {stopWatch.ElapsedMilliseconds} ms ---------- ");
}
else
{
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>MAPO-MONO</i>
<h4>Version: 1.2.2210.2420</h4>
<h4>Version: 1.2.2210.2511</h4>
<br /> Release Note:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
1.2.2210.2420
1.2.2210.2511
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>1.2.2210.2420</version>
<version>1.2.2210.2511</version>
<url>http://nexus.steamware.net/repository/SWS/MP.MONO.DECODER/stable/LAST/MP.Mon.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/MP.MONO.DECODER/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+1 -1
View File
@@ -41,6 +41,6 @@
//"AlarmRegexp": "^{.*}",
"BlinkCount": 3,
"DbSampleInt": 60,
"BlinkPeriodMSec": 1200
"BlinkPeriodMSec": 2000
}
}
+29 -6
View File
@@ -506,18 +506,39 @@ namespace MP.MONO.Data.Controllers
bool fatto = false;
using (MapoMonoContext localDbCtx = new MapoMonoContext())
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
try
{
localDbCtx
.DbSetAlarmRec
.Add(newItem);
await localDbCtx.SaveChangesAsync();
fatto = true;
// verifico non sia già aperto...
// verifico eventuali items già aperti da NON dover aggiungere...
var stillOpenAlarms = localDbCtx
.DbSetAlarmRec
.Where(x => x.DtStart >= x.DtEnd && x.AlarmId == newItem.AlarmId)
.Select(x=> x.AlarmId)
.ToList();
// se ho trovato --> salto!
if (stillOpenAlarms != null && stillOpenAlarms.Count > 0)
{
Log.Error($"Errore: trovato {stillOpenAlarms.Count} istanze già attive | Id: {newItem.AlarmId}");
}
else
{
localDbCtx
.DbSetAlarmRec
.Add(newItem);
await localDbCtx.SaveChangesAsync();
fatto = true;
}
}
catch (Exception exc)
{
Log.Error($"Eccezione durante AlarmRecInsert{Environment.NewLine}{exc}");
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Info($"AlarmRecInsert| DB insert 1 rec | {ts.TotalMilliseconds} ms");
}
return fatto;
}
@@ -538,6 +559,7 @@ namespace MP.MONO.Data.Controllers
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
#if false
// verifico eventuali items già aperti da NON dover aggiungere...
List<int>? stillOpenAlarms = localDbCtx
.DbSetAlarmRec
@@ -564,7 +586,8 @@ namespace MP.MONO.Data.Controllers
newItems.Remove(singleItem);
}
}
}
}
#endif
if (newItems.Count > 0)
{
+1 -1
View File
@@ -6,7 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>AnyCPU;x86;x64</Platforms>
<Version>1.2.2210.2420</Version>
<Version>1.2.2210.2510</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -324,7 +324,7 @@ void simAlarms()
newAlarm = rand.Next(0, 100) <= percAllarmi;
if (newAlarm)
{
int numNew = rand.Next(1, MaxAddAllarmi);
int numNew = rand.Next(2, MaxAddAllarmi);
// ciclo x aggiungere il numero di allarmi indicato
for (int i = 0; i < numNew; i++)
{
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>MAPO-MONO</i>
<h4>Version: 1.2.2210.2420</h4>
<h4>Version: 1.2.2210.2510</h4>
<br /> Release Note:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
1.2.2210.2420
1.2.2210.2510
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>1.2.2210.2420</version>
<version>1.2.2210.2510</version>
<url>http://nexus.steamware.net/repository/SWS/MP.MONO.SIM/stable/LAST/MP.Mon.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/MP.MONO.SIM/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+1 -1
View File
@@ -45,7 +45,7 @@
"MinSaveIntSec": 5,
"PercAllarmi": 60,
//"PercAllarmi": 20,
"MaxAddAllarmi": 6,
"MaxAddAllarmi": 10,
"MaxDurationAllarmi": 30,
"PeriodRefresh": 10,
"PeriodOk": 10,
+2 -2
View File
@@ -142,7 +142,7 @@ namespace MP.MONO.UI.Data
{
dbResult = await dbController.AlarmLogGetFilt(machineId, skipRec, numRec);
rawData = JsonConvert.SerializeObject(dbResult);
await redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromMilliseconds(1000));
await redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromMilliseconds(250));
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
@@ -216,7 +216,7 @@ namespace MP.MONO.UI.Data
{
dbResult = await dbController.AlarmRecGetFilt(MachineId, skipRec, numRec);
rawData = JsonConvert.SerializeObject(dbResult);
await redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromMilliseconds(1000));
await redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromMilliseconds(250));
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
+1 -1
View File
@@ -5,7 +5,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Platforms>AnyCPU;x86;x64</Platforms>
<Version>1.2.2210.2509</Version>
<Version>1.2.2210.2510</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>MAPO-MONO</i>
<h4>Version: 1.2.2210.2509</h4>
<h4>Version: 1.2.2210.2510</h4>
<br /> Release Note:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
1.2.2210.2509
1.2.2210.2510
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>1.2.2210.2509</version>
<version>1.2.2210.2510</version>
<url>http://nexus.steamware.net/repository/SWS/MP.MONO.UI/stable/LAST/MP.Mon.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/MP.MONO.UI/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>