using CMS_CORE_Library.Models; using System; using System.Collections.Generic; using System.Configuration; 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 TeamDev.SDK.MVVM; using Thermo.Active.Config; using Thermo.Active.Database.Controllers; using Thermo.Active.Model.DTOModels; 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("recipeNotes"), HttpGet] public IHttpActionResult GetRecipeNotes() { return Ok(NcAdapter.RecipeLiveData.recipeNotes); } [Route("recipeChanged"), HttpGet] public IHttpActionResult GetChanged() { return Ok(NcAdapter.RecipeLiveData.hasChanged); } [Route("update"), HttpPut] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] public IHttpActionResult WriteParameters(Dictionary parametersList) { if (parametersList != null) { if (NcAdapter.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); libraryError = ncAdapter.ReadRecipeData(true, true, 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 con i parametri specificati x ritardo/raggruppamento ncAdapter.WriteRecipeParams(updtRecipe, ncAdapter.nMaxParamWrite, ncAdapter.delayParamWrite); // verifico SE siano cambiati rispetto a versione originale... var originalRecipe = NcFileAdapter.LoadRecipe($"{NcAdapter.RecipeLiveData.RecipeDir}{NcAdapter.RecipeLiveData.RecipeName}"); // comparazione parametri... bool isEqual = false; ncAdapter.paramsComparer(originalRecipe.RecipeParameters, NcAdapter.RecipeLiveData.RecipeParameters, out isEqual); // salvo se la ricetta SIA cambiata NcAdapter.RecipeLiveData.hasChanged = !isEqual; // ora gestisco la lettura della overview di "modificata" + varie x HMI notifyHmi(); } // 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] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] public IHttpActionResult ConfirmEdit(RecipeSection section) { if (NcAdapter.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.errorCode} | {libraryError.exception} | {libraryError.localizationKey}"); return BadRequest(libraryError.localizationKey); } // SE HO una section != null/empty --> salvo come modificata... 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); } // salvo ricetta LIVE SaveLiveRecipeParams(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] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] public IHttpActionResult CancelEdit() { if (NcAdapter.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... SaveLiveRecipeParams(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] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] public IHttpActionResult Load(string newName) { // chiamo metodo di lettura... var dataRead = NcFileAdapter.LoadRecipe(newName); if (dataRead == null) { ThermoActiveLogger.LogError($"LoadRecipe error"); return NotFound(); } // salvo in memoria ricetta live NcAdapter.RecipeLiveData = dataRead; // update current live data! NcFileAdapter.SaveRecipeCurrent(); CmsError libraryError = WriteCurrentRecipeToPlc(); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ConfirmEdit error | {libraryError.exception}"); return BadRequest(libraryError.localizationKey); } // scrivo sul PLC il comando conferma! libraryError = ncAdapter.ConfirmRecipeData(true); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ConfirmEdit error | {libraryError.errorCode} | {libraryError.exception} | {libraryError.localizationKey}"); return BadRequest(libraryError.localizationKey); } // ora gestisco la lettura della overview di "modificata" + varie x HMI notifyHmi(); // Get new data from PLC libraryError = ncAdapter.ReadWarmers(false, out Dictionary currWarmers); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"Load error | ReadWarmers | {libraryError.errorCode} | {libraryError.exception} | {libraryError.localizationKey}"); return BadRequest(libraryError.localizationKey); } // pubblico MessageServices.Current.Publish(SEND_THERMO_WARMERS_DATA, null, currWarmers); // ritorno solo fatto! return Ok(); } /// /// Load tempalte recipe from file and save as new current... /// /// [Route("new"), HttpPut] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] 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); } // scrivo sul PLC il comando conferma! libraryError = ncAdapter.ConfirmRecipeData(true); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"ConfirmEdit error | {libraryError.errorCode} | {libraryError.exception} | {libraryError.localizationKey}"); 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() { // 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(); // salvo utente! using (UsersController usersController = new UsersController()) { var userData = usersController.GetUserInfo(Convert.ToInt32(userId.Value)); NcAdapter.RecipeLiveData.UserSave = userData.Id.ToString(); } // 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); } // salvo su disco ricetta corrente NcFileAdapter.SaveRecipe($"{NcAdapter.RecipeLiveData.RecipeDir}{NcAdapter.RecipeLiveData.RecipeName}", NcAdapter.RecipeLiveData); // ora salvo ANCHE i dati live... SaveLiveRecipeParams(currParams); // ritorno solo fatto! return Ok(); } /// /// Save current recipe from PLC with new name /// /// [Route("saveAs"), HttpPut] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] public IHttpActionResult SaveAs(string newName) { // 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(); // salvo utente! using (UsersController usersController = new UsersController()) { var userData = usersController.GetUserInfo(Convert.ToInt32(userId.Value)); NcAdapter.RecipeLiveData.UserSave = userData.Id.ToString(); } // 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... NcAdapter.RecipeLiveData.RecipeParameters = currParams; // e salvo su disco NcFileAdapter.SaveRecipe(newName, NcAdapter.RecipeLiveData); // ora gestisco la lettura della overview di "modificata" + varie x HMI notifyHmi(); // ritorno solo fatto! return Ok(); } /// /// Save current recipe from PLC to Template /// /// [Route("saveTemplate"), HttpPut] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] 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 channels di riscaldo... libraryError = ncAdapter.ReadWarmers(false, 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... NcAdapter.RecipeLiveData.RecipeParameters = currParams; // carico i dati dei riscaldi... var currChSet = new Dictionary(); foreach (var item in currWarmers) { currChSet.Add(item.Key, item.Value.SetpointHMI); } NcAdapter.RecipeLiveData.ChannelSetpoints = currChSet; // e salvo su disco NcFileAdapter.SaveRecipeTemplate(); // ritorno solo fatto! return Ok(); } [Route("uploadImage"), HttpPost] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] 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("updateNote"), HttpPost] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] public IHttpActionResult UpdateNote(string recipeNotes) { // salvo note... if (!string.IsNullOrEmpty(recipeNotes)) { NcAdapter.RecipeLiveData.recipeNotes = recipeNotes.Trim(); } // e salvo su disco NcFileAdapter.SaveRecipe($"{NcAdapter.RecipeLiveData.RecipeDir}{NcAdapter.RecipeLiveData.RecipeName}", NcAdapter.RecipeLiveData); return Ok(); } [Route("saveAll"), HttpPost] [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.RECIPE_MANAGER, Action = ACTIONS.READ)] public async Task SaveAll(string newName, string recipeNotes, double estimTimeSec) { // 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(); // salvo utente! using (UsersController usersController = new UsersController()) { var userData = usersController.GetUserInfo(Convert.ToInt32(userId.Value)); NcAdapter.RecipeLiveData.UserSave = userData.Id.ToString(); } // salvo note... if (!string.IsNullOrEmpty(recipeNotes)) { NcAdapter.RecipeLiveData.recipeNotes = recipeNotes.Trim(); } 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 NcAdapter.RecipeLiveData.RecipeParameters = currParams; // ora salvo il dato del TC stimato se presente if (estimTimeSec > 0) { NcAdapter.RecipeLiveData.TC_last = estimTimeSec; } // indico che non è + modificata... NcAdapter.RecipeLiveData.hasChanged = false; // e salvo su disco NcFileAdapter.SaveRecipe(newName, NcAdapter.RecipeLiveData); } return Ok(); } /// /// Do actual recipe parameters FileSave /// /// private static void SaveLiveRecipeParams(Dictionary currParams) { try { // ora salvo ANCHE i dati live... NcAdapter.RecipeLiveData.RecipeParameters = currParams; // verifico SE siano cambiati rispetto a versione originale... var originalRecipe = NcFileAdapter.LoadRecipe($"{NcAdapter.RecipeLiveData.RecipeDir}{NcAdapter.RecipeLiveData.RecipeName}"); // comparazione parametri... bool isEqual = false; ncAdapter.paramsComparer(originalRecipe.RecipeParameters, currParams, out isEqual); NcAdapter.RecipeLiveData.hasChanged = !isEqual; // e salvo su disco NcFileAdapter.SaveRecipeCurrent(); // ora gestisco la lettura della overview di "modificata" + varie x HMI notifyHmi(); } catch (Exception exc) { ThermoActiveLogger.LogError($"Recipe | SaveCurrentRecipeParams exception | {exc}"); } } /// /// Esegue notifica HMI delle modifiche sulla ricetta/riscaldi /// /// protected static CmsError notifyHmi() { CmsError libraryError = NO_ERROR; // invio dati NUOVA ricetta (DOPO aver sistemato PLC) DTORecipeStatus message = new DTORecipeStatus() { recipeName = NcAdapter.RecipeLiveData.RecipeName, hasChanged = NcAdapter.RecipeLiveData.hasChanged, forceSend = true }; MessageServices.Current.Publish(SEND_THERMO_RECIPE_CHANGED, null, message); // invio dati warmers aggiornati... // Get new data from PLC libraryError = ncAdapter.ReadWarmers(false, out Dictionary currWarmers); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"Load error | ReadWarmers | {libraryError.errorCode} | {libraryError.exception} | {libraryError.localizationKey}"); return libraryError; } // pubblico MessageServices.Current.Publish(SEND_THERMO_WARMERS_DATA, null, currWarmers); return libraryError; } /// /// 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 NcAdapter.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, ncAdapter.nMaxParamWrite, ncAdapter.delayParamWrite); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | WriteRecipeParams error | {checkError.exception}"); return checkError; } using (UserSoftkeysController controller = new UserSoftkeysController()) { DTOKeyboardSoftKeyModel keybKey = controller.GetKeyboardFavoriteSoftkeysLoggedUser(); libraryError = ncAdapter.WriteKeyboardStarSoftkey(keybKey.IdStar1, keybKey.IdStar2); if (libraryError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | WriteKeyboardStarSoftkey error | {checkError.exception}"); return libraryError; } } // process ch load setup... Dictionary newRisk = new Dictionary(); foreach (var item in NcAdapter.RecipeLiveData.ChannelSetpoints) { newRisk.Add(item.Key, item.Value); } // write to PLC SetPointHMI (%) checkError = ncAdapter.WriteRecipeWarmChSetpHMI(newRisk); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | WriteRecipeWarmChSetpHMI error | {checkError.exception}"); return checkError; } // Disable Thermocam Mode + OnOff checkError = ncAdapter.SetTCamMode(false); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | SetTCamMode error | {checkError.exception}"); return checkError; } checkError = ncAdapter.SetTCamActiv(false); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | SetTCamActiv error | {checkError.exception}"); return checkError; } // reset ActTemp Dictionary resetTCamEnab = new Dictionary(); Dictionary resetTCamTemp = new Dictionary(); foreach (var item in NcAdapter.RecipeLiveData.ChannelSetpoints) { resetTCamEnab.Add(item.Key, false); resetTCamTemp.Add(item.Key, 0); } checkError = ncAdapter.WriteRecipeWarmChTCamTempAct(resetTCamTemp); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | WriteRecipeWarmChTCamTempAct error | {checkError.exception}"); return checkError; } // write to PLC TempRif (°C) if (NcAdapter.RecipeLiveData.ChannelTCamTempReq == null) { NcAdapter.RecipeLiveData.ChannelTCamTempReq = resetTCamTemp; } checkError = ncAdapter.WriteRecipeWarmChTCamTempSet(NcAdapter.RecipeLiveData.ChannelTCamTempReq); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | WriteRecipeWarmChTCamTempSet error | {checkError.exception}"); return checkError; } // write to PLC TCamChEnab if (NcAdapter.RecipeLiveData.ChannelTCamEnab == null) { NcAdapter.RecipeLiveData.ChannelTCamEnab = resetTCamEnab; } checkError = ncAdapter.WriteRecipeWarmChTCamEnab(NcAdapter.RecipeLiveData.ChannelTCamEnab); if (checkError.IsError()) { ThermoActiveLogger.LogError($"WriteCurrentRecipeToPlc | WriteRecipeWarmChTCamEnab error | {checkError.exception}"); return checkError; } // send message for warmers updated data... // 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; } } }