diff options
Diffstat (limited to 'Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs')
| -rw-r--r-- | Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs | 2784 |
1 files changed, 790 insertions, 1994 deletions
diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index bce386bfe..180db3b1d 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -40,11 +40,6 @@ using Tango.Integration.Emergency; using Tango.PMR.MachineStatus; using Newtonsoft.Json; using Tango.PMR.Integration; -using System.Globalization; -using Tango.PMR.Power; -using Tango.PMR.ThreadLoading; -using Tango.BL.DTO; -using Tango.PMR.IFS; namespace Tango.Integration.Operation { @@ -58,39 +53,17 @@ namespace Tango.Integration.Operation public const String FIRMWARE_UPGRADE_FOLDER_NAME = "UpgradePackage"; public const String FIRMWARE_UPGRADE_CONFIG_FILE_NAME = "package.cfg"; public const String JOB_DESCRIPTION_FILE_NAME = "job_segments.jdf"; - public const int MAX_DISPENSER_NANOLITER = 130000000; - public const double MAX_MIDTANK_LITERS = 1.8; - public const double EMPTY_MIDTANK_LITERS = 0.2; - public const double LOW_MIDTANK_LITERS = 0.3; - public const double OVERALL_TEMPERATURE_OK = 35; - public const double OVERALL_TEMPERATURE_WARNING = 35; - public const double OVERALL_TEMPERATURE_ERROR = 40; private bool _diagnosticsSent; private bool _eventsSent; private bool _debugSent; private bool _machineStatusSent; - private bool _inkFillingStatusSent; - private bool _threadLoadingSent; + private EmbeddedLogItem _last_embedded_debug_log; 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 DateTime _jobStartDate; - private DateTime? _jobUploadingStartDate; - private DateTime? _jobHeatingStartDate; - private DateTime? _jobActualStartDate; - private List<Event> _emulatedEvents; public static String EmbeddedLogsFolder { get; private set; } public static String EmbeddedLogsTag { get; private set; } - public static SessionFileLogger SessionLogger { get; set; } - public static String CachedJobOperationFile { get; set; } #region Constructors @@ -109,15 +82,6 @@ namespace Tango.Integration.Operation FileLogger fileLogger = new FileLogger(EmbeddedLogsFolder, EmbeddedLogsTag) { Enabled = true }; EmbeddedLogManager.RegisterLogger(fileLogger); } - - if (SessionLogger == null) - { - SessionLogger = new SessionFileLogger(); - LogManager.Default.RegisterLogger(SessionLogger); - } - - - CachedJobOperationFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Job Resume", Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName), "CachedJobOperation.cache"); } /// <summary> @@ -125,15 +89,12 @@ namespace Tango.Integration.Operation /// </summary> public MachineOperator() : base() { - _emulatedEvents = new List<Event>(); - ComponentName = $"Machine Operator {_component_counter++}"; DeviceInformation = new DeviceInformation(); MachineEventsStateProvider = new DefaultMachineEventsStateProvider(); JobRunsLogger = new BasicJobRunsLogger(this); JobRunsLogger.Start(); EnableEventsNotification = true; EnableMachineStatusUpdates = true; - EnableInkFillingStatus = true; EnableJobResume = true; LogEmbeddedDebuggingToFile = true; FirmwareUpgradeMode = FirmwareUpgradeModes.DFU | FirmwareUpgradeModes.TFP_PACKAGE; @@ -141,8 +102,6 @@ namespace Tango.Integration.Operation EmergencyNotificationProvider = new UsbEmergencyNotificationProvider("COM1"); EnableJobLiquidQuantityValidation = true; FailsWithAdapter = true; - ContinuousRequestTimeout = TimeSpan.FromSeconds(2); - ResetInkFllingStatus(); } /// <summary> @@ -189,6 +148,26 @@ namespace Tango.Integration.Operation public event EventHandler<CartridgeValidationEventArgs> CartridgeValidationRequestReceived; /// <summary> + /// Occurs when a request has been sent. + /// </summary> + public event EventHandler<IMessage> RequestSent; + + /// <summary> + /// Occurs when a response has been sent. + /// </summary> + public event EventHandler<IMessage> ResponseSent; + + /// <summary> + /// Occurs when a request has timed out. + /// </summary> + public event EventHandler<RequestFailedEventArgs> RequestFailed; + + /// <summary> + /// Occurs when a request response has been received. + /// </summary> + public event EventHandler<IMessage> ResponseReceived; + + /// <summary> /// Reports about the job printing preparation progress. /// </summary> public event EventHandler<PreparingJobProgressEventArgs> PreparingJobProgress; @@ -223,89 +202,11 @@ namespace Tango.Integration.Operation /// </summary> public event EventHandler<ResumingJobEventArgs> ResumingJob; - /// <summary> - /// Occurs when the machine was connected and device has reported IsAfterReset. - /// </summary> - public event EventHandler FirmwareStarted; - - /// <summary> - /// Occurs when power down has started. - /// </summary> - public event EventHandler<PowerDownStartedEventArgs> PowerDownStarted; - - /// <summary> - /// Occurs when the thread loading status has changed. - /// </summary> - public event EventHandler<StartThreadLoadingResponse> ThreadLoadingStatusChanged; - - /// <summary> - /// Occurs when a thread loading confirmation is required. - /// </summary> - public event EventHandler<ThreadLoadingConfirmationRequiredEventArgs> ThreadLoadingConfirmationRequired; - - /// <summary> - /// Occurs when thread loading has completed. - /// </summary> - public event EventHandler<StartThreadLoadingResponse> ThreadLoadingCompleted; - - /// <summary> - /// Occurs when thread loading has failed. - /// </summary> - public event EventHandler<StartThreadLoadingResponse> ThreadLoadingFailed; - - /// <summary> - /// Occurs when the power up sequence has started. - /// </summary> - public event EventHandler<StartPowerUpResponse> PowerUpStarted; - - /// <summary> - /// Occurs when the power up sequence progress has changed. - /// </summary> - public event EventHandler<StartPowerUpResponse> PowerUpProgress; - - /// <summary> - /// Occurs when power up sequence has completed successfully. - /// </summary> - public event EventHandler<StartPowerUpResponse> PowerUpCompleted; - - /// <summary> - /// Occurs when power up sequence has failed. - /// </summary> - public event EventHandler<StartPowerUpResponse> PowerUpFailed; - - /// <summary> - /// Occurs when power up sequence has ended. Could be due to no response to the request! - /// </summary> - public event EventHandler PowerUpEnded; - - /// <summary> - /// Occurs when a head cleaning job has ended. - /// </summary> - public event EventHandler<HeadCleaningEndedEventArgs> HeadCleaningEnded; - - /// <summary> - /// Occurs when the ink filling status has changed. - /// </summary> - public event EventHandler<InkFillingStatusChangedEventArgs> InkFillingStatusChanged; - #endregion #region Properties /// <summary> - /// Gets or sets a value indicating whether to create a new designated session log file each successful connection. - /// This log file will contain standard logs that have occurred between the last connection and disconnection states. - /// </summary> - public static bool EnableSessionLogFile - { - get { return SessionLogger.Enabled; } - set - { - SessionLogger.Enabled = value; - } - } - - /// <summary> /// Gets or sets the job handling mode. /// </summary> public JobHandlerModes JobHandlingMode { get; set; } @@ -320,11 +221,6 @@ namespace Tango.Integration.Operation /// </summary> public JobUnitsMethods JobUnitsMethod { get; set; } - /// <summary> - /// Gets or sets the way of calculating how much liquid was spent during the job. - /// </summary> - public JobLiquidQuantityCalculationMode JobLiquidQuantityCalculationMode { get; set; } - private MachineStatuses _status; /// <summary> /// Gets the current machine status. @@ -341,20 +237,11 @@ namespace Tango.Integration.Operation OnStatusChanged(value); RaisePropertyChanged(nameof(IsPrinting)); RaisePropertyChanged(nameof(CanPrint)); - RaisePropertyChanged(nameof(IsConnected)); LogManager.Log("Machine operator status changed: " + _status); } } } - /// <summary> - /// Gets a value indicating whether the machine is connected and status is not disconnected. - /// </summary> - public bool IsConnected - { - get { return State == TransportComponentState.Connected && Status != MachineStatuses.Disconnected; } - } - private MachineStatus _machineStatus; /// <summary> /// Gets the machine embedded device status. @@ -362,27 +249,7 @@ namespace Tango.Integration.Operation public MachineStatus MachineStatus { get { return _machineStatus; } - private set { _machineStatus = value; RaisePropertyChangedAuto(); } - } - - private InkFillingStatus _inkFillingStatus; - /// <summary> - /// Gets or sets the ink filling status. - /// </summary> - public InkFillingStatus InkFillingStatus - { - get { return _inkFillingStatus; } - private set { _inkFillingStatus = value; RaisePropertyChangedAuto(); } - } - - private StartThreadLoadingResponse _threadLoadingStatus; - /// <summary> - /// Gets the current thread loading status. - /// </summary> - public StartThreadLoadingResponse ThreadLoadingStatus - { - get { return _threadLoadingStatus; } - private set { _threadLoadingStatus = value; RaisePropertyChangedAuto(); } + set { _machineStatus = value; RaisePropertyChangedAuto(); } } /// <summary> @@ -414,7 +281,7 @@ namespace Tango.Integration.Operation { get { - return Status == MachineStatuses.ReadyToDye || Status == MachineStatuses.PowerUp || Status == MachineStatuses.Standby; + return Status == MachineStatuses.ReadyToDye; } } @@ -520,36 +387,6 @@ namespace Tango.Integration.Operation } } - private bool _enableInkFillingStatus; - public bool EnableInkFillingStatus - { - get { return _enableInkFillingStatus; } - set - { - if (_enableInkFillingStatus != value) - { - _enableInkFillingStatus = value; - RaisePropertyChangedAuto(); - OnEnableInkFillingStatus(value); - } - } - } - - private bool _enableAutomaticThreadLoading; - /// <summary> - /// Gets or sets a value indicating whether to enable automatic thread loading support. - /// </summary> - public bool EnableAutomaticThreadLoading - { - get { return _enableAutomaticThreadLoading; } - set - { - _enableAutomaticThreadLoading = value; - RaisePropertyChangedAuto(); - OnEnableAutomaticThreadLoadingChanged(value); - } - } - private bool _enableJobResume; /// <summary> /// Gets or sets a value indicating whether to check whether a job is in progress after connection was successful. @@ -579,16 +416,6 @@ namespace Tango.Integration.Operation } } - private bool _enablePowerUpSequence; - /// <summary> - /// Gets or sets a value indicating whether to enable the power sequence tracking. - /// </summary> - public bool EnablePowerUpSequence - { - get { return _enablePowerUpSequence; } - set { _enablePowerUpSequence = value; RaisePropertyChangedAuto(); } - } - /// <summary> /// Gets or sets the machine events state provider used to get notifications about current machine events and errors. /// </summary> @@ -634,11 +461,6 @@ namespace Tango.Integration.Operation /// </summary> public IEmergencyNotificationProvider EmergencyNotificationProvider { get; set; } - /// <summary> - /// Gets or sets the general continuous request timeout. - /// </summary> - public TimeSpan ContinuousRequestTimeout { get; set; } - #endregion #region Virtual Methods @@ -656,34 +478,33 @@ namespace Tango.Integration.Operation bool responseLogged = false; _diagnosticsSent = true; - LogManager.Log($"Sending '{nameof(StartDiagnosticsRequest)}'..."); - - SendContinuousRequest<StartDiagnosticsRequest, StartDiagnosticsResponse>(request, new TransportContinuousRequestConfig() { ShouldLog = false }).ObserveOn(new NewThreadScheduler()).Subscribe( + SendContinuousRequest<StartDiagnosticsRequest, StartDiagnosticsResponse>(request).ObserveOn(new NewThreadScheduler()).Subscribe( (response) => { + OnDiagnosticsDataAvailable(response); + if (!responseLogged) { - _diagnosticsTime = DateTime.Now; + LogResponseReceived(response.Message); responseLogged = true; } - else - { - _diagnosticsTime = _diagnosticsTime.Add(TimeSpan.FromMilliseconds(response.Message.ElapsedMilli)); - } - - response.Message.DateTime = _diagnosticsTime.ToString("MM/dd/yyyy HH:mm:ss.fff"); - - OnDiagnosticsDataAvailable(response); }, (ex) => { _diagnosticsSent = false; + + if (!(ex is ContinuousResponseAbortedException)) + { + LogRequestFailed(request, ex); + } }, () => { _diagnosticsSent = false; LogManager.Log("Diagnostics response completed!?", LogCategory.Warning); }); + + LogRequestSent(request); } else if (_diagnosticsSent) { @@ -695,9 +516,14 @@ namespace Tango.Integration.Operation try { - var res = await SendRequest<StopDiagnosticsRequest, StopDiagnosticsResponse>(req, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(req); + var res = await SendRequest<StopDiagnosticsRequest, StopDiagnosticsResponse>(req); + LogResponseReceived(res.Message); + } + catch (Exception ex) + { + LogRequestFailed(req, ex); } - catch { } } } } @@ -715,25 +541,33 @@ namespace Tango.Integration.Operation bool responseLogged = false; _eventsSent = true; - SendContinuousRequest<StartEventsNotificationRequest, StartEventsNotificationResponse>(request, new TransportContinuousRequestConfig() { ShouldLog = true }).ObserveOn(new NewThreadScheduler()).Subscribe( + SendContinuousRequest<StartEventsNotificationRequest, StartEventsNotificationResponse>(request).ObserveOn(new NewThreadScheduler()).Subscribe( (response) => { OnEventsNotification(response); if (!responseLogged) { + LogResponseReceived(response.Message); responseLogged = true; } }, (ex) => { _eventsSent = false; + + if (!(ex is ContinuousResponseAbortedException)) + { + LogRequestFailed(request, ex); + } }, () => { _eventsSent = false; LogManager.Log("Events Notification response completed!?", LogCategory.Warning); }); + + LogRequestSent(request); } else if (_eventsSent) { @@ -745,9 +579,14 @@ namespace Tango.Integration.Operation try { - var res = await SendRequest<StopEventsNotificationRequest, StopEventsNotificationResponse>(req, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(req); + var res = await SendRequest<StopEventsNotificationRequest, StopEventsNotificationResponse>(req); + LogResponseReceived(res.Message); + } + catch (Exception ex) + { + LogRequestFailed(req, ex); } - catch { } } } } @@ -765,13 +604,14 @@ namespace Tango.Integration.Operation bool responseLogged = false; _debugSent = true; - SendContinuousRequest<StartDebugLogRequest, StartDebugLogResponse>(request, new TransportContinuousRequestConfig() { ShouldLog = true }).ObserveOn(new NewThreadScheduler()) + SendContinuousRequest<StartDebugLogRequest, StartDebugLogResponse>(request).ObserveOn(new NewThreadScheduler()) .Subscribe ( (response) => { if (!responseLogged) { + LogResponseReceived(response.Message); responseLogged = true; } @@ -780,11 +620,18 @@ namespace Tango.Integration.Operation (ex) => { _debugSent = false; + + if (!(ex is ContinuousResponseAbortedException)) + { + LogRequestFailed(request, ex); + } }, () => { _debugSent = false; }); + + LogRequestSent(request); } else if (_debugSent) { @@ -796,9 +643,14 @@ namespace Tango.Integration.Operation try { - var res = await SendRequest<StopDebugLogRequest, StopDebugLogResponse>(req, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(req); + var res = await SendRequest<StopDebugLogRequest, StopDebugLogResponse>(req); + LogResponseReceived(res.Message); + } + catch (Exception ex) + { + LogRequestFailed(req, ex); } - catch { } } } } @@ -816,25 +668,33 @@ namespace Tango.Integration.Operation bool responseLogged = false; _machineStatusSent = true; - SendContinuousRequest<StartMachineStatusUpdateRequest, StartMachineStatusUpdateResponse>(request, new TransportContinuousRequestConfig() { ShouldLog = true }).ObserveOn(new NewThreadScheduler()).Subscribe( + SendContinuousRequest<StartMachineStatusUpdateRequest, StartMachineStatusUpdateResponse>(request).ObserveOn(new NewThreadScheduler()).Subscribe( (response) => { OnMachineStatusChanged(response); if (!responseLogged) { + LogResponseReceived(response.Message); responseLogged = true; } }, (ex) => { _machineStatusSent = false; + + if (!(ex is ContinuousResponseAbortedException)) + { + LogRequestFailed(request, ex); + } }, () => { _machineStatusSent = false; LogManager.Log("Machine status update response completed!?", LogCategory.Warning); }); + + LogRequestSent(request); } else if (_machineStatusSent) { @@ -846,98 +706,14 @@ namespace Tango.Integration.Operation try { - var res = await SendRequest<StopMachineStatusUpdateRequest, StopMachineStatusUpdateResponse>(req, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(req); + var res = await SendRequest<StopMachineStatusUpdateRequest, StopMachineStatusUpdateResponse>(req); + LogResponseReceived(res.Message); } - catch { } - } - } - } - - /// <summary> - /// Called when the enable ink filling status has been changed. - /// </summary> - /// <param name="value">if set to <c>true</c> [value].</param> - protected virtual void OnEnableInkFillingStatus(bool value) - { - if (value && State == TransportComponentState.Connected && !_inkFillingStatusSent) - { - var request = new StartInkFillingStatusRequest(); - - bool responseLogged = false; - _inkFillingStatusSent = true; - - SendContinuousRequest<StartInkFillingStatusRequest, StartInkFillingStatusResponse>(request, new TransportContinuousRequestConfig() { ShouldLog = true }).ObserveOn(new NewThreadScheduler()).Subscribe( - (response) => - { - OnInkFillingStatusChanged(response); - - if (!responseLogged) - { - responseLogged = true; - } - }, - (ex) => - { - _inkFillingStatusSent = false; - }, - () => - { - _inkFillingStatusSent = false; - LogManager.Log("Ink filling status response completed!?", LogCategory.Warning); - }); - } - else if (_inkFillingStatusSent) - { - _inkFillingStatusSent = false; - } - } - - /// <summary> - /// Called when the enable automatic thread loading has been changed - /// </summary> - /// <param name="value">if set to <c>true</c> [value].</param> - protected virtual async void OnEnableAutomaticThreadLoadingChanged(bool value) - { - if (value && State == TransportComponentState.Connected && !_threadLoadingSent) - { - var request = new StartThreadLoadingRequest(); - - bool responseLogged = false; - _threadLoadingSent = true; - - SendContinuousRequest<StartThreadLoadingRequest, StartThreadLoadingResponse>(request, new TransportContinuousRequestConfig() { ShouldLog = true }).ObserveOn(new NewThreadScheduler()).Subscribe( - (response) => - { - OnThreadLoadingStatusChanged(response); - - if (!responseLogged) - { - responseLogged = true; - } - }, - (ex) => - { - _threadLoadingSent = false; - }, - () => - { - _threadLoadingSent = false; - LogManager.Log("Thread loading response completed!?", LogCategory.Warning); - }); - } - else if (_threadLoadingSent) - { - _threadLoadingSent = false; - - if (State == TransportComponentState.Connected) - { - var req = new StopThreadLoadingRequest(); - - try + catch (Exception ex) { - var res = await SendRequest<StopThreadLoadingRequest, StopThreadLoadingResponse>(req, new TransportRequestConfig() { ShouldLog = true }); + LogRequestFailed(req, ex); } - catch { } } } } @@ -959,17 +735,7 @@ namespace Tango.Integration.Operation { if (MachineEventsStateProvider != null) { - var events = response.Events; - - foreach (var emulated in _emulatedEvents) - { - if (!events.Any(x => x.Type == emulated.Type)) - { - events.Add(emulated); - } - } - - MachineEventsStateProvider.ApplyEvents(events); + MachineEventsStateProvider.ApplyEvents(response.Events); } EventsNotification?.Invoke(this, response); @@ -981,16 +747,30 @@ namespace Tango.Integration.Operation /// <param name="data">The sensors data.</param> protected virtual void OnDebugLogAvailable(StartDebugLogResponse data) { - if (LogEmbeddedDebuggingToFile && EmbeddedLogManager != null) + if (_last_embedded_debug_log == null || _last_embedded_debug_log.DebugLogResponse.Message != data.Message) { - EmbeddedLogManager.Log(new EmbeddedLogItem(data)); + _last_embedded_debug_log = new EmbeddedLogItem(data); + + if (LogEmbeddedDebuggingToFile && EmbeddedLogManager != null) + { + EmbeddedLogManager.Log(_last_embedded_debug_log); + } + + DebugLogAvailable?.Invoke(this, data); } + else + { + _last_embedded_debug_log.Repeated++; - DebugLogAvailable?.Invoke(this, data); + if (LogEmbeddedDebuggingToFile && EmbeddedLogManager != null) + { + EmbeddedLogManager.Log(new EmbeddedLogItem(data)); + } + } } /// <summary> - /// Called when the machine status has been updated. + /// Called when the machine status has been update /// </summary> /// <param name="response">The response.</param> protected virtual void OnMachineStatusChanged(StartMachineStatusUpdateResponse response) @@ -1004,188 +784,87 @@ namespace Tango.Integration.Operation if (changed) { - OnMachineStateChanged(MachineStatus.State); - } - } - - /// <summary> - /// Called when ink filling status has been changed. - /// </summary> - /// <param name="response">The response.</param> - protected virtual void OnInkFillingStatusChanged(StartInkFillingStatusResponse response) - { - if (response.Status == null || response.Status.CartridgesStatuses == null || response.Status.CartridgesStatuses.Count == 0) return; + LogManager.Log($"Machine State Changed: {MachineStatus.State}."); - int index = -1; - bool raiseChange = false; - - foreach (var remoteCartridge in response.Status.CartridgesStatuses) - { - index++; - - if (remoteCartridge.Cartridge == null) - { - LogManager.Log($"Remote cartridge arrived with null cartridge at position [{index}] and will be ignored.", LogCategory.Error); - continue; - } - - var localCartridge = InkFillingStatus.CartridgesStatuses.SingleOrDefault(x => x.Cartridge.Index == remoteCartridge.Cartridge.Index && x.Cartridge.Slot == remoteCartridge.Cartridge.Slot); - - if (localCartridge != null) + switch (MachineStatus.State) { - if (localCartridge.State != remoteCartridge.State) - { - localCartridge.State = remoteCartridge.State; - LogManager.Log($"{localCartridge.Cartridge.Slot} Cartridge '{localCartridge.Cartridge.Index}' state changed: '{localCartridge.State}' => '{remoteCartridge.State}'."); - } - - if (remoteCartridge.Cartridge.Tag != null) - { - LogManager.Log($"{localCartridge.Cartridge.Slot} Cartridge '{localCartridge.Cartridge.Index}' Tag arrived:\n{remoteCartridge.Cartridge.Tag.ToJsonString()}"); - } - - localCartridge.Message = remoteCartridge.Message; - localCartridge.ProgressPercentage = remoteCartridge.ProgressPercentage; - - raiseChange = true; - } - else - { - LogManager.Log($"Could not locate local cartridge with slot '{remoteCartridge.Cartridge.Slot}' and index '{remoteCartridge.Cartridge.Index}'.", LogCategory.Error); + case MachineState.Initializing: + Status = MachineStatuses.Service; + break; + //case MachineState.PreparingJob: + // Status = MachineStatuses.GettingReady; + // break; + case MachineState.Ready: + Status = MachineStatuses.ReadyToDye; + break; + //case MachineState.Sleep: + // Status = MachineStatuses.Standby; + // break; + case MachineState.PowerOff: + Status = MachineStatuses.ShuttingDown; + break; + case MachineState.Error: + Status = MachineStatuses.Error; + break; } } - - if (raiseChange) - { - RaisePropertyChanged(nameof(InkFillingStatus)); - InkFillingStatusChanged?.Invoke(this, new InkFillingStatusChangedEventArgs() { Status = InkFillingStatus }); - } } /// <summary> - /// Called when the machine state has been changed. + /// Called when the request has been sent /// </summary> - /// <param name="state">The state.</param> - protected async virtual void OnMachineStateChanged(MachineState state) + /// <param name="response">The request.</param> + protected virtual void OnRequestSent(IMessage request) { - LogManager.Log($"Machine State Changed: {state}."); - - if (IsPrinting) - { - LogManager.Log($"Machine state change will not affect the machine operator status as it is now in a '{Status}' status.", LogCategory.Warning); - return; - } - - switch (state) - { - case MachineState.PowerUp: - Status = MachineStatuses.PowerUp; - break; - //case MachineState.PreparingJob: - // Status = MachineStatuses.GettingReady; - // break; - case MachineState.Ready: - Status = MachineStatuses.ReadyToDye; - break; - case MachineState.Sleep: - Status = MachineStatuses.Standby; - break; - case MachineState.PowerOff: - Status = MachineStatuses.ShuttingDown; - if (!_isPowerDownRequestInProgress) - { - try - { - await PowerDown(); - } - catch { } - } - break; - case MachineState.Error: - //Status = MachineStatuses.Error; - break; - } + RequestSent?.Invoke(this, request); } /// <summary> - /// Called when the thread loading status has been changed. + /// Called when the response has been received /// </summary> /// <param name="response">The response.</param> - protected virtual void OnThreadLoadingStatusChanged(StartThreadLoadingResponse response) + protected virtual void OnResponseReceived(IMessage response) { - bool changed = (ThreadLoadingStatus == null || response.State != ThreadLoadingStatus.State || response.ErrorReason != ThreadLoadingStatus.ErrorReason); - - if (changed) - { - ThreadLoadingStatus = response; - ThreadLoadingStatusChanged?.Invoke(this, response); - - LogManager.Log($"Thread Loading Status Changed: {ThreadLoadingStatus.State}."); - - switch (ThreadLoadingStatus.State) - { - case ThreadLoadingState.ReadyForLoading: - - LogManager.Log("Thread loading is ready for loading. Invoking confirmation event..."); - - ThreadLoadingConfirmationRequired?.Invoke(this, new ThreadLoadingConfirmationRequiredEventArgs((processTable) => - { - //Confirm Action - try - { - var process = processTable.ToProcessParametersPMR(); - LogManager.Log($"Thread loading confirmation received with process parameters:\n{process.ToJsonString()}"); - LogManager.Log("Sending continue thread loading request..."); - var r = SendRequest<ContinueThreadLoadingRequest, ContinueThreadLoadingResponse>(new ContinueThreadLoadingRequest() - { - ProcessParameters = process, - }, new TransportRequestConfig() { ShouldLog = true }).Result; - } - catch (Exception ex) - { - LogManager.Log(ex, "Error confirming thread loading sequence."); - } - }) - { - Status = ThreadLoadingStatus, - }); - break; - case ThreadLoadingState.Completed: - ThreadLoadingCompleted?.Invoke(this, ThreadLoadingStatus); - break; - case ThreadLoadingState.FinalizationError: - case ThreadLoadingState.PreparationError: - ThreadLoadingFailed?.Invoke(this, ThreadLoadingStatus); - break; - } - } + ResponseReceived?.Invoke(this, response); } /// <summary> /// Called when a new request has been received. /// </summary> /// <param name="container">The request.</param> - protected override void OnRequestReceived(RequestReceivedEventArgs e) + protected override void OnRequestReceived(MessageContainer container) { - base.OnRequestReceived(e); - - if (e.Handled) return; - - var container = e.Container; + base.OnRequestReceived(container); if (container.Type == MessageType.CartridgeValidationRequest) { - e.Handled = true; OnCartridgeValidationRequestReceived(container.Token, MessageFactory.ExtractMessageFromContainer<CartridgeValidationRequest>(container)); } else if (container.Type == MessageType.UpdateStatusRequest) { - e.Handled = true; OnUpdateStatusRequestReceived(container.Token, MessageFactory.ExtractMessageFromContainer<UpdateStatusRequest>(container)); } } /// <summary> + /// Called when the response has been sent + /// </summary> + /// <param name="response">The response.</param> + protected virtual void OnResponseSent(IMessage response) + { + ResponseSent?.Invoke(this, response); + } + + /// <summary> + /// Called when the request has been failed + /// </summary> + /// <param name="request">The request.</param> + protected virtual void OnRequestFailed(IMessage request, Exception exception) + { + RequestFailed?.Invoke(this, new RequestFailedEventArgs(request, exception)); + } + + /// <summary> /// Called when the machine status has been changed /// </summary> /// <param name="status">The status.</param> @@ -1241,115 +920,7 @@ namespace Tango.Integration.Operation LogManager.Log(ex); } - try - { - SendResponse<UpdateStatusResponse>(new UpdateStatusResponse(), token); - } - catch (Exception ex) - { - LogManager.Log(ex, "Error sending UpdateStatus response."); - } - } - - /// <summary> - /// Called when the printing has been started. - /// </summary> - /// <param name="handler">The handler.</param> - /// <param name="job">The job.</param> - protected virtual void OnPrintingStarted(JobHandler handler, Job job, bool isResumed = false) - { - PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, job) - { - StartDate = _jobStartDate, - IsResumed = isResumed - }); - } - - /// <summary> - /// Called when the printing has been completed. - /// </summary> - /// <param name="handler">The handler.</param> - /// <param name="job">The job.</param> - protected virtual void OnPrintingCompleted(JobHandler handler, Job job) - { - PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, job) - { - LiquidQuantities = _lastJobLiquidQuantities.ToList(), - StartDate = _jobStartDate, - UploadingStartTime = _jobUploadingStartDate, - HeatingStartTime = _jobHeatingStartDate, - ActualStartTime = _jobActualStartDate, - }); - - OnPrintingEnded(handler, job); - } - - /// <summary> - /// Called when the printing has been failed. - /// </summary> - /// <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) - { - PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, job, exception) - { - LiquidQuantities = _lastJobLiquidQuantities.ToList(), - StartDate = _jobStartDate, - UploadingStartTime = _jobUploadingStartDate, - HeatingStartTime = _jobHeatingStartDate, - ActualStartTime = _jobActualStartDate, - }); - OnPrintingEnded(handler, job); - } - - /// <summary> - /// Called when the printing has been aborted. - /// </summary> - /// <param name="handler">The handler.</param> - /// <param name="job">The job.</param> - protected virtual void OnPrintingAborted(JobHandler handler, Job job) - { - PrintingAborted?.Invoke(this, new PrintingEventArgs(handler, job) - { - LiquidQuantities = _lastJobLiquidQuantities.ToList(), - StartDate = _jobStartDate, - UploadingStartTime = _jobUploadingStartDate, - HeatingStartTime = _jobHeatingStartDate, - ActualStartTime = _jobActualStartDate, - }); - OnPrintingEnded(handler, job); - } - - /// <summary> - /// Called when the printing has been ended. - /// </summary> - /// <param name="handler">The handler.</param> - /// <param name="job">The job.</param> - protected virtual void OnPrintingEnded(JobHandler handler, Job job) - { - PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, job) - { - LiquidQuantities = _lastJobLiquidQuantities.ToList(), - StartDate = _jobStartDate, - UploadingStartTime = _jobUploadingStartDate, - HeatingStartTime = _jobHeatingStartDate, - ActualStartTime = _jobActualStartDate, - }); - } - - protected virtual void OnHeadCleaningEnded(HeadCleaningHandler handler, JobRunStatus status) - { - SaveLastJobLiquidQuantities(null, null, null, null); - - HeadCleaningEnded?.Invoke(this, new HeadCleaningEndedEventArgs() - { - StartDate = _jobStartDate, - Length = handler.Status.Total, - EndPosition = handler.Status.Progress, - Status = status, - LiquidQuantities = _lastJobLiquidQuantities.ToList(), - }); + SendResponse<UpdateStatusResponse>(new UpdateStatusResponse()); } #endregion @@ -1370,23 +941,7 @@ namespace Tango.Integration.Operation _debugSent = false; _eventsSent = false; _machineStatusSent = false; - - if (Status != MachineStatuses.Disconnected) - { - Status = MachineStatuses.Disconnected; - ResetEvents(); - ResetInkFllingStatus(); - } - } - } - - private void ResetEvents() - { - if (MachineEventsStateProvider != null) - { - LogManager.Log("Resetting active events..."); - _emulatedEvents.Clear(); - MachineEventsStateProvider.Reset(); + Status = MachineStatuses.Disconnected; } } @@ -1398,30 +953,28 @@ namespace Tango.Integration.Operation { if (Status == MachineStatuses.Upgrading) return; - Status = MachineStatuses.Disconnected; - - if (MachineStatus != null) - { - MachineStatus.State = MachineState.Ready; - } - - SessionLogger.EndSession(); - if (State == TransportComponentState.Connected) { DisconnectRequest request = new DisconnectRequest(); + LogRequestSent(request); try { - var response = await SendRequest<DisconnectRequest, DisconnectResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + var response = await SendRequest<DisconnectRequest, DisconnectResponse>(request); + LogResponseReceived(response.Message); Status = MachineStatuses.Disconnected; } - catch { } + catch (Exception ex) + { + LogRequestFailed(request, ex); + } } - ResetEvents(); - ResetInkFllingStatus(); + if (MachineEventsStateProvider != null) + { + MachineEventsStateProvider.Reset(); + } await base.Disconnect(); } @@ -1447,14 +1000,12 @@ namespace Tango.Integration.Operation Password = "1234", UnixTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds() }; + LogRequestSent(request); try { - var response = await SendRequest<ConnectRequest, ConnectResponse>(request, new TransportRequestConfig() { ShouldLog = true }); - - SessionLogger.CreateSession(); - - _isPowerDownRequestInProgress = false; + var response = await SendRequest<ConnectRequest, ConnectResponse>(request); + LogResponseReceived(response.Message); if (Status != MachineStatuses.Upgrading) { @@ -1472,27 +1023,15 @@ namespace Tango.Integration.Operation OnEnableEmbeddedDebuggingChanged(EnableEmbeddedDebugging); OnEnableEventsNotification(EnableEventsNotification); OnEnableMachineStatusUpdatesChanged(EnableMachineStatusUpdates); - OnEnableAutomaticThreadLoadingChanged(EnableAutomaticThreadLoading); - OnEnableInkFillingStatus(EnableInkFillingStatus); - - if (EnablePowerUpSequence) - { - TrackPowerUpSequence(); - } if (EnableJobResume) { ResumeJob(); } - - if (response.Message.IsAfterReset) - { - FirmwareStarted?.Invoke(this, new EventArgs()); - } } catch (Exception ex) { - SessionLogger.EndSession(); + LogRequestFailed(request, ex); await base.Disconnect(); throw ex; } @@ -1507,202 +1046,35 @@ namespace Tango.Integration.Operation #region Private Methods - private void ResetInkFllingStatus() - { - if (InkFillingStatus == null) - { - var status = new InkFillingStatus(); - - for (int i = 0; i < 8; i++) - { - status.CartridgesStatuses.Add(new CartridgeStatus() - { - Cartridge = new Cartridge() - { - Index = i, - Slot = CartridgeSlot.Ink, - }, - State = CartridgeState.Absent - }); - } - - status.CartridgesStatuses.Add(new CartridgeStatus() - { - Cartridge = new Cartridge() { Index = 0, Slot = CartridgeSlot.WasteMiddle }, - State = CartridgeState.Absent - }); - - status.CartridgesStatuses.Add(new CartridgeStatus() - { - Cartridge = new Cartridge() { Index = 1, Slot = CartridgeSlot.WasteLower }, - State = CartridgeState.Absent - }); - - InkFillingStatus = status; - } - else - { - foreach (var cartridge in InkFillingStatus.CartridgesStatuses) - { - cartridge.ProgressPercentage = 0; - cartridge.Message = String.Empty; - cartridge.State = CartridgeState.Absent; - } - } - - InkFillingStatusChanged?.Invoke(this, new InkFillingStatusChangedEventArgs() { Status = InkFillingStatus }); - } - - private void SaveCachedJobOperation(Job job) - { - try - { - LogManager.Log("Caching current job operation..."); - CachedJobOperation cache = new CachedJobOperation(); - cache.JobDTO = JobDTO.FromObservable(job); - cache.MachineStatus = MachineStatus; - cache.ProcessParametersDTO = ProcessParametersTableDTO.FromObservable(CurrentProcessParameters); - cache.MachineConfigurationDTO = ConfigurationDTO.FromObservable(job.Machine.Configuration); - var json = JsonConvert.SerializeObject(cache); - Directory.CreateDirectory(Path.GetDirectoryName(CachedJobOperationFile)); - File.WriteAllText(CachedJobOperationFile, json); - } - catch (Exception ex) - { - LogManager.Log(ex, "Error caching job operation for job resume."); - } - } - - private CachedJobOperation LoadCachedJobOperation() - { - try - { - LogManager.Log("Loading last cached job operation..."); - String json = File.ReadAllText(CachedJobOperationFile); - CachedJobOperation cache = JsonConvert.DeserializeObject<CachedJobOperation>(json); - return cache; - } - catch (Exception ex) - { - LogManager.Log(ex, "Error loading cache of last job operation for job resume."); - return null; - } - } - - private void TrackPowerUpSequence() - { - LogManager.Log("Starting power up sequence tracking..."); - - bool started = false; - bool completed = false; - PowerUpState lastState = PowerUpState.None; - - SendContinuousRequest<StartPowerUpRequest, StartPowerUpResponse>(new StartPowerUpRequest(), new TransportContinuousRequestConfig() - { - ShouldLog = true, - Timeout = TimeSpan.FromSeconds(5) - }).Subscribe((response) => - { - if (!started) - { - started = true; - PowerUpStarted?.Invoke(this, response); - } - - PowerUpProgress?.Invoke(this, response); - - var state = response.Message.State; - - if (state != lastState) - { - LogManager.Log($"Power up sequence state changed to '{state}'..."); - - switch (state) - { - case PowerUpState.Error: - completed = true; - LogManager.Log($"Power up sequence failed with state '{state}'. ({response.Message.Message})"); - PowerUpFailed?.Invoke(this, response); - PowerUpEnded?.Invoke(this, new EventArgs()); - break; - case PowerUpState.Cancelled: - completed = true; - LogManager.Log($"Power up sequence canceled with state '{state}'. ({response.Message.Message})"); - PowerUpEnded?.Invoke(this, new EventArgs()); - break; - case PowerUpState.MachineReadyToDye: - completed = true; - LogManager.Log($"Power up sequence completed successfully with state '{state}'. ({response.Message.Message})"); - PowerUpCompleted?.Invoke(this, response); - PowerUpEnded?.Invoke(this, new EventArgs()); - break; - } - - lastState = state; - } - - }, (ex) => - { - if (!completed) - { - completed = true; - LogManager.Log(ex, "Power up sequence tracking failed."); - PowerUpEnded?.Invoke(this, new EventArgs()); - } - }, () => - { - if (!completed) - { - completed = true; - PowerUpEnded?.Invoke(this, new EventArgs()); - } - }); - } - 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 }); + var res = await SendRequest<CurrentJobRequest, CurrentJobResponse>(new CurrentJobRequest()); 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; - } + JobTicket jobTicket = res.Message.JobTicket; - Job job = null; - Configuration configuration = null; - ProcessParametersTable processParameters = null; + ProcessParametersTable processParameters = new ProcessParametersTable(); + jobTicket.ProcessParameters.MapPrimitivesTo(processParameters); - try - { - processParameters = cache.ProcessParametersDTO.ToObservable(); - job = cache.JobDTO.ToObservable(); - configuration = cache.MachineConfigurationDTO.ToObservable(); - _machineStatusBeforeJobStart = cache.MachineStatus; - CurrentProcessParameters = processParameters; - } - catch (Exception ex) + ResumingJobEventArgs args = new ResumingJobEventArgs((job) => { - LogManager.Log(ex, "Error deserializing cache job operation. Aborting resume."); - return; - } - - JobTicket jobTicket = res.Message.JobTicket; + if (Status != MachineStatuses.ReadyToDye) + { + throw new InvalidOperationException("Could not print while status = " + Status); + } - ResumingJobEventArgs args = new ResumingJobEventArgs(() => - { RunningJob = null; RunningJobStatus = null; + var originalJob = job; + + CurrentProcessParameters = processParameters; + var request = new ResumeCurrentJobRequest(); JobHandler handler = null; @@ -1711,125 +1083,109 @@ namespace Tango.Integration.Operation { 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) - { - Status = MachineStatuses.ReadyToDye; - } - } + var result = await SendRequest<AbortJobRequest, AbortJobResponse>(new AbortJobRequest()); + PrintingAborted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + handler.RaiseCanceled(); } catch (Exception ex) { - handler.CanCancel = true; LogManager.Log(ex, "Failed to cancel job."); } - }, job, jobTicket, processParameters, JobHandlingMode); + }, originalJob, jobTicket, processParameters, JobHandlingMode); handler.StatusChanged += (x, s) => { RunningJobStatus = s; }; - - _jobStartDate = DateTime.UtcNow; - _jobUploadingStartDate = _jobStartDate; - _jobHeatingStartDate = _jobStartDate; - _jobActualStartDate = null; + LogRequestSent(request); bool responseLogged = false; - bool completed = false; Thread.Sleep(500); //Just wait maybe Shlomo is getting this message to fast after restart ? + bool completed = false; - SendContinuousRequest<ResumeCurrentJobRequest, ResumeCurrentJobResponse>(request, new TransportContinuousRequestConfig() { ContinuousTimeout = ContinuousRequestTimeout, 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 (!responseLogged) - { - Status = MachineStatuses.GettingReady; - responseLogged = true; - RunningJob = job; - OnPrintingStarted(handler, job, true); - } - - if (JobHandlingMode == JobHandlerModes.SettingUp) - { - if (response.Message.Status.Progress > CurrentProcessParameters.DryerBufferLengthMeters) - { - if (!completed) - { - Status = MachineStatuses.Printing; - } - } - } - else - { - if (response.Message.Status.Progress > 0) - { - if (!completed) - { - Status = MachineStatuses.Printing; - } - } - } - } - }, (ex) => - { - if (!completed) - { - completed = true; - - if (Status != MachineStatuses.Disconnected) - { - Status = MachineStatuses.ReadyToDye; - } + SendContinuousRequest<ResumeCurrentJobRequest, ResumeCurrentJobResponse>(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => + { + if (!completed) + { + if (!responseLogged) + { + if (_last_job_status != null) + { + _last_job_status.IsCanceled = false; + _last_job_status.IsCompleted = false; + _last_job_status.IsFailed = false; + handler.Status = _last_job_status; + } + } - if (!handler.IsCanceled) - { - SaveLastJobLiquidQuantities(job, configuration, processParameters, handler); + handler.RaiseStatusReceived(response.Message.Status); - Exception finalException = ex; + if (!responseLogged) + { + Status = MachineStatuses.GettingReady; + responseLogged = true; + RunningJob = originalJob; + PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + LogResponseReceived(response.Message); + } - if (ex is ContinuousResponseAbortedException continuousException) - { - finalException = new ContinuousResponseAbortedException($"Job aborted by the embedded device ({continuousException.Container.ErrorMessage})."); - } + if (JobHandlingMode == JobHandlerModes.SettingUp) + { + if (response.Message.Status.Progress > processParameters.DryerBufferLengthMeters) + { + if (!completed) + { + Status = MachineStatuses.Printing; + } + } + } + else + { + if (response.Message.Status.Progress > 0) + { + if (!completed) + { + Status = MachineStatuses.Printing; + } + } + } + } + }, (ex) => + { + if (!completed) + { + completed = true; + if (!(ex is ContinuousResponseAbortedException)) + { + Status = MachineStatuses.ReadyToDye; - OnPrintingFailed(handler, job, finalException); - handler.RaiseFailed(finalException); - } - } - }, () => - { - if (!completed) - { - completed = true; - Status = MachineStatuses.ReadyToDye; - SaveLastJobLiquidQuantities(job, configuration, processParameters, handler); - OnPrintingCompleted(handler, job); - handler.RaiseCompleted(); - } - }); + if (!handler.IsCanceled) + { + PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, originalJob, ex)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + handler.RaiseFailed(ex); + LogRequestFailed(request, ex); + } + } + else + { + Status = MachineStatuses.ReadyToDye; + } + } + }, () => + { + if (!completed) + { + completed = true; + Status = MachineStatuses.ReadyToDye; + PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + handler.RaiseCompleted(); + } + }); return handler; }); @@ -1845,6 +1201,42 @@ namespace Tango.Integration.Operation } /// <summary> + /// Logs the request sent. + /// </summary> + /// <param name="message">The message.</param> + protected void LogRequestSent(IMessage message) + { + if (!(message is FileChunkUploadRequest) && !(message is FileDownloadRequest)) + { + LogManager.Log(String.Format("Sending request '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); + OnRequestSent(message); + } + } + + /// <summary> + /// Logs the request failed. + /// </summary> + /// <param name="message">The message.</param> + protected void LogRequestFailed(IMessage message, Exception ex) + { + LogManager.Log(String.Format("Request failed '{0}'...{1}{2}{1}{3}", message.GetType().Name, Environment.NewLine, message.ToJsonString(), ex.ToString()), LogCategory.Error); + OnRequestFailed(message, ex); + } + + /// <summary> + /// Logs the response received. + /// </summary> + /// <param name="message">The message.</param> + protected void LogResponseReceived(IMessage message) + { + if (!(message is FileChunkUploadResponse) && !(message is FileDownloadResponse)) + { + LogManager.Log(String.Format("Response received '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); + OnResponseReceived(message); + } + } + + /// <summary> /// Creates a PMR job segment. /// </summary> /// <param name="segment">The segment.</param> @@ -1862,25 +1254,11 @@ namespace Tango.Integration.Operation if (GradientGenerationConfiguration != null && GradientGenerationConfiguration.IsEnabled && segment.BrushStops.Count > 1) { LogManager.Log($"Generate segment {segment.SegmentIndex} gradient..."); - try - { - stops = GradientGenerationConfiguration.Generate(segment, job, processParameters, (e) => - { - PreparingJobProgress?.Invoke(this, e); - }); - } - catch (Exception ex) - { - throw new InvalidOperationException($"Error occurred while trying to generate a gradient.\n{ex.Message}"); - } - LogManager.Log($"Gradient generated."); - - PreparingJobProgress?.Invoke(this, new PreparingJobProgressEventArgs() + stops = GradientGenerationConfiguration.Generate(segment, job, processParameters, (e) => { - Job = job, - Total = job.Segments.Sum(x => x.Length), - Progress = job.Segments.Sum(x => x.Length), + PreparingJobProgress?.Invoke(this, e); }); + LogManager.Log($"Gradient generated."); } foreach (var stop in stops) @@ -1949,11 +1327,12 @@ namespace Tango.Integration.Operation request.JobTicket = ticket; + LogRequestSent(request); bool responseLogged = false; 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) => + SendContinuousRequest<JobRequest, JobResponse>(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => { response.Message.Status.Progress += previous_segments_length; @@ -1964,7 +1343,8 @@ namespace Tango.Integration.Operation responseLogged = true; Status = MachineStatuses.Printing; RunningJob = handler.Job; - OnPrintingStarted(handler, handler.Job); + PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, handler.Job)); + LogResponseReceived(response.Message); } }, (ex) => @@ -1975,8 +1355,10 @@ namespace Tango.Integration.Operation if (!handler.IsCanceled) { - OnPrintingFailed(handler, handler.Job, ex); + PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, handler.Job, ex)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, handler.Job)); handler.RaiseFailed(ex); + LogRequestFailed(request, ex); } } else @@ -1988,7 +1370,8 @@ namespace Tango.Integration.Operation if (segment == job.OrderedSegments.Last()) { Status = MachineStatuses.ReadyToDye; - OnPrintingCompleted(handler, handler.Job); + PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, handler.Job)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, handler.Job)); handler.RaiseCompleted(); } else @@ -1998,7 +1381,8 @@ namespace Tango.Integration.Operation ContinueSingleSpoolJob(segment.GetNextSegment(), job, processParameters, handler); }, () => { - OnPrintingAborted(handler, handler.Job); + PrintingAborted?.Invoke(this, new PrintingEventArgs(handler, handler.Job)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, handler.Job)); Status = MachineStatuses.ReadyToDye; handler.RaiseCanceled(); }); @@ -2008,8 +1392,6 @@ namespace Tango.Integration.Operation private void ValidateJobLiquidQuantity(Job job, ProcessParametersTable processParameters, Configuration configuration) { - LogManager.Log("Validating job liquid quantities..."); - Dictionary<int, double> liquidQuantities = new Dictionary<int, double>(); foreach (var pack in configuration.NoneEmptyIdsPacks.OrderBy(x => x.PackIndex)) @@ -2017,8 +1399,6 @@ namespace Tango.Integration.Operation liquidQuantities.Add(pack.PackIndex, 0); } - int resolution = GradientGenerationConfiguration.ResolutionCM; - for (int i = 0; i < Math.Max(job.NumberOfUnits, 1); i++) { for (int segmentIndex = 0; segmentIndex < job.Segments.Count; segmentIndex++) @@ -2026,177 +1406,6 @@ namespace Tango.Integration.Operation var segment = job.Segments[segmentIndex]; var segment_length_cm = segment.Length * 100d; - List<BrushStop> orderedBrushCollection = segment.BrushStops.OrderBy(x => x.OffsetMeters).ToList(); - - int solid_gradient_oeff = orderedBrushCollection.Count == 1 ? 1 : 2; - double prev_offset_cm = 0; - - for (int brushIndex = 0; brushIndex < orderedBrushCollection.Count; brushIndex++) - { - var brush = orderedBrushCollection[brushIndex]; - double brush_length_centimeters = 0d; - double brush_offset_cm = 0; - - if ((brushIndex + 1) < orderedBrushCollection.Count) - { - brush_offset_cm = (brush.OffsetMeters * 100d); - double next_brush_offset_cm = (orderedBrushCollection[brushIndex + 1].OffsetMeters * 100d); - brush_length_centimeters = ((next_brush_offset_cm - brush_offset_cm) + (brush_offset_cm - prev_offset_cm)); - - if (brushIndex == 0) - { - // add a resolution step for first brush - brush_length_centimeters += resolution; - } - } - else//last brush or solid brush - { - brush_length_centimeters = (segment_length_cm - prev_offset_cm); - if (orderedBrushCollection.Count > 1) - { - // add a resolution for last brush , not solid brush - brush_length_centimeters -= resolution; - } - } - - prev_offset_cm = brush_offset_cm; - - foreach (var liquidVolumes in brush.LiquidVolumes) - { - liquidQuantities[liquidVolumes.IdsPack.PackIndex] += liquidVolumes.NanoliterPerCentimeter * (brush_length_centimeters / solid_gradient_oeff); - } - } - } - } - - if (MachineStatus != null) - { - var exception = new InsufficientLiquidQuantityException($"Insufficient liquids level."); - - bool shouldThrow = false; - - foreach (var liquidQuantity in liquidQuantities) - { - int index = liquidQuantity.Key; - var packLevel = MachineStatus.IDSPacksLevels.SingleOrDefault(x => x.Index == index); - var idsPack = configuration.NoneEmptyIdsPacks.SingleOrDefault(x => x.PackIndex == index); - - if (packLevel != null) - { - var idsLevel = new InsufficientLiquidQuantityException.IDSPackLevel() - { - IdsPack = idsPack, - Current = packLevel.DispenserLevel, - Required = (int)liquidQuantities[index], - Maximum = MAX_DISPENSER_NANOLITER, - }; - - LogManager.Log($"Required {idsLevel.IdsPack.LiquidType.Type}: {idsLevel.Required}, Current: {idsLevel.Current}"); - - if (idsLevel.Required > idsLevel.Current) - { - shouldThrow = true; - string display_value = (((double)(idsLevel.Required - idsLevel.Current) / 1000000)).ToString("N2", CultureInfo.InvariantCulture); - idsLevel.Message = $"Missing {display_value} CC to complete the job."; - - if (idsLevel.Required > idsLevel.Maximum) - { - display_value = (((double)(idsLevel.Required - idsLevel.Maximum)) / 1000000).ToString("N2", CultureInfo.InvariantCulture); - idsLevel.Message = $"Required ink exceeds the maximum capacity of the dispenser by {display_value} CC. Please reduce the segment length."; - } - } - - exception.IdsPackLevels.Add(idsLevel); - } - else - { - LogManager.Log($"Could not validate required liquid quantity for job. Missing IDS Pack level at index {index}.", LogCategory.Warning); - } - } - - if (shouldThrow) - { - LogManager.Log("Liquid quantity validation failed due to insufficient quantity. Throwing exception..."); - - exception.IdsPackLevels = exception.IdsPackLevels.OrderBy(x => x.IdsPack.PackIndex).ToList(); - - throw LogManager.Log(exception, JsonConvert.SerializeObject(exception.IdsPackLevels.Select(x => new - { - Liquid = x.IdsPack.LiquidType.Name, - x.Required, - x.Current - }).ToList())); - } - } - else - { - LogManager.Log("Could not validate required liquid quantity for job. No machine status received", LogCategory.Warning); - } - } - - /// <summary> - /// Assign the liquid quantities spent by the last job using the job and the handler last status. - /// </summary> - /// <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) - { - if (configuration == null) - { - configuration = _machineConfiguration; - } - - try - { - _lastJobLiquidQuantities = new List<BL.ValueObjects.JobRunLiquidQuantity>(); - - if (JobLiquidQuantityCalculationMode == JobLiquidQuantityCalculationMode.MachineStatus) - { - foreach (var pack in configuration.NoneEmptyIdsPacks.ToList()) - { - var packLevelAfter = MachineStatus.IDSPacksLevels.SingleOrDefault(x => x.Index == pack.PackIndex); - var packLevelBefore = _machineStatusBeforeJobStart.IDSPacksLevels.SingleOrDefault(x => x.Index == pack.PackIndex); - - if (packLevelAfter != null && packLevelBefore != null) - { - _lastJobLiquidQuantities.Add(new BL.ValueObjects.JobRunLiquidQuantity() - { - LiquidType = pack.LiquidType.Type, - Quantity = packLevelBefore.DispenserLevel - packLevelAfter.DispenserLevel, - }); - } - } - } - else - { - _lastJobLiquidQuantities = CreateJobRunLiquidQuantities(job, configuration, processParameters, handler.Status.Progress, handler.Status.TotalProgress); - } - } - catch (Exception ex) - { - LogManager.Log(ex, LogCategory.Critical, "Error saving last job liquid quantities."); - } - } - - private void ValidateJobLiquidQuantity(JobTicket ticket, ProcessParametersTable processParameters, Configuration configuration) - { - LogManager.Log("Validating job liquid quantity..."); - - Dictionary<int, double> liquidQuantities = new Dictionary<int, double>(); - - foreach (var pack in configuration.NoneEmptyIdsPacks.OrderBy(x => x.PackIndex)) - { - liquidQuantities.Add(pack.PackIndex, 0); - } - - for (int i = 0; i < Math.Max(ticket.NumberOfUnits, 1); i++) - { - for (int segmentIndex = 0; segmentIndex < ticket.Segments.Count; segmentIndex++) - { - var segment = ticket.Segments[segmentIndex]; - var segment_length_cm = segment.Length * 100d; - var stop_count = segment.BrushStops.Count - (segment.BrushStops.Count == 1 ? 0 : 1); var stop_length_centimeters = segment_length_cm / stop_count; @@ -2204,9 +1413,9 @@ namespace Tango.Integration.Operation { var stop = segment.BrushStops[stopIndex]; - foreach (var dispenser in stop.Dispensers) + foreach (var liquidVolumes in stop.LiquidVolumes) { - liquidQuantities[dispenser.Index] += dispenser.NanoliterPerCentimeter * stop_length_centimeters; + liquidQuantities[liquidVolumes.IdsPack.PackIndex] += liquidVolumes.NanoliterPerCentimeter * stop_length_centimeters; } } } @@ -2230,8 +1439,7 @@ namespace Tango.Integration.Operation { IdsPack = idsPack, Current = packLevel.DispenserLevel, - Required = (int)liquidQuantities[index], - Maximum = MAX_DISPENSER_NANOLITER, + Required = (int)liquidQuantities[index] }; if (liquidQuantities[index] > packLevel.DispenserLevel) @@ -2266,139 +1474,6 @@ namespace Tango.Integration.Operation #endregion - #region Public Static Methods - - /// <summary> - /// Creates the job run liquid quantities. - /// </summary> - /// <param name="job">The job.</param> - /// <param name="configuration">The configuration.</param> - /// <param name="processParameters">The process parameters.</param> - /// <param name="position">The position.</param> - /// <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) - { - var units = Math.Max(job.NumberOfUnits, 1); - - var effectiveSegments = new List<Segment>(); - for (int i = 0; i < units; i++) - { - if (i > 0 && job.EnableInterSegment) - { - effectiveSegments.Add(Job.CreateInterSegment(job.InterSegmentLength)); - } - - foreach (var segment in job.EffectiveSegments) - { - effectiveSegments.Add(segment.Clone(job)); - } - } - - effectiveSegments.Add(Job.CreateInterSegment(processParameters.DryerBufferLengthMeters)); - - double total = length; - double position_cm = position * 100d; - double total_length = 0; - - Dictionary<int, double> liquidQuantities = new Dictionary<int, double>(); - - foreach (var pack in configuration.NoneEmptyIdsPacks.OrderBy(x => x.PackIndex)) - { - liquidQuantities.Add(pack.PackIndex, 0); - } - - bool stop_calc = false; - - for (int segmentIndex = 0; segmentIndex < effectiveSegments.Count && !stop_calc; segmentIndex++) - { - var segment = effectiveSegments[segmentIndex]; - var segment_length_cm = segment.Length * 100d; - - List<BrushStop> orderedBrushCollection = segment.BrushStops.OrderBy(x => x.OffsetMeters).ToList(); - - int solid_gradient_oeff = orderedBrushCollection.Count == 1 ? 1 : 2; - double prev_offset_cm = 0; - double delta_brushLenghtToStopPosition = 0d; - - double position_interval_centimeters = 0d;//interval for calculation where the stop occurred - for (int brushIndex = 0; brushIndex < orderedBrushCollection.Count && !stop_calc; brushIndex++) - { - var brush = orderedBrushCollection[brushIndex]; - double brush_length_centimeters = 0d; - double brush_offset_cm = 0; - - if ((brushIndex + 1) < orderedBrushCollection.Count) - { - brush_offset_cm = (brush.OffsetMeters * 100d); - double next_brush_offset_cm = (orderedBrushCollection[brushIndex + 1].OffsetMeters * 100d); - brush_length_centimeters = (next_brush_offset_cm - prev_offset_cm); - double brush_length_centimeters_before_calc = brush_length_centimeters; - - if (delta_brushLenghtToStopPosition > 0)//calculate second brush - { - brush_length_centimeters = ((position_interval_centimeters - delta_brushLenghtToStopPosition) * (position_interval_centimeters - delta_brushLenghtToStopPosition)) / position_interval_centimeters; - stop_calc = true; - } - else if (total_length + prev_offset_cm + brush_length_centimeters > position_cm)//calculate first brush - { - position_interval_centimeters = brush_length_centimeters; - delta_brushLenghtToStopPosition = (total_length + prev_offset_cm + brush_length_centimeters) - position_cm; - brush_length_centimeters = brush_length_centimeters - (delta_brushLenghtToStopPosition * delta_brushLenghtToStopPosition / brush_length_centimeters); - } - } - else//last brush or solid brush - { - brush_length_centimeters = (segment_length_cm - prev_offset_cm); - if (delta_brushLenghtToStopPosition > 0)//second brush - { - brush_length_centimeters = ((position_interval_centimeters - delta_brushLenghtToStopPosition) * (position_interval_centimeters - delta_brushLenghtToStopPosition)) / position_interval_centimeters; - stop_calc = true; - } - else if (orderedBrushCollection.Count == 1 && (total_length + segment_length_cm) > position_cm)// solid brush - { - brush_length_centimeters = position_cm - total_length; - stop_calc = true; - } - } - - prev_offset_cm = brush_offset_cm; - - if (brush.LiquidVolumes != null) - { - foreach (var liquidVolumes in brush.LiquidVolumes) - { - liquidQuantities[liquidVolumes.IdsPack.PackIndex] += liquidVolumes.NanoliterPerCentimeter * (brush_length_centimeters / solid_gradient_oeff); - } - } - } - total_length += segment_length_cm; - } - - List<BL.ValueObjects.JobRunLiquidQuantity> quantities = new List<BL.ValueObjects.JobRunLiquidQuantity>(); - - foreach (var liquidQuantity in liquidQuantities) - { - int index = liquidQuantity.Key; - var idsPack = configuration.NoneEmptyIdsPacks.SingleOrDefault(x => x.PackIndex == index); - - if (idsPack != null) - { - quantities.Add(new BL.ValueObjects.JobRunLiquidQuantity() - { - LiquidType = idsPack.LiquidType.Type, - Quantity = (int)liquidQuantities[index], - }); - } - } - - return quantities; - } - - - #endregion - #region Public Methods /// <summary> @@ -2426,16 +1501,7 @@ namespace Tango.Integration.Operation throw new NullReferenceException("Could not locate an active process parameters tables group for RML " + job.Rml.Name); } - ProcessParametersTable processParameters = null; - - try - { - processParameters = converter.GetRecommendedProcessParameters(job); - } - catch (Exception ex) - { - throw LogManager.Log(new InvalidOperationException($"An error occurred while trying to resolve the recommended process parameters.\n{ex.Message}")); - } + var processParameters = converter.GetRecommendedProcessParameters(job); if (processParameters == null) { @@ -2445,104 +1511,104 @@ namespace Tango.Integration.Operation //Perform color correction foreach (var stop in jobSegments.SelectMany(x => x.BrushStops)) { - //if (stop.LiquidVolumes == null || stop.BrushColorSpace == ColorSpaces.Volume) - //{ - if (stop.BrushColorSpace == ColorSpaces.RGB || stop.BrushColorSpace == ColorSpaces.LAB) + if (stop.LiquidVolumes == null) { - var output = converter.Convert(stop, false); - - //TODO: Restore this when Mirta conversion is working as expected. - //if (suggestions.OutOfGamut) - //{ - // throw new InvalidOperationException("Cannot print a brush stop which is out of gamut."); - //} - - stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); - - foreach (var outputLiquid in output.SingleCoordinates.OutputLiquids) + if (stop.BrushColorSpace == ColorSpaces.RGB || stop.BrushColorSpace == ColorSpaces.LAB) { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == outputLiquid.LiquidType.ToInt32()); + var output = converter.Convert(stop, false); - if (liquidVolume == null) - { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + outputLiquid.LiquidType + "'."); - } + //TODO: Restore this when Mirta conversion is working as expected. + //if (suggestions.OutOfGamut) + //{ + // throw new InvalidOperationException("Cannot print a brush stop which is out of gamut."); + //} - liquidVolume.Volume = outputLiquid.Volume; - } - } - else if (stop.BrushColorSpace == ColorSpaces.Catalog) - { - if (stop.ColorCatalogsItem != null) - { stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); + foreach (var outputLiquid in output.SingleCoordinates.OutputLiquids) { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Cyan); + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == outputLiquid.LiquidType.ToInt32()); if (liquidVolume == null) { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Cyan + "'."); + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + outputLiquid.LiquidType + "'."); } - liquidVolume.Volume = stop.ColorCatalogsItem.Cyan; + liquidVolume.Volume = outputLiquid.Volume; } - + } + else if (stop.BrushColorSpace == ColorSpaces.Catalog) + { + if (stop.ColorCatalogsItem != null) { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Magenta); + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); - if (liquidVolume == null) + if (stop.ColorCatalogsItem.Cyan > 0) { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Magenta + "'."); - } + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Cyan.ToInt32()); - liquidVolume.Volume = stop.ColorCatalogsItem.Magenta; - } + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Cyan + "'."); + } - { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Yellow); + liquidVolume.Volume = stop.ColorCatalogsItem.Cyan; + } - if (liquidVolume == null) + if (stop.ColorCatalogsItem.Magenta > 0) { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Yellow + "'."); - } + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Magenta.ToInt32()); - liquidVolume.Volume = stop.ColorCatalogsItem.Yellow; - } + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Magenta + "'."); + } - { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Black); + liquidVolume.Volume = stop.ColorCatalogsItem.Magenta; + } - if (liquidVolume == null) + if (stop.ColorCatalogsItem.Yellow > 0) { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Black + "'."); + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Yellow.ToInt32()); + + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Yellow + "'."); + } + + liquidVolume.Volume = stop.ColorCatalogsItem.Yellow; } - liquidVolume.Volume = stop.ColorCatalogsItem.Black; + if (stop.ColorCatalogsItem.Black > 0) + { + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Black.ToInt32()); + + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Black + "'."); + } + + liquidVolume.Volume = stop.ColorCatalogsItem.Black; + } + } + else + { + throw new InvalidOperationException($"No catalog item specified for segment color."); } } - else if (!stop.IsTransparent) + else if (stop.BrushColorSpace == ColorSpaces.Volume) { - throw new InvalidOperationException($"No catalog item specified for segment color."); + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); } else { - stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); + throw new InvalidOperationException($"Unsupported color space {stop.BrushColorSpace}."); } } - else if (stop.BrushColorSpace == ColorSpaces.Volume) - { - stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); - } - else - { - throw new InvalidOperationException($"Unsupported color space {stop.BrushColorSpace}."); - } - //} if (job.EnableLubrication) { - var lubricantVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.Lubricant); + var lubricantVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.IdsPack.LiquidType.Code == LiquidTypes.Lubricant.ToInt32()); if (lubricantVolume != null) { @@ -2564,26 +1630,13 @@ namespace Tango.Integration.Operation { return Task.Factory.StartNew(() => { - if (!CanPrint) + if (Status != MachineStatuses.ReadyToDye) { 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; @@ -2592,59 +1645,10 @@ namespace Tango.Integration.Operation job.NumberOfUnits = 1; } - if (job.EnableLubrication) - { - LogManager.Log("Job lubrication is enabled. Settings all brush stops to 100% lubricant."); - - try - { - foreach (var stop in job.Segments.SelectMany(x => x.BrushStops).Where(x => x.BrushColorSpace != ColorSpaces.Volume)) - { - var lubricantVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.Lubricant); - - if (lubricantVolume != null) - { - lubricantVolume.Volume = 100; - } - } - } - catch (Exception ex) - { - System.Diagnostics.Debugger.Break(); - LogManager.Log(ex, "Error in setting automatic lubrication volumes."); - } - } - 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 transparent/white brush stops..."); - foreach (var stop in job.Segments.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; - } - } - - //Validate liquid quantities.. if (EnableJobLiquidQuantityValidation) { ValidateJobLiquidQuantity(job, processParameters, job.Machine.Configuration); } - else - { - LogManager.Log("Liquid quantity validation is disabled. Skipping..."); - } var originalJob = job; var clonedJob = job.Clone(); @@ -2683,94 +1687,57 @@ namespace Tango.Integration.Operation if (JobUnitsMethod == JobUnitsMethods.Device) { - ticket.NumberOfUnits = (uint)Math.Max(job.NumberOfUnits, 1); + ticket.NumberOfUnits = (uint)job.NumberOfUnits; } - //Spool parameters ticket.Spool = new JobSpool(); + job.SpoolType.MapPrimitivesTo(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) + var spool = job.Machine.Spools.SingleOrDefault(x => x.SpoolType == job.SpoolType); + + if (spool == 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; + throw new InvalidOperationException("Job spool type is not registered with this machine."); } - - //Override spool parameters from Machine Spool calibration - var machineSpool = job.Machine.Spools.FirstOrDefault(x => x.SpoolType.Guid == job.SpoolType.Guid); - if (machineSpool != null) + else { - ticket.Spool.LimitSwitchStartPointOffset = machineSpool.LimitSwitchStartPointOffset != null ? machineSpool.LimitSwitchStartPointOffset.Value : ticket.Spool.LimitSwitchStartPointOffset; + spool.MapPrimitivesTo(ticket.Spool); } - //Thread Parameters - ticket.ThreadParameters = new ThreadParameters(); - job.Rml.MapPrimitivesTo(ticket.ThreadParameters); + ticket.Spool.JobSpoolType = (JobSpoolType)job.SpoolType.Code; 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; - JobHandler handler = null; - StorageFileHandler fileUploadHandler = null; + bool canceled = false; bool requestSent = false; handler = new JobHandler(async () => { try { - if (handler.CanCancel) + if (!canceled) { - handler.CanCancel = false; - handler.IsCanceled = true; - LogManager.Log("Aborting current job..."); + canceled = true; LogManager.Log($"Aborting current gradient generation..."); GradientGenerationConfiguration.AbortCurrentGeneration(); - if (fileUploadHandler != null) + if (requestSent) { - LogManager.Log("Job is currently uploading. Aborting file upload..."); - await fileUploadHandler.Cancel(); - fileUploadHandler = null; - LogManager.Log("Job upload canceled."); - OnPrintingAborted(handler, clonedJob); - handler.RaiseCanceled(); - if (Status != MachineStatuses.Disconnected) - { - Status = MachineStatuses.ReadyToDye; - } + var result = await SendRequest<AbortJobRequest, AbortJobResponse>(new AbortJobRequest()); } - else - { - if (requestSent) - { - var result = await SendRequest<AbortJobRequest, AbortJobResponse>(new AbortJobRequest(), new TransportRequestConfig() { ShouldLog = true }); - } - SaveLastJobLiquidQuantities(clonedJob, originalJob.Machine.Configuration, processParameters, handler); - OnPrintingAborted(handler, clonedJob); - handler.RaiseCanceled(); - if (Status != MachineStatuses.Disconnected) - { - Status = MachineStatuses.ReadyToDye; - } - } + PrintingAborted?.Invoke(this, new PrintingEventArgs(handler, clonedJob)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, clonedJob)); + handler.RaiseCanceled(); } } catch (Exception ex) { - handler.CanCancel = true; LogManager.Log(ex, "Failed to cancel job."); } }, clonedJob, ticket, processParameters, JobHandlingMode); @@ -2788,15 +1755,9 @@ namespace Tango.Integration.Operation ThreadFactory.StartNew(async () => { - if (handler.IsCanceled) - { - Status = MachineStatuses.ReadyToDye; - return; - } - Status = MachineStatuses.GettingReady; RunningJob = clonedJob; - OnPrintingStarted(handler, clonedJob); + PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, clonedJob)); Thread.Sleep(100); @@ -2827,28 +1788,6 @@ namespace Tango.Integration.Operation } } - //Log Job Outline (Only first and last brush stops if gradient). - var ticketToLog = ticket.Clone(); - ticketToLog.UploadStrategy = JobUploadStrategy; - 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); - } - - LogManager.Log($"Job outline for '{job.Name}':\n{ticketToLog.ToJsonString()}"); - if (handler.IsCanceled) { Status = MachineStatuses.ReadyToDye; @@ -2886,13 +1825,10 @@ namespace Tango.Integration.Operation request.JobTicket = ticket.Clone(); request.JobTicket.UploadStrategy = JobUploadStrategy; - LogManager.Log($"Job upload method is set to {JobUploadStrategy}..."); + //Use this if you want to log the entire job... + var logRequest = request.Clone(); - if (handler.IsCanceled) - { - Status = MachineStatuses.ReadyToDye; - return; - } + LogManager.Log($"Job upload method is set to {JobUploadStrategy}..."); var oldKeepAlive = UseKeepAlive; @@ -2914,21 +1850,9 @@ namespace Tango.Integration.Operation Message = "Uploading job description file...", }); - if (handler.IsCanceled) - { - Status = MachineStatuses.ReadyToDye; - return; - } - LogManager.Log("Creating storage API manager..."); var storage = CreateStorageManager(); - if (handler.IsCanceled) - { - Status = 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. @@ -2947,183 +1871,346 @@ namespace Tango.Integration.Operation 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..."); + LogManager.Log($"Uploading job description file '{job_file_path}' of size: {ms.Length}"); + await storage.UploadFileSync(job_file_path, ms); + LogManager.Log("Job upload completed successfully."); - 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) => + ms.Dispose(); + + request.JobTicket.JobDescriptionFile = job_file_path; + } + catch (Exception ex) + { + UseKeepAlive = oldKeepAlive; + Status = MachineStatuses.ReadyToDye; + PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, clonedJob, ex)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, clonedJob)); + handler.RaiseFailed(ex); + LogRequestFailed(request, ex); + return; + } + } + + if (handler.IsCanceled) + { + UseKeepAlive = oldKeepAlive; + Status = MachineStatuses.ReadyToDye; + return; + } + + LogRequestSent(request); + bool responseLogged = false; + bool completed = false; //Use this in case Shlomo is sending progress after completion. + + SendContinuousRequest<JobRequest, JobResponse>(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => + { + if (!completed) + { + handler.RaiseStatusReceived(response.Message.Status); + _last_job_status = handler.Status; + + if (response.Message.Status.Progress > 0) { - uploadCompletion.SetException(e); - }; + if (oldKeepAlive != UseKeepAlive) + { + UseKeepAlive = oldKeepAlive; + } + } - try + if (!responseLogged) { - await uploadCompletion.Task; + requestSent = true; + responseLogged = true; + LogResponseReceived(response.Message); } - catch (Exception ue) + + if (JobHandlingMode == JobHandlerModes.SettingUp) { - if (uploadException != null) - { - throw uploadException; - } - else + if (response.Message.Status.Progress > processParameters.DryerBufferLengthMeters) { - throw ue; + if (!completed) + { + Status = MachineStatuses.Printing; + } } } - finally + else { - try + if (response.Message.Status.Progress > 0) { - fileUploadHandler = null; - ms.Dispose(); + if (!completed) + { + Status = MachineStatuses.Printing; + } } - catch { } } + } + + }, (ex) => + { + if (!completed) + { + completed = true; - if (uploadCanceled) + UseKeepAlive = oldKeepAlive; + + if (!(ex is ContinuousResponseAbortedException)) { - return; + Status = MachineStatuses.ReadyToDye; + + if (!handler.IsCanceled) + { + PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, clonedJob, ex)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, clonedJob)); + handler.RaiseFailed(ex); + LogRequestFailed(request, ex); + } } else { - LogManager.Log("Job upload completed successfully."); + Status = MachineStatuses.ReadyToDye; } - - request.JobTicket.JobDescriptionFile = job_file_path; } - catch (Exception ex) + }, () => + { + if (!completed) { + completed = true; + UseKeepAlive = oldKeepAlive; + Status = MachineStatuses.ReadyToDye; - OnPrintingFailed(handler, clonedJob, ex); - handler.RaiseFailed(ex); - return; + PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, clonedJob)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, clonedJob)); + handler.RaiseCompleted(); } + }); + }); + + return handler; + + }); + } + + /// <summary> + /// Executes a print stub for emulating a full 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> + /// <returns></returns> + /// <exception cref="InvalidOperationException"> + /// Cannot print a brush stop with volume color space when process parameters table has not been specified. + /// or + /// Could not print while status = " + Status + /// </exception> + /// <exception cref="NullReferenceException"> + /// Job RML is null + /// or + /// Could not locate an active process parameters tables group for RML " + job.Rml.Name + /// or + /// Could not locate process parameters table index " + processParametersTableIndex + " in group " + processGroup.Name + " for RML " + job.Rml.Name + /// or + /// Liquid volume not found for color conversion output liquid '" + outputLiquid.LiquidType + "'. + /// </exception> + public Task<JobHandler> PrintStub(Job job) + { + return Task.Factory.StartNew<JobHandler>(() => + { + + //Check not brush stop has color space 'Volume'. + if (job.Segments.SelectMany(x => x.BrushStops).ToList().Exists(x => x.ColorSpace.Code == ColorSpaces.Volume.ToInt32())) + { + throw new InvalidOperationException("Cannot print a brush stop with volume color space when process parameters table has not been specified."); + } + + //Get least common process parameters table index. + int processParametersTableIndex = 0; + + 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); + } + + var processParameters = processGroup.ProcessParametersTables.FirstOrDefault(x => x.TableIndex == processParametersTableIndex); + + if (processParameters == null) + { + throw new NullReferenceException("Could not locate process parameters table index " + processParametersTableIndex + " in group " + processGroup.Name + " for RML " + job.Rml.Name); + } + + //Perform color correction + foreach (var stop in job.Segments.SelectMany(x => x.BrushStops)) + { + if (stop.LiquidVolumes == null) + { + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); } - else + + foreach (var liquidVolume in stop.LiquidVolumes) { - _jobUploadingStartDate = DateTime.UtcNow; + liquidVolume.Volume = 10; } + } - if (handler.IsCanceled) + if (Status != MachineStatuses.ReadyToDye) + { + throw new InvalidOperationException("Could not print while status = " + Status); + } + + RunningJob = null; + RunningJobStatus = null; + + var originalJob = job; + + CurrentProcessParameters = processParameters; + + StubJobRequest request = new StubJobRequest(); + + if (job.NumberOfUnits < 1) + { + job.NumberOfUnits = 1; + } + + job = job.Clone(); + + var segments = job.OrderedSegments.ToList(); + + for (int i = 0; i < job.NumberOfUnits - 1; i++) + { + foreach (var s in segments) { - UseKeepAlive = oldKeepAlive; - Status = MachineStatuses.ReadyToDye; - return; + job.Segments.Add(s); } + } - _machineStatusBeforeJobStart = MachineStatus.Clone(); + JobTicket ticket = new JobTicket(); + ticket.Guid = originalJob.Guid; + ticket.EnableInterSegment = job.EnableInterSegment; + ticket.InterSegmentLength = job.InterSegmentLength; + ticket.Length = job.Length; + ticket.WindingMethod = (JobWindingMethod)job.WindingMethod.Code; + ticket.Spool = new JobSpool(); - SaveCachedJobOperation(clonedJob); //Cache job and machine status for job resume! + job.SpoolType.MapPrimitivesTo(ticket.Spool); + ticket.Spool.JobSpoolType = (JobSpoolType)job.SpoolType.Code; - bool responseLogged = false; - bool completed = false; //Use this in case Shlomo is sending progress after completion. + ProcessParameters process = new ProcessParameters(); + processParameters.MapPrimitivesTo(process); + ticket.ProcessParameters = process; - _jobHeatingStartDate = DateTime.UtcNow; + foreach (var segment in job.OrderedSegments) + { + JobSegment jobSegment = new JobSegment(); + jobSegment.Length = segment.LengthWithFactor; + jobSegment.Name = segment.Name; - SendContinuousRequest<JobRequest, JobResponse>(request, new TransportContinuousRequestConfig() { ContinuousTimeout = ContinuousRequestTimeout.Add(TimeSpan.FromSeconds(3)), ShouldLog = true }).Subscribe((response) => - { - if (!completed) - { - handler.RaiseStatusReceived(response.Message.Status); - _last_job_status = handler.Status; + foreach (var stop in segment.BrushStops) + { + JobBrushStop jobStop = new JobBrushStop(); + jobStop.Index = stop.StopIndex; + jobStop.OffsetPercent = stop.OffsetPercent; + jobStop.OffsetMeters = stop.OffsetMeters; - if (response.Message.Status.Progress > 0) - { - if (oldKeepAlive != UseKeepAlive) - { - UseKeepAlive = oldKeepAlive; - } + if (stop.LiquidVolumes == null) + { + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); + } - if (_jobActualStartDate == null) - { - _jobActualStartDate = DateTime.UtcNow; - } - } + foreach (var liquidVolume in stop.LiquidVolumes) + { + JobDispenser dispenser = new JobDispenser(); + dispenser.Index = liquidVolume.IdsPack.PackIndex; + dispenser.Volume = liquidVolume.Volume; + dispenser.DispenserLiquidType = (DispenserLiquidType)liquidVolume.IdsPack.LiquidType.Code; + dispenser.DispenserStepDivision = (DispenserStepDivision)liquidVolume.DispenserStepDivision; - if (!responseLogged) - { - requestSent = true; - responseLogged = true; - } + dispenser.NanoliterPerPulse = liquidVolume.IdsPack.Dispenser.NlPerPulse; - if (JobHandlingMode == JobHandlerModes.SettingUp) - { - if (response.Message.Status.Progress > processParameters.DryerBufferLengthMeters) - { - if (!completed) - { - Status = MachineStatuses.Printing; - } - } - } - else - { - if (response.Message.Status.Progress > 0) - { - if (!completed) - { - Status = MachineStatuses.Printing; - } - } - } - } + dispenser.LiquidMaxNanoliterPerCentimeter = liquidVolume.LiquidMaxNanoliterPerCentimeter; + dispenser.NanoliterPerCentimeter = liquidVolume.NanoliterPerCentimeter; + dispenser.NanolitterPerSecond = liquidVolume.NanoliterPerSecond; + dispenser.PulsePerSecond = liquidVolume.PulsePerSecond; - }, (ex) => - { - if (!completed) - { - completed = true; + jobStop.Dispensers.Add(dispenser); + } - UseKeepAlive = oldKeepAlive; + jobSegment.BrushStops.Add(jobStop); + } - if (Status != MachineStatuses.Disconnected) - { - Status = MachineStatuses.ReadyToDye; - } + ticket.Segments.Add(jobSegment); + } - if (!handler.IsCanceled) - { - SaveLastJobLiquidQuantities(originalJob, originalJob.Machine.Configuration, processParameters, handler); + request.JobTicket = ticket; - Exception finalException = ex; + JobHandler handler = null; - if (ex is ContinuousResponseAbortedException continuousException) - { - finalException = new ContinuousResponseAbortedException($"Job aborted by the embedded device ({continuousException.Container.ErrorMessage})."); - } + handler = new JobHandler(async () => + { + try + { + var result = await SendRequest<StubAbortJobRequest, StubAbortJobResponse>(new StubAbortJobRequest()); + PrintingAborted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + handler.RaiseCanceled(); + } + catch (Exception ex) + { + LogManager.Log(ex, "Failed to cancel job."); + } + }, originalJob, ticket, processParameters, JobHandlingMode); - OnPrintingFailed(handler, originalJob, finalException); - handler.RaiseFailed(finalException); - } - } - }, () => - { - if (!completed) - { - completed = true; + handler.StatusChanged += (x, s) => + { + RunningJobStatus = s; + }; + + LogRequestSent(request); + bool responseLogged = false; - UseKeepAlive = oldKeepAlive; + SendContinuousRequest<StubJobRequest, StubJobResponse>(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => + { + handler.RaiseStatusReceived(response.Message.Status); + + if (!responseLogged) + { + responseLogged = true; + Status = MachineStatuses.Printing; + RunningJob = originalJob; + PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + LogResponseReceived(response.Message); + } + }, (ex) => + { + if (!(ex is ContinuousResponseAbortedException)) + { + Status = MachineStatuses.ReadyToDye; - Status = MachineStatuses.ReadyToDye; - SaveLastJobLiquidQuantities(clonedJob, originalJob.Machine.Configuration, processParameters, handler); - OnPrintingCompleted(handler, clonedJob); - handler.RaiseCompleted(); - } - }); + if (!handler.IsCanceled) + { + PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, originalJob, ex)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + handler.RaiseFailed(ex); + LogRequestFailed(request, ex); + } + } + else + { + Status = MachineStatuses.ReadyToDye; + } + }, () => + { + Status = MachineStatuses.ReadyToDye; + PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + handler.RaiseCompleted(); }); return handler; @@ -3147,10 +2234,13 @@ namespace Tango.Integration.Operation try { CurrentProcessParameters = processParameters; - response = await SendRequest<UploadProcessParametersRequest, UploadProcessParametersResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + response = await SendRequest<UploadProcessParametersRequest, UploadProcessParametersResponse>(request); + LogResponseReceived(response); } catch (Exception ex) { + LogRequestFailed(request, ex); throw ex; } @@ -3165,8 +2255,6 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<UploadHardwareConfigurationResponse> UploadHardwareConfiguration(HardwareVersion hardwareVersion, Configuration configuration) { - _machineConfiguration = configuration; - try { hardwareVersion = configuration.GetHardwareConfiguration().Merge(hardwareVersion); @@ -3251,14 +2339,14 @@ namespace Tango.Integration.Operation try { - LogManager.Log($"Sending '{nameof(UploadHardwareConfigurationRequest)}'..."); - LogManager.Log($"{nameof(UploadHardwareConfigurationRequest)} request:\n{request.HardwareConfiguration.ToJsonString()}", LogCategory.Debug); - CurrentHardwareConfiguration = hardwareConfiguration; - response = await SendRequest<UploadHardwareConfigurationRequest, UploadHardwareConfigurationResponse>(request, new TransportRequestConfig() { ShouldLog = false }); + LogRequestSent(request); + response = await SendRequest<UploadHardwareConfigurationRequest, UploadHardwareConfigurationResponse>(request); + LogResponseReceived(response); } catch (Exception ex) { + LogRequestFailed(request, ex); throw ex; } @@ -3276,10 +2364,13 @@ namespace Tango.Integration.Operation try { - response = await SendRequest<MotorJoggingRequest, MotorJoggingResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + response = await SendRequest<MotorJoggingRequest, MotorJoggingResponse>(request); + LogResponseReceived(response); } catch (Exception ex) { + LogRequestFailed(request, ex); throw ex; } @@ -3293,7 +2384,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<MotorAbortJoggingResponse> StopMotorJogging(MotorAbortJoggingRequest request) { - return await SendRequest<MotorAbortJoggingRequest, MotorAbortJoggingResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<MotorAbortJoggingRequest, MotorAbortJoggingResponse>(request); } /// <summary> @@ -3303,7 +2395,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public IObservable<MotorHomingResponse> StartMotorHoming(MotorHomingRequest request) { - return SendContinuousRequest<MotorHomingRequest, MotorHomingResponse>(request, new TransportContinuousRequestConfig() { ContinuousTimeout = ContinuousRequestTimeout, ShouldLog = true }).Select(x => x.Message); + LogRequestSent(request); + return SendContinuousRequest<MotorHomingRequest, MotorHomingResponse>(request, null, TimeSpan.FromSeconds(5)).Select(x => x.Message); } /// <summary> @@ -3313,7 +2406,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<MotorAbortHomingResponse> StopMotorHoming(MotorAbortHomingRequest request) { - return await SendRequest<MotorAbortHomingRequest, MotorAbortHomingResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<MotorAbortHomingRequest, MotorAbortHomingResponse>(request); } /// <summary> @@ -3323,7 +2417,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<DispenserJoggingResponse> StartDispenserJogging(DispenserJoggingRequest request) { - return await SendRequest<DispenserJoggingRequest, DispenserJoggingResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<DispenserJoggingRequest, DispenserJoggingResponse>(request); } /// <summary> @@ -3333,7 +2428,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<DispenserAbortJoggingResponse> StopDispenserJogging(DispenserAbortJoggingRequest request) { - return await SendRequest<DispenserAbortJoggingRequest, DispenserAbortJoggingResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<DispenserAbortJoggingRequest, DispenserAbortJoggingResponse>(request); } /// <summary> @@ -3343,7 +2439,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public IObservable<DispenserHomingResponse> StartDispenserHoming(DispenserHomingRequest request) { - return SendContinuousRequest<DispenserHomingRequest, DispenserHomingResponse>(request, new TransportContinuousRequestConfig() { ContinuousTimeout = ContinuousRequestTimeout, ShouldLog = true }).Select(x => x.Message); + LogRequestSent(request); + return SendContinuousRequest<DispenserHomingRequest, DispenserHomingResponse>(request, null, TimeSpan.FromSeconds(5)).Select(x => x.Message); } /// <summary> @@ -3353,7 +2450,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<DispenserAbortHomingResponse> StopDispenserHoming(DispenserAbortHomingRequest request) { - return await SendRequest<DispenserAbortHomingRequest, DispenserAbortHomingResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<DispenserAbortHomingRequest, DispenserAbortHomingResponse>(request); } /// <summary> @@ -3363,7 +2461,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<SetDigitalOutResponse> SetDigitalOut(SetDigitalOutRequest request) { - return await SendRequest<SetDigitalOutRequest, SetDigitalOutResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<SetDigitalOutRequest, SetDigitalOutResponse>(request); } /// <summary> @@ -3373,7 +2472,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<ThreadJoggingResponse> StartThreadJogging(ThreadJoggingRequest request) { - return await SendRequest<ThreadJoggingRequest, ThreadJoggingResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<ThreadJoggingRequest, ThreadJoggingResponse>(request); } /// <summary> @@ -3383,7 +2483,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<ThreadAbortJoggingResponse> StopThreadJogging(ThreadAbortJoggingRequest request) { - return await SendRequest<ThreadAbortJoggingRequest, ThreadAbortJoggingResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<ThreadAbortJoggingRequest, ThreadAbortJoggingResponse>(request); } /// <summary> @@ -3393,7 +2494,8 @@ namespace Tango.Integration.Operation /// <returns></returns> public async Task<SetComponentValueResponse> SetComponentValue(SetComponentValueRequest request) { - return await SendRequest<SetComponentValueRequest, SetComponentValueResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<SetComponentValueRequest, SetComponentValueResponse>(request); } /// <summary> @@ -3414,10 +2516,13 @@ namespace Tango.Integration.Operation try { - response = await SendRequest<SetHeaterStateRequest, SetHeaterStateResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + response = await SendRequest<SetHeaterStateRequest, SetHeaterStateResponse>(request); + LogResponseReceived(response); } catch (Exception ex) { + LogRequestFailed(request, ex); throw ex; } @@ -3443,10 +2548,13 @@ namespace Tango.Integration.Operation try { - response = await SendRequest<SetBlowerStateRequest, SetBlowerStateResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + response = await SendRequest<SetBlowerStateRequest, SetBlowerStateResponse>(request); + LogResponseReceived(response); } catch (Exception ex) { + LogRequestFailed(request, ex); throw ex; } @@ -3470,10 +2578,13 @@ namespace Tango.Integration.Operation try { - response = await SendRequest<SetValveStateRequest, SetValveStateResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + response = await SendRequest<SetValveStateRequest, SetValveStateResponse>(request); + LogResponseReceived(response); } catch (Exception ex) { + LogRequestFailed(request, ex); throw ex; } @@ -3488,7 +2599,8 @@ namespace Tango.Integration.Operation public async Task<ResolveEventResponse> ResolveEvent(PMR.Diagnostics.EventType eventType) { ResolveEventRequest request = new ResolveEventRequest() { Type = eventType }; - return await SendRequest<ResolveEventRequest, ResolveEventResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + return await SendRequest<ResolveEventRequest, ResolveEventResponse>(request); } /// <summary> @@ -3508,10 +2620,13 @@ namespace Tango.Integration.Operation Value = 0x0 }; - response = await SendRequest<StubFpgaWriteRegRequest, StubFpgaWriteRegResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + response = await SendRequest<StubFpgaWriteRegRequest, StubFpgaWriteRegResponse>(request); + LogResponseReceived(response); } catch (Exception ex) { + LogRequestFailed(request, ex); throw ex; } @@ -3525,10 +2640,13 @@ namespace Tango.Integration.Operation Value = 0x1 }; - response = await SendRequest<StubFpgaWriteRegRequest, StubFpgaWriteRegResponse>(request, new TransportRequestConfig() { ShouldLog = true }); + LogRequestSent(request); + response = await SendRequest<StubFpgaWriteRegRequest, StubFpgaWriteRegResponse>(request); + LogResponseReceived(response); } catch (Exception ex) { + LogRequestFailed(request, ex); throw ex; } @@ -3536,16 +2654,6 @@ namespace Tango.Integration.Operation } /// <summary> - /// Directs the embedded device to switch to stand-by mode. - /// </summary> - /// <returns></returns> - public async Task StandBy() - { - LogManager.Log("Switching to stand-by mode..."); - await SendRequest<StandByRequest, StandByResponse>(new StandByRequest(), new TransportRequestConfig() { ShouldLog = true }); - } - - /// <summary> /// Resets the device through the DFU channel. /// </summary> /// <returns></returns> @@ -3608,10 +2716,8 @@ namespace Tango.Integration.Operation /// Upgrades the firmware. /// </summary> /// <param name="tfpStream">The TFP stream (Tango Firmware Package File).</param> - /// <param name="isEmulated">Specify whether the connected machine is emulated and to skip the actual DFU interface.</param> /// <returns></returns> - /// <exception cref="InvalidOperationException"></exception> - public virtual async Task<FirmwareUpgradeHandler> UpgradeFirmware(Stream tfpStream, bool isEmulated = false) + public async Task<FirmwareUpgradeHandler> UpgradeFirmware(Stream tfpStream) { bool cancel = false; ZipFile zip = null; @@ -3626,60 +2732,33 @@ namespace Tango.Integration.Operation try { - LogManager.Log("Starting firmware upgrade..."); - LogManager.Log($"Firmware upgrade flags: {String.Join(", ", FirmwareUpgradeMode.GetFlags<FirmwareUpgradeModes>().Select(x => x.ToString()))}"); - - if (!CanPrint) + if (Status != MachineStatuses.ReadyToDye) { throw LogManager.Log(new InvalidOperationException($"Could not perform firmware upgrade while operator status is '{Status}'.")); } - LogManager.Log("Extracting tfp package..."); var package_info = await GetFirmwarePackageInfo(tfpStream); tfpStream.Position = 0; - LogManager.Log("Validating TFP package..."); - package_info.Validate(); - - LogManager.Log("Reading zip stream..."); zip = ZipFile.Read(tfpStream); - double packageUploadTotal = 0; - - try - { - packageUploadTotal = zip.Entries.Sum(x => x.UncompressedSize); - } - catch (Exception ex) - { - LogManager.Log(ex, "Error calculating total package upload bytes."); - } - - LogManager.Log("Creating storage manager..."); var storage = CreateStorageManager(); - LogManager.Log("Getting storage drive information..."); var drive = await storage.GetStorageDrive(); - LogManager.Log($"Storage drive info:\n{drive.ToJsonString()}"); - LogManager.Log("Getting root folder..."); var root = await storage.GetRootFolder(); - LogManager.Log($"Root folder: '{root.Path}'"); var existing_folder = root.Items.SingleOrDefault(x => x.Name == FIRMWARE_UPGRADE_FOLDER_NAME); if (existing_folder != null) { - LogManager.Log("Root folder exists. Deleting..."); await storage.DeleteItem(existing_folder); } String package_folder = Path.Combine(drive.Root, FIRMWARE_UPGRADE_FOLDER_NAME); - LogManager.Log($"Creating new folder: '{package_folder}'."); await storage.CreateFolder(package_folder); List<StorageFileHandler> handlers = new List<StorageFileHandler>(); List<ZipEntry> entries = zip.Entries.ToList(); List<Stream> streams = new List<Stream>(); - LogManager.Log("Disabling keep alive..."); var keepAlive = UseKeepAlive; UseKeepAlive = false; @@ -3702,102 +2781,49 @@ namespace Tango.Integration.Operation { if (FirmwareUpgradeMode.HasFlag(FirmwareUpgradeModes.DFU)) { - if (package_info.ContainsMcu()) - { - LogManager.Log("DFU enabled. Starting upgrade via DFU..."); - LogManager.Log("Extracting MCU file..."); - ZipEntry mcuEntry = null; - try - { - mcuEntry = entries.Single(x => x.FileName == package_info.FileDescriptors.Single(y => y.Destination == VersionFileDestination.Mcu).FileName); - entries.Remove(mcuEntry); - } - catch (Exception ex) - { - LogManager.Log(ex, "Error extracting MCU file from package."); - upgradeHandler.RaiseFailed(new IOException("Error retrieving MCU file from package.", ex)); - return; - } - - MemoryStream ms = new MemoryStream(); - mcuEntry.Extract(ms); - ms.Position = 0; - byte[] data = ms.ToArray(); - ms.Dispose(); + var mcuEntry = zip.Entries.Single(x => x.FileName == package_info.FileDescriptors.Single(y => y.Destination == VersionFileDestination.Mcu).FileName); + MemoryStream ms = new MemoryStream(); + mcuEntry.Extract(ms); + ms.Position = 0; + byte[] data = ms.ToArray(); + ms.Dispose(); - FirmwareUpgradeManager upgradeManager = new FirmwareUpgradeManager(); - upgradeManager.UpgradeProgress += (sender, e) => - { - upgradeHandler.RaiseProgress(FirmwareUpgradeStatus.Upgrading, e.State.ToDescription(), false, e.Total, e.Progress); - }; - - LogManager.Log("Disconnecting adapter..."); - Adapter.Disconnect().Wait(); + FirmwareUpgradeManager upgradeManager = new FirmwareUpgradeManager(); + upgradeManager.UpgradeProgress += (sender, e) => + { + upgradeHandler.Total = (long)e.Total; + upgradeHandler.RaiseProgress((long)e.Progress, FirmwareUpgradeStatus.Upgrading, e.State.ToDescription()); + }; - ResetEvents(); - ResetInkFllingStatus(); + Adapter.Disconnect().Wait(); - try - { - if (!isEmulated) - { - LogManager.Log("Upgrading..."); - upgradeManager.PerformUpgrade(data).Wait(); - } - else - { - LogManager.Log("Upgrading (emulated)..."); - Thread.Sleep(3000); - } - } - catch (Exception ex) - { - LogManager.Log("Firmware upgrade failed while doing DFU upload. We need to destroy the whole transport layer.", LogCategory.Error); - Status = MachineStatuses.Disconnected; - upgradeHandler.RaiseFailed(ex); - OnFailed(ex); - return; - } + if (MachineEventsStateProvider != null) + { + MachineEventsStateProvider.Reset(); + } - LogManager.Log("Waiting for the device..."); - upgradeHandler.RaiseProgress(FirmwareUpgradeStatus.Upgrading, "Waiting for the device..."); - Thread.Sleep(5000); + upgradeManager.PerformUpgrade(data).Wait(); - LogManager.Log("Reconnecting adapter..."); - upgradeHandler.RaiseProgress(FirmwareUpgradeStatus.Upgrading, "Connecting..."); - Adapter.Connect().Wait(); + upgradeHandler.RaiseProgress(100, FirmwareUpgradeStatus.Upgrading, "Waiting for the device..."); + Thread.Sleep(5000); - Connect().Wait(); + upgradeHandler.RaiseProgress(100, FirmwareUpgradeStatus.Upgrading, "Connecting..."); + Adapter.Connect().Wait(); + Connect().Wait(); - LogManager.Log("Connected..."); - upgradeHandler.RaiseProgress(FirmwareUpgradeStatus.Upgrading, "Connected."); - Thread.Sleep(2000); + upgradeHandler.RaiseProgress(100, FirmwareUpgradeStatus.Upgrading, "Connected."); + Thread.Sleep(2000); - LogManager.Log("Waiting..."); - upgradeHandler.RaiseProgress(FirmwareUpgradeStatus.Upgrading, "Waiting..."); - Thread.Sleep(2000); + upgradeHandler.RaiseProgress(100, FirmwareUpgradeStatus.Upgrading, "Waiting..."); + Thread.Sleep(2000); - Status = MachineStatuses.Upgrading; - } - else - { - LogManager.Log("DFU is enabled but no MCU file was found on the package. Skipping..."); - } + Status = MachineStatuses.Upgrading; } - //Upload tfp package only if specified in flag && package info contains more files other than the mcu bin file. if (FirmwareUpgradeMode.HasFlag(FirmwareUpgradeModes.TFP_PACKAGE)) { - if (package_info.ContainsNoneMcu()) - { - LogManager.Log("TFP package is enabled. Starting upload..."); - uploadNext(); - } - else - { - LogManager.Log("TFP package is enabled but no other files other than the MCU file were found on the package. Skipping..."); - postActivation(); - } + upgradeHandler.Total = zip.Entries.Sum(x => x.UncompressedSize); + uploadNext(); } else { @@ -3821,8 +2847,6 @@ namespace Tango.Integration.Operation var entry = entries.First(); entries.Remove(entry); - LogManager.Log($"Uploading file '{entry.FileName}'..."); - var reader = entry.OpenReader(); streams.Add(reader); @@ -3839,7 +2863,7 @@ namespace Tango.Integration.Operation return; } - upgradeHandler.RaiseProgress(FirmwareUpgradeStatus.Uploading, $"Uploading '{entry.FileName}'...", false, packageUploadTotal, upgradeHandler.Current + e.Delta); + upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.Uploading, $"Uploading '{entry.FileName}'..."); }; } catch (Exception ex) @@ -3858,12 +2882,11 @@ namespace Tango.Integration.Operation { try { - LogManager.Log("Validating version..."); streams.ForEach(x => x.Dispose()); - upgradeHandler.RaiseProgress(FirmwareUpgradeStatus.Validating, "Validating version..."); + upgradeHandler.RaiseProgress(upgradeHandler.Total, FirmwareUpgradeStatus.Validating, "Validating version..."); var validateRequest = new ValidateVersionRequest(); validateRequest.Path = package_folder; - var validateResponse = SendRequest<ValidateVersionRequest, ValidateVersionResponse>(validateRequest, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(10), ShouldLog = true }).Result; + var validateResponse = SendRequest<ValidateVersionRequest, ValidateVersionResponse>(validateRequest, TimeSpan.FromSeconds(10)).Result; activate(); } catch (Exception ex) @@ -3876,42 +2899,10 @@ namespace Tango.Integration.Operation { try { - TaskCompletionSource<object> activationCompletion = new TaskCompletionSource<object>(); - - bool completed = false; - - LogManager.Log("Activating version..."); - - upgradeHandler.RaiseProgress(FirmwareUpgradeStatus.Activating, "Activating version..."); - + upgradeHandler.RaiseProgress(upgradeHandler.Total, FirmwareUpgradeStatus.Activating, "Activating version..."); var activateRequest = new ActivateVersionRequest(); activateRequest.Path = package_folder; - - SendContinuousRequest<ActivateVersionRequest, ActivateVersionResponse>(activateRequest, new TransportContinuousRequestConfig() { Timeout = TimeSpan.FromSeconds(10), ContinuousTimeout = TimeSpan.FromSeconds(10), ShouldLog = true }) - .Subscribe((response) => - { - if (!completed && response.Message.Progress > 0) - { - upgradeHandler.RaiseProgress(FirmwareUpgradeStatus.Activating, "Activating version...", false, response.Message.Total, response.Message.Progress); - } - }, (ex) => - { - if (!completed) - { - completed = true; - activationCompletion.SetException(ex); - } - }, () => - { - if (!completed) - { - completed = true; - activationCompletion.SetResult(true); - } - }); - - var result = activationCompletion.Task.GetAwaiter().GetResult(); - + var activateResponse = SendRequest<ActivateVersionRequest, ActivateVersionResponse>(activateRequest, TimeSpan.FromSeconds(10)).Result; postActivation(); } catch (Exception ex) @@ -3922,10 +2913,8 @@ namespace Tango.Integration.Operation postActivation = new Action(() => { - LogManager.Log("Firmware upgrade completed."); upgradeHandler.RaiseCompleted(); Status = MachineStatuses.ReadyToDye; - LogManager.Log("Enabling keep alive..."); UseKeepAlive = keepAlive; }); @@ -3975,7 +2964,7 @@ namespace Tango.Integration.Operation { var validateRequest = new ValidateVersionRequest(); validateRequest.Path = path; - await SendRequest<ValidateVersionRequest, ValidateVersionResponse>(validateRequest, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(10), ShouldLog = true }); + await SendRequest<ValidateVersionRequest, ValidateVersionResponse>(validateRequest, TimeSpan.FromSeconds(10)); } /// <summary> @@ -3986,200 +2975,7 @@ namespace Tango.Integration.Operation { var activateRequest = new ActivateVersionRequest(); activateRequest.Path = path; - await SendRequest<ActivateVersionRequest, ActivateVersionResponse>(activateRequest, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(10), ShouldLog = true }); - } - - /// <summary> - /// Turns off the machine. - /// </summary> - /// <returns></returns> - public Task<PowerDownHandler> PowerDown() - { - if (_isPowerDownRequestInProgress) - { - throw new InvalidOperationException("Machine power down is already in progress."); - } - - _isPowerDownRequestInProgress = true; - - PowerDownHandler handler = new PowerDownHandler(new Task(() => - { - _isPowerDownRequestInProgress = false; - Thread.Sleep(2000); - var r = SendRequest<AbortPowerDownRequest, AbortPowerDownResponse>(new AbortPowerDownRequest(), new TransportRequestConfig() { ShouldLog = true }).Result; - })); - - Task.Factory.StartNew(() => - { - Thread.Sleep(100); - - bool firstResponse = true; - - SendContinuousRequest<StartPowerDownRequest, StartPowerDownResponse>(new StartPowerDownRequest(), new TransportContinuousRequestConfig() { ContinuousTimeout = TimeSpan.FromSeconds(2), ShouldLog = true }).ObserveOn(new NewThreadScheduler()).Subscribe((response) => - { - if (firstResponse) - { - firstResponse = false; - Status = MachineStatuses.ShuttingDown; - } - - handler.RaiseStatusChanged(response); - }, (ex) => - { - if (_isPowerDownRequestInProgress) - { - _isPowerDownRequestInProgress = false; - LogManager.Log(ex, "Power down error."); - handler.RaiseFailed(ex); - } - }, () => - { - if (_isPowerDownRequestInProgress) - { - _isPowerDownRequestInProgress = false; - handler.RaiseCompleted(); - } - }); - }); - - PowerDownStarted?.Invoke(this, new PowerDownStartedEventArgs() - { - Handler = handler, - }); - - return Task.FromResult(handler); - } - - /// <summary> - /// Turns off the machine. - /// </summary> - /// <returns></returns> - public Task<HeadCleaningHandler> PerformHeadCleaning() - { - if (_isHeadCleaningInProgress) - { - throw new InvalidOperationException("Head cleaning is already in progress."); - } - - if (!CanPrint) - { - throw new InvalidOperationException($"Cannot perform head cleaning while machine status is '{Status}'."); - } - - _isHeadCleaningInProgress = true; - bool _completed = false; - - HeadCleaningHandler handler = null; - handler = new HeadCleaningHandler(() => - { - _isHeadCleaningInProgress = false; - Thread.Sleep(1000); - - if (!_completed) - { - _completed = true; - OnHeadCleaningEnded(handler, JobRunStatus.Aborted); - } - - var r = SendRequest<AbortHeadCleaningRequest, AbortHeadCleaningResponse>(new AbortHeadCleaningRequest(), new TransportRequestConfig() { ShouldLog = true }).Result; - }); - - Task.Factory.StartNew(() => - { - Thread.Sleep(100); - - _lastJobLiquidQuantities = new List<BL.ValueObjects.JobRunLiquidQuantity>(); - _machineStatusBeforeJobStart = MachineStatus.Clone(); - - bool firstResponse = true; - _jobStartDate = DateTime.UtcNow; - - SendContinuousRequest<StartHeadCleaningRequest, StartHeadCleaningResponse>(new StartHeadCleaningRequest(), new TransportContinuousRequestConfig() { ContinuousTimeout = TimeSpan.FromSeconds(5), ShouldLog = true }).ObserveOn(new NewThreadScheduler()).Subscribe((response) => - { - if (firstResponse) - { - firstResponse = false; - } - - handler.RaiseStatusChanged(response); - }, (ex) => - { - if (!(ex is ContinuousResponseAbortedException)) - { - _isHeadCleaningInProgress = false; - LogManager.Log(ex, "Head cleaning error."); - handler.RaiseFailed(ex); - } - - if (!_completed) - { - _completed = true; - OnHeadCleaningEnded(handler, JobRunStatus.Failed); - } - }, () => - { - _isHeadCleaningInProgress = false; - handler.RaiseCompleted(); - - if (!_completed) - { - _completed = true; - OnHeadCleaningEnded(handler, JobRunStatus.Completed); - } - }); - }); - - return Task.FromResult(handler); - } - - /// <summary> - /// Starts the automatic thread loading process. - /// </summary> - /// <returns></returns> - public async Task StartThreadLoading() - { - var response = await SendRequest<TryThreadLoadingRequest, TryThreadLoadingResponse>(new TryThreadLoadingRequest()); - } - - /// <summary> - /// Continues the current thread loading. - /// </summary> - /// <param name="processParameters">The process parameters.</param> - /// <returns></returns> - public async Task ContinueThreadLoading(ProcessParametersTable processParameters) - { - var process = processParameters.ToProcessParametersPMR(); - var r = await SendRequest<ContinueThreadLoadingRequest, ContinueThreadLoadingResponse>(new ContinueThreadLoadingRequest() - { - ProcessParameters = process, - }, new TransportRequestConfig() { ShouldLog = true }); - } - - /// <summary> - /// Attempts to jog the thread in order to check whether there are no thread breaking issues. - /// </summary> - /// <returns></returns> - public async Task AttemptThreadJogging() - { - var r = await SendRequest<AttemptThreadJoggingRequest, AttemptThreadJoggingResponse>(new AttemptThreadJoggingRequest() - { - - }, new TransportRequestConfig() { ShouldLog = true, Timeout = TimeSpan.FromSeconds(20) }); - } - - /// <summary> - /// Emulates a hardware event that will last for the specified timeout. - /// </summary> - /// <param name="ev">Type of the event.</param> - /// <param name="timeout">The timeout.</param> - public async void PushEmulatedEvent(Event ev, TimeSpan timeout) - { - if (!_emulatedEvents.Exists(x => x.Type == ev.Type)) - { - _emulatedEvents.Add(ev); - await Task.Delay(timeout); - _emulatedEvents.Remove(ev); - } + await SendRequest<ActivateVersionRequest, ActivateVersionResponse>(activateRequest, TimeSpan.FromSeconds(10)); } #endregion |
