diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2025-08-14 03:43:16 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2025-08-14 03:43:16 +0300 |
| commit | d9322cdd83c46d1add0a3c8421e28ee878c29396 (patch) | |
| tree | db0dd91f24b9ae7af438f498a4f6200e04977599 | |
| parent | 61bc5d6672a0dd3c7fd0f8e1a95d5c037fb20cab (diff) | |
| download | Tango-d9322cdd83c46d1add0a3c8421e28ee878c29396.tar.gz Tango-d9322cdd83c46d1add0a3c8421e28ee878c29396.zip | |
Machine Operator Printing Operations Major Refactoring.
Revived Job Resume for X1/X4/PPC.
14 files changed, 1563 insertions, 1560 deletions
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/ViewModels/MainViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/ViewModels/MainViewVM.cs index 5e0d36da5..59de35d51 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/ViewModels/MainViewVM.cs @@ -70,31 +70,38 @@ namespace Tango.PPC.Jobs.ViewModels { _handler = e.JobHandler; - if (resuming) + if (!BuildProvider.MachineType.IsXMachine()) { - resuming = false; - - InvokeUI(() => + if (resuming) { - NavigationManager.NavigateTo<JobsV2Module>(nameof(JobProgressView)); + resuming = false; - if (_last_failed_job_notification != null) + InvokeUI(() => { - _last_failed_job_notification.Close(); - _last_failed_job_notification = null; - } - }); + NavigationManager.NavigateTo<JobsV2Module>(nameof(JobProgressView)); + + if (_last_failed_job_notification != null) + { + _last_failed_job_notification.Close(); + _last_failed_job_notification = null; + } + }); + } } } - private void MachineOperator_ResumingJob(object sender, ResumingJobEventArgs e) + private async void MachineOperator_ResumingJob(object sender, ResumingJobEventArgs e) { LogManager.Log($"Job resume request '{e.JobGuid}' approving..."); try { - e.Approve(); - resuming = true; + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + var job = await new JobBuilder(db).Set(e.JobGuid).WithRML(null).WithConfiguration().WithSegments().WithBrushStops().BuildAsync(); + e.Approve(job); + resuming = true; + } } catch (Exception ex) { diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs index d1fb283b0..84b8a8851 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs @@ -488,7 +488,7 @@ namespace Tango.PPC.Common.Synchronization { _synchronizedOnce = true; - if (!IsEnabled || IsSynchronizing) return; + if (!IsEnabled || IsSynchronizing || _machineProvider.MachineOperator.IsPrinting) return; var settings = SettingsManager.Default.GetOrCreate<PPCSettings>(); diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineStatusViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineStatusViewVM.cs index 59f4d4f93..f153b3636 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineStatusViewVM.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineStatusViewVM.cs @@ -1207,7 +1207,7 @@ namespace Tango.PPC.UI.ViewModels } } - private async void DropResume() + private void DropResume() { if (Job != null && HasResumeModel) { diff --git a/Software/Visual_Studio/Tango.BL/Entities/BrushStop.cs b/Software/Visual_Studio/Tango.BL/Entities/BrushStop.cs index 8de903a46..f41cfec9c 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/BrushStop.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/BrushStop.cs @@ -29,6 +29,7 @@ namespace Tango.BL.Entities private ActionTimer _syncTimer; private static List<String> _colorPropertyNames; public const double MAX_INK_UPTAKE = 400; + private object _lock = new object(); #region Enums @@ -155,7 +156,21 @@ namespace Tango.BL.Entities [JsonIgnore] public ObservableCollection<LiquidVolume> LiquidVolumesOrderedPigmented { - get { return LiquidVolumes != null ? LiquidVolumes.Where(x => x.IdsPack.LiquidType.HasPigment).OrderBy(x => x.IdsPack.LiquidType.PreferredIndex).ToObservableCollection() : null; } + get + { + if (LiquidVolumes != null) + { + lock (_lock) + { + var list = LiquidVolumes.ToList().Where(x => x.IdsPack.LiquidType.HasPigment).OrderBy(x => x.IdsPack.LiquidType.PreferredIndex).ToObservableCollection(); + return list; + } + } + else + { + return null; + } + } } public void SetLiquidVolume(LiquidTypes liquidType, double volume) @@ -170,7 +185,21 @@ namespace Tango.BL.Entities [JsonIgnore] public ObservableCollection<LiquidVolume> LiquidVolumesOrderedPigmentedForStandardUser { - get { return LiquidVolumes != null ? LiquidVolumes.Where(x => x.IdsPack.LiquidType.HasPigment && x.IdsPack.LiquidType.AvailableForStandardUser).OrderBy(x => x.IdsPack.LiquidType.PreferredIndex).ToObservableCollection() : null; } + get + { + if (LiquidVolumes != null) + { + lock (_lock) + { + var list = LiquidVolumes.ToList().Where(x => x.IdsPack.LiquidType.HasPigment && x.IdsPack.LiquidType.AvailableForStandardUser).OrderBy(x => x.IdsPack.LiquidType.PreferredIndex).ToList().ToObservableCollection(); + return list; + } + } + else + { + return null; + } + } } /// <summary> @@ -515,17 +544,19 @@ namespace Tango.BL.Entities /// <param name="processParametersTable">The process parameters table.</param> public void SetLiquidVolumes(Configuration configuration, Rml rml, ProcessParametersTable processParametersTable) { + //lock (_lock) + //{ LiquidVolumes = new ObservableCollection<LiquidVolume>(); - lock (LiquidVolumes) + lock (_lock) { foreach (var idsPack in configuration.GetSupportedIdsPacks(rml)) { var liquidVolume = new LiquidVolume(configuration, idsPack, rml, processParametersTable, this); liquidVolume.VolumeChanged += LiquidVolume_VolumeChanged; LiquidVolumes.Add(liquidVolume); - } + } } foreach (var volume in LiquidVolumes.ToList()) @@ -537,6 +568,7 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(LiquidVolumesOrdered)); RaisePropertyChanged(nameof(LiquidVolumesOrderedPigmented)); RaisePropertyChanged(nameof(LiquidVolumesOrderedPigmentedForStandardUser)); + //} } /// <summary> diff --git a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs index 1bf2d3cb7..09f5ea2ac 100644 --- a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs +++ b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs @@ -326,6 +326,7 @@ namespace Tango.Emulations.Emulators public override Task Start() { + _current_job_resume_token = null; _isAfterReset = true; return base.Start(); } @@ -930,6 +931,10 @@ namespace Tango.Emulations.Emulators }, _current_job_resume_token); } } + else + { + LogManager.Log($"[Machine Enulator]: Job Progress: {progress}"); + } if (addedResume) { @@ -997,25 +1002,43 @@ namespace Tango.Emulations.Emulators if (_failJob) { - Transporter.SendResponse<JobResponse>(new JobResponse() + if (_current_job_resume_token == null) { + Transporter.SendResponse<JobResponse>(new JobResponse() + { - }, request.Container.Token, new TransportResponseConfig() { - ErrorCode = ErrorCode.JobThreadBreak, - ErrorMessage = "This is a message about a thread break from the emulator", - EventType = PMR.Diagnostics.EventType.ThreadBreak, - }); + }, request.Container.Token, new TransportResponseConfig() + { + ErrorCode = ErrorCode.JobThreadBreak, + ErrorMessage = "This is a message about a thread break from the emulator", + EventType = PMR.Diagnostics.EventType.ThreadBreak, + }); + } + else + { + Transporter.SendResponse<CurrentJobResponse>(new CurrentJobResponse() + { + + }, request.Container.Token, new TransportResponseConfig() + { + ErrorCode = ErrorCode.JobThreadBreak, + ErrorMessage = "This is a message about a thread break from the emulator", + EventType = PMR.Diagnostics.EventType.ThreadBreak, + }); + } break; } if (_cancelJob) { + _current_job_resume_token = null; break; } } if (_cancelJob) { + _current_job_resume_token = null; break; } } diff --git a/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs b/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs index 1596c4b22..293e0bcc6 100644 --- a/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs +++ b/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs @@ -123,212 +123,223 @@ namespace Tango.Integration.JobRuns private void InsertJobRun(PrintingEventArgs e, JobRunStatus status, Exception exception) { - if (ShouldLog()) + if (!e.IsResumingJob) { - if (e.Job.Guid == _job.Guid) + if (ShouldLog()) { - Task.Factory.StartNew(() => + if (e.Job.Guid == _job.Guid) { - try + Task.Factory.StartNew(() => { - using (var db = ObservablesContext.CreateDefault()) + try { - var colorSpaces = db.ColorSpaces.ToList(); - - JobRun run = new JobRun(); - - run.UserGuid = _job.UserGuid; - run.StartDate = e.StartDate; - run.UploadingStartDate = e.UploadingStartTime; - run.HeatingStartDate = e.HeatingStartTime; - run.ActualStartDate = e.ActualStartTime; - run.EndDate = DateTime.UtcNow; - run.JobName = _job.Name; - run.Source = JobSource; - run.Designation = _job.Designation; - run.JobGuid = _job.Guid; - run.RmlGuid = _job.RmlGuid; - run.MachineGuid = _job.MachineGuid; - run.JobRunStatus = status; - run.EndPosition = e.JobHandler.Status.Progress; - run.NumberOfUnits = _job.NumberOfUnits; - run.JobLength = e.JobHandler.Status.TotalProgress; - run.JobLogicalLength = e.Job.Length; - run.LiquidQuantities = e.LiquidQuantities; - run.IsGradient = _job.Segments.Any(x => x.BrushStops.Count > 1); - run.GradientResolutionCm = MachineOperator.GradientGenerationConfiguration.ResolutionCM; - run.ActualStartPosition = e.Job.ResumeStartPosition; - run.ActualEndPosition = e.JobHandler.Status.ProgressMinusSettingUp; - - if (_defaultMachine != null) + using (var db = ObservablesContext.CreateDefault()) { - run.MachineType = _defaultMachine.MachineType; - } - else if (_job.Machine != null) - { - run.MachineType = _job.Machine.MachineType; - } + var colorSpaces = db.ColorSpaces.ToList(); - var jobFile = e.Job.ToJobFileWhenLoaded(); + JobRun run = new JobRun(); - try - { - if (_job.Designation == JobDesignations.FineTuning) + run.UserGuid = _job.UserGuid; + run.StartDate = e.StartDate; + run.UploadingStartDate = e.UploadingStartTime; + run.HeatingStartDate = e.HeatingStartTime; + run.ActualStartDate = e.ActualStartTime; + run.EndDate = DateTime.UtcNow; + run.JobName = _job.Name; + run.Source = JobSource; + run.Designation = _job.Designation; + run.JobGuid = _job.Guid; + run.RmlGuid = _job.RmlGuid; + run.MachineGuid = _job.MachineGuid; + run.JobRunStatus = status; + run.EndPosition = e.JobHandler.Status.Progress; + run.NumberOfUnits = _job.NumberOfUnits; + run.JobLength = e.JobHandler.Status.TotalProgress; + run.JobLogicalLength = e.Job.Length; + run.LiquidQuantities = e.LiquidQuantities; + run.IsGradient = _job.Segments.Any(x => x.BrushStops.Count > 1); + run.GradientResolutionCm = MachineOperator.GradientGenerationConfiguration.ResolutionCM; + run.ActualStartPosition = e.Job.ResumeStartPosition; + run.ActualEndPosition = e.JobHandler.Status.ProgressMinusSettingUp; + + if (_defaultMachine != null) { - jobFile.Segments.First().BrushStops.First().ColorSpaceGuid = colorSpaces.First(x => x.Code == (int)ColorSpaces.LAB).Guid; + run.MachineType = _defaultMachine.MachineType; + } + else if (_job.Machine != null) + { + run.MachineType = _job.Machine.MachineType; } - } - catch (Exception ex) - { - LogManager.Log(ex, "Error setting brush stop color space to LAB on fine tuning job run (JobFileString)."); - } - - run.JobString = jobFile.ToString(); - - run.ApplicationVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); - run.FirmwareVersion = MachineOperator.DeviceInformation?.Version; - run.CeVersion = _job.Rml.ColorConversionVersion.ToString(); - run.ProcessParametersTableGuid = MachineOperator.CurrentProcessParameters?.Guid; - - //Set individual liquid quantities - - //Cyan - var cyan = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Cyan); - run.CyanQuantity = cyan != null ? cyan.Quantity : 0; - - //Magenta - var magenta = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Magenta); - run.MagentaQuantity = magenta != null ? magenta.Quantity : 0; - - //Yellow - var yellow = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Yellow); - run.YellowQuantity = yellow != null ? yellow.Quantity : 0; - //Black - var black = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Black); - run.BlackQuantity = black != null ? black.Quantity : 0; + var jobFile = e.Job.ToJobFileWhenLoaded(); - //TI - var ti = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.TransparentInk); - run.TransparentQuantity = ti != null ? ti.Quantity : 0; + try + { + if (_job.Designation == JobDesignations.FineTuning) + { + jobFile.Segments.First().BrushStops.First().ColorSpaceGuid = colorSpaces.First(x => x.Code == (int)ColorSpaces.LAB).Guid; + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error setting brush stop color space to LAB on fine tuning job run (JobFileString)."); + } - //Lubricant - var lubricant = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Lubricant); - run.LubricantQuantity = lubricant != null ? lubricant.Quantity : 0; + run.JobString = jobFile.ToString(); - //Cleaner - var cleaner = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Cleaner); - run.CleanerQuantity = cleaner != null ? cleaner.Quantity : 0; + run.ApplicationVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); + run.FirmwareVersion = MachineOperator.DeviceInformation?.Version; + run.CeVersion = _job.Rml.ColorConversionVersion.ToString(); + run.ProcessParametersTableGuid = MachineOperator.CurrentProcessParameters?.Guid; - //Light Cyan - var lightCyan = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.LightCyan); - run.LightCyanQuantity = lightCyan != null ? lightCyan.Quantity : 0; + //Set liquid quantities + SetJobRunLiquidQuantities(run, run.LiquidQuantities); - //Light Magenta - var lightMagenta = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.LightMagenta); - run.LightMagentaQuantity = lightMagenta != null ? lightMagenta.Quantity : 0; + if (exception != null) + { + run.FailedMessage = exception.FlattenMessage(); + } - //Light Yellow - var lightYellow = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.LightYellow); - run.LightYellowQuantity = lightYellow != null ? lightYellow.Quantity : 0; + if (_job.Designation == JobDesignations.FineTuning) + { + try + { + run.FineTuningString = JsonConvert.SerializeObject(_job.VectorFineTuningRunModel); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error serializing fine tuning model for job run."); + } + } - //Blue - var blue = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Blue); - run.BlueQuantity = blue != null ? blue.Quantity : 0; + db.JobRuns.Add(run); - //Light Blue - var lightBlue = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.LightBlue); - run.LightBlueQuantity = lightBlue != null ? lightBlue.Quantity : 0; + e.Job.LastRun = DateTime.UtcNow; + _job.LastRun = DateTime.UtcNow; - //Orange - var orange = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Orange); - run.OrangeQuantity = orange != null ? orange.Quantity : 0; + var job = db.Jobs.SingleOrDefault(x => x.Guid == _job.Guid); - //Light Orange - var lightOrange = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.LightOrange); - run.LightOrangeQuantity = lightOrange != null ? lightOrange.Quantity : 0; + if (job != null) + { + job.LastRun = DateTime.UtcNow; + } - //Rubine - var rubine = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Rubine); - run.RubineQuantity = rubine != null ? rubine.Quantity : 0; + LogManager.Log($"Inserting job run for '{run.JobName}'...\n{run.ToJsonString(nameof(JobRun.JobString), nameof(JobRun.LiquidQuantityString))}"); - //Light Rubine - var lightRubine = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.LightRubine); - run.LightRubineQuantity = lightRubine != null ? lightRubine.Quantity : 0; + db.SaveChanges(); - //Navy - var navy = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Navy); - run.NavyQuantity = navy != null ? navy.Quantity : 0; + JobRunInfo jobRunInfo = new JobRunInfo(); + jobRunInfo.JobRunID = run.ID; + jobRunInfo.JobTicket = _jobTicket; + jobRunInfo.Events = _currentJobEvents.Select(x => MachinesEventDTO.FromObservable(x)).ToList(); + jobRunInfo.StartMachineStatus = _startMachineStatus; + jobRunInfo.EndMachineStatus = MachineOperator.MachineStatus?.Clone(); - //Violet - var violet = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Violet); - run.VioletQuantity = violet != null ? violet.Quantity : 0; + if (CreateJobRunsFiles) + { + try + { + Directory.CreateDirectory(JobRunsFolder); - if (exception != null) - { - run.FailedMessage = exception.FlattenMessage(); - } + String json = jobRunInfo.ToJsonString(); + File.WriteAllText(Path.Combine(JobRunsFolder, $"{run.ID}.run"), json); - if (_job.Designation == JobDesignations.FineTuning) - { - try - { - run.FineTuningString = JsonConvert.SerializeObject(_job.VectorFineTuningRunModel); - } - catch (Exception ex) - { - LogManager.Log(ex, "Error serializing fine tuning model for job run."); + LogManager.Log($"JobRun extended info file '{run.ID}' created."); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error creating job run extended info file."); + } } + + JobRunAvailable?.Invoke(this, new JobRunAvailableEventArgs() { JobRunInfo = jobRunInfo, JobRun = run }); } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error logging the last job run to the database."); + } + }); + } + } + } + else + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + try + { + var run = db.JobRuns.OrderByDescending(x => x.LastUpdated).FirstOrDefault(x => x.JobGuid == _job.Guid); - db.JobRuns.Add(run); + if (run == null) + { + LogManager.Log($"Error updating job run by resumed job. Could not locate the existing job run by job guid '{_job.Guid}'."); + return; + } - e.Job.LastRun = DateTime.UtcNow; - _job.LastRun = DateTime.UtcNow; + run.LastUpdated = DateTime.UtcNow; + run.EndDate = DateTime.UtcNow; + run.JobRunStatus = status; + run.EndPosition = e.JobHandler.Status.Progress; + run.JobLength = e.JobHandler.Status.TotalProgress; + run.ActualEndPosition = e.JobHandler.Status.ProgressMinusSettingUp; - var job = db.Jobs.SingleOrDefault(x => x.Guid == _job.Guid); + if (exception != null) + { + run.FailedMessage = exception.FlattenMessage(); + } + else + { + run.FailedMessage = null; + } - if (job != null) - { - job.LastRun = DateTime.UtcNow; - } + var newQuantities = e.LiquidQuantities.ToList(); + var oldQuantities = run.LiquidQuantities.ToList(); - LogManager.Log($"Inserting job run for '{run.JobName}'...\n{run.ToJsonString(nameof(JobRun.JobString), nameof(JobRun.LiquidQuantityString))}"); + SetJobRunLiquidQuantities(run, newQuantities, update: true); - db.SaveChanges(); + //Append liquid quantities string. + foreach (var newQuantity in newQuantities) + { + var oldQuantity = oldQuantities.FirstOrDefault(x => x.LiquidType == newQuantity.LiquidType); + if (oldQuantity != null) + { + oldQuantity.Quantity += newQuantity.Quantity; + } + else + { + oldQuantities.Add(newQuantity); + } + } - JobRunInfo jobRunInfo = new JobRunInfo(); - jobRunInfo.JobRunID = run.ID; - jobRunInfo.JobTicket = _jobTicket; - jobRunInfo.Events = _currentJobEvents.Select(x => MachinesEventDTO.FromObservable(x)).ToList(); - jobRunInfo.StartMachineStatus = _startMachineStatus; - jobRunInfo.EndMachineStatus = MachineOperator.MachineStatus?.Clone(); + run.LiquidQuantities = oldQuantities; - if (CreateJobRunsFiles) - { - try - { - Directory.CreateDirectory(JobRunsFolder); + db.SaveChanges(); - String json = jobRunInfo.ToJsonString(); - File.WriteAllText(Path.Combine(JobRunsFolder, $"{run.ID}.run"), json); + //TODO: Needs to resubmit this to Azure! Then in Azure Distinct by job run ID, by job guid, by latest! - LogManager.Log($"JobRun extended info file '{run.ID}' created."); - } - catch (Exception ex) - { - LogManager.Log(ex, "Error creating job run extended info file."); - } - } + try + { + String jobInfoPath = Path.Combine(JobRunsFolder, $"{run.ID}.run"); - JobRunAvailable?.Invoke(this, new JobRunAvailableEventArgs() { JobRunInfo = jobRunInfo, JobRun = run }); + if (File.Exists(jobInfoPath)) + { + String json = File.ReadAllText(jobInfoPath); + JobRunInfo info = JsonConvert.DeserializeObject<JobRunInfo>(json); + info.Events.AddRange(_currentJobEvents.Select(x => MachinesEventDTO.FromObservable(x)).ToList()); + info.EndMachineStatus = MachineOperator.MachineStatus?.Clone(); + File.WriteAllText(jobInfoPath, info.ToJsonString()); } } catch (Exception ex) { - LogManager.Log(ex, "Error logging the last job run to the database."); + LogManager.Log(ex, "Error while trying to update jobrun info file after job resume."); } - }); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error while trying to update jobrun by resumed job."); + } } } } @@ -359,47 +370,7 @@ namespace Tango.Integration.JobRuns run.JobLength = e.Length; run.LiquidQuantities = e.LiquidQuantities; - //Set individual liquid quantities - - //Cyan - var cyan = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Cyan); - run.CyanQuantity = cyan != null ? cyan.Quantity : 0; - - //Magenta - var magenta = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Magenta); - run.MagentaQuantity = magenta != null ? magenta.Quantity : 0; - - //Yellow - var yellow = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Yellow); - run.YellowQuantity = yellow != null ? yellow.Quantity : 0; - - //Black - var black = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Black); - run.BlackQuantity = black != null ? black.Quantity : 0; - - //TI - var ti = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.TransparentInk); - run.TransparentQuantity = ti != null ? ti.Quantity : 0; - - //Lubricant - var lubricant = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Lubricant); - run.LubricantQuantity = lubricant != null ? lubricant.Quantity : 0; - - //Cleaner - var cleaner = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.Cleaner); - run.CleanerQuantity = cleaner != null ? cleaner.Quantity : 0; - - //Light Cyan - var lightCyan = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.LightCyan); - run.LightCyanQuantity = lightCyan != null ? lightCyan.Quantity : 0; - - //Light Magenta - var lightMagenta = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.LightMagenta); - run.LightMagentaQuantity = lightMagenta != null ? lightMagenta.Quantity : 0; - - //Light Yellow - var lightYellow = run.LiquidQuantities.SingleOrDefault(x => x.LiquidType == LiquidTypes.LightYellow); - run.LightYellowQuantity = lightYellow != null ? lightYellow.Quantity : 0; + SetJobRunLiquidQuantities(run, run.LiquidQuantities); //if (exception != null) //{ @@ -421,6 +392,43 @@ namespace Tango.Integration.JobRuns } } + private void SetJobRunLiquidQuantities(JobRun run, List<BL.ValueObjects.JobRunLiquidQuantity> quantities, bool update = false) + { + if (run == null || quantities == null) + return; + + // Map each LiquidType to the corresponding JobRun property updater + var setters = new Dictionary<LiquidTypes, Action<long>> + { + { LiquidTypes.Cyan, q => run.CyanQuantity = update ? run.CyanQuantity + q : q }, + { LiquidTypes.Magenta, q => run.MagentaQuantity = update ? run.MagentaQuantity + q : q }, + { LiquidTypes.Yellow, q => run.YellowQuantity = update ? run.YellowQuantity + q : q }, + { LiquidTypes.Black, q => run.BlackQuantity = update ? run.BlackQuantity + q : q }, + { LiquidTypes.TransparentInk, q => run.TransparentQuantity = update ? run.TransparentQuantity + q : q }, + { LiquidTypes.Lubricant, q => run.LubricantQuantity = update ? run.LubricantQuantity + q : q }, + { LiquidTypes.Cleaner, q => run.CleanerQuantity = update ? run.CleanerQuantity + q : q }, + { LiquidTypes.LightCyan, q => run.LightCyanQuantity = update ? run.LightCyanQuantity + q : q }, + { LiquidTypes.LightMagenta, q => run.LightMagentaQuantity = update ? run.LightMagentaQuantity + q : q }, + { LiquidTypes.LightYellow, q => run.LightYellowQuantity = update ? run.LightYellowQuantity + q : q }, + { LiquidTypes.Blue, q => run.BlueQuantity = update ? run.BlueQuantity + q : q }, + { LiquidTypes.LightBlue, q => run.LightBlueQuantity = update ? run.LightBlueQuantity + q : q }, + { LiquidTypes.Orange, q => run.OrangeQuantity = update ? run.OrangeQuantity + q : q }, + { LiquidTypes.LightOrange, q => run.LightOrangeQuantity = update ? run.LightOrangeQuantity + q : q }, + { LiquidTypes.Rubine, q => run.RubineQuantity = update ? run.RubineQuantity + q : q }, + { LiquidTypes.LightRubine, q => run.LightRubineQuantity = update ? run.LightRubineQuantity + q : q }, + { LiquidTypes.Navy, q => run.NavyQuantity = update ? run.NavyQuantity + q : q }, + { LiquidTypes.Violet, q => run.VioletQuantity = update ? run.VioletQuantity + q : q } + }; + + foreach (var liquidType in setters.Keys) + { + var quantityObj = quantities.SingleOrDefault(x => x.LiquidType == liquidType); + var quantity = quantityObj?.Quantity ?? 0; + setters[liquidType](quantity); + } + } + + #endregion #region Public Methods @@ -469,29 +477,12 @@ namespace Tango.Integration.JobRuns InsertJobRun(e, JobRunStatus.Completed, null); } - private async void Machine_PrintingStarted(object sender, PrintingEventArgs e) + private void Machine_PrintingStarted(object sender, PrintingEventArgs e) { _job = e.Job; _currentJobEvents = new List<MachinesEvent>(); _startMachineStatus = MachineOperator.MachineStatus?.Clone(); _jobTicket = e.JobHandler.JobTicket; - - //if (_job.Designation == JobDesignations.FineTuning) return; - - if (e.IsResumed) - { - try - { - using (ObservablesContext db = ObservablesContext.CreateDefault()) - { - _job = await new JobBuilder(db).Set(e.Job.Guid).WithConfiguration().WithSegments().WithBrushStops().BuildAsync(); - } - } - catch (Exception ex) - { - LogManager.Log(ex, "Error loading resumed job from database."); - } - } } private void MachineOperator_HeadCleaningEnded(object sender, HeadCleaningEndedEventArgs e) diff --git a/Software/Visual_Studio/Tango.Integration/Operation/CachedJobOperation.cs b/Software/Visual_Studio/Tango.Integration/Operation/CachedJobOperation.cs index cca0ca516..7b009e7c0 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/CachedJobOperation.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/CachedJobOperation.cs @@ -14,5 +14,6 @@ namespace Tango.Integration.Operation public MachineStatus MachineStatus { get; set; } public ProcessParametersTableDTO ProcessParametersDTO { get; set; } public ConfigurationDTO MachineConfigurationDTO { get; set; } + public AdditionalJobConfiguration Config { get; set; } } } diff --git a/Software/Visual_Studio/Tango.Integration/Operation/DefaultGradientGenerationConfiguration.cs b/Software/Visual_Studio/Tango.Integration/Operation/DefaultGradientGenerationConfiguration.cs index 31cab35a3..47b324b9c 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/DefaultGradientGenerationConfiguration.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/DefaultGradientGenerationConfiguration.cs @@ -243,7 +243,7 @@ namespace Tango.Integration.Operation LiquidVolumesStop cmyk = new LiquidVolumesStop(); - foreach (var v in refStop.LiquidVolumesOrderedPigmentedForStandardUser) + foreach (var v in refStop.LiquidVolumesOrderedPigmentedForStandardUser.ToList()) { cmyk.Volumes[v.LiquidType] = (float)((offset - before.OffsetPercent) * (after.Volumes[v.LiquidType] - before.Volumes[v.LiquidType]) / (after.OffsetPercent - before.OffsetPercent) + before.Volumes[v.LiquidType]); } @@ -255,7 +255,7 @@ namespace Tango.Integration.Operation private LiquidVolumesStop GetCMYK(BrushStop stop) { LiquidVolumesStop s = new LiquidVolumesStop(); - foreach (var v in stop.LiquidVolumesOrderedPigmentedForStandardUser) + foreach (var v in stop.LiquidVolumesOrderedPigmentedForStandardUser.ToList()) { s.Volumes[v.LiquidType] = v.Volume; } diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index fed6825f3..c38348bce 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -46,6 +46,7 @@ using Tango.PMR.ThreadLoading; using Tango.BL.DTO; using Tango.PMR.IFS; using System.Runtime.CompilerServices; +using Tango.BL.Interfaces; namespace Tango.Integration.Operation { @@ -75,18 +76,62 @@ namespace Tango.Integration.Operation private bool _machineStatusSent; private bool _inkFillingStatusSent; private bool _threadLoadingSent; - private static RunningJobStatus _last_job_status; private bool _isPowerDownRequestInProgress; private bool _isHeadCleaningInProgress; - private List<BL.ValueObjects.JobRunLiquidQuantity> _lastJobLiquidQuantities; private DateTime _diagnosticsTime; - private MachineStatus _machineStatusBeforeJobStart; private Configuration _machineConfiguration; + private MachineStatus _lastMachineStatus; + + protected class CurrentJobContext + { + private List<BL.ValueObjects.JobRunLiquidQuantity> _liquidQuantities; + private Func<CurrentJobContext, List<BL.ValueObjects.JobRunLiquidQuantity>> _getLiquidQuantities; + + public MachineStatus MachineStatusOnCreation { get; private set; } + + public DateTime StartDate { get; set; } + public DateTime? UploadingStartDate { get; set; } + public DateTime? HeatingStartDate { get; set; } + public DateTime? ActualStartDate { get; set; } + + public Job Job { get; set; } + public Job OriginalJob { get; set; } + public Job ClonedJob { get; set; } + public Job JobForJobRun { get; set; } + + public JobTicket JobTicket { get; set; } + + public JobHandler JobHandler { get; set; } + + public bool RequestSent { get; set; } + public JobRequest JobRequest { get; set; } + + public bool JobCompleted { get; set; } + public bool ResponseLogged { get; set; } + + public bool InitialUseKeepAlive { get; set; } + + public bool IsResumingJob { get; set; } + + public List<BL.ValueObjects.JobRunLiquidQuantity> GetLiquidQuantities() + { + if (_liquidQuantities == null) + { + _liquidQuantities = _getLiquidQuantities(this).ToList(); + } + + return _liquidQuantities; + } + + public CurrentJobContext(MachineStatus currentMachineStatus, Func<CurrentJobContext, List<BL.ValueObjects.JobRunLiquidQuantity>> getLiquidQuantities) + { + MachineStatusOnCreation = currentMachineStatus.Clone(); + _getLiquidQuantities = getLiquidQuantities; + JobRequest = new JobRequest(); + StartDate = DateTime.UtcNow; + } + } - private DateTime _jobStartDate; - private DateTime? _jobUploadingStartDate; - private DateTime? _jobHeatingStartDate; - private DateTime? _jobActualStartDate; private List<Event> _emulatedEvents; private List<BitResultComposition> _bitResults; private JobSpoolType _currentSpoolType; @@ -850,6 +895,7 @@ namespace Tango.Integration.Operation SendContinuousRequest<StartMachineStatusUpdateRequest, StartMachineStatusUpdateResponse>(request, new TransportContinuousRequestConfig() { ShouldLog = true }).ObserveOn(new NewThreadScheduler()).Subscribe( (response) => { + _lastMachineStatus = response.Message.Status?.Clone(); OnMachineStatusChanged(response); if (!responseLogged) @@ -1308,14 +1354,14 @@ namespace Tango.Integration.Operation /// </summary> /// <param name="handler">The handler.</param> /// <param name="job">The job.</param> - protected virtual void OnPrintingStarted(JobHandler handler, Job job, bool isResumed = false) + protected virtual void OnPrintingStarted(CurrentJobContext context) { LogManager.Log("Raising printing started event..."); - PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, job) + PrintingStarted?.Invoke(this, new PrintingEventArgs(context.JobHandler, context.JobForJobRun) { - StartDate = _jobStartDate, - IsResumed = isResumed + StartDate = context.StartDate, + IsResumingJob = context.IsResumingJob }); } @@ -1324,20 +1370,21 @@ namespace Tango.Integration.Operation /// </summary> /// <param name="handler">The handler.</param> /// <param name="job">The job.</param> - protected virtual void OnPrintingCompleted(JobHandler handler, Job job) + protected virtual void OnPrintingCompleted(CurrentJobContext context) { LogManager.Log("Raising printing completed event..."); - PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, job) + PrintingCompleted?.Invoke(this, new PrintingEventArgs(context.JobHandler, context.JobForJobRun) { - LiquidQuantities = _lastJobLiquidQuantities.ToList(), - StartDate = _jobStartDate, - UploadingStartTime = _jobUploadingStartDate, - HeatingStartTime = _jobHeatingStartDate, - ActualStartTime = _jobActualStartDate, + LiquidQuantities = context.GetLiquidQuantities(), + StartDate = context.StartDate, + UploadingStartTime = context.UploadingStartDate, + HeatingStartTime = context.HeatingStartDate, + ActualStartTime = context.ActualStartDate, + IsResumingJob = context.IsResumingJob }); - OnPrintingEnded(handler, job); + OnPrintingEnded(context); } /// <summary> @@ -1346,19 +1393,20 @@ namespace Tango.Integration.Operation /// <param name="handler">The handler.</param> /// <param name="job">The job.</param> /// <param name="exception">The exception.</param> - protected virtual void OnPrintingFailed(JobHandler handler, Job job, Exception exception) + protected virtual void OnPrintingFailed(CurrentJobContext context, Exception exception) { LogManager.Log("Raising printing failed event..."); - PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, job, exception) + PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(context.JobHandler, context.JobForJobRun, exception) { - LiquidQuantities = _lastJobLiquidQuantities.ToList(), - StartDate = _jobStartDate, - UploadingStartTime = _jobUploadingStartDate, - HeatingStartTime = _jobHeatingStartDate, - ActualStartTime = _jobActualStartDate, + LiquidQuantities = context.GetLiquidQuantities(), + StartDate = context.StartDate, + UploadingStartTime = context.UploadingStartDate, + HeatingStartTime = context.HeatingStartDate, + ActualStartTime = context.ActualStartDate, + IsResumingJob = context.IsResumingJob }); - OnPrintingEnded(handler, job); + OnPrintingEnded(context); } /// <summary> @@ -1366,19 +1414,20 @@ namespace Tango.Integration.Operation /// </summary> /// <param name="handler">The handler.</param> /// <param name="job">The job.</param> - protected virtual void OnPrintingAborted(JobHandler handler, Job job) + protected virtual void OnPrintingAborted(CurrentJobContext context) { LogManager.Log("Raising printing aborted event..."); - PrintingAborted?.Invoke(this, new PrintingEventArgs(handler, job) + PrintingAborted?.Invoke(this, new PrintingEventArgs(context.JobHandler, context.JobForJobRun) { - LiquidQuantities = _lastJobLiquidQuantities.ToList(), - StartDate = _jobStartDate, - UploadingStartTime = _jobUploadingStartDate, - HeatingStartTime = _jobHeatingStartDate, - ActualStartTime = _jobActualStartDate, + LiquidQuantities = context.GetLiquidQuantities(), + StartDate = context.StartDate, + UploadingStartTime = context.UploadingStartDate, + HeatingStartTime = context.HeatingStartDate, + ActualStartTime = context.ActualStartDate, + IsResumingJob = context.IsResumingJob }); - OnPrintingEnded(handler, job); + OnPrintingEnded(context); } /// <summary> @@ -1386,33 +1435,32 @@ namespace Tango.Integration.Operation /// </summary> /// <param name="handler">The handler.</param> /// <param name="job">The job.</param> - protected virtual void OnPrintingEnded(JobHandler handler, Job job) + protected virtual void OnPrintingEnded(CurrentJobContext context) { IsSpoolReplaced = false; LogManager.Log("Raising printing ended event..."); - PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, job) + PrintingEnded?.Invoke(this, new PrintingEventArgs(context.JobHandler, context.JobForJobRun) { - LiquidQuantities = _lastJobLiquidQuantities.ToList(), - StartDate = _jobStartDate, - UploadingStartTime = _jobUploadingStartDate, - HeatingStartTime = _jobHeatingStartDate, - ActualStartTime = _jobActualStartDate, + LiquidQuantities = context.GetLiquidQuantities(), + StartDate = context.StartDate, + UploadingStartTime = context.UploadingStartDate, + HeatingStartTime = context.HeatingStartDate, + ActualStartTime = context.ActualStartDate, + IsResumingJob = context.IsResumingJob }); } - protected virtual void OnHeadCleaningEnded(HeadCleaningHandler handler, JobRunStatus status) + protected virtual void OnHeadCleaningEnded(CurrentJobContext context, HeadCleaningHandler handler, JobRunStatus status) { - SaveLastJobLiquidQuantities(null, null, null, null); - HeadCleaningEnded?.Invoke(this, new HeadCleaningEndedEventArgs() { - StartDate = _jobStartDate, + StartDate = context.StartDate, Length = handler.Status.Total, EndPosition = handler.Status.Progress, Status = status, - LiquidQuantities = _lastJobLiquidQuantities.ToList(), + LiquidQuantities = context.GetLiquidQuantities(), }); } @@ -1444,7 +1492,7 @@ namespace Tango.Integration.Operation _eventsSent = false; _machineStatusSent = false; - MachineStatus = null; + //MachineStatus = null; if (Status != MachineStatuses.Disconnected) { @@ -1562,7 +1610,7 @@ namespace Tango.Integration.Operation if (EnableJobResume) { - //ResumeJob(); + ResumeJob(); } if (response.Message.IsAfterReset) @@ -1642,7 +1690,7 @@ namespace Tango.Integration.Operation InkFillingStatusChanged?.Invoke(this, new InkFillingStatusChangedEventArgs() { Status = InkFillingStatus }); } - private void SaveCachedJobOperation(Job job) + private void SaveCachedJobOperation(Job job, AdditionalJobConfiguration config) { try { @@ -1652,6 +1700,7 @@ namespace Tango.Integration.Operation cache.MachineStatus = MachineStatus; cache.ProcessParametersDTO = ProcessParametersTableDTO.FromObservable(CurrentProcessParameters); cache.MachineConfigurationDTO = ConfigurationDTO.FromObservable(job.Machine.Configuration); + cache.Config = config; var json = JsonConvert.SerializeObject(cache); Directory.CreateDirectory(Path.GetDirectoryName(CachedJobOperationFile)); File.WriteAllText(CachedJobOperationFile, json); @@ -1748,197 +1797,197 @@ namespace Tango.Integration.Operation }); } - private async void ResumeJob() - { - LogManager.Log("Checking if a job is in progress..."); + //private async void ResumeJob() + //{ + // LogManager.Log("Checking if a job is in progress..."); - try - { - var res = await SendRequest<CurrentJobRequest, CurrentJobResponse>(new CurrentJobRequest(), new TransportRequestConfig() { ShouldLog = true }); + // try + // { + // var res = await SendRequest<CurrentJobRequest, CurrentJobResponse>(new CurrentJobRequest(), new TransportRequestConfig() { ShouldLog = true }); - if (res.Message.IsJobInProgress) - { - LogManager.Log("Job is in progress. Trying to resume job..."); - CachedJobOperation cache = LoadCachedJobOperation(); + // if (res.Message.IsJobInProgress) + // { + // LogManager.Log("Job is in progress. Trying to resume job..."); + // CachedJobOperation cache = LoadCachedJobOperation(); - if (cache == null) - { - LogManager.Log("Cannot resume current job with no cached operation.", LogCategory.Error); - return; - } + // if (cache == null) + // { + // LogManager.Log("Cannot resume current job with no cached operation.", LogCategory.Error); + // return; + // } - Job job = null; - Configuration configuration = null; - ProcessParametersTable processParameters = null; + // Job job = null; + // Configuration configuration = null; + // ProcessParametersTable processParameters = null; - try - { - processParameters = cache.ProcessParametersDTO.ToObservable(); - job = cache.JobDTO.ToObservable(); - configuration = cache.MachineConfigurationDTO.ToObservable(); - CurrentProcessParameters = processParameters; - } - catch (Exception ex) - { - LogManager.Log(ex, "Error deserializing cache job operation. Aborting resume."); - return; - } + // try + // { + // processParameters = cache.ProcessParametersDTO.ToObservable(); + // job = cache.JobDTO.ToObservable(); + // configuration = cache.MachineConfigurationDTO.ToObservable(); + // CurrentProcessParameters = processParameters; + // } + // catch (Exception ex) + // { + // LogManager.Log(ex, "Error deserializing cache job operation. Aborting resume."); + // return; + // } - JobTicket jobTicket = res.Message.JobTicket; + // JobTicket jobTicket = res.Message.JobTicket; - ResumingJobEventArgs args = new ResumingJobEventArgs(() => - { - RunningJob = null; - RunningJobStatus = null; + // ResumingJobEventArgs args = new ResumingJobEventArgs(() => + // { + // RunningJob = null; + // RunningJobStatus = null; - var request = new ResumeCurrentJobRequest(); + // var request = new ResumeCurrentJobRequest(); - JobHandler handler = null; + // JobHandler handler = null; - handler = new JobHandler(async () => - { - try - { - if (handler.CanCancel) - { - handler.CanCancel = false; - handler.IsCanceled = true; - LogManager.Log("Aborting current job..."); - var result = await SendRequest<AbortJobRequest, AbortJobResponse>(new AbortJobRequest(), new TransportRequestConfig() { ShouldLog = true }); - SaveLastJobLiquidQuantities(job, configuration, processParameters, handler); - OnPrintingAborted(handler, job); - handler.RaiseCanceled(); - if (Status != MachineStatuses.Disconnected) - { - UpdateStatus(MachineStatuses.ReadyToDye); - } - } - } - catch (Exception ex) - { - handler.CanCancel = true; - LogManager.Log(ex, "Failed to cancel job."); - } - }, job, jobTicket, processParameters, JobHandlingMode); + // handler = new JobHandler(async () => + // { + // try + // { + // if (handler.CanCancel) + // { + // handler.CanCancel = false; + // handler.IsCanceled = true; + // LogManager.Log("Aborting current job..."); + // var result = await SendRequest<AbortJobRequest, AbortJobResponse>(new AbortJobRequest(), new TransportRequestConfig() { ShouldLog = true }); + // SaveLastJobLiquidQuantities(job, configuration, processParameters, handler); + // OnPrintingAborted(handler, job); + // handler.RaiseCanceled(); + // if (Status != MachineStatuses.Disconnected) + // { + // UpdateStatus(MachineStatuses.ReadyToDye); + // } + // } + // } + // catch (Exception ex) + // { + // handler.CanCancel = true; + // LogManager.Log(ex, "Failed to cancel job."); + // } + // }, job, jobTicket, processParameters, JobHandlingMode); - handler.StatusChanged += (x, s) => - { - RunningJobStatus = s; - }; + // handler.StatusChanged += (x, s) => + // { + // RunningJobStatus = s; + // }; - if (MachineStatus != null) - { - _machineStatusBeforeJobStart = MachineStatus.Clone(); - } - else - { - _machineStatusBeforeJobStart = cache.MachineStatus.Clone(); - } + // if (MachineStatus != null) + // { + // _machineStatusBeforeJobStart = MachineStatus.Clone(); + // } + // else + // { + // _machineStatusBeforeJobStart = cache.MachineStatus.Clone(); + // } - _jobStartDate = DateTime.UtcNow; - _jobUploadingStartDate = _jobStartDate; - _jobHeatingStartDate = _jobStartDate; - _jobActualStartDate = null; + // _jobStartDate = DateTime.UtcNow; + // _jobUploadingStartDate = _jobStartDate; + // _jobHeatingStartDate = _jobStartDate; + // _jobActualStartDate = null; - bool responseLogged = false; - bool completed = false; + // bool responseLogged = false; + // bool completed = false; - Thread.Sleep(500); //Just wait maybe Shlomo is getting this message to fast after restart ? + // Thread.Sleep(500); //Just wait maybe Shlomo is getting this message to fast after restart ? - SendContinuousRequest<ResumeCurrentJobRequest, ResumeCurrentJobResponse>(request, new TransportContinuousRequestConfig() { ContinuousTimeout = TimeSpan.FromSeconds(10), ShouldLog = true }).Subscribe((response) => - { - if (!completed) - { - handler.RaiseStatusReceived(response.Message.Status); - _last_job_status = handler.Status; + // SendContinuousRequest<ResumeCurrentJobRequest, ResumeCurrentJobResponse>(request, new TransportContinuousRequestConfig() { ContinuousTimeout = TimeSpan.FromSeconds(10), ShouldLog = true }).Subscribe((response) => + // { + // if (!completed) + // { + // handler.RaiseStatusReceived(response.Message.Status); + // _last_job_status = handler.Status; - if (response.Message.Status.Progress > 0) - { - if (_jobActualStartDate == null) - { - _jobActualStartDate = DateTime.UtcNow; - } - } + // if (response.Message.Status.Progress > 0) + // { + // if (_jobActualStartDate == null) + // { + // _jobActualStartDate = DateTime.UtcNow; + // } + // } - if (!responseLogged) - { - UpdateStatus(MachineStatuses.GettingReady); - responseLogged = true; - RunningJob = job; - OnPrintingStarted(handler, job, true); - } + // if (!responseLogged) + // { + // UpdateStatus(MachineStatuses.GettingReady); + // responseLogged = true; + // RunningJob = job; + // OnPrintingStarted(handler, job, true); + // } - if (JobHandlingMode == JobHandlerModes.SettingUp) - { - if (response.Message.Status.Progress > CurrentProcessParameters.DryerBufferLengthMeters) - { - if (!completed) - { - UpdateStatus(MachineStatuses.Printing); - } - } - } - else - { - if (response.Message.Status.Progress > 0) - { - if (!completed) - { - UpdateStatus(MachineStatuses.Printing); - } - } - } - } - }, (ex) => - { - if (!completed) - { - completed = true; + // if (JobHandlingMode == JobHandlerModes.SettingUp) + // { + // if (response.Message.Status.Progress > CurrentProcessParameters.DryerBufferLengthMeters) + // { + // if (!completed) + // { + // UpdateStatus(MachineStatuses.Printing); + // } + // } + // } + // else + // { + // if (response.Message.Status.Progress > 0) + // { + // if (!completed) + // { + // UpdateStatus(MachineStatuses.Printing); + // } + // } + // } + // } + // }, (ex) => + // { + // if (!completed) + // { + // completed = true; - if (Status != MachineStatuses.Disconnected) - { - UpdateStatus(MachineStatuses.ReadyToDye); - } + // if (Status != MachineStatuses.Disconnected) + // { + // UpdateStatus(MachineStatuses.ReadyToDye); + // } - if (!handler.IsCanceled) - { - SaveLastJobLiquidQuantities(job, configuration, processParameters, handler); + // if (!handler.IsCanceled) + // { + // SaveLastJobLiquidQuantities(job, configuration, processParameters, handler); - Exception finalException = ex; + // Exception finalException = ex; - if (ex is ContinuousResponseAbortedException continuousException) - { - finalException = new ContinuousResponseAbortedException($"Job aborted by the embedded device ({continuousException.Container.ErrorMessage})."); - } + // if (ex is ContinuousResponseAbortedException continuousException) + // { + // finalException = new ContinuousResponseAbortedException($"Job aborted by the embedded device ({continuousException.Container.ErrorMessage})."); + // } - OnPrintingFailed(handler, job, finalException); - handler.RaiseFailed(finalException); - } - } - }, () => - { - if (!completed) - { - completed = true; - UpdateStatus(MachineStatuses.ReadyToDye); - SaveLastJobLiquidQuantities(job, configuration, processParameters, handler); - OnPrintingCompleted(handler, job); - handler.RaiseCompleted(); - } - }); + // OnPrintingFailed(handler, job, finalException); + // handler.RaiseFailed(finalException); + // } + // } + // }, () => + // { + // if (!completed) + // { + // completed = true; + // UpdateStatus(MachineStatuses.ReadyToDye); + // SaveLastJobLiquidQuantities(job, configuration, processParameters, handler); + // OnPrintingCompleted(handler, job); + // handler.RaiseCompleted(); + // } + // }); - return handler; - }); + // return handler; + // }); - args.JobGuid = jobTicket.Guid; - ResumingJob?.Invoke(this, args); - } - } - catch (Exception ex) - { - LogManager.Log(ex); - } - } + // args.JobGuid = jobTicket.Guid; + // ResumingJob?.Invoke(this, args); + // } + // } + // catch (Exception ex) + // { + // LogManager.Log(ex); + // } + //} /// <summary> /// Creates a PMR job segment. @@ -2022,85 +2071,85 @@ namespace Tango.Integration.Operation return jobSegment; } - private void ContinueSingleSpoolJob(Segment segment, Job job, ProcessParametersTable processParameters, JobHandler handler) - { - JobRequest request = new JobRequest(); + //private void ContinueSingleSpoolJob(Segment segment, Job job, ProcessParametersTable processParameters, JobHandler handler) + //{ + // JobRequest request = new JobRequest(); - JobTicket ticket = new JobTicket(); - ticket.Guid = handler.Job.Guid; - ticket.EnableInterSegment = job.EnableInterSegment; - ticket.InterSegmentLength = job.InterSegmentLength; - ticket.Length = segment.Length; - ticket.WindingMethod = (JobWindingMethod)job.WindingMethod.Code; - ticket.Spool = new JobSpool(); + // JobTicket ticket = new JobTicket(); + // ticket.Guid = handler.Job.Guid; + // ticket.EnableInterSegment = job.EnableInterSegment; + // ticket.InterSegmentLength = job.InterSegmentLength; + // ticket.Length = segment.Length; + // ticket.WindingMethod = (JobWindingMethod)job.WindingMethod.Code; + // ticket.Spool = new JobSpool(); - job.SpoolType.MapPrimitivesTo(ticket.Spool); - ticket.Spool.JobSpoolType = (JobSpoolType)job.SpoolType.Code; + // job.SpoolType.MapPrimitivesTo(ticket.Spool); + // ticket.Spool.JobSpoolType = (JobSpoolType)job.SpoolType.Code; - ProcessParameters process = new ProcessParameters(); - processParameters.MapPrimitivesTo(process); - ticket.ProcessParameters = process; + // ProcessParameters process = new ProcessParameters(); + // processParameters.MapPrimitivesTo(process); + // ticket.ProcessParameters = process; - ticket.Segments.Add(CreatePMRJobSegment(segment, job, processParameters)); + // ticket.Segments.Add(CreatePMRJobSegment(segment, job, processParameters)); - request.JobTicket = ticket; + // request.JobTicket = ticket; - bool responseLogged = false; + // bool responseLogged = false; - var previous_segments_length = job.Segments.Where(x => x.SegmentIndex < segment.SegmentIndex).Sum(x => x.Length); + // var previous_segments_length = job.Segments.Where(x => x.SegmentIndex < segment.SegmentIndex).Sum(x => x.Length); - SendContinuousRequest<JobRequest, JobResponse>(request, new TransportContinuousRequestConfig() { ContinuousTimeout = ContinuousRequestTimeout, ShouldLog = true }).Subscribe((response) => - { - response.Message.Status.Progress += previous_segments_length; + // SendContinuousRequest<JobRequest, JobResponse>(request, new TransportContinuousRequestConfig() { ContinuousTimeout = ContinuousRequestTimeout, ShouldLog = true }).Subscribe((response) => + // { + // response.Message.Status.Progress += previous_segments_length; - handler.RaiseStatusReceived(response.Message.Status); + // handler.RaiseStatusReceived(response.Message.Status); - if (!responseLogged && segment == job.OrderedSegments.First()) - { - responseLogged = true; - UpdateStatus(MachineStatuses.Printing); - RunningJob = handler.Job; - OnPrintingStarted(handler, handler.Job); - } + // if (!responseLogged && segment == job.OrderedSegments.First()) + // { + // responseLogged = true; + // UpdateStatus(MachineStatuses.Printing); + // RunningJob = handler.Job; + // OnPrintingStarted(handler, handler.Job); + // } - }, (ex) => - { - if (!(ex is ContinuousResponseAbortedException)) - { - UpdateStatus(MachineStatuses.ReadyToDye); + // }, (ex) => + // { + // if (!(ex is ContinuousResponseAbortedException)) + // { + // UpdateStatus(MachineStatuses.ReadyToDye); - if (!handler.IsCanceled) - { - OnPrintingFailed(handler, handler.Job, ex); - handler.RaiseFailed(ex); - } - } - else - { - UpdateStatus(MachineStatuses.ReadyToDye); - } - }, () => - { - if (segment == job.OrderedSegments.Last()) - { - UpdateStatus(MachineStatuses.ReadyToDye); - OnPrintingCompleted(handler, handler.Job); - handler.RaiseCompleted(); - } - else - { - handler.RaiseSpoolChangeRequired(() => - { - ContinueSingleSpoolJob(segment.GetNextSegment(), job, processParameters, handler); - }, () => - { - OnPrintingAborted(handler, handler.Job); - UpdateStatus(MachineStatuses.ReadyToDye); - handler.RaiseCanceled(); - }); - } - }); - } + // if (!handler.IsCanceled) + // { + // OnPrintingFailed(handler, handler.Job, ex); + // handler.RaiseFailed(ex); + // } + // } + // else + // { + // UpdateStatus(MachineStatuses.ReadyToDye); + // } + // }, () => + // { + // if (segment == job.OrderedSegments.Last()) + // { + // UpdateStatus(MachineStatuses.ReadyToDye); + // OnPrintingCompleted(handler, handler.Job); + // handler.RaiseCompleted(); + // } + // else + // { + // handler.RaiseSpoolChangeRequired(() => + // { + // ContinueSingleSpoolJob(segment.GetNextSegment(), job, processParameters, handler); + // }, () => + // { + // OnPrintingAborted(handler, handler.Job); + // UpdateStatus(MachineStatuses.ReadyToDye); + // handler.RaiseCanceled(); + // }); + // } + // }); + //} private List<RequiredLiquid> ValidateJobLiquidQuantity(Job job, ProcessParametersTable processParameters, Configuration configuration) { @@ -2356,25 +2405,22 @@ namespace Tango.Integration.Operation /// <param name="job">The job.</param> /// <param name="configuration">The configuration.</param> /// <param name="handler">The handler.</param> - private void SaveLastJobLiquidQuantities(Job job, Configuration configuration, ProcessParametersTable processParameters, JobHandler handler) + private List<BL.ValueObjects.JobRunLiquidQuantity> GetJobRunLiquidQuantities(CurrentJobContext context) { LogManager.Log($"Calculating job run liquid quantities using '{JobLiquidQuantityCalculationMode}' method..."); - if (configuration == null) - { - configuration = _machineConfiguration; - } + var liquidQuantities = new List<BL.ValueObjects.JobRunLiquidQuantity>(); try { - _lastJobLiquidQuantities = new List<BL.ValueObjects.JobRunLiquidQuantity>(); - - if (JobLiquidQuantityCalculationMode == JobLiquidQuantityCalculationMode.MachineStatus) + //if (JobLiquidQuantityCalculationMode == JobLiquidQuantityCalculationMode.MachineStatus) + //{ + foreach (var pack in _machineConfiguration.NoneEmptyIdsPacks.ToList()) { - foreach (var pack in configuration.NoneEmptyIdsPacks.ToList()) + try { var packLevelAfter = MachineStatus.IDSPacksLevels.SingleOrDefault(x => x.Index == pack.PackIndex); - var packLevelBefore = _machineStatusBeforeJobStart.IDSPacksLevels.SingleOrDefault(x => x.Index == pack.PackIndex); + var packLevelBefore = context.MachineStatusOnCreation.IDSPacksLevels.SingleOrDefault(x => x.Index == pack.PackIndex); if (packLevelAfter != null && packLevelBefore != null) { @@ -2384,25 +2430,32 @@ namespace Tango.Integration.Operation continue; } - _lastJobLiquidQuantities.Add(new BL.ValueObjects.JobRunLiquidQuantity() + liquidQuantities.Add(new BL.ValueObjects.JobRunLiquidQuantity() { LiquidType = pack.LiquidType.Type, Quantity = packLevelBefore.DispenserLevel64 - packLevelAfter.DispenserLevel64, }); } } + catch (Exception ex) + { + LogManager.Log(ex, $"Error calculating liquid quantity for {pack.LiquidType.Name}"); + } } - else - { - _lastJobLiquidQuantities = CreateJobRunLiquidQuantities(job, configuration, processParameters, handler.Status.Progress, handler.Status.TotalProgress); - } + //} + //else + //{ + // liquidQuantities = CreateJobRunLiquidQuantitiesUsingIntegral(job, configuration, processParameters, jobProgress, jobTotalProgress); + //} - LogManager.Log($"Job run liquid quantities calculation completed:\n{_lastJobLiquidQuantities.ToJsonString()}"); + LogManager.Log($"Job run liquid quantities calculation completed:\n{liquidQuantities.ToJsonString()}"); } catch (Exception ex) { LogManager.Log(ex, LogCategory.Critical, "Error calculating and saving last job run liquid quantities."); } + + return liquidQuantities; } #endregion @@ -2419,7 +2472,7 @@ namespace Tango.Integration.Operation /// <param name="length">The length.</param> /// <param name="gradientResolution">The gradient resolution.</param> /// <returns></returns> - public static List<BL.ValueObjects.JobRunLiquidQuantity> CreateJobRunLiquidQuantities(Job job, Configuration configuration, ProcessParametersTable processParameters, double position, double length) + public static List<BL.ValueObjects.JobRunLiquidQuantity> CreateJobRunLiquidQuantitiesUsingIntegral(Job job, Configuration configuration, ProcessParametersTable processParameters, double position, double length) { var units = Math.Max(job.NumberOfUnits, 1); @@ -2543,876 +2596,6 @@ namespace Tango.Integration.Operation #region Public Methods /// <summary> - /// Prints the specified job. - /// The process parameters table will be calculated using color conversion gamut region. - /// This method cannot accept brush stops with 'Volume' as color space. - /// </summary> - /// <param name="job">The job.</param> - /// <param name="config">Optional job configuration.</param> - /// <returns></returns> - public async Task<JobHandler> Print(Job job, AdditionalJobConfiguration config = null) - { - ProcessParametersTable processParameters = null; - - if (config == null) config = new AdditionalJobConfiguration(); - - await Task.Factory.StartNew(() => - { - IColorConverter converter = new DefaultColorConverter(); - - if (job.Rml == null) - { - throw new NullReferenceException("Job RML is null"); - } - - var processGroup = job.Rml.ProcessParametersTablesGroups.FirstOrDefault(x => x.Active); - - if (processGroup == null) - { - throw new NullReferenceException("Could not locate an active process parameters tables group for RML " + job.Rml.Name); - } - - try - { - bool useLightInks = config.UseLightInks; - if (job.OrderedSegmentsWithGroups.Count > 1 && !job.EnableInterSegment) useLightInks = false; - - processParameters = converter.GetRecommendedProcessParameters(job, useLightInks); - } - catch (Exception ex) - { - throw LogManager.Log(new InvalidOperationException($"An error occurred while trying to resolve the recommended process parameters.\n{ex.Message}")); - } - - if (processParameters == null) - { - throw new NullReferenceException("Could not locate any process parameters table in group " + processGroup.Name + " for RML " + job.Rml.Name); - } - - try - { - foreach (var stop in job.OrderedSegmentsWithGroups.SelectMany(x => x.BrushStops).ToList()) - { - stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); - } - } - catch (Exception ex) - { - throw LogManager.Log(new InvalidOperationException($"An error occurred while trying to apply final liquid volumes.\n{ex.Message}")); - } - }); - - return await Print(job, processParameters, config); - } - - /// <summary> - /// Prints the specified job using the specified job parameters. - /// </summary> - /// <param name="job">The job.</param> - /// <param name="processParameters">Process parameters table</param> - /// <returns></returns> - public Task<JobHandler> Print(Job job, ProcessParametersTable processParameters, AdditionalJobConfiguration config = null) - { - //processParameters.DryerBufferLength = 10; //TODO: REMOVE !!! - - return Task.Factory.StartNew(() => - { - if (config == null) config = new AdditionalJobConfiguration(); - - if (!CanPrint) - { - throw new InvalidOperationException("Could not print while status = " + Status); - } - - _jobStartDate = DateTime.UtcNow; - - LogManager.Log($"Executing job '{job.Name}'..."); - - if (MachineStatus == null) - { - LogManager.Log("Aborting job execution. No machine status received yet."); - throw new InvalidOperationException("Cannot execute a job before at least one machine status has been received."); - } - - _lastJobLiquidQuantities = new List<BL.ValueObjects.JobRunLiquidQuantity>(); - _jobUploadingStartDate = null; - _jobHeatingStartDate = null; - _jobActualStartDate = null; - - RunningJob = null; - RunningJobStatus = null; - - if (job.NumberOfUnits < 1) - { - job.NumberOfUnits = 1; - } - - var originalJob = job; - var clonedJob = job.Clone(); - clonedJob.Guid = job.Guid; - clonedJob.Name = job.Name; - - job = job.Clone(); - job.Guid = originalJob.Guid; - job.Name = originalJob.Name; - - var jobSegments = job.OrderedSegmentsWithGroups; - - //Color Conversion - if (config.UseColorConversion) - { - IColorConverter converter = new DefaultColorConverter(); - - bool useLightInks = config.UseLightInks; - - //Use light inks only if one segment or inter segment is enabled. - if (MachineType == MachineTypes.TS1800 && job.OrderedSegmentsWithGroups.Count > 1 && !job.EnableInterSegment) useLightInks = false; - - foreach (var segment in jobSegments) - { - foreach (var stop in segment.BrushStops) - { - try - { - var output = converter.Convert(stop, false, useLightInks && segment.BrushStops.Count == 1); //Use light inks only if this is a solid segment. - output.ApplyOnBrushStopLiquidVolumes(stop, processParameters); - } - catch (Exception ex) - { - throw new InvalidOperationException($"Error processing the coordinates of stop '{stop.StopIndex}' of segment '{stop.Segment.SegmentIndex}'.", ex); - } - - if (stop.IsLiquidVolumesOutOfRange) - { - throw new InvalidOperationException($"The specified ink volumes at segment {segment.SegmentIndex} exceeds the maximum allowed total volume for the current thread."); - } - } - } - } - - //Lubrication - if (job.EnableLubrication) - { - if (config.UseLubricantVolume) - { - LogManager.Log($"Job custom lubrication is enabled. Settings all brush stops to {config.LubricationVolume}% lubricant."); - - foreach (var stop in jobSegments.SelectMany(x => x.BrushStops).ToList()) - { - var lubricantVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.Lubricant); - - if (lubricantVolume != null) - { - lubricantVolume.Volume = config.LubricationVolume; - } - } - } - else - { - LogManager.Log($"Job auto lubrication is enabled. Settings all none Volume brush stops to 100% lubricant."); - - foreach (var stop in jobSegments.SelectMany(x => x.BrushStops).Where(x => x.BrushColorSpace != ColorSpaces.Volume).ToList()) - { - var lubricantVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.Lubricant); - - if (lubricantVolume != null) - { - lubricantVolume.Volume = 100; - } - } - } - } - else - { - LogManager.Log("Job lubrication is disabled."); - } - - //Modify transparent/white brush stops. (Transparent/white stops should be all zeros and 100% TI) - LogManager.Log("Modifying all 'white' brush stops..."); - foreach (var stop in job.OrderedSegmentsWithGroups.SelectMany(x => x.BrushStops).Where(x => x.IsTransparent || x.IsWhite).ToList()) - { - foreach (var liquidVolume in stop.LiquidVolumes.Where(x => x.LiquidType != LiquidTypes.TransparentInk && x.LiquidType != LiquidTypes.Lubricant).ToList()) - { - liquidVolume.Volume = 0; - } - - var tiLiquid = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.TransparentInk); - - if (tiLiquid != null) - { - tiLiquid.Volume = 100; - } - } - - var segments = job.OrderedSegmentsWithGroups.ToList(); - - List<RequiredLiquid> requiredLiquids = null; - - //Validate liquid quantities - if (EnableJobLiquidQuantityValidation && MachineType == MachineTypes.TS1800) - { - if (!originalJob.Rml.UseColorLibGradients) //Validate liquid quantities when ColorLib generate gradient is disabled - { - requiredLiquids = ValidateJobLiquidQuantity(job, processParameters, job.Machine.Configuration); - } - else //Validate liquid quantities when ColorLib generate gradient is enabled - { - JobTicket t = new JobTicket(); - t.NumberOfUnits = (uint)originalJob.NumberOfUnits; - - foreach (var segment in segments) - { - if (segment is Segment simpleSegment) - { - t.Segments.Add(CreatePMRJobSegment(simpleSegment, originalJob, processParameters)); - } - else if (segment is SegmentsGroup group) - { - List<JobSegment> groupSegments = new List<JobSegment>(); - - foreach (var innerSegment in group.OrderedSegments) - { - groupSegments.Add(CreatePMRJobSegment(innerSegment, originalJob, processParameters)); - } - - for (int i = 0; i < group.Repeats; i++) - { - t.Segments.AddRange(groupSegments.ToList()); - } - } - } - - requiredLiquids = ValidateJobLiquidQuantity(t, processParameters, job.Machine.Configuration); - } - } - else - { - LogManager.Log("Liquid quantity validation is disabled. Skipping..."); - } - - CurrentProcessParameters = processParameters; - - JobRequest request = new JobRequest(); - - var jobForJobRun = job.Clone(); - jobForJobRun.Guid = job.Guid; - jobForJobRun.Name = job.Name; - jobForJobRun.ID = job.ID; - - if (config.ResumeConfig != null) - { - jobForJobRun.ResumeStartPosition = config.ResumeConfig.ResumeProgress; - } - - int max = job.OrderedSegmentsWithGroups.Last().SegmentIndex + 1; - - for (int i = 0; i < job.NumberOfUnits - 1; i++) - { - foreach (var s in segments) - { - var cloned = s.Clone(job); - cloned.SegmentIndex = max++; - - if (cloned is Segment simpleSegment) - { - job.Segments.Add(simpleSegment); - } - else if (cloned is SegmentsGroup g) - { - job.SegmentsGroups.Add(g); - } - } - } - - JobTicket ticket = new JobTicket(); - ticket.Guid = originalJob.Guid; - ticket.EnableInterSegment = job.EnableInterSegment; - ticket.InterSegmentLength = Math.Max(job.InterSegmentLength, 1); - ticket.EnableLubrication = job.EnableLubrication; - ticket.Length = job.Length; - ticket.WindingMethod = (JobWindingMethod)job.WindingMethod.Code; - ticket.UploadStrategy = JobUploadStrategy; - - if (JobUnitsMethod == JobUnitsMethods.Device) - { - ticket.NumberOfUnits = (uint)Math.Max(job.NumberOfUnits, 1); - } - - //Spool parameters - ticket.Spool = new JobSpool(); - job.SpoolType.MapPropertiesTo(ticket.Spool); - ticket.Spool.JobSpoolType = (JobSpoolType)job.SpoolType.Code; - - //Override spool parameters from RML Spool calibration - var rmlSpool = job.Rml.RmlsSpools.FirstOrDefault(x => x.SpoolType.Guid == job.SpoolType.Guid); - if (rmlSpool != null) - { - ticket.Spool.RotationsPerPassage = rmlSpool.RotationsPerPassage != null ? rmlSpool.RotationsPerPassage.Value : ticket.Spool.RotationsPerPassage; - ticket.Spool.Length = rmlSpool.Length != null ? rmlSpool.Length.Value : ticket.Spool.Length; - ticket.Spool.BackingRate = rmlSpool.BackingRate != null ? rmlSpool.BackingRate.Value : ticket.Spool.BackingRate; - ticket.Spool.BottomBackingRate = rmlSpool.BottomBackingRate != null ? rmlSpool.BottomBackingRate.Value : ticket.Spool.BottomBackingRate; - ticket.Spool.BtsrSpoolTension = rmlSpool.BtsrSpoolTension != null ? rmlSpool.BtsrSpoolTension.Value : ticket.Spool.BtsrSpoolTension; - ticket.Spool.StartOffsetPulses = rmlSpool.StartOffsetPulses != null ? rmlSpool.StartOffsetPulses.Value : ticket.Spool.StartOffsetPulses; - ticket.Spool.SegmentOffsetPulses = rmlSpool.SegmentOffsetPulses != null ? rmlSpool.SegmentOffsetPulses.Value : ticket.Spool.SegmentOffsetPulses; - } - - //Override spool parameters from Machine Spool calibration - var machineSpool = job.Machine.Spools.FirstOrDefault(x => x.SpoolType.Guid == job.SpoolType.Guid); - if (machineSpool != null) - { - ticket.Spool.LimitSwitchStartPointOffset = machineSpool.LimitSwitchStartPointOffset != null ? machineSpool.LimitSwitchStartPointOffset.Value : ticket.Spool.LimitSwitchStartPointOffset; - //ticket.Spool.StartOffsetPulses = machineSpool.StartOffsetPulses != null ? machineSpool.StartOffsetPulses.Value : ticket.Spool.StartOffsetPulses; - //ticket.Spool.BackingRate = machineSpool.BackingRate != null ? machineSpool.BackingRate.Value : ticket.Spool.BackingRate; - //ticket.Spool.SegmentOffsetPulses = machineSpool.SegmentOffsetPulses != null ? machineSpool.SegmentOffsetPulses.Value : ticket.Spool.SegmentOffsetPulses; - //ticket.Spool.BottomBackingRate = machineSpool.BottomBackingRate != null ? machineSpool.BottomBackingRate.Value : ticket.Spool.BottomBackingRate; - } - - //Thread Parameters - ticket.ThreadParameters = new ThreadParameters(); - job.Rml.MapPrimitivesTo(ticket.ThreadParameters); - - ProcessParameters process = new ProcessParameters(); - processParameters.MapPrimitivesTo(process); - ticket.ProcessParameters = process; - - //Head Cleaning Parameters - ticket.HeadCleaningParameters = new HeadCleaningParameters(); - ticket.HeadCleaningParameters.CleanerFlow = job.Rml.CleanerFlow; - ticket.HeadCleaningParameters.ArcHeadCleaningMotorSpeed = job.Rml.ArcHeadCleaningMotorSpeed; - - //BTSR Parameters - ticket.BtsrParameters = new PMR.BTSR.BtsrParameters(); - ticket.BtsrParameters.BtsrApplicationType = job.Rml.BtsrApplicationType != null ? (PMR.BTSR.BtsrApplicationType)job.Rml.BtsrApplicationType.Code : PMR.BTSR.BtsrApplicationType.Seamless; - ticket.BtsrParameters.BtsrYarnType = job.Rml.BtsrYarnType != null ? (PMR.BTSR.BtsrYarnType)job.Rml.BtsrYarnType.Code : PMR.BTSR.BtsrYarnType.AllYarn3; - ticket.BtsrParameters.TensionError = (float)job.Rml.BtsrTensionError; - - JobHandler handler = null; - StorageFileHandler fileUploadHandler = null; - - bool requestSent = false; - - handler = new JobHandler(async () => - { - try - { - if (handler.CanCancel) - { - handler.CanCancel = false; - handler.IsCanceled = true; - LogManager.Log("Aborting current job..."); - LogManager.Log($"Aborting current gradient generation..."); - GradientGenerationConfiguration.AbortCurrentGeneration(); - - if (fileUploadHandler != null) - { - LogManager.Log("Job is currently uploading. Aborting file upload..."); - await fileUploadHandler.Cancel(); - fileUploadHandler = null; - LogManager.Log("Job upload canceled."); - if (Status != MachineStatuses.Disconnected) - { - UpdateStatus(MachineStatuses.ReadyToDye); - } - OnPrintingAborted(handler, jobForJobRun); - handler.RaiseCanceled(); - } - else - { - if (requestSent) - { - var result = await SendRequest<AbortJobRequest, AbortJobResponse>(new AbortJobRequest(), new TransportRequestConfig() { ShouldLog = true }); - } - - SaveLastJobLiquidQuantities(clonedJob, originalJob.Machine.Configuration, processParameters, handler); - - if (Status != MachineStatuses.Disconnected) - { - UpdateStatus(MachineStatuses.ReadyToDye); - } - - OnPrintingAborted(handler, jobForJobRun); - handler.RaiseCanceled(); - } - } - } - catch (Exception ex) - { - handler.CanCancel = true; - LogManager.Log(ex, "Failed to cancel job."); - } - }, clonedJob, ticket, processParameters, JobHandlingMode, config.ResumeConfig); - - handler.StatusChanged += (x, s) => - { - RunningJobStatus = s; - }; - - if (!job.IsAllSegmentsPerSpool) - { - ContinueSingleSpoolJob(job.OrderedSegments.First(), job, processParameters, handler); - return handler; - } - - ThreadFactory.StartNew(async () => - { - if (handler.IsCanceled) - { - UpdateStatus(MachineStatuses.ReadyToDye); - return; - } - - UpdateStatus(MachineStatuses.GettingReady); - RunningJob = clonedJob; - OnPrintingStarted(handler, clonedJob); - - Thread.Sleep(100); - - handler.RaiseStatusReceived(new JobStatus() - { - CurrentSegmentIndex = 0, - Progress = 0, - Message = "Preparing Job...", - }); - - foreach (var segment in segments) - { - try - { - if (segment is Segment simpleSegment) - { - ticket.Segments.Add(CreatePMRJobSegment(simpleSegment, originalJob, processParameters)); - } - else if (segment is SegmentsGroup group) - { - List<JobSegment> groupSegments = new List<JobSegment>(); - - foreach (var innerSegment in group.OrderedSegments) - { - groupSegments.Add(CreatePMRJobSegment(innerSegment, originalJob, processParameters)); - } - - for (int i = 0; i < group.Repeats; i++) - { - ticket.Segments.AddRange(groupSegments.ToList()); - } - } - } - catch (Exception ex) - { - handler.RaiseFailed(ex); - UpdateStatus(MachineStatuses.ReadyToDye); - return; - } - - if (handler.IsCanceled) - { - UpdateStatus(MachineStatuses.ReadyToDye); - return; - } - } - - //Log Job Outline (Only first and last brush stops if gradient). - var ticketToLog = ticket.Clone(); - ticketToLog.Segments.Clear(); - - foreach (var seg in ticket.Segments) - { - JobSegment segmentToLog = new JobSegment(); - - segmentToLog.Length = seg.Length; - segmentToLog.BrushStops.Add(seg.BrushStops.First()); - - if (seg.BrushStops.Count > 1) - { - segmentToLog.BrushStops.Add(seg.BrushStops.Last()); - } - - ticketToLog.Segments.Add(segmentToLog); - } - - if (!job.EnableInterSegment) - { - NormalizeJobTicket(ticketToLog, processParameters); - } - - LogManager.Log($"Job outline for '{job.Name}':\n{ticketToLog.ToJsonString()}"); - - if (handler.IsCanceled) - { - UpdateStatus(MachineStatuses.ReadyToDye); - return; - } - - var segs = new List<JobSegment>(); - - if (JobUnitsMethod == JobUnitsMethods.Operator) - { - for (int i = 0; i < job.NumberOfUnits; i++) - { - foreach (var s in ticket.Segments) - { - var cloned = s.Clone(); - segs.Add(cloned); - } - } - } - else - { - foreach (var s in ticket.Segments) - { - var cloned = s.Clone(); - segs.Add(cloned); - } - } - - if (segs.Count > 0) - { - ticket.Segments.Clear(); - ticket.Segments.AddRange(segs); - } - - if (!job.EnableInterSegment) - { - NormalizeJobTicket(ticket, processParameters); - } - - request.JobTicket = ticket.Clone(); - - LogManager.Log($"Job upload method is set to {JobUploadStrategy}..."); - - if (handler.IsCanceled) - { - UpdateStatus(MachineStatuses.ReadyToDye); - return; - } - - var oldKeepAlive = UseKeepAlive; - - if (requiredLiquids != null) - { - JobPrepareRequest prepareRequest = new JobPrepareRequest(); - prepareRequest.ProcessParameters = ticket.ProcessParameters; - - foreach (var requiredLiquid in requiredLiquids) - { - JobPrepareDispenser prepareDispenser = new JobPrepareDispenser(); - prepareDispenser.DispenserLiquidType = (DispenserLiquidType)requiredLiquid.IdsPack.LiquidType.Type; - prepareDispenser.Index = requiredLiquid.IdsPack.PackIndex; - prepareDispenser.TotalNanoliter = Convert.ToInt32(requiredLiquid.Quantity); - prepareDispenser.Active = requiredLiquid.Quantity > 0; - - prepareRequest.Dispensers.Add(prepareDispenser); - } - - try - { - var response = await SendRequest<JobPrepareRequest, JobPrepareResponse>(prepareRequest, new TransportRequestConfig() - { - ShouldLog = true, - Timeout = TimeSpan.FromSeconds(10) - }); - } - catch (ResponseErrorException ex) - { - LogManager.Log(ex, "Error sending job preparation request. Aborting job..."); - UseKeepAlive = oldKeepAlive; - UpdateStatus(MachineStatuses.ReadyToDye); - OnPrintingFailed(handler, jobForJobRun, ex); - handler.RaiseFailed(ex); - return; - } - catch (Exception ex) - { - LogManager.Log(ex, "Error sending job preparation request."); - } - } - - if (JobUploadStrategy == JobUploadStrategy.JobDescriptionFile) - { - LogManager.Log("Generating job description file..."); - - try - { - request.JobTicket.Segments.Clear(); - - JobDescriptionFile jobDescriptionFile = new JobDescriptionFile(ticket.Segments); - MemoryStream ms = jobDescriptionFile.ToStream(); - - handler.RaiseStatusReceived(new JobStatus() - { - CurrentSegmentIndex = 0, - Progress = 0, - Message = "Uploading job description file...", - }); - - if (handler.IsCanceled) - { - UpdateStatus(MachineStatuses.ReadyToDye); - return; - } - - LogManager.Log("Creating storage API manager..."); - var storage = CreateStorageManager(); - - if (handler.IsCanceled) - { - UpdateStatus(MachineStatuses.ReadyToDye); - return; - } - - //Suppress keep alive while job uploads. - //storage.SuppressKeepAliveWhileFileUploads = true; - UseKeepAlive = false; //This is a work around for Shlomo not managing to keep alive while parsing the file. - - LogManager.Log("Getting storage drive information..."); - var storageInfo = await storage.GetStorageDrive(); - LogManager.Log("Getting root folder information..."); - var root_folder = await storage.GetRootFolder(); - - var existing_item = root_folder.Items.SingleOrDefault(x => x.Name == JOB_DESCRIPTION_FILE_NAME); - if (existing_item != null) - { - LogManager.Log("Removing previous job description file..."); - await storage.DeleteItem(existing_item); - } - - String job_file_path = Path.Combine(storageInfo.Root, JOB_DESCRIPTION_FILE_NAME); - - LogManager.Log($"Uploading job description file '{job_file_path}' of size: {ms.Length} bytes..."); - - TaskCompletionSource<object> uploadCompletion = new TaskCompletionSource<object>(); - _jobUploadingStartDate = DateTime.UtcNow; - fileUploadHandler = await storage.UploadFile(job_file_path, ms); - bool uploadCanceled = false; - Exception uploadException = null; - fileUploadHandler.Canceled += (_, __) => - { - uploadCanceled = true; - uploadCompletion.SetResult(true); - }; - fileUploadHandler.Completed += (_, __) => - { - uploadCompletion.SetResult(true); - }; - fileUploadHandler.Failed += (_, e) => - { - uploadCompletion.SetException(e); - }; - - try - { - await uploadCompletion.Task; - } - catch (Exception ue) - { - if (uploadException != null) - { - throw uploadException; - } - else - { - throw ue; - } - } - finally - { - try - { - fileUploadHandler = null; - ms.Dispose(); - } - catch { } - } - - if (uploadCanceled) - { - return; - } - else - { - LogManager.Log("Job upload completed successfully."); - } - - request.JobTicket.JobDescriptionFile = job_file_path; - } - catch (Exception ex) - { - UseKeepAlive = oldKeepAlive; - UpdateStatus(MachineStatuses.ReadyToDye); - OnPrintingFailed(handler, jobForJobRun, ex); - handler.RaiseFailed(ex); - return; - } - } - else - { - _jobUploadingStartDate = DateTime.UtcNow; - } - - if (handler.IsCanceled) - { - UseKeepAlive = oldKeepAlive; - UpdateStatus(MachineStatuses.ReadyToDye); - return; - } - - _machineStatusBeforeJobStart = MachineStatus.Clone(); - - SaveCachedJobOperation(clonedJob); //Cache job and machine status for job resume! - - bool responseLogged = false; - bool completed = false; //Use this in case Shlomo is sending progress after completion. - - _jobHeatingStartDate = DateTime.UtcNow; - - if (handler.IsCanceled) - { - UseKeepAlive = oldKeepAlive; - UpdateStatus(MachineStatuses.ReadyToDye); - return; - } - - double resumePreProgress = 0; - - if (config.ResumeConfig != null) - { - LogManager.Log("Job Resume Detected..."); - - resumePreProgress = config.ResumeConfig.GlobalStartPosition;// - config.ResumeConfig.FirstUnitStartPosition;//- processParameters.DryerBufferLengthMeters; - - request.FirstUnitStartPosition = config.ResumeConfig.GlobalStartPosition; - - //LogManager.Log($" resumePreProgress = {resumePreProgress}, GlobalStartPosition {config.ResumeConfig.GlobalStartPosition} FirstUnitStartPosition {request.FirstUnitStartPosition}"); - request.JobTicket.Length = (request.JobTicket.Length / Math.Max(request.JobTicket.NumberOfUnits, 1)) * (int)Math.Max(config.ResumeConfig.RemainingUnits, 1); - request.JobTicket.NumberOfUnits = (uint)Math.Max(config.ResumeConfig.RemainingUnits, 1); - - LogManager.Log($"Resume Config:\n{config.ResumeConfig.ToJsonString()}\n"); - } - - SendContinuousRequest<JobRequest, JobResponse>(request, new TransportContinuousRequestConfig() { Timeout = TimeSpan.FromSeconds(10), ContinuousTimeout = TimeSpan.FromSeconds(10), ShouldLog = true }).Subscribe((response) => - { - if (!completed) - { - //if (resumePreProgress > 0 && response.Message.Status.Progress > 0) - //{ - // //LogManager.Log($"Appending Resume Progress {resumePreProgress} + {response.Message.Status.Progress}", LogCategory.Debug); - // //response.Message.Status.Progress += resumePreProgress; - //} - - handler.RaiseStatusReceived(response.Message.Status); - _last_job_status = handler.Status; - - if (response.Message.Status.Progress > 0) - if (oldKeepAlive != UseKeepAlive) - { - { - UseKeepAlive = oldKeepAlive; - } - - if (_jobActualStartDate == null) - { - _jobActualStartDate = DateTime.UtcNow; - } - } - - if (!responseLogged) - { - requestSent = true; - responseLogged = true; - } - - if (JobHandlingMode == JobHandlerModes.SettingUp) - { - var printingStartPosition = processParameters.DryerBufferLengthMeters; - - if (config != null && config.ResumeConfig != null && config.ResumeConfig.GlobalStartPosition > 0) - { - printingStartPosition = config.ResumeConfig.GlobalStartPosition; - } - - if (response.Message.Status.Progress > printingStartPosition) - { - if (!completed) - { - UpdateStatus(MachineStatuses.Printing); - } - } - } - else - { - if (response.Message.Status.Progress > 0) - { - if (!completed) - { - UpdateStatus(MachineStatuses.Printing); - } - } - } - } - - }, (ex) => - { - if (!completed) - { - completed = true; - - UseKeepAlive = oldKeepAlive; - - if (Status != MachineStatuses.Disconnected) - { - UpdateStatus(MachineStatuses.ReadyToDye); - } - - if (!handler.IsCanceled) - { - SaveLastJobLiquidQuantities(originalJob, originalJob.Machine.Configuration, processParameters, handler); - - Exception finalException = ex; - - if (ex is ContinuousResponseAbortedException continuousException) - { - finalException = new ContinuousResponseAbortedException($"Job aborted by the embedded device ({continuousException.Container.ErrorMessage})."); - } - - handler.RaiseFailed(finalException); - OnPrintingFailed(handler, jobForJobRun, finalException); - } - } - }, () => - { - if (!completed) - { - completed = true; - - UseKeepAlive = oldKeepAlive; - - UpdateStatus(MachineStatuses.ReadyToDye); - SaveLastJobLiquidQuantities(clonedJob, originalJob.Machine.Configuration, processParameters, handler); - handler.RaiseCompleted(); - OnPrintingCompleted(handler, jobForJobRun); - } - }); - }); - - return handler; - - }); - } - - private void NormalizeJobTicket(JobTicket ticket, ProcessParametersTable processParameters) - { - var maxNanoStop = ticket.Segments.SelectMany(x => x.BrushStops).OrderBy(x => x.GetTotalNanoliterPerCentimeter()).Last(); - double maxNanoliter = maxNanoStop.GetTotalNanoliterPerCentimeter(); - - LogManager.Log($"Normalizing brush stops TI quantities by {maxNanoliter} nanoliters..."); - - foreach (var stop in ticket.Segments.SelectMany(x => x.BrushStops).Where(x => x != maxNanoStop)) - { - stop.NormalizeStop(maxNanoliter, processParameters.MinInkUptake, processParameters.DyeingSpeed); - } - } - - /// <summary> /// Uploads the specified process parameters to the embedded device. /// </summary> /// <param name="processParameters">The process parameters.</param> @@ -4498,6 +3681,8 @@ namespace Tango.Integration.Operation _isHeadCleaningInProgress = true; bool _completed = false; + var context = CreateJobContext(null, null); + HeadCleaningHandler handler = null; handler = new HeadCleaningHandler(() => { @@ -4507,7 +3692,7 @@ namespace Tango.Integration.Operation if (!_completed) { _completed = true; - OnHeadCleaningEnded(handler, JobRunStatus.Aborted); + OnHeadCleaningEnded(context, handler, JobRunStatus.Aborted); } var r = SendRequest<AbortHeadCleaningRequest, AbortHeadCleaningResponse>(new AbortHeadCleaningRequest(), new TransportRequestConfig() { ShouldLog = true }).Result; @@ -4517,11 +3702,7 @@ namespace Tango.Integration.Operation { Thread.Sleep(100); - _lastJobLiquidQuantities = new List<BL.ValueObjects.JobRunLiquidQuantity>(); - _machineStatusBeforeJobStart = MachineStatus.Clone(); - bool firstResponse = true; - _jobStartDate = DateTime.UtcNow; SendContinuousRequest<StartHeadCleaningRequest, StartHeadCleaningResponse>(new StartHeadCleaningRequest() { IsLongJob = longCleaning }, new TransportContinuousRequestConfig() { ContinuousTimeout = TimeSpan.FromSeconds(5), ShouldLog = true }).ObserveOn(new NewThreadScheduler()).Subscribe((response) => { @@ -4543,7 +3724,7 @@ namespace Tango.Integration.Operation if (!_completed) { _completed = true; - OnHeadCleaningEnded(handler, JobRunStatus.Failed); + OnHeadCleaningEnded(context, handler, JobRunStatus.Failed); } }, () => { @@ -4553,7 +3734,7 @@ namespace Tango.Integration.Operation if (!_completed) { _completed = true; - OnHeadCleaningEnded(handler, JobRunStatus.Completed); + OnHeadCleaningEnded(context, handler, JobRunStatus.Completed); } }); }); @@ -4787,7 +3968,7 @@ namespace Tango.Integration.Operation { try { - await SendRequest<SetWhiteThreadSkipRequest, SetWhiteThreadSkipResponse>(new SetWhiteThreadSkipRequest() { Enabled = enable}); + await SendRequest<SetWhiteThreadSkipRequest, SetWhiteThreadSkipResponse>(new SetWhiteThreadSkipRequest() { Enabled = enable }); LogManager.Log($"Machine white thread skip is now {(enable ? "Enabled" : "Disabled")}."); } catch (Exception ex) @@ -4797,5 +3978,896 @@ namespace Tango.Integration.Operation } #endregion + + #region Print + + /// <summary> + /// Prints the specified job. + /// The process parameters table will be calculated using color conversion gamut region. + /// This method cannot accept brush stops with 'Volume' as color space. + /// </summary> + /// <param name="job">The job.</param> + /// <param name="config">Optional job configuration.</param> + /// <returns></returns> + public async Task<JobHandler> Print(Job job, AdditionalJobConfiguration config = null) + { + ProcessParametersTable processParameters = null; + + if (config == null) config = new AdditionalJobConfiguration(); + + await Task.Factory.StartNew(() => + { + IColorConverter converter = new DefaultColorConverter(); + + if (job.Rml == null) + { + throw new NullReferenceException("Job RML is null"); + } + + var processGroup = job.Rml.ProcessParametersTablesGroups.FirstOrDefault(x => x.Active); + + if (processGroup == null) + { + throw new NullReferenceException("Could not locate an active process parameters tables group for RML " + job.Rml.Name); + } + + try + { + bool useLightInks = config.UseLightInks; + if (job.OrderedSegmentsWithGroups.Count > 1 && !job.EnableInterSegment) useLightInks = false; + + processParameters = converter.GetRecommendedProcessParameters(job, useLightInks); + } + catch (Exception ex) + { + throw LogManager.Log(new InvalidOperationException($"An error occurred while trying to resolve the recommended process parameters.\n{ex.Message}")); + } + + if (processParameters == null) + { + throw new NullReferenceException("Could not locate any process parameters table in group " + processGroup.Name + " for RML " + job.Rml.Name); + } + + try + { + foreach (var stop in job.OrderedSegmentsWithGroups.SelectMany(x => x.BrushStops).ToList()) + { + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); + } + } + catch (Exception ex) + { + throw LogManager.Log(new InvalidOperationException($"An error occurred while trying to apply final liquid volumes.\n{ex.Message}")); + } + }); + + return await Print(job, processParameters, config); + } + + /// <summary> + /// Prints the specified job using the specified job parameters. + /// </summary> + /// <param name="job">The job.</param> + /// <param name="processParameters">Process parameters table</param> + /// <returns></returns> + public Task<JobHandler> Print(Job job, ProcessParametersTable processParameters, AdditionalJobConfiguration config = null) + { + return Task.Run(async () => + { + if (config == null) config = new AdditionalJobConfiguration(); + + if (!CanPrint) + { + throw new InvalidOperationException("Could not print while status = " + Status); + } + + LogManager.Log($"Executing job '{job.Name}'..."); + + if (MachineStatus == null) + { + LogManager.Log("Aborting job execution. No machine status received yet."); + throw new InvalidOperationException("Cannot execute a job before at least one machine status has been received."); + } + + var context = CreateJobContext(job, config); + + CurrentProcessParameters = processParameters; + + UseKeepAlive = false; + + try + { + //Color Conversion + await ApplyColorConversion(context.Job, processParameters, config); + + //Lubrication + await ApplyLubrication(context.Job, config); + + //Modify transparent/white brush stops. (Transparent/white stops should be all zeros and 100% TI) + await ApplyTransparentBrushStops(context.Job); + + //Validate liquid quantities + List<RequiredLiquid> requiredLiquids = await PerformLiquidQuantityValidation(context.Job, processParameters); + + //Normalize Segments Group (Deprecated) + await ApplySegmentsGroupsToJob(context.Job); + + //Create Job Ticket + context.JobTicket = await CreateJobTicket(context, processParameters); + + //Create Job Handler + context.JobHandler = CreateJobHandler(processParameters, config, context); + + //Apply PMR Segments to Job Ticket + await ApplyPMRSegmentsToJobTicket(context, processParameters); + + //Log Job Outline (Only first and last brush stops if gradient). + //await LogJobOutline(job, processParameters, ticket); + + //Add job ticket segments per number of units for the actual request. + context.JobRequest.JobTicket = await NormalizeJobTicketUnits(job, processParameters, context.JobTicket); + + //Send Job Preperation Request. + await SendJobPrepareRequest(context, requiredLiquids); + + //Upload Job Description File. + await UploadJobDescriptionFile(context); + + ApplyResumeConfig(context, config); + + //Cache job and machine status for job resume. + SaveCachedJobOperation(context.ClonedJob, config); + } + catch (Exception) + { + UseKeepAlive = context.InitialUseKeepAlive; + throw; + } + + ThreadFactory.StartNew(() => + { + Thread.Sleep(100); //Give some time for callers to register for the job handler events.. + UpdateStatus(MachineStatuses.GettingReady); + OnPrintingStarted(context); + + SendContinuousRequest<JobRequest, JobResponse>(context.JobRequest, new TransportContinuousRequestConfig() { Timeout = TimeSpan.FromSeconds(10), ContinuousTimeout = TimeSpan.FromSeconds(10), ShouldLog = true }).Subscribe((response) => + { + ProcessJobStatus(context, response.Message.Status, processParameters, config?.ResumeConfig); + }, (ex) => + { + ProcessJobError(context, processParameters, ex); + }, () => + { + ProcessJobCompletion(context, processParameters); + }); + }); + + return context.JobHandler; + }); + } + + private async void ResumeJob() + { + LogManager.Log("Checking if a job is in progress..."); + + try + { + var res = await SendRequest<CurrentJobRequest, CurrentJobResponse>(new CurrentJobRequest(), new TransportRequestConfig() { ShouldLog = true }); + + if (res.Message.IsJobInProgress) + { + LogManager.Log("Job is in progress. Trying to resume job..."); + CachedJobOperation cache = LoadCachedJobOperation(); + + if (cache == null) + { + LogManager.Log("Cannot resume current job with no cached operation.", LogCategory.Error); + return; + } + + if (res.Message.JobTicket == null) + { + LogManager.Log("Cannot resume current. No job ticket received by the embedded device.", LogCategory.Error); + return; + } + + Guid g; + if (res.Message.JobTicket.Guid == null || !Guid.TryParse(res.Message.JobTicket.Guid, out g)) + { + LogManager.Log("Cannot resume current. Invalid job guid received by the embedded device.", LogCategory.Error); + return; + } + + var processParameters = cache.ProcessParametersDTO.ToObservable(); + var job = cache.JobDTO.ToObservable(); + var machineConfiguration = cache.MachineConfigurationDTO.ToObservable(); + var config = cache.Config; + + CurrentProcessParameters = processParameters; + _machineConfiguration = machineConfiguration; + + ResumingJobEventArgs args = new ResumingJobEventArgs((actualJob) => + { + var context = CreateJobContext(actualJob, config, _lastMachineStatus); + context.IsResumingJob = true; + context.JobTicket = res.Message.JobTicket; + context.JobHandler = CreateJobHandler(processParameters, config, context); + + RunningJob = null; + RunningJobStatus = null; + + var request = new ResumeCurrentJobRequest(); + + ThreadFactory.StartNew(() => + { + Thread.Sleep(1000); //Give some time for callers to register for the job handler events.. + UpdateStatus(MachineStatuses.GettingReady); + OnPrintingStarted(context); + + SendContinuousRequest<ResumeCurrentJobRequest, ResumeCurrentJobResponse>(request, new TransportContinuousRequestConfig() { Timeout = TimeSpan.FromSeconds(10), ContinuousTimeout = TimeSpan.FromSeconds(10), ShouldLog = true }).Subscribe((response) => + { + ProcessJobStatus(context, response.Message.Status, processParameters, config?.ResumeConfig); + }, (ex) => + { + ProcessJobError(context, processParameters, ex); + }, () => + { + ProcessJobCompletion(context, processParameters); + }); + }); + + return context.JobHandler; + }); + + args.JobGuid = res.Message.JobTicket.Guid; + ResumingJob?.Invoke(this, args); + } + } + catch (Exception ex) + { + LogManager.Log(ex); + } + } + + private void ApplyResumeConfig(CurrentJobContext context, AdditionalJobConfiguration config) + { + if (config.ResumeConfig != null) + { + LogManager.Log("Job Resume Detected..."); + + context.JobRequest.FirstUnitStartPosition = config.ResumeConfig.GlobalStartPosition; + + context.JobRequest.JobTicket.Length = (context.JobRequest.JobTicket.Length / Math.Max(context.JobRequest.JobTicket.NumberOfUnits, 1)) * (int)Math.Max(config.ResumeConfig.RemainingUnits, 1); + context.JobRequest.JobTicket.NumberOfUnits = (uint)Math.Max(config.ResumeConfig.RemainingUnits, 1); + + LogManager.Log($"Resume Config:\n{config.ResumeConfig.ToJsonString()}\n"); + } + } + + private void ProcessJobStatus(CurrentJobContext context, JobStatus status, ProcessParametersTable processParameters, AdditionalJobConfiguration.ResumeConfiguration resumeConfig) + { + if (!context.JobCompleted) + { + context.JobHandler.RaiseStatusReceived(status); + + if (!context.ResponseLogged) + { + context.HeatingStartDate = DateTime.UtcNow; + context.RequestSent = true; + context.ResponseLogged = true; + } + + if (status.Progress > 0) + { + if (context.InitialUseKeepAlive != UseKeepAlive) + { + UseKeepAlive = context.InitialUseKeepAlive; + } + + if (context.ActualStartDate == null) + { + context.ActualStartDate = DateTime.UtcNow; + } + } + + if (JobHandlingMode == JobHandlerModes.SettingUp) + { + var printingStartPosition = processParameters.DryerBufferLengthMeters; + + if (resumeConfig != null && resumeConfig.GlobalStartPosition > 0) + { + printingStartPosition = resumeConfig.GlobalStartPosition; + } + + if (status.Progress > printingStartPosition) + { + if (!context.JobCompleted) + { + UpdateStatus(MachineStatuses.Printing); + } + } + } + else + { + if (status.Progress > 0) + { + if (!context.JobCompleted) + { + UpdateStatus(MachineStatuses.Printing); + } + } + } + } + } + + private void ProcessJobError(CurrentJobContext context, ProcessParametersTable processParameters, Exception ex) + { + if (!context.JobCompleted) + { + context.JobCompleted = true; + + UseKeepAlive = context.InitialUseKeepAlive; + + if (Status != MachineStatuses.Disconnected) + { + UpdateStatus(MachineStatuses.ReadyToDye); + } + + if (!context.JobHandler.IsCanceled) + { + Exception finalException = ex; + + if (ex is ContinuousResponseAbortedException continuousException) + { + finalException = new ContinuousResponseAbortedException($"Job aborted by the embedded device ({continuousException.Container.ErrorMessage})."); + } + + context.JobHandler.RaiseFailed(finalException); + OnPrintingFailed(context, finalException); + } + } + } + + private void ProcessJobCompletion(CurrentJobContext context, ProcessParametersTable processParameters) + { + if (!context.JobCompleted) + { + context.JobCompleted = true; + + UseKeepAlive = context.InitialUseKeepAlive; + + UpdateStatus(MachineStatuses.ReadyToDye); + context.JobHandler.RaiseCompleted(); + OnPrintingCompleted(context); + } + } + + private void OnJobHandlerStatusChanged(object sender, RunningJobStatus e) + { + RunningJobStatus = e; + } + + private async void OnJobHandlerCanceled(CurrentJobContext context) + { + try + { + if (context.JobHandler.CanCancel) + { + context.JobHandler.CanCancel = false; + context.JobHandler.IsCanceled = true; + LogManager.Log("Aborting current job..."); + + if (context.RequestSent) + { + var result = await SendRequest<AbortJobRequest, AbortJobResponse>(new AbortJobRequest(), new TransportRequestConfig() { ShouldLog = true }); + } + + if (Status != MachineStatuses.Disconnected) + { + UpdateStatus(MachineStatuses.ReadyToDye); + } + + OnPrintingAborted(context); + context.JobHandler.RaiseCanceled(); + } + } + catch (Exception ex) + { + context.JobHandler.CanCancel = true; + LogManager.Log(ex, "Failed to cancel job."); + } + } + + private async Task UploadJobDescriptionFile(CurrentJobContext context) + { + context.UploadingStartDate = DateTime.UtcNow; + + if (JobUploadStrategy == JobUploadStrategy.JobDescriptionFile) + { + LogManager.Log("Generating job description file..."); + + context.JobRequest.JobTicket.Segments.Clear(); + + JobDescriptionFile jobDescriptionFile = new JobDescriptionFile(context.JobTicket.Segments); + MemoryStream ms = jobDescriptionFile.ToStream(); + + context.JobHandler.RaiseStatusReceived(new JobStatus() + { + CurrentSegmentIndex = 0, + Progress = 0, + Message = "Uploading job description file...", + }); + + LogManager.Log("Creating storage API manager..."); + var storage = CreateStorageManager(); + + LogManager.Log("Getting storage drive information..."); + var storageInfo = await storage.GetStorageDrive(); + LogManager.Log("Getting root folder information..."); + var root_folder = await storage.GetRootFolder(); + + var existing_item = root_folder.Items.SingleOrDefault(x => x.Name == JOB_DESCRIPTION_FILE_NAME); + if (existing_item != null) + { + LogManager.Log("Removing previous job description file..."); + await storage.DeleteItem(existing_item); + } + + String job_file_path = Path.Combine(storageInfo.Root, JOB_DESCRIPTION_FILE_NAME); + + LogManager.Log($"Uploading job description file '{job_file_path}' of size: {ms.Length} bytes..."); + + TaskCompletionSource<object> uploadCompletion = new TaskCompletionSource<object>(); + + var uploader = await storage.UploadFile(job_file_path, ms); + uploader.Canceled += (_, __) => + { + uploadCompletion.SetResult(true); + }; + uploader.Completed += (_, __) => + { + uploadCompletion.SetResult(true); + }; + uploader.Failed += (_, e) => + { + uploadCompletion.SetException(e); + }; + + await uploadCompletion.Task; + + context.JobRequest.JobTicket.JobDescriptionFile = job_file_path; + } + } + + private async Task SendJobPrepareRequest(CurrentJobContext context, List<RequiredLiquid> requiredLiquids) + { + if (requiredLiquids.Count > 0) + { + JobPrepareRequest prepareRequest = new JobPrepareRequest(); + prepareRequest.ProcessParameters = context.JobTicket.ProcessParameters; + + foreach (var requiredLiquid in requiredLiquids) + { + JobPrepareDispenser prepareDispenser = new JobPrepareDispenser(); + prepareDispenser.DispenserLiquidType = (DispenserLiquidType)requiredLiquid.IdsPack.LiquidType.Type; + prepareDispenser.Index = requiredLiquid.IdsPack.PackIndex; + prepareDispenser.TotalNanoliter = Convert.ToInt32(requiredLiquid.Quantity); + prepareDispenser.Active = requiredLiquid.Quantity > 0; + + prepareRequest.Dispensers.Add(prepareDispenser); + } + + var response = await SendRequest<JobPrepareRequest, JobPrepareResponse>(prepareRequest, new TransportRequestConfig() + { + ShouldLog = true, + Timeout = TimeSpan.FromSeconds(10) + }); + } + } + + private Task<JobTicket> NormalizeJobTicketUnits(Job job, ProcessParametersTable processParameters, JobTicket ticket) + { + return Task.Run(() => + { + ticket = ticket.Clone(); + + var segs = new List<JobSegment>(); + + if (JobUnitsMethod == JobUnitsMethods.Operator) + { + for (int i = 0; i < job.NumberOfUnits; i++) + { + foreach (var s in ticket.Segments) + { + var cloned = s.Clone(); + segs.Add(cloned); + } + } + } + else + { + foreach (var s in ticket.Segments) + { + var cloned = s.Clone(); + segs.Add(cloned); + } + } + + if (segs.Count > 0) + { + ticket.Segments.Clear(); + ticket.Segments.AddRange(segs); + } + + if (!job.EnableInterSegment) + { + NormalizeJobTicket(ticket, processParameters); + } + + return ticket; + }); + } + + private Task LogJobOutline(Job job, ProcessParametersTable processParameters, JobTicket ticket) + { + return Task.Run(() => + { + var ticketToLog = ticket.Clone(); + ticketToLog.Segments.Clear(); + + foreach (var seg in ticket.Segments) + { + JobSegment segmentToLog = new JobSegment(); + + segmentToLog.Length = seg.Length; + segmentToLog.BrushStops.Add(seg.BrushStops.First()); + + if (seg.BrushStops.Count > 1) + { + segmentToLog.BrushStops.Add(seg.BrushStops.Last()); + } + + ticketToLog.Segments.Add(segmentToLog); + } + + if (!job.EnableInterSegment) + { + NormalizeJobTicket(ticketToLog, processParameters); + } + + LogManager.Log($"Job outline for '{job.Name}':\n{ticketToLog.ToJsonString()}"); + }); + } + + private static void RaiseHandlerInitialStatus(JobHandler handler) + { + handler.RaiseStatusReceived(new JobStatus() + { + CurrentSegmentIndex = 0, + Progress = 0, + Message = "Preparing Job...", + }); + } + + private Task ApplyPMRSegmentsToJobTicket(CurrentJobContext context, ProcessParametersTable processParameters) + { + return Task.Run(() => + { + foreach (var segment in context.Job.OrderedSegmentsWithGroups.ToList()) + { + if (segment is Segment simpleSegment) + { + context.JobTicket.Segments.Add(CreatePMRJobSegment(simpleSegment, context.OriginalJob, processParameters)); + } + else if (segment is SegmentsGroup group) + { + List<JobSegment> groupSegments = new List<JobSegment>(); + + foreach (var innerSegment in group.OrderedSegments) + { + groupSegments.Add(CreatePMRJobSegment(innerSegment, context.OriginalJob, processParameters)); + } + + for (int i = 0; i < group.Repeats; i++) + { + context.JobTicket.Segments.AddRange(groupSegments.ToList()); + } + } + } + }); + } + + private JobHandler CreateJobHandler(ProcessParametersTable processParameters, AdditionalJobConfiguration config, CurrentJobContext context) + { + JobHandler handler = new JobHandler(() => OnJobHandlerCanceled(context), context.ClonedJob, context.JobTicket, processParameters, JobHandlingMode, config.ResumeConfig); + handler.StatusChanged += OnJobHandlerStatusChanged; + return handler; + } + + private Task<JobTicket> CreateJobTicket(CurrentJobContext context, ProcessParametersTable processParameters) + { + Job job = context.Job; + + return Task.Run(() => + { + JobTicket ticket = new JobTicket(); + ticket.Guid = context.OriginalJob.Guid; + ticket.EnableInterSegment = job.EnableInterSegment; + ticket.InterSegmentLength = Math.Max(job.InterSegmentLength, 1); + ticket.EnableLubrication = job.EnableLubrication; + ticket.Length = job.Length; + ticket.WindingMethod = (JobWindingMethod)job.WindingMethod.Code; + ticket.UploadStrategy = JobUploadStrategy; + + if (JobUnitsMethod == JobUnitsMethods.Device) + { + ticket.NumberOfUnits = (uint)Math.Max(job.NumberOfUnits, 1); + } + + //Spool parameters + ticket.Spool = new JobSpool(); + job.SpoolType.MapPropertiesTo(ticket.Spool); + ticket.Spool.JobSpoolType = (JobSpoolType)job.SpoolType.Code; + + //Override spool parameters from RML Spool calibration + var rmlSpool = job.Rml.RmlsSpools.FirstOrDefault(x => x.SpoolType.Guid == job.SpoolType.Guid); + if (rmlSpool != null) + { + ticket.Spool.RotationsPerPassage = rmlSpool.RotationsPerPassage != null ? rmlSpool.RotationsPerPassage.Value : ticket.Spool.RotationsPerPassage; + ticket.Spool.Length = rmlSpool.Length != null ? rmlSpool.Length.Value : ticket.Spool.Length; + ticket.Spool.BackingRate = rmlSpool.BackingRate != null ? rmlSpool.BackingRate.Value : ticket.Spool.BackingRate; + ticket.Spool.BottomBackingRate = rmlSpool.BottomBackingRate != null ? rmlSpool.BottomBackingRate.Value : ticket.Spool.BottomBackingRate; + ticket.Spool.BtsrSpoolTension = rmlSpool.BtsrSpoolTension != null ? rmlSpool.BtsrSpoolTension.Value : ticket.Spool.BtsrSpoolTension; + ticket.Spool.StartOffsetPulses = rmlSpool.StartOffsetPulses != null ? rmlSpool.StartOffsetPulses.Value : ticket.Spool.StartOffsetPulses; + ticket.Spool.SegmentOffsetPulses = rmlSpool.SegmentOffsetPulses != null ? rmlSpool.SegmentOffsetPulses.Value : ticket.Spool.SegmentOffsetPulses; + } + + //Override spool parameters from Machine Spool calibration + var machineSpool = job.Machine.Spools.FirstOrDefault(x => x.SpoolType.Guid == job.SpoolType.Guid); + if (machineSpool != null) + { + ticket.Spool.LimitSwitchStartPointOffset = machineSpool.LimitSwitchStartPointOffset != null ? machineSpool.LimitSwitchStartPointOffset.Value : ticket.Spool.LimitSwitchStartPointOffset; + //ticket.Spool.StartOffsetPulses = machineSpool.StartOffsetPulses != null ? machineSpool.StartOffsetPulses.Value : ticket.Spool.StartOffsetPulses; + //ticket.Spool.BackingRate = machineSpool.BackingRate != null ? machineSpool.BackingRate.Value : ticket.Spool.BackingRate; + //ticket.Spool.SegmentOffsetPulses = machineSpool.SegmentOffsetPulses != null ? machineSpool.SegmentOffsetPulses.Value : ticket.Spool.SegmentOffsetPulses; + //ticket.Spool.BottomBackingRate = machineSpool.BottomBackingRate != null ? machineSpool.BottomBackingRate.Value : ticket.Spool.BottomBackingRate; + } + + //Thread Parameters + ticket.ThreadParameters = new ThreadParameters(); + job.Rml.MapPrimitivesTo(ticket.ThreadParameters); + + ProcessParameters process = new ProcessParameters(); + processParameters.MapPrimitivesTo(process); + ticket.ProcessParameters = process; + + //Head Cleaning Parameters + ticket.HeadCleaningParameters = new HeadCleaningParameters(); + ticket.HeadCleaningParameters.CleanerFlow = job.Rml.CleanerFlow; + ticket.HeadCleaningParameters.ArcHeadCleaningMotorSpeed = job.Rml.ArcHeadCleaningMotorSpeed; + + //BTSR Parameters + ticket.BtsrParameters = new PMR.BTSR.BtsrParameters(); + ticket.BtsrParameters.BtsrApplicationType = job.Rml.BtsrApplicationType != null ? (PMR.BTSR.BtsrApplicationType)job.Rml.BtsrApplicationType.Code : PMR.BTSR.BtsrApplicationType.Seamless; + ticket.BtsrParameters.BtsrYarnType = job.Rml.BtsrYarnType != null ? (PMR.BTSR.BtsrYarnType)job.Rml.BtsrYarnType.Code : PMR.BTSR.BtsrYarnType.AllYarn3; + ticket.BtsrParameters.TensionError = (float)job.Rml.BtsrTensionError; + return ticket; + }); + } + + private Task ApplySegmentsGroupsToJob(Job job) + { + return Task.Run(() => + { + int max = job.OrderedSegmentsWithGroups.Last().SegmentIndex + 1; + + for (int i = 0; i < job.NumberOfUnits - 1; i++) + { + foreach (var s in job.OrderedSegmentsWithGroups.ToList()) + { + var cloned = s.Clone(job); + cloned.SegmentIndex = max++; + + if (cloned is Segment simpleSegment) + { + job.Segments.Add(simpleSegment); + } + else if (cloned is SegmentsGroup g) + { + job.SegmentsGroups.Add(g); + } + } + } + }); + } + + private Task<List<RequiredLiquid>> PerformLiquidQuantityValidation(Job job, ProcessParametersTable processParameters) + { + return Task.Run(() => + { + List<RequiredLiquid> requiredLiquids = new List<RequiredLiquid>(); + + //Validate liquid quantities + if (EnableJobLiquidQuantityValidation && MachineType == MachineTypes.TS1800) + { + requiredLiquids = ValidateJobLiquidQuantity(job, processParameters, job.Machine.Configuration); + } + else + { + LogManager.Log("Liquid quantity validation is disabled. Skipping..."); + } + + return requiredLiquids; + }); + } + + private Task ApplyTransparentBrushStops(Job job) + { + return Task.Run(() => + { + LogManager.Log("Modifying all 'white' brush stops..."); + foreach (var stop in job.OrderedSegmentsWithGroups.SelectMany(x => x.BrushStops).Where(x => x.IsTransparent || x.IsWhite).ToList()) + { + foreach (var liquidVolume in stop.LiquidVolumes.Where(x => x.LiquidType != LiquidTypes.TransparentInk && x.LiquidType != LiquidTypes.Lubricant).ToList()) + { + liquidVolume.Volume = 0; + } + + var tiLiquid = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.TransparentInk); + + if (tiLiquid != null) + { + tiLiquid.Volume = 100; + } + } + }); + } + + private Task ApplyLubrication(Job job, AdditionalJobConfiguration config) + { + return Task.Run(() => + { + if (job.EnableLubrication) + { + if (config.UseLubricantVolume) + { + LogManager.Log($"Job custom lubrication is enabled. Settings all brush stops to {config.LubricationVolume}% lubricant."); + + foreach (var stop in job.OrderedSegmentsWithGroups.ToList().SelectMany(x => x.BrushStops).ToList()) + { + var lubricantVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.Lubricant); + + if (lubricantVolume != null) + { + lubricantVolume.Volume = config.LubricationVolume; + } + } + } + else + { + LogManager.Log($"Job auto lubrication is enabled. Settings all none Volume brush stops to 100% lubricant."); + + foreach (var stop in job.OrderedSegmentsWithGroups.ToList().SelectMany(x => x.BrushStops).Where(x => x.BrushColorSpace != ColorSpaces.Volume).ToList()) + { + var lubricantVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.Lubricant); + + if (lubricantVolume != null) + { + lubricantVolume.Volume = 100; + } + } + } + } + else + { + LogManager.Log("Job lubrication is disabled."); + } + }); + } + + private Task ApplyColorConversion(Job job, ProcessParametersTable processParameters, AdditionalJobConfiguration config) + { + return Task.Run(() => + { + if (config.UseColorConversion) + { + IColorConverter converter = new DefaultColorConverter(); + + bool useLightInks = config.UseLightInks; + + //Use light inks only if one segment or inter segment is enabled. + if (MachineType == MachineTypes.TS1800 && job.OrderedSegmentsWithGroups.Count > 1 && !job.EnableInterSegment) useLightInks = false; + + foreach (var segment in job.OrderedSegmentsWithGroups.ToList()) + { + foreach (var stop in segment.BrushStops) + { + try + { + var output = converter.Convert(stop, false, useLightInks && segment.BrushStops.Count == 1); //Use light inks only if this is a solid segment. + output.ApplyOnBrushStopLiquidVolumes(stop, processParameters); + } + catch (Exception ex) + { + throw new InvalidOperationException($"Error processing the coordinates of stop '{stop.StopIndex}' of segment '{stop.Segment.SegmentIndex}'.", ex); + } + + if (stop.IsLiquidVolumesOutOfRange) + { + throw new InvalidOperationException($"The specified ink volumes at segment {segment.SegmentIndex} exceeds the maximum allowed total volume for the current thread."); + } + } + } + } + }); + } + + protected CurrentJobContext CreateJobContext(Job job, AdditionalJobConfiguration config, MachineStatus machineStatus = null) + { + var jobContext = new CurrentJobContext(machineStatus ?? MachineStatus, GetJobRunLiquidQuantities); + + jobContext.InitialUseKeepAlive = UseKeepAlive; + + jobContext.StartDate = DateTime.UtcNow; + + RunningJob = null; + RunningJobStatus = null; + + if (job != null) + { + if (job.NumberOfUnits < 1) + { + job.NumberOfUnits = 1; + } + + jobContext.Job = job; + jobContext.OriginalJob = job; + + var clonedJob = job.Clone(); + clonedJob.Guid = job.Guid; + clonedJob.Name = job.Name; + + jobContext.ClonedJob = clonedJob; + + job = job.Clone(); + job.Guid = jobContext.OriginalJob.Guid; + job.Name = jobContext.OriginalJob.Name; + jobContext.Job = job; + + var jobForJobRun = job.Clone(); + jobForJobRun.Guid = job.Guid; + jobForJobRun.Name = job.Name; + jobForJobRun.ID = job.ID; + + if (config.ResumeConfig != null) + { + jobForJobRun.ResumeStartPosition = config.ResumeConfig.ResumeProgress; + } + + jobContext.JobForJobRun = jobForJobRun; + + RunningJob = clonedJob; + } + + return jobContext; + } + + private Task NormalizeJobTicket(JobTicket ticket, ProcessParametersTable processParameters) + { + return Task.Run(() => + { + var maxNanoStop = ticket.Segments.SelectMany(x => x.BrushStops).OrderBy(x => x.GetTotalNanoliterPerCentimeter()).Last(); + double maxNanoliter = maxNanoStop.GetTotalNanoliterPerCentimeter(); + + LogManager.Log($"Normalizing brush stops TI quantities by {maxNanoliter} nanoliters..."); + + foreach (var stop in ticket.Segments.SelectMany(x => x.BrushStops).Where(x => x != maxNanoStop)) + { + stop.NormalizeStop(maxNanoliter, processParameters.MinInkUptake, processParameters.DyeingSpeed); + } + }); + } + + #endregion } } diff --git a/Software/Visual_Studio/Tango.Integration/Operation/PrintingEventArgs.cs b/Software/Visual_Studio/Tango.Integration/Operation/PrintingEventArgs.cs index ff2fc4623..5703d481d 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/PrintingEventArgs.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/PrintingEventArgs.cs @@ -17,7 +17,7 @@ namespace Tango.Integration.Operation public DateTime? UploadingStartTime { get; set; } public DateTime? HeatingStartTime { get; set; } public DateTime? ActualStartTime { get; set; } - public bool IsResumed { get; set; } + public bool IsResumingJob { get; set; } public PrintingEventArgs(JobHandler jobHandler, Job job) { diff --git a/Software/Visual_Studio/Tango.Integration/Operation/ResumingJobEventArgs.cs b/Software/Visual_Studio/Tango.Integration/Operation/ResumingJobEventArgs.cs index 55728f799..e3b40b4aa 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/ResumingJobEventArgs.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/ResumingJobEventArgs.cs @@ -9,18 +9,18 @@ namespace Tango.Integration.Operation { public class ResumingJobEventArgs : EventArgs { - private Func<JobHandler> _approveAction; + private Func<Job, JobHandler> _approveAction; public String JobGuid { get; set; } - public ResumingJobEventArgs(Func<JobHandler> approveAction) + public ResumingJobEventArgs(Func<Job, JobHandler> approveAction) { _approveAction = approveAction; } - public JobHandler Approve() + public JobHandler Approve(Job job) { - return _approveAction(); + return _approveAction(job); } } } diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 6133a98d5..e04a41be4 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -172,8 +172,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.RemoteRunner.UI", "Ut EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{0048447D-1D94-4E60-9DAD-7349C777CB4E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.PPC.Jobs", "PPC\Modules\Tango.PPC.Jobs\Tango.PPC.Jobs.csproj", "{096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.HashGenerator", "Utilities\Tango.HashGenerator\Tango.HashGenerator.csproj", "{0440A135-0DF0-4232-AB3C-98B9283123B3}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.Hive", "Tango.Hive\Tango.Hive.csproj", "{942134AC-6EA2-4500-8F22-0F739B70A05F}" @@ -8591,122 +8589,6 @@ Global {4FD16878-1A44-4CCE-9589-5FC630FACDE9}.X1|x64.Build.0 = Release|Any CPU {4FD16878-1A44-4CCE-9589-5FC630FACDE9}.X1|x86.ActiveCfg = Release|Any CPU {4FD16878-1A44-4CCE-9589-5FC630FACDE9}.X1|x86.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|Any CPU.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|Any CPU.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|ARM.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|ARM.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|ARM64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|ARM64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|x64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|x64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|x86.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.AppVeyor|x86.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|ARM.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|ARM.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|ARM64.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|x64.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|x64.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|x86.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Debug|x86.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka_Debug|Any CPU.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka_Debug|ARM.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka_Debug|ARM.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka_Debug|ARM64.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka_Debug|ARM64.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka_Debug|x64.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka_Debug|x64.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka_Debug|x86.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka_Debug|x86.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka|Any CPU.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka|ARM.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka|ARM.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka|ARM64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka|ARM64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka|x64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka|x64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka|x86.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Eureka|x86.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|Any CPU.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|Any CPU.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|ARM.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|ARM.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|ARM64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|ARM64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|x64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|x64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|x86.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.0|x86.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|Any CPU.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|Any CPU.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|ARM.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|ARM.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|ARM64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|ARM64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|x64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|x64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|x86.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.5|x86.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|Any CPU.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|Any CPU.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|ARM.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|ARM.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|ARM64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|ARM64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|x64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|x64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|x86.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release 4.6.1|x86.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|Any CPU.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|ARM.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|ARM.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|ARM64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|ARM64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|x64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|x64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|x86.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.Release|x86.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|Any CPU.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|Any CPU.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|ARM.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|ARM.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|ARM64.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|ARM64.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|x64.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|x64.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|x86.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS_Debug|x86.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|Any CPU.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|Any CPU.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|ARM.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|ARM.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|ARM64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|ARM64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|x64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|x64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|x86.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.TS|x86.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1_Debug|Any CPU.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1_Debug|ARM.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1_Debug|ARM.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1_Debug|ARM64.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1_Debug|ARM64.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1_Debug|x64.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1_Debug|x64.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1_Debug|x86.ActiveCfg = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1_Debug|x86.Build.0 = Debug|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1|Any CPU.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1|ARM.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1|ARM.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1|ARM64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1|ARM64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1|x64.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1|x64.Build.0 = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1|x86.ActiveCfg = Release|Any CPU - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3}.X1|x86.Build.0 = Release|Any CPU {0440A135-0DF0-4232-AB3C-98B9283123B3}.AppVeyor|Any CPU.ActiveCfg = Release|Any CPU {0440A135-0DF0-4232-AB3C-98B9283123B3}.AppVeyor|Any CPU.Build.0 = Release|Any CPU {0440A135-0DF0-4232-AB3C-98B9283123B3}.AppVeyor|ARM.ActiveCfg = Release|Any CPU @@ -26034,7 +25916,6 @@ Global {654BEDA3-16FB-44FF-ADE7-B52E50B02E63} = {C81ED1A3-D18C-4D80-A8F5-061994A14A60} {4FD16878-1A44-4CCE-9589-5FC630FACDE9} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} {0048447D-1D94-4E60-9DAD-7349C777CB4E} = {C81ED1A3-D18C-4D80-A8F5-061994A14A60} - {096F16C8-6D06-4B5F-9496-B9D2DF2D94A3} = {0048447D-1D94-4E60-9DAD-7349C777CB4E} {0440A135-0DF0-4232-AB3C-98B9283123B3} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} {808E47B6-BAA7-4D23-83CB-40C53DC4B38A} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} {91B70E9B-66A7-4873-AE10-400E71CF404F} = {0048447D-1D94-4E60-9DAD-7349C777CB4E} @@ -26164,13 +26045,13 @@ Global {C891B2F7-E63A-40E2-B6CE-A22A69B4D86A} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8 - SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} - BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear - BuildVersion_UpdateAssemblyVersion = True - BuildVersion_UpdateFileVersion = False - BuildVersion_StartDate = 2000/1/1 - BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs BuildVersion_UseGlobalSettings = False + BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs + BuildVersion_StartDate = 2000/1/1 + BuildVersion_UpdateFileVersion = False + BuildVersion_UpdateAssemblyVersion = True + BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear + SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} + EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8 EndGlobalSection EndGlobal diff --git a/Software/Visual_Studio/Utilities/Tango.JobProgressTester.UI/Tango.JobProgressTester.UI.csproj b/Software/Visual_Studio/Utilities/Tango.JobProgressTester.UI/Tango.JobProgressTester.UI.csproj index eb5297422..ff194c1b4 100644 --- a/Software/Visual_Studio/Utilities/Tango.JobProgressTester.UI/Tango.JobProgressTester.UI.csproj +++ b/Software/Visual_Studio/Utilities/Tango.JobProgressTester.UI/Tango.JobProgressTester.UI.csproj @@ -97,10 +97,6 @@ <None Include="App.config" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\..\PPC\Modules\Tango.PPC.Jobs\Tango.PPC.Jobs.csproj"> - <Project>{096f16c8-6d06-4b5f-9496-b9d2df2d94a3}</Project> - <Name>Tango.PPC.Jobs</Name> - </ProjectReference> <ProjectReference Include="..\..\PPC\Tango.PPC.Common\Tango.PPC.Common.csproj"> <Project>{0be74eee-22cb-4dba-b896-793b9e1a3ac0}</Project> <Name>Tango.PPC.Common</Name> diff --git a/Software/Visual_Studio/Utilities/Tango.JobRunsGenerator/Program.cs b/Software/Visual_Studio/Utilities/Tango.JobRunsGenerator/Program.cs index 71d5779a6..1509bdd6e 100644 --- a/Software/Visual_Studio/Utilities/Tango.JobRunsGenerator/Program.cs +++ b/Software/Visual_Studio/Utilities/Tango.JobRunsGenerator/Program.cs @@ -71,7 +71,7 @@ namespace Tango.JobRunsGenerator if (run.JobName == null) run.JobName = job.Name; if (run.RmlGuid == null) run.RmlGuid = job.RmlGuid; if (run.JobString == null) run.JobString = job.ToJobFileWhenLoaded().ToString(); - if (run.LiquidQuantityString == null) run.LiquidQuantities = MachineOperator.CreateJobRunLiquidQuantities(job, machine.Configuration, job.Rml.GetActiveProcessGroup().ProcessParametersTables.First(), run.EndPosition, job.LengthIncludingNumberOfUnits); + if (run.LiquidQuantityString == null) run.LiquidQuantities = MachineOperator.CreateJobRunLiquidQuantitiesUsingIntegral(job, machine.Configuration, job.Rml.GetActiveProcessGroup().ProcessParametersTables.First(), run.EndPosition, job.LengthIncludingNumberOfUnits); if (run.UserGuid == null) run.UserGuid = job.UserGuid; if (run.UploadingStartDate == null) run.UploadingStartDate = run.StartDate; if (run.HeatingStartDate == null) run.HeatingStartDate = run.StartDate; |
