diff --git a/Libs/CMS_CORE_Library.dll b/Libs/CMS_CORE_Library.dll index a234e993..85d8be42 100644 Binary files a/Libs/CMS_CORE_Library.dll and b/Libs/CMS_CORE_Library.dll differ diff --git a/Step.Config/Config/toolManagerConfig.xml b/Step.Config/Config/toolManagerConfig.xml index d8a1dc71..cd5ac029 100644 --- a/Step.Config/Config/toolManagerConfig.xml +++ b/Step.Config/Config/toolManagerConfig.xml @@ -1,8 +1,8 @@  - true - true + false + false true true true diff --git a/Step.Core/ThreadsFunctions.cs b/Step.Core/ThreadsFunctions.cs index 035fe165..ac5764e4 100644 --- a/Step.Core/ThreadsFunctions.cs +++ b/Step.Core/ThreadsFunctions.cs @@ -621,6 +621,46 @@ public static class ThreadsFunctions } } + public static void ReadPartProgramQueueData() + { + NcHandler ncHandler = new NcHandler(); + Stopwatch sw = new Stopwatch(); + + try + { + // Try connection + CmsError libraryError = ncHandler.Connect(); + if (libraryError.errorCode != 0) + ManageLibraryError(libraryError); + + while (true) + { + sw.Restart(); + + // Check if client is connected + if (ncHandler.numericalControl.NC_IsConnected()) + { + // Read data + libraryError = ncHandler.GetSelectedProcessQueue(out List queue); + if (libraryError.IsError()) + ManageLibraryError(libraryError); + + MessageServices.Current.Publish(SEND_QUEUE_DATA, null, queue); + } + else + TryNcConnection(); + sw.Stop(); + + // Wait + Thread.Sleep(CalcSleepTime(500, (int)sw.ElapsedMilliseconds)); + } + } + catch (ThreadAbortException) + { + ncHandler.Dispose(); + } + } + #endregion Nc functions threads #region SupportFunctions diff --git a/Step.Core/ThreadsHandler.cs b/Step.Core/ThreadsHandler.cs index 5b0b4391..ccecf853 100644 --- a/Step.Core/ThreadsHandler.cs +++ b/Step.Core/ThreadsHandler.cs @@ -23,7 +23,8 @@ namespace Step.Core ThreadsFunctions.ReadAxesNamesData, ThreadsFunctions.ReadActiveProgramData, ThreadsFunctions.UpdateToolsData, - ThreadsFunctions.ReadNcMagazineActive + ThreadsFunctions.ReadNcMagazineActive, + ThreadsFunctions.ReadPartProgramQueueData // ThreadsFunctions.ReadNcSoftKeysData, }; diff --git a/Step.Database/Controllers/NcToolManagerController.cs b/Step.Database/Controllers/NcToolManagerController.cs index 5e587cd7..6223a842 100644 --- a/Step.Database/Controllers/NcToolManagerController.cs +++ b/Step.Database/Controllers/NcToolManagerController.cs @@ -485,17 +485,5 @@ namespace Step.Database.Controllers dbCtx.SaveChanges(); } - - public int GetFirstId(IEnumerable objIds) - { - List listOfPossibleIds = Enumerable.Range(1, objIds.Max()).ToList(); - - IEnumerable res = listOfPossibleIds.Except(objIds).ToList(); - - if (res.Count() > 0) - return res.First(); - else - return 1; - } } } \ No newline at end of file diff --git a/Step.Model/Constants.cs b/Step.Model/Constants.cs index 6a10fff7..618c74b8 100644 --- a/Step.Model/Constants.cs +++ b/Step.Model/Constants.cs @@ -157,6 +157,7 @@ namespace Step.Model public const string SEND_ACTIVE_PROGRAM_DATA = "SEND_ACTIVE_PROGRAM_DATA"; public const string UPDATE_TOOLS_DATA = "UPDATE_TOOLS_DATA"; public const string NC_MAGAZINE_IS_ACTIVE = "UPDATE_NC_MAGAZINE_STATUS"; + public const string SEND_QUEUE_DATA = "SEND_QUEUE_DATA"; public const string BROADCAST_DATA = "BROADCAST_DATA"; diff --git a/Step.Model/DTOModels/DTOQueueModel.cs b/Step.Model/DTOModels/DTOQueueModel.cs new file mode 100644 index 00000000..e6e48d4c --- /dev/null +++ b/Step.Model/DTOModels/DTOQueueModel.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static CMS_CORE_Library.DataStructures; +using static Step.Model.Constants; + +namespace Step.Model.DTOModels +{ + public class DTOQueueModel + { + public int Id { get; set; } + + public string PartProgramName { get; set; } + + public int Reps { get; set; } + + public int RemainingReps { get; set; } + + public string AbsolutePath { get; set; } + + public QUEUE_STATUS Status { get; set; } + + public override bool Equals(object obj) + { + var item = obj as DTOQueueModel; + if (item == null) + return false; + + if (Id != item.Id) + return false; + + if (PartProgramName != item.PartProgramName) + return false; + + if (Reps != item.Reps) + return false; + + if (RemainingReps != item.RemainingReps) + return false; + + if (Status != item.Status) + return false; + + return true; + } + } +} diff --git a/Step.Model/Step.Model.csproj b/Step.Model/Step.Model.csproj index d76c657d..c222adf1 100644 --- a/Step.Model/Step.Model.csproj +++ b/Step.Model/Step.Model.csproj @@ -93,6 +93,7 @@ + diff --git a/Step.NC/NcHandler.cs b/Step.NC/NcHandler.cs index 3faf19b5..067e687c 100644 --- a/Step.NC/NcHandler.cs +++ b/Step.NC/NcHandler.cs @@ -25,6 +25,9 @@ namespace Step.NC { public Nc numericalControl; + public static Dictionary> PartProgramQueue = new Dictionary>(); + private static int QueueRunningIndex = 0; + public NcHandler() { // Choose NC @@ -33,13 +36,13 @@ namespace Step.NC public void Dispose() { - if(NcConfig.NcVendor != NC_VENDOR.SIEMENS) + if (NcConfig.NcVendor != NC_VENDOR.SIEMENS) numericalControl.NC_Disconnect(); } public CmsError Connect() { - // Connect NC + // Connect NC if (!numericalControl.NC_IsConnected()) return numericalControl.NC_Connect(); @@ -146,7 +149,7 @@ namespace Step.NC return cmsError; } - public CmsError UploadPartProgramAndActivate(string localPath, string fileName, out ActiveProgramDataModel programData) + public CmsError UploadPartProgram(string localPath, string fileName, out ActiveProgramDataModel programData) { programData = new ActiveProgramDataModel(); // Upload to NC @@ -158,17 +161,192 @@ namespace Step.NC // Delete local file File.Delete(localPath + "\\" + fileName); + return cmsError; + } + + public CmsError UploadPartProgramAndActivate(string localPath, string fileName, out ActiveProgramDataModel programData) + { + programData = new ActiveProgramDataModel(); + // Upload to NC + string newFilePath = ""; + CmsError cmsError = UploadPartProgram(localPath, fileName, out programData); + // Get selectedProcess id ushort selectedProcess = 0; cmsError = numericalControl.PROC_RSelectedProcess(ref selectedProcess); if (cmsError.IsError()) return cmsError; - // Activate - return numericalControl.FILES_WSetActiveProgram(selectedProcess, newFilePath, ref programData); + // Activate updated program + return numericalControl.FILES_WSetActiveProgram(selectedProcess, newFilePath, ref programData); + } + + public CmsError GetSelectedProcessQueue(out List queueList) + { + queueList = new List(); + // Get selectedProcess id + ushort selectedProcess = 0; + CmsError cmsError = numericalControl.PROC_RSelectedProcess(ref selectedProcess); + if (cmsError.IsError()) + return cmsError; + + QueueStatusModel queueData = new QueueStatusModel(); + + cmsError = numericalControl.FILES_RQueueData(ref queueData); + + if (queueData.LoadNextProgram) + { + // Check if there is already a pp queue for the selected process + if (PartProgramQueue.ContainsKey(selectedProcess)) + { + // Check if runnig exist + if (PartProgramQueue[selectedProcess].ElementAtOrDefault(QueueRunningIndex) != null) + { + var actualItem = PartProgramQueue[selectedProcess][QueueRunningIndex]; + // Check if there are remaining reps before change part program + if (actualItem.RemainingReps > 1) + actualItem.RemainingReps -= 1; + else + { + // Set as finished + actualItem.RemainingReps = 0; + if (PartProgramQueue[selectedProcess].ElementAtOrDefault(QueueRunningIndex + 1) != null) + // if next exist set next as current pp + QueueRunningIndex += 1; + } + } + } + } + + // Set status + if (PartProgramQueue.ContainsKey(selectedProcess) && PartProgramQueue[selectedProcess].ElementAtOrDefault(QueueRunningIndex) != null) + PartProgramQueue[selectedProcess][QueueRunningIndex].Status = queueData.Status; + + return GetProcessQueue(selectedProcess, out queueList); + } + + public CmsError GetProcessQueue(int processId, out List queueList) + { + queueList = new List(); + // Check if there is already a pp queue + if (!PartProgramQueue.ContainsKey(processId)) + return INCORRECT_PARAMETERS_ERROR; + + // Add new process to + queueList = PartProgramQueue[processId]; + + return NO_ERROR; + } + + public CmsError UploadPartProgramAddToQueue(string localPath, string fileName, int reps, out ActiveProgramDataModel programData) + { + programData = new ActiveProgramDataModel(); + // Upload to NC + CmsError cmsError = UploadPartProgram(localPath, fileName, out programData); + + // Get selectedProcess id + ushort selectedProcess = 0; + cmsError = numericalControl.PROC_RSelectedProcess(ref selectedProcess); + if (cmsError.IsError()) + return cmsError; + + DTOQueueModel tmpQueue = new DTOQueueModel() + { + PartProgramName = fileName, + Reps = reps, + RemainingReps = reps, + AbsolutePath = programData.Path, + Status = QUEUE_STATUS.NOT_ACTIVE + }; + + // Check if there is already a pp queue + if (!PartProgramQueue.ContainsKey(selectedProcess)) + PartProgramQueue.Add(selectedProcess, new List()); + + tmpQueue.Id = SupportFunctions.GetNextId(PartProgramQueue[selectedProcess].Select(x => x.Id)); + + // Add new process to + PartProgramQueue[selectedProcess].Add(tmpQueue); + + return cmsError; + } + + public CmsError SwapQueueItems(int processId, int item1Index, int item2Index) + { + item1Index = item1Index - 1; + item2Index = item2Index - 1; + + // Check if there is a queue + if (!PartProgramQueue.ContainsKey(processId)) + return INCORRECT_PARAMETERS_ERROR; + // Check if items exists + if (PartProgramQueue[processId].ElementAtOrDefault(item1Index) == null || PartProgramQueue[processId].ElementAtOrDefault(item2Index) == null) + return INCORRECT_PARAMETERS_ERROR; + + // Create a item + DTOQueueModel tmp = PartProgramQueue[processId][item1Index]; + + // Swap item 1 with 2 + PartProgramQueue[processId][item1Index] = PartProgramQueue[processId][item2Index]; + // Swap 2 with tmp + PartProgramQueue[processId][item2Index] = tmp; + + // Swap ids + PartProgramQueue[processId][item2Index].Id = item2Index + 1; + // Swap 2 with tmp + PartProgramQueue[processId][item1Index].Id = item1Index + 1; + + return NO_ERROR; + } + + public CmsError EditQueueItemReps(int processId, int itemIndex, int reps) + { + itemIndex = itemIndex - 1; + // Check if there is a queue + if (!PartProgramQueue.ContainsKey(processId)) + return INCORRECT_PARAMETERS_ERROR; + // Check if items exists + if (PartProgramQueue[processId].ElementAtOrDefault(itemIndex) == null) + return INCORRECT_PARAMETERS_ERROR; + // Check if Program is running + if (PartProgramQueue[processId][itemIndex].Status == QUEUE_STATUS.RUNNING) + return INCORRECT_PARAMETERS_ERROR; + + PartProgramQueue[processId][itemIndex].Reps = reps; + PartProgramQueue[processId][itemIndex].RemainingReps = reps; + + return NO_ERROR; + } + + public CmsError RemoveFromQueue(int id, int processId) + { + // Check if there is a queue + if (PartProgramQueue.ContainsKey(processId)) + { + // Find item by id + DTOQueueModel tmpQueueItem = PartProgramQueue[processId] + .Where(x => x.Id == id) + .FirstOrDefault(); + + if (tmpQueueItem != null) + PartProgramQueue[processId].Remove(tmpQueueItem); + } + + return NO_ERROR; + } + + public CmsError EmptyQueue(int processId) + { + // Check if there is a queue + if (PartProgramQueue.ContainsKey(processId)) + { + PartProgramQueue[processId] = new List(); + } + + return NO_ERROR; } #endregion File manager - + #region Read Data public CmsError GetNcGenericData(out DTONcGenericDataModel genericData) @@ -951,7 +1129,7 @@ namespace Step.NC { config.FamilyOptionActive = false; categories.Add("family"); - config.ToolsConfiguration = config.ToolsConfiguration.Where(x => !(x.Name == "familyId")).ToList(); + config.ToolsConfiguration = config.ToolsConfiguration.Where(x => !(x.Name == "familyId")).ToList(); config.ToolsConfiguration = config.ToolsConfiguration.Concat(config.FamiliesConfiguration.FamilyConfiguration).ToList(); } else @@ -988,12 +1166,11 @@ namespace Step.NC if (!ToolManagerConfig.BallufOpt) categories.Add("balluf"); - + config.ToolsConfiguration = config.ToolsConfiguration.Where(x => !categories.Contains(x.Category)).ToList(); config.FamiliesConfiguration.FamilyConfiguration = config.FamiliesConfiguration.FamilyConfiguration.Where(x => !categories.Contains(x.Category)).ToList(); config.ShanksConfiguration.ShankConfiguration = config.ShanksConfiguration.ShankConfiguration.Where(x => !categories.Contains(x.Category)).ToList(); config.MagazinePosConfiguration = config.MagazinePosConfiguration.Where(x => !categories.Contains(x.Category)).ToList(); - } return cmsError; @@ -1099,13 +1276,11 @@ namespace Step.NC return numericalControl.PLC_WPowerOnData(id, true); } - public CmsError SetActiveLanguage(CultureInfo language) { // Set to true power on data by id return numericalControl.NC_WLanguage(language); } - #endregion Write data @@ -1369,7 +1544,7 @@ namespace Step.NC { return numericalControl.TOOLS_WOffset(offsetId, offsetData); } - + public CmsError UpdateToolOffsetId(int toolId, int positionId, int offsetId, out DTONcToolModel toolWithOffsets) { toolWithOffsets = new DTONcToolModel(); @@ -1625,7 +1800,7 @@ namespace Step.NC // Update nc families return numericalControl.TOOLS_WUpdateFamilies(families); } - + public CmsError UpdateMagazinePosition(DbNcMagazinePositionModel dbPos, DTONcMagazinePositionModel dtoPos, out DTONcMagazinePositionModel magPos) { magPos = new DTONcMagazinePositionModel(); @@ -1709,7 +1884,7 @@ namespace Step.NC return cmsError; } - return NO_ERROR; + return NO_ERROR; } public CmsError UpdateMagazinePositionConf() @@ -1905,7 +2080,7 @@ namespace Step.NC public CmsError GetNcMagazineStatus(out Dictionary status) { status = new Dictionary(); - return numericalControl.TOOLS_RMagazineStatus(ref status); + return numericalControl.TOOLS_RMagazineStatus(ref status); } #endregion Osai/Fanuc Tools diff --git a/Step.Utils/supportFunctions.cs b/Step.Utils/supportFunctions.cs index bc4477fc..75f55ab5 100644 --- a/Step.Utils/supportFunctions.cs +++ b/Step.Utils/supportFunctions.cs @@ -1,4 +1,6 @@ -using System.Reflection; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using static Step.Model.Constants; namespace Step.Utils @@ -99,6 +101,26 @@ namespace Step.Utils } } } + + public static int GetNextId(IEnumerable objIds) + { + if (objIds.Count() == 0) + return 1; + + return objIds.Max() + 1; + } + + public static int GetFirstId(IEnumerable objIds) + { + List listOfPossibleIds = Enumerable.Range(1, objIds.Max()).ToList(); + + IEnumerable res = listOfPossibleIds.Except(objIds).ToList(); + + if (res.Count() > 0) + return res.First(); + else + return 1; + } } } \ No newline at end of file diff --git a/Step/Controllers/WebApi/NcFileController.cs b/Step/Controllers/WebApi/NcFileController.cs index ed2cfb7e..9a855aa3 100644 --- a/Step/Controllers/WebApi/NcFileController.cs +++ b/Step/Controllers/WebApi/NcFileController.cs @@ -116,6 +116,7 @@ namespace Step.Controllers.WebApi return Ok(); } + [Route("shared_files"), HttpGet] public IHttpActionResult GetSharedFolderFileList(string sharedPath) @@ -156,5 +157,103 @@ namespace Step.Controllers.WebApi return Ok(filelist); } + + + #region Queue Manager + + [Route("queue/add"), HttpPost] + public async Task UploadToQueue() + { + 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 == "file") + { + using (NcHandler ncHandler = new NcHandler()) + { + ncHandler.Connect(); + + File.WriteAllBytes(TEMP_FILE + item.FileName, item.Data); + + // Get reps + var repsParam = formItems.Where(x => x.ParameterName == "reps").FirstOrDefault(); + // Check if reps parameter is null or isn't a valid int + if (repsParam == null || !Int32.TryParse(repsParam.Value, out int reps)) + return BadRequest(); + + CmsError cmsError = ncHandler.UploadPartProgramAddToQueue(TEMP_FILE, item.FileName, reps, out ActiveProgramDataModel programData); + if (cmsError.IsError()) + return BadRequest(cmsError.localizationKey); + } + } + else if (item.ParameterName == "image") + { + File.WriteAllBytes(PART_PRG_IMAGES + item.FileName, item.Data); + } + } + } + + return Ok(); + } + + [Route("queue/{processId:int}/remove/{itemId:int}"), HttpDelete] + public IHttpActionResult RemoveFromQueue(int processId, int itemId) + { + using (NcHandler ncHandler = new NcHandler()) + { + ncHandler.Connect(); + + CmsError cmsError = ncHandler.RemoveFromQueue(processId, itemId); + if (cmsError.IsError()) + return BadRequest(cmsError.localizationKey); + } + + return Ok(); + } + + [Route("queue/{processId:int}/swap"), HttpPut] + public IHttpActionResult SwapQueueItems(int processId, SwapItems itemsPositions) + { + using (NcHandler ncHandler = new NcHandler()) + { + CmsError cmsError = ncHandler.SwapQueueItems(processId, itemsPositions.Item1Position, itemsPositions.Item2Position); + if (cmsError.IsError()) + return BadRequest(cmsError.localizationKey); + } + + return Ok(); + } + + [Route("queue/{processId:int}/edit/{positionId:int}"), HttpPut] + public IHttpActionResult EditQueueItem(int processId, int positionId, SwapItems reps) + { + using (NcHandler ncHandler = new NcHandler()) + { + CmsError cmsError = ncHandler.EditQueueItemReps(processId, positionId, reps.Reps ); + if (cmsError.IsError()) + return BadRequest(cmsError.localizationKey); + } + + return Ok(); + } + + public class SwapItems + { + public int Item1Position; + + public int Item2Position; + + public int Reps; + } + + #endregion } } \ No newline at end of file diff --git a/Step/Listeners/ListenersHandler.cs b/Step/Listeners/ListenersHandler.cs index c2213ebf..52ce0c83 100644 --- a/Step/Listeners/ListenersHandler.cs +++ b/Step/Listeners/ListenersHandler.cs @@ -80,6 +80,11 @@ namespace Step.Listeners SignalRListener.SendNcMagazineIsActive(a); })); + infos.Add(MessageServices.Current.Subscribe(SEND_QUEUE_DATA, (a, b) => + { + SignalRListener.SendPartProgramQueue(a); + })); + // Database infos.Add(MessageServices.Current.Subscribe(UPDATE_TOOLS_DATA, (a, b) => diff --git a/Step/Listeners/SignalR/SignalRListener.cs b/Step/Listeners/SignalR/SignalRListener.cs index 2f6e6d0c..b594a5b1 100644 --- a/Step/Listeners/SignalR/SignalRListener.cs +++ b/Step/Listeners/SignalR/SignalRListener.cs @@ -3,6 +3,7 @@ using Step.Config; using Step.Controllers.SignalR; using Step.Model.DTOModels; using Step.Model.DTOModels.ToolModels; +using Step.Utils; using System; using System.Collections.Generic; using System.Diagnostics; @@ -26,6 +27,7 @@ namespace Step.Listeners.SignalR private static DTOMagazineActionModel LastMagazineStatus = new DTOMagazineActionModel(); private static DTOActiveProgramDataModel LastProgramData = new DTOActiveProgramDataModel(); private static Dictionary LastNcMagazineIsActive = new Dictionary(); + private static List LastPartProgramQueue = new List(); private static bool LastIsNcConnected = false; @@ -226,6 +228,25 @@ namespace Step.Listeners.SignalR } } + public static void SendPartProgramQueue(object queue) + { + List newQueue = queue as List; + var context = GlobalHost.ConnectionManager.GetHubContext(); + if (!LastPartProgramQueue.SequenceEqual(newQueue)) + { + LastPartProgramQueue = new List(); + + foreach(var queueItem in newQueue) + { + DTOQueueModel tmp = new DTOQueueModel(); + SupportFunctions.CopyProperties(queueItem, tmp); + LastPartProgramQueue.Add(tmp); + } + + context.Clients.Group("ncData").partProgramQueue(newQueue.ToList()); + } + } + private volatile static object _broadcastlock = new Object(); public static void BroadcastData() @@ -273,7 +294,9 @@ namespace Step.Listeners.SignalR // Send active program data context.Clients.Group("ncData").activeProgramData(LastProgramData); // Send magazine is active data - context.Clients.Group("ncData").magazineIsActive(LastNcMagazineIsActive); + context.Clients.Group("ncData").magazineIsActive(LastNcMagazineIsActive); + // Send PP Queue + context.Clients.Group("ncData").partProgramQueue(LastPartProgramQueue); Debug.WriteLine(string.Format("{0} {1} Broadcast..completed", DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss"), DateTime.Now.Millisecond)); Monitor.Exit(_broadcastlock);