Merge branch 'feature/add/risk' into develop

This commit is contained in:
Samuele Locatelli
2020-06-08 11:14:39 +02:00
10 changed files with 473 additions and 39 deletions
+28
View File
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Thermo.Active.Config
{
/// <summary>
/// Live data for Thermo Active
/// </summary>
public class LiveData
{
/// <summary>
/// Current loaded recipe
/// </summary>
public string RecipeName = "current.json";
/// <summary>
/// Dictionary of all parameters and values
/// </summary>
public Dictionary<string, double> RecipeParameters;
/// <summary>
/// Dictionary of all channels and relative setpoints
/// </summary>
public Dictionary<int, double> ChannelSetpoints;
}
}
+12 -4
View File
@@ -32,10 +32,8 @@ namespace Thermo.Active.Config
public static List<NcSoftKeysModel> NcSoftKeysConfig;
public static List<AlarmsConfigModel> InitialAlarmsConfig;
public static List<HeadsConfigModel> HeadsConfig;
public static List<RecipeConfigModel> RecipeConfig;
public static List<ModBlockConfigModel> ModBlockConfig;
public static List<RiskResistModel> RiskResistConfig;
public static List<RiskChannelModel> RiskChannelConfig;
public static CmsConnectConfigModel CmsConnectConfig;
public static AreasConfigModel ProductionConfig;
@@ -55,5 +53,15 @@ namespace Thermo.Active.Config
public static List<string> MacrosConfig;
public static string CMSMainProgramContent;
// Thermo
public static List<RecipeConfigModel> RecipeConfig;
public static List<ModBlockConfigModel> ModBlockConfig;
public static List<RiskResistModel> RiskResistConfig;
public static List<RiskChannelModel> RiskChannelConfig;
public static LiveData RecipeLiveData;
}
}
+98 -3
View File
@@ -15,6 +15,7 @@ using System.Xml.Serialization;
using static Thermo.Active.Config.ServerConfig;
using static Thermo.Active.Model.Constants;
using static Thermo.Active.Utils.SupportFunctions;
using Newtonsoft.Json;
namespace Thermo.Active.Config
{
@@ -39,7 +40,7 @@ namespace Thermo.Active.Config
// ReadCMSConnectConfig();
ReadMacros();
ReadScadaFile();
//ReadMainProgram();
ReadLiveData();
}
catch (XmlException ex)
{
@@ -687,7 +688,7 @@ namespace Thermo.Active.Config
{
// cerco il TIPO...
var riferimento = Riferimenti.Find(x => x.Id == resistenza.Tipo);
if(riferimento!=null)
if (riferimento != null)
{
RiskChannelConfig.Add(new RiskChannelModel()
{
@@ -790,15 +791,109 @@ namespace Thermo.Active.Config
.Select(x => x.Value)
.ToList();
}
/// <summary>
/// Try to load live data from json persistence file
/// </summary>
public static void ReadLiveData()
{
if (File.Exists(LIVE_RECIPE_PATH))
{
// load all text data
var rawData = File.ReadAllText(LIVE_RECIPE_PATH);
try
{
// deserialize to object
RecipeLiveData = JsonConvert.DeserializeObject<LiveData>(rawData);
}
catch
{ }
}
else
{
// setup new object
RecipeLiveData = new LiveData()
{
RecipeName = "current.json",
ChannelSetpoints = new Dictionary<int, double>(),
RecipeParameters = new Dictionary<string, double>()
};
}
}
/// <summary>
/// Try to write live data to json persistence file
/// </summary>
public static void WriteLiveData()
{
try
{
// serialize
string rawData = JsonConvert.SerializeObject(RecipeLiveData);
// save live!
File.WriteAllText(LIVE_RECIPE_PATH, rawData);
}
catch
{ }
}
/// <summary>
/// Try to load selected recipe to live data (memory and json persistence file)
/// </summary>
public static void LoadRecipe(string filePath)
{
if (File.Exists(filePath))
{
// check filePath...
if (!filePath.Contains(RECIPE_DIRECTORY))
{
// aggiungo base path!
filePath = RECIPE_DIRECTORY + filePath;
}
// load all text data
var rawData = File.ReadAllText(filePath);
try
{
// deserialize to object
RecipeLiveData = JsonConvert.DeserializeObject<LiveData>(rawData);
}
catch
{ }
// update current live data!
WriteLiveData();
}
}
/// <summary>
/// Try to save live recipe to selected filePath
/// </summary>
public static void SaveRecipe(string filePath)
{
try
{
// serialize
string rawData = JsonConvert.SerializeObject(RecipeLiveData);
// save live!
File.WriteAllText(LIVE_RECIPE_PATH, rawData);
// check filePath...
if (!filePath.Contains(RECIPE_DIRECTORY))
{
// aggiungo base path!
filePath = RECIPE_DIRECTORY + filePath;
}
// save!
File.WriteAllText(filePath, rawData);
}
catch
{ }
}
#if false
public static void ReadMainProgram()
{
if (File.Exists(MAIN_PROGRAM_CONFIG_PATH))
{
CMSMainProgramContent = File.ReadAllText(MAIN_PROGRAM_CONFIG_PATH);
}
}
}
#endif
public static string CalculateHash(string filename)
{
@@ -32,6 +32,9 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
@@ -52,6 +55,7 @@
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Compile Include="LiveData.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerConfig.cs" />
<Compile Include="ServerConfigController.cs" />
@@ -175,5 +179,11 @@
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Recipes\" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net462" />
</packages>
+3
View File
@@ -210,6 +210,7 @@ namespace Thermo.Active.Model
public static string WEBSITE_DIRECTORY = BASE_PATH + "\\view";
#endif
public const string CONFIG_DIRECTORY = "Config\\";
public const string RECIPE_DIRECTORY = "Recipes\\";
public const string RESOURCE_DIRECTORY = @"Thermo.Active.Config.Config.";
public const string SERVER_CONFIG_SCHEMA_PATH = RESOURCE_DIRECTORY + @"serverConfigValidator.xsd";
public const string SERVER_CONFIG_PATH = CONFIG_DIRECTORY + "serverConfig.xml";
@@ -252,6 +253,8 @@ namespace Thermo.Active.Model
public const string MAIN_PROGRAM_CONFIG_PATH = CONFIG_DIRECTORY + "customMainProgram.txt";
public const string LIVE_RECIPE_PATH = RECIPE_DIRECTORY + "current.json";
public static string LANGUAGE_PACK_DIRECTORY = BASE_PATH + "\\languages\\";
public static string LANGUAGE_SCHEMA_PATH = BASE_PATH + "\\LanguageValidator.xsd";
+53 -18
View File
@@ -1621,15 +1621,11 @@ namespace Thermo.Active.NC
CmsError cmsError = NO_ERROR;
currOverview = new Dictionary<string, RecipeCatStatus>();
// !!!FARE davvero!!!
#if false
// gestione errore
cmsError = ReadScadaData(schema, out currParam);
// leggo la ricetta!
var currRecipe = new Dictionary<string, DTORecipeParam>();
cmsError = ReadFullRecipe(out currRecipe);
if (cmsError.IsError())
return cmsError;
#endif
// calcolo!
return cmsError;
// leggo l'intero array delle DB... QUI FAKE sulle DB configurate...
List<DTORecipeConfigModel> recipeConfig = RecipeConfig.Select(x => new DTORecipeConfigModel()
@@ -1645,34 +1641,51 @@ namespace Thermo.Active.NC
}).ToList();
RecipeCatStatus currStatus = RecipeCatStatus.Unchanged;
int countCat = 0;
// percorro conf ricetta...
foreach (var item in recipeConfig)
{
// ogni 20 incremento...
if (countCat < 20)
currStatus = RecipeCatStatus.Unchanged;
// cerco SE ci sia già uno status...
if (currOverview.ContainsKey(item.Category))
{
currStatus = RecipeCatStatus.Unchanged;
currStatus = currOverview[item.Category];
}
else if (countCat < 40)
// se lo stato è errore --> esco...
if (currStatus == RecipeCatStatus.HasError)
{
currStatus = RecipeCatStatus.ChangedOk;
continue;
}
// altrimenti controllo
else
{
currStatus = RecipeCatStatus.HasError;
// se in errore --> registro...
if (currRecipe[item.Label].Status.HasError)
{
currStatus = RecipeCatStatus.HasError;
}
// FARE verificare il significato di questo changed (se è da file o da HMI/PLC)
else if (currRecipe[item.Label].SetpointHMI != currRecipe[item.Label].SetpointPLC)
{
currStatus = RecipeCatStatus.ChangedOk;
}
else
{
currStatus = RecipeCatStatus.Unchanged;
}
}
// se non c'è aggiungo
// ora verifico overview finale: se non c'è aggiungo
if (!currOverview.ContainsKey(item.Category))
{
currOverview.Add(item.Category, currStatus);
countCat = 0;
}
else
{
// se il valore è maggiore --> aggiorno
currOverview[item.Category] = (int)currStatus > (int)currOverview[item.Category] ? currStatus : currOverview[item.Category];
}
countCat++;
}
// restituisco cod errore se trovato
@@ -1731,6 +1744,28 @@ namespace Thermo.Active.NC
return cmsError;
}
/// <summary>
/// Returns resistances configuration
/// </summary>
/// <param name="currWarmersResistances">List of configured resistances</param>
/// <returns></returns>
public CmsError GetWarmersResistances(out Dictionary<int, Model.ConfigModels.RiskResistModel> currWarmersResistances)
{
CmsError cmsError = NO_ERROR;
currWarmersResistances = new Dictionary<int, Model.ConfigModels.RiskResistModel>();
// read and return config
if (NcConfig.NcVendor == NC_VENDOR.S7NET)
{
foreach (var item in RiskResistConfig)
{
currWarmersResistances.Add(item.Id, item);
}
}
// restituisco cod errore se trovato
return cmsError;
}
#endregion Read Data
+57 -2
View File
@@ -19,6 +19,61 @@ namespace Thermo.Active.NC
{
public class NcFileAdapter : NcAdapter
{
/// <summary>
/// Read file from local devices ad give back string content
/// </summary>
/// <param name="path"></param>
/// <param name="fileContent"></param>
/// <returns></returns>
public CmsError ReadFileContent(string path, out string fileContent)
{
// init
fileContent = "";
if (!string.IsNullOrEmpty(path))
{
// check existing
if (File.Exists(path))
{
// read all lines as string
fileContent = File.ReadAllText(path);
}
else
{
return FILE_NOT_FOUND_ERROR;
}
}
else
{
return FILE_NOT_FOUND_ERROR;
}
return NO_ERROR;
}
/// <summary>
/// Save string content to file
/// </summary>
/// <param name="path"></param>
/// <param name="fileContent"></param>
/// <returns></returns>
public CmsError WriteFileContent(string path, string fileContent)
{
if (!string.IsNullOrEmpty(path))
{
if (!string.IsNullOrEmpty(fileContent))
{
File.WriteAllText(path, fileContent);
}
}
else
{
return FILE_NOT_FOUND_ERROR;
}
return NO_ERROR;
}
public CmsError GetFileList(string path, out List<PreviewFileModel> fileList)
{
fileList = new List<PreviewFileModel>();
@@ -41,8 +96,8 @@ namespace Thermo.Active.NC
if (cmsError.IsError())
return cmsError;
string [] names = fileInfo.Name.Split('/');
if(names.Length > 0)
string[] names = fileInfo.Name.Split('/');
if (names.Length > 0)
{
string name = names.Last();
if (!String.IsNullOrWhiteSpace(name))
@@ -13,6 +13,7 @@ using static CMS_CORE_Library.Models.DataStructures;
using static Thermo.Active.Config.ServerConfig;
using static Thermo.Active.Model.Constants;
using Thermo.Active.Model.DTOModels.Recipe;
using Thermo.Active.Config;
namespace Thermo.Active.Controllers.WebApi
{
@@ -54,8 +55,6 @@ namespace Thermo.Active.Controllers.WebApi
}
}
[Route("update"), HttpPut]
public IHttpActionResult WriteParameters(Dictionary<string, double> parametersList)
{
@@ -116,6 +115,23 @@ namespace Thermo.Active.Controllers.WebApi
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
// recupero i dati LIVE dei parametri HMI della ricetta...
cmsError = ncAdapter.ReadFullRecipe(out Dictionary<string, DTORecipeParam> currRecipe);
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
// rileggo la ricetta
var currParams = new Dictionary<string, double>();
foreach (var item in currRecipe)
{
currParams.Add(item.Key, item.Value.SetpointHMI);
}
// ora salvo ANCHE i dati live...
RecipeLiveData.RecipeParameters = currParams;
// e salvo su disco
ServerConfigController.WriteLiveData();
// ritorno solo fatto!
return Ok();
}
@@ -140,11 +156,117 @@ namespace Thermo.Active.Controllers.WebApi
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
// recupero i dati LIVE dei parametri HMI della ricetta...
cmsError = ncAdapter.ReadFullRecipe(out Dictionary<string, DTORecipeParam> currRecipe);
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
var currParams = new Dictionary<string, double>();
foreach (var item in currRecipe)
{
currParams.Add(item.Key, item.Value.SetpointPLC);
}
// ora salvo ANCHE i dati live...
RecipeLiveData.RecipeParameters = currParams;
// e salvo su disco
ServerConfigController.WriteLiveData();
// ritorno solo fatto!
return Ok();
}
}
/// <summary>
/// Save current recipe from PLC to default
/// </summary>
/// <returns></returns>
[Route("save"), HttpPut]
public IHttpActionResult Save()
{
using (NcFileAdapter ncAdapter = new NcFileAdapter())
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.errorCode != 0)
return NotFound();
// recupero i dati LIVE dei parametri HMI della ricetta...
CmsError cmsError = ncAdapter.ReadFullRecipe(out Dictionary<string, DTORecipeParam> currRecipe);
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
var currParams = new Dictionary<string, double>();
foreach (var item in currRecipe)
{
currParams.Add(item.Key, item.Value.SetpointPLC);
}
// ora salvo ANCHE i dati live...
RecipeLiveData.RecipeParameters = currParams;
// e salvo su disco
ServerConfigController.WriteLiveData();
// ritorno solo fatto!
return Ok();
}
}
/// <summary>
/// Save current recipe from PLC with new name
/// </summary>
/// <returns></returns>
[Route("saveAs"), HttpPut]
public IHttpActionResult SaveAs(string newName)
{
using (NcFileAdapter ncAdapter = new NcFileAdapter())
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.errorCode != 0)
return NotFound();
// recupero i dati LIVE dei parametri HMI della ricetta...
CmsError cmsError = ncAdapter.ReadFullRecipe(out Dictionary<string, DTORecipeParam> currRecipe);
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
var currParams = new Dictionary<string, double>();
foreach (var item in currRecipe)
{
currParams.Add(item.Key, item.Value.SetpointPLC);
}
// ora salvo ANCHE i dati live...
RecipeLiveData.RecipeParameters = currParams;
// e salvo su disco
ServerConfigController.SaveRecipe(newName);
// ritorno solo fatto!
return Ok();
}
}
/// <summary>
/// load recipe from file and send to PLC
/// </summary>
/// <returns></returns>
[Route("load"), HttpPut]
public IHttpActionResult Load(string newName)
{
using (NcFileAdapter ncAdapter = new NcFileAdapter())
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.errorCode != 0)
return NotFound();
// chiamo metodo di lettura...
ServerConfigController.LoadRecipe(newName);
// ritorno solo fatto!
return Ok();
}
}
}
}
@@ -19,8 +19,8 @@ namespace Thermo.Active.Controllers.WebApi
[RoutePrefix("api/warmers")]
public class WarmersController : ApiController
{
[Route("current"), HttpGet]
public IHttpActionResult GetCurrentWarmers()
[Route("channels"), HttpGet]
public IHttpActionResult GetCurrentWarmersChannels()
{
using (NcAdapter ncAdapter = new NcAdapter())
{
@@ -36,18 +36,39 @@ namespace Thermo.Active.Controllers.WebApi
return Ok(currWarmers);
}
}
// FIXME TODO determinare IN PRIMIS nel modello COSA e come aggiornare...
#if false
[Route("update"), HttpPut]
public IHttpActionResult WriteWarmers(Dictionary<string, double> parametersList)
[Route("resistances"), HttpGet]
public IHttpActionResult GetCurrentWarmersResistances()
{
using (NcAdapter ncAdapter = new NcAdapter())
{
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.errorCode != 0)
return NotFound();
CmsError cmsError = ncAdapter.GetWarmersResistances(out Dictionary<int, Model.ConfigModels.RiskResistModel> currWarmers);
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
return Ok(currWarmers);
}
}
[Route("update"), HttpPut]
public IHttpActionResult WriteSetpoints(Dictionary<int, double> channelsList)
{
// scrive su CHp da ricetta oppure da override x parametri utente...
using (NcAdapter ncAdapter = new NcAdapter())
{
#if false
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.errorCode != 0)
return NotFound();
// read recipe!
CmsError cmsError = ncAdapter.ReadFullRecipe(out Dictionary<string, DTORecipeParam> prevRecipe);
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
@@ -71,13 +92,66 @@ namespace Thermo.Active.Controllers.WebApi
}
// scrivo sul PLC
ncAdapter.WriteRecipeParams(updtRecipe);
ncAdapter.WriteRecipeParams(updtRecipe);
#endif
// ritorno solo fatto!
return Ok();
}
}
}
/// <summary>
/// Confirm recipe modification (parameters: HMI --> PLC)
/// </summary>
/// <returns></returns>
[Route("confirm"), HttpPut]
public IHttpActionResult ConfirmEdit()
{
using (NcAdapter ncAdapter = new NcAdapter())
{
#if false
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.errorCode != 0)
return NotFound();
// scrivo sul PLC il comando conferma!
CmsError cmsError = ncAdapter.ConfirmRecipeData(true);
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
#endif
// ritorno solo fatto!
return Ok();
}
}
/// <summary>
/// Cancel recipe modification (parameters: PLC --> HMI)
/// </summary>
/// <returns></returns>
[Route("cancel"), HttpPut]
public IHttpActionResult CancelEdit()
{
using (NcAdapter ncAdapter = new NcAdapter())
{
#if false
// Try connection
CmsError libraryError = ncAdapter.Connect();
if (libraryError.errorCode != 0)
return NotFound();
// scrivo sul PLC il comando annula!
CmsError cmsError = ncAdapter.ConfirmRecipeData(false);
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
#endif
// ritorno solo fatto!
return Ok();
}
}
}
}