using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL; using Tango.BL.Builders; using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.Core; using Tango.Integration.Operation; namespace Tango.Integration.JobRuns { /// /// Represents a basic database job runs logger. /// /// public class BasicJobRunsLogger : ExtendedObject, IJobRunsLogger { private Job _job; private Machine _defaultMachine; #region Properties /// /// Gets the machine operator. /// public IMachineOperator MachineOperator { get; private set; } /// /// Gets a value indicating whether this instance is started. /// public bool IsStarted { get; private set; } /// /// Gets or sets the job designations of which the logger should log (supports multiple flags). /// public JobDesignations JobDesignationFilter { get; set; } /// /// Gets or sets the job run source when logging job runs. /// public JobSource JobSource { get; set; } #endregion #region Constructors /// /// Initializes a new instance of the class. /// /// The machine operator. public BasicJobRunsLogger(IMachineOperator machineOperator) { JobDesignationFilter = JobDesignations.Default | JobDesignations.SampleDye | JobDesignations.FineTuning; MachineOperator = machineOperator; Init(); } #endregion #region Private Methods /// /// Initializes this instance. /// private void Init() { MachineOperator.PrintingStarted -= Machine_PrintingStarted; MachineOperator.PrintingStarted += Machine_PrintingStarted; MachineOperator.PrintingCompleted -= Machine_PrintingCompleted; MachineOperator.PrintingCompleted += Machine_PrintingCompleted; MachineOperator.PrintingAborted -= Machine_PrintingAborted; MachineOperator.PrintingAborted += Machine_PrintingAborted; MachineOperator.PrintingFailed -= Machine_PrintingFailed; MachineOperator.PrintingFailed += Machine_PrintingFailed; MachineOperator.HeadCleaningEnded += MachineOperator_HeadCleaningEnded; } private bool ShouldLog() { return IsStarted && _job != null && JobDesignationFilter.HasFlag(_job.Designation); } private void InsertJobRun(PrintingEventArgs e, JobRunStatus status, Exception exception) { if (ShouldLog()) { if (e.Job.Guid == _job.Guid) { Task.Factory.StartNew(() => { try { using (var db = ObservablesContext.CreateDefault()) { 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.JobLength = _job.LengthIncludingNumberOfUnits; //Should I use this or the below ?? run.JobLength = e.JobHandler.Status.TotalProgress; run.LiquidQuantities = e.LiquidQuantities; run.IsGradient = _job.Segments.Any(x => x.BrushStops.Count > 1); run.GradientResolutionCm = MachineOperator.GradientGenerationConfiguration.ResolutionCM; run.JobString = _job.ToJobFileWhenLoaded().ToString(); //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; if (exception != null) { run.FailedMessage = exception.FlattenMessage(); } db.JobRuns.Add(run); e.Job.LastRun = DateTime.UtcNow; _job.LastRun = DateTime.UtcNow; var job = db.Jobs.SingleOrDefault(x => x.Guid == _job.Guid); if (job != null) { job.LastRun = DateTime.UtcNow; } db.SaveChanges(); } } catch (Exception ex) { LogManager.Log(ex, "Error logging the last job run to the database."); } }); } } } private void InsertHeadCleaningJobRun(HeadCleaningEndedEventArgs e) { if (IsStarted && _defaultMachine != null) { Task.Factory.StartNew(() => { try { using (var db = ObservablesContext.CreateDefault()) { JobRun run = new JobRun(); run.IsHeadCleaning = true; run.StartDate = e.StartDate; run.UploadingStartDate = e.StartDate; run.HeatingStartDate = e.StartDate; run.ActualStartDate = e.StartDate; run.EndDate = DateTime.UtcNow; run.JobName = "HEAD CLEANING"; run.Source = JobSource; run.MachineGuid = _defaultMachine.Guid; run.JobRunStatus = e.Status; run.EndPosition = e.EndPosition; 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; //if (exception != null) //{ // run.FailedMessage = exception.FlattenMessage(); //} db.JobRuns.Add(run); db.SaveChanges(); } } catch (Exception ex) { LogManager.Log(ex, "Error logging the last head cleaning job run to the database."); } }); } } #endregion #region Public Methods /// /// Starts the logger. /// public void Start() { IsStarted = true; } /// /// Stops the logger. /// public void Stop() { IsStarted = false; } /// /// Sets the head cleaning parameters. /// /// The machine. public void SetDefaultMachine(Machine machine) { _defaultMachine = machine; } #endregion #region Event Handlers private void Machine_PrintingFailed(object sender, PrintingFailedEventArgs e) { InsertJobRun(e, JobRunStatus.Failed, e.Exception); } private void Machine_PrintingAborted(object sender, PrintingEventArgs e) { InsertJobRun(e, JobRunStatus.Aborted, null); } private void Machine_PrintingCompleted(object sender, PrintingEventArgs e) { InsertJobRun(e, JobRunStatus.Completed, null); } private async void Machine_PrintingStarted(object sender, PrintingEventArgs e) { _job = e.Job; 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) { InsertHeadCleaningJobRun(e); } #endregion } }