using CMS_CORE_Library.Models; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Security.Claims; using System.Threading.Tasks; using System.Web; using System.Web.Http; using System.Windows.Media.Animation; using Thermo.Active.Config; using Thermo.Active.Database.Controllers; using Thermo.Active.Model.DTOModels.ThRecipe; using Thermo.Active.Model.DTOModels.ThWarmers; using Thermo.Active.NC; using Thermo.Active.Utils; using static CMS_CORE_Library.Models.DataStructures; using static Thermo.Active.Config.ServerConfig; using static Thermo.Active.Model.Constants; namespace Thermo.Active.Controllers.WebApi { [RoutePrefix("api/recipe")] public class RecipeController : ApiController { /// /// Oggetto adapter condiviso da WebAPI /// protected static NcAdapter ncAdapter = new NcAdapter(); [Route("overview"), HttpGet] public IHttpActionResult GetOverview() { // // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ncAdapter Not connected! | GetOverview | {libraryError.exception}"); } libraryError = ncAdapter.GetRecipeOverview(out Dictionary currOverview); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"GetRecipeOverview error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } return Ok(currOverview); } [Route("current"), HttpGet] public IHttpActionResult GetCurrentParameters() { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"NC Not connected! | GetCurrentParameters | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } libraryError = ncAdapter.ReadFullRecipe(out Dictionary currRecipe); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"GetRecipeOverview error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } return Ok(currRecipe); } [Route("update"), HttpPut] public IHttpActionResult WriteParameters(Dictionary parametersList) { if (parametersList != null) { if (NcFileAdapter.RecipeLiveData != null) { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"NC Not connected! | WriteParameters | {libraryError.exception}"); return InternalServerError(); } // read recipe! libraryError = ncAdapter.ReadFullRecipe(out Dictionary prevRecipe); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"GetRecipeOverview error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } Dictionary updtRecipe = new Dictionary(); foreach (var item in parametersList) { if (prevRecipe.ContainsKey(item.Key)) { // aggiorno il valore HMI nel parametro var currParam = prevRecipe[item.Key]; // se il parametro richiesto è DIVERSO dal precedente su HMI... if (currParam.SetpointHMI != item.Value) { currParam.SetpointHMI = item.Value; // salvo (1 parametro, potrei fare N...) updtRecipe.Add(item.Key, currParam); } } else { ThermoActiveLogger.LogError($"WriteParameters error | key not found: {item.Key}"); return NotFound(); } } if (updtRecipe.Count > 0) { // scrivo sul PLC ncAdapter.WriteRecipeParams(updtRecipe); } // ritorno solo fatto! return Ok(); } else { // non pronto! ThermoActiveLogger.LogError($"RecipeLiveData null | WriteParameters"); return InternalServerError(); } } else { ThermoActiveLogger.LogError($"RecipeLiveData null | Empty Parameters"); return BadRequest(); } } /// /// Confirm recipe modification (parameters: HMI --> PLC) /// /// section confirmed (string as in overview) /// [Route("confirm"), HttpPut] public IHttpActionResult ConfirmEdit(RecipeSection section) { if (NcFileAdapter.RecipeLiveData != null) { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"NC Not connected! | Recipe ConfirmEdit | {libraryError.exception}"); return InternalServerError(); } // scrivo sul PLC il comando conferma! libraryError = ncAdapter.ConfirmRecipeData(true); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ConfirmEdit error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } // SE HO una section != null/empty --> salvo come modificata... if (section != null) { try { NcFileAdapter.upsRecipeOverview(section, RecipeCatStatus.ChangedOk); } catch (Exception exc) { ThermoActiveLogger.LogError($"Error on set recipe overview | section: {section}{Environment.NewLine}{exc}"); } } // recupero i dati LIVE dei parametri HMI della ricetta... libraryError = ncAdapter.ReadFullRecipe(out Dictionary currRecipe); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ConfirmEdit error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } // rileggo la ricetta var currParams = new Dictionary(); foreach (var item in currRecipe) { currParams.Add(item.Key, item.Value.SetpointHMI); } SaveCurrentRecipeParams(currParams); // ritorno solo fatto! return Ok(); } else { // non pronto! ThermoActiveLogger.LogError($"RecipeLiveData null | Empty"); return InternalServerError(); } } /// /// Cancel recipe modification (parameters: PLC --> HMI) /// /// [Route("cancel"), HttpPut] public IHttpActionResult CancelEdit() { if (NcFileAdapter.RecipeLiveData != null) { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"NC Not connected! | Recipe CancelEdit | {libraryError.exception}"); return InternalServerError(); } // scrivo sul PLC il comando annula! libraryError = ncAdapter.ConfirmRecipeData(false); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ConfirmEdit error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } // recupero i dati LIVE dei parametri HMI della ricetta... libraryError = ncAdapter.ReadFullRecipe(out Dictionary currRecipe); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ConfirmEdit error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } var currParams = new Dictionary(); foreach (var item in currRecipe) { currParams.Add(item.Key, item.Value.SetpointPLC); } // ora salvo ANCHE i dati live... SaveCurrentRecipeParams(currParams); // ritorno solo fatto! return Ok(); } else { // non pronto! ThermoActiveLogger.LogError($"RecipeLiveData null | Empty"); return InternalServerError(); } } /// /// load recipe from file and send to PLC /// /// [Route("load"), HttpPut] public IHttpActionResult Load(string newName) { // chiamo metodo di lettura... bool fatto = NcFileAdapter.LoadRecipe(newName); if (!fatto) { ThermoActiveLogger.LogError($"LoadRecipe error"); return NotFound(); } CmsError libraryError = WriteCurrentRecipeToPlc(); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ConfirmEdit error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } // ritorno solo fatto! return Ok(); } /// /// Load tempalte recipe from file and save as new current... /// /// [Route("new"), HttpPut] public IHttpActionResult NewRecipe() { // chiamo metodo di lettura... bool fatto = NcFileAdapter.LoadTemplate(); if (!fatto) { ThermoActiveLogger.LogError($"LoadRecipe error"); return NotFound(); } CmsError libraryError = WriteCurrentRecipeToPlc(); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ConfirmEdit error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } // ritorno solo fatto! return Ok(); } /// /// Save current recipe from PLC to default /// /// [Route("save"), HttpPut] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] public IHttpActionResult Save() { int currUserId = 0; // recupero dati utente loggato var identity = User.Identity as ClaimsIdentity; // Find user id from the bearer token var userId = identity.Claims.FirstOrDefault(c => c.Type == USER_ID_KEY); if (userId == null) return Unauthorized(); using (UsersController usersController = new UsersController()) { var userData = usersController.GetUserInfo(Convert.ToInt32(userId.Value)); currUserId = userData.Id; } // recupero i dati LIVE dei parametri HMI della ricetta... CmsError libraryError = ncAdapter.ReadFullRecipe(out Dictionary currRecipe); if (libraryError.IsError()) return BadRequest(libraryError.localizationKey); var currParams = new Dictionary(); foreach (var item in currRecipe) { currParams.Add(item.Key, item.Value.SetpointPLC); } // ora salvo ANCHE i dati live... SaveCurrentRecipeParams(currParams); // ritorno solo fatto! return Ok(); } /// /// Save current recipe from PLC with new name /// /// [Route("saveAs"), HttpPut] public IHttpActionResult SaveAs(string newName) { #if false // recupero dati utente loggato var identity = User.Identity as ClaimsIdentity; // Find user id from the bearer token var userId = identity.Claims.FirstOrDefault(c => c.Type == USER_ID_KEY); if (userId == null) return Unauthorized(); using (UsersController usersController = new UsersController()) { var userData = usersController.GetUserInfo(Convert.ToInt32(userId.Value)); } #endif // recupero i dati LIVE dei parametri HMI della ricetta... CmsError libraryError = ncAdapter.ReadFullRecipe(out Dictionary currRecipe); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"SaveAs error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } var currParams = new Dictionary(); foreach (var item in currRecipe) { currParams.Add(item.Key, item.Value.SetpointPLC); } // ora salvo ANCHE i dati live... NcFileAdapter.RecipeLiveData.RecipeParameters = currParams; // e salvo su disco NcFileAdapter.SaveRecipe(newName, NcFileAdapter.RecipeLiveData); // ritorno solo fatto! return Ok(); } /// /// Save current recipe from PLC to Template /// /// [Route("saveTemplate"), HttpPut] public IHttpActionResult SaveTemplate() { // recupero i dati LIVE dei parametri HMI della ricetta... CmsError libraryError = ncAdapter.ReadFullRecipe(out Dictionary currRecipe); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"SaveTemplate error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } // recupero i dati LIVE dei carichi load dei cahnnels di riscaldo... libraryError = ncAdapter.ReadWarmers(out Dictionary currWarmers); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ReadWarmers error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } // uso i valopri HMI... var currParams = new Dictionary(); foreach (var item in currRecipe) { currParams.Add(item.Key, item.Value.SetpointHMI); } // ora salvo nei dati live... NcFileAdapter.RecipeLiveData.RecipeParameters = currParams; // carico i dati dei riscaldi... var currChSet = new Dictionary(); foreach (var item in currWarmers) { currChSet.Add(item.Key, item.Value.SetpointHMI); } NcFileAdapter.RecipeLiveData.ChannelSetpoints = currChSet; // e salvo su disco NcFileAdapter.SaveRecipeTemplate(); // ritorno solo fatto! return Ok(); } [Route("uploadImage"), HttpPost] public async Task UpdloadImage() { bool imageUploaded = false; if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } List formItems = await MultipartHandler.ManageMultiPartFileAsync(Request); foreach (FormItem item in formItems) { if (item.IsAFile) { if (item.ParameterName == "image" || item.MediaType.StartsWith("image/")) { string filePath = item.FileName; imageUploaded = NcFileAdapter.SaveRecipeImage(item.FileName, item.Data); } } } return Ok(); } [Route("saveAll"), HttpPost] //[WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.USER_FUNCTIONS, Action = ACTIONS.READ)] public async Task SaveAll(string newName, double estimTimeSec) { #if false // recupero dati utente loggato var identity = User.Identity as ClaimsIdentity; // Find user id from the bearer token var userId = identity.Claims.FirstOrDefault(c => c.Type == USER_ID_KEY); if (userId == null) return Unauthorized(); using (UsersController usersController = new UsersController()) { var userData = usersController.GetUserInfo(Convert.ToInt32(userId.Value)); } #endif bool imageUploaded = false; if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } List formItems = await MultipartHandler.ManageMultiPartFileAsync(Request); foreach (FormItem item in formItems) { if (item.IsAFile) { if (item.ParameterName == "image" || item.MediaType.StartsWith("image/")) { string filePath = item.FileName; imageUploaded = NcFileAdapter.SaveRecipeImage(item.FileName, item.Data); } } } if (!string.IsNullOrEmpty(newName)) { // recupero i dati LIVE dei parametri HMI della ricetta... CmsError libraryError = ncAdapter.ReadFullRecipe(out Dictionary currRecipe); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"SaveAll error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } var currParams = new Dictionary(); foreach (var item in currRecipe) { currParams.Add(item.Key, item.Value.SetpointPLC); } // salvo parametri NcFileAdapter.RecipeLiveData.RecipeParameters = currParams; // ora salvo il dato del TC stimato se presente if (estimTimeSec > 0) { NcFileAdapter.RecipeLiveData.TC_last = estimTimeSec; } // e salvo su disco NcFileAdapter.SaveRecipe(newName, NcFileAdapter.RecipeLiveData); } return Ok(); } /// /// Do actual recipe parameters FileSave /// /// private static void SaveCurrentRecipeParams(Dictionary currParams) { try { // ora salvo ANCHE i dati live... NcFileAdapter.RecipeLiveData.RecipeParameters = currParams; // e salvo su disco NcFileAdapter.SaveRecipeCurrent(); } catch (Exception exc) { ThermoActiveLogger.LogError($"Recipe | SaveCurrentRecipeParams exception | {exc}"); } } /// /// write current recipe to PLC /// /// public static CmsError WriteCurrentRecipeToPlc() { CmsError checkError = NO_ERROR; // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) { ThermoActiveLogger.LogError($"NC Not connected! | Load | {libraryError.exception}"); return libraryError; } // copy data to PLC checkError = ncAdapter.ReadFullRecipe(out Dictionary prevRecipe); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | ReadFullRecipe error | {checkError.exception}"); return checkError; } // save parameters to PLC!!! Dictionary updtRecipe = new Dictionary(); foreach (var item in NcFileAdapter.RecipeLiveData.RecipeParameters) { if (prevRecipe.ContainsKey(item.Key)) { // aggiorno il valore HMI nel parametro var currParam = prevRecipe[item.Key]; currParam.SetpointHMI = item.Value; // salvo (1 parametro, potrei fare N...) updtRecipe.Add(item.Key, currParam); } else { ThermoActiveLogger.LogError($"prevRecipe not found | key: {item.Key}"); return NOT_FOUND_ERROR; } } // write to PLC checkError = ncAdapter.WriteRecipeParams(updtRecipe); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | WriteRecipeParams error | {checkError.exception}"); return checkError; } // process ch load setup... Dictionary newRisk = new Dictionary(); foreach (var item in NcFileAdapter.RecipeLiveData.ChannelSetpoints) { newRisk.Add(item.Key, item.Value); } // write to PLC checkError = ncAdapter.WriteRecipeWarmChSetpHMI(newRisk); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | WriteRecipeWarmChSetpHMI error | {checkError.exception}"); return checkError; } // enable recipe! scrivo sul PLC il comando conferma! libraryError = ncAdapter.ConfirmRecipeData(true); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ReadWarmers error | {libraryError.exception}"); return checkError; } return checkError; } } }