using System; using System.Collections.Generic; using System.Linq; using System.Text; using ChamChat.Models; namespace ChamChat { public class PLxKPH_Task : Task { public PLxKPH_Task(Client Client, Profile Profile) : base(Client, Profile) { _Profile = Profile; _Client = Client; _SerSteps = _Profile.SerializedStepList; } private const Int32 PollingIntervalSeconds = 10; private List _SerSteps; public override Boolean IsControlledProgrammable(Profile profile) { ClientMessage msg = new ClientMessage(String.Format("The {0} can only operate in stand alone mode.", _Client.TypeDescription)); _Client.ClientMessages = new List(); _Client.ClientMessages.Add(msg); return false; } protected override void ThreadStandAlone() { // Write profile try { if (!_Client.WriteProfile(_Profile)) { _Status = TaskStatus.Stopped; return; } } catch (Exception ex) { _Status = TaskStatus.ExceptionOccured; _TaskProgress = string.Format("Client WriteProfile() exception: {0}", ex.Message); return; } // Start client try { if (!_Client.Start()) { _Status = TaskStatus.Stopped; return; } } catch (Exception ex) { _Status = TaskStatus.ExceptionOccured; _TaskProgress = string.Format("Client Start() exception: {0}", ex.Message); return; } DateTime lastPolled = DateTime.Now; while (_Status == TaskStatus.IsRunning) { // Poll only every 'PollingIntervalSeconds' seconds if (DateTime.Now > lastPolled.AddSeconds(PollingIntervalSeconds)) { // Is finished? try { if (_Client.IsFinished()) { _Status = TaskStatus.Finished; continue; } } catch { } try { // Client return "Current conditions are x °C and x %rh" _TaskProgress = _Client.Progress(); double runTimeMin = (DateTime.Now - StartOfTask).TotalMinutes; double p = runTimeMin / _Profile.DurationMin * 100; double remainTimeMin = Math.Max(0,_Profile.DurationMin - runTimeMin); double hrs = Math.Floor(remainTimeMin /60); double min = Math.Floor(remainTimeMin - 60 * hrs); _TaskProgress += String.Format(", {0:0.0}% completed, {1:0}h{2:00} remaining",p, hrs,min ); } catch { } lastPolled = DateTime.Now; } System.Threading.Thread.Sleep(100); if (_Status == TaskStatus.AbortRequested) { try { if (_Client.Stop()) _Status = TaskStatus.Aborted; } catch { } } _isKicking = true; } _isKicking = false; } protected override void ThreadControlled() { Int32 iCurrentSerialStep = -1; DateTime startOfCurrentProgram = new DateTime(1900, 1, 1); DateTime endOfCurrentProgram = new DateTime(1900, 1, 1); Step currentStep = _SerSteps[0]; DateTime lastPolled = DateTime.Now; while (_Status == TaskStatus.IsRunning) { if (DateTime.Now > endOfCurrentProgram) { iCurrentSerialStep++; // Last step has been performed? if (iCurrentSerialStep > _SerSteps.Count - 1) { _Client.Stop(); _Status = TaskStatus.Finished; AddEventLog("Last step performed"); continue; } // Get step details currentStep = _SerSteps[iCurrentSerialStep]; double TargetT = currentStep.T; double TargetRH = currentStep.RH; double DurationMin = currentStep.DurationMin; double StartT = currentStep.T; // Set start to be target, but change to value of previous step if ramped. if (currentStep.RampCtrlT) { if (iCurrentSerialStep == 0) StartT = 23; else StartT = _SerSteps[iCurrentSerialStep - 1].T; } double StartRH = currentStep.RH; // Set start to be target, but change to value of previous step if ramped. if (currentStep.RampCtrlRH) { if (iCurrentSerialStep == 0) StartRH = 60; else StartRH = _SerSteps[iCurrentSerialStep - 1].RH; } RestartClient(DurationMin, StartT, TargetT, StartRH, TargetRH); if (_Status != TaskStatus.IsRunning) continue; // Update variables startOfCurrentProgram = DateTime.Now; endOfCurrentProgram = DateTime.Now.AddMinutes(DurationMin); lastPolled = DateTime.Now; #region Update events try { string s = "Set conditions: "; if (currentStep.RampCtrlT) s += String.Format("to {0:0.0} °C ({1:0.00} ˜°C/min), ", TargetT, (TargetT - StartT) / DurationMin); else s += String.Format("{0:0.0} °C, ", TargetT); if (currentStep.RampCtrlRH) s += String.Format("to {0:0.0} %rh ({1:0.00} ˜%rh/min), ", TargetRH, (TargetRH - StartRH) / DurationMin); else s += String.Format("{0:0.0} %rh, ", TargetRH); s += string.Format("{0:0}h{1:00}", currentStep.Hours, currentStep.Minutes); AddEventLog(s); s = string.Format("Partial profile end is {0:00}-{1:00} @ {2:00}:{3:00}:{4:00}", endOfCurrentProgram.Day, endOfCurrentProgram.Month, endOfCurrentProgram.Hour, endOfCurrentProgram.Minute, endOfCurrentProgram.Second); AddEventLog(s); } catch (Exception ex) { AddEventLog("Update events: " + ex.Message); } #endregion Update events } // Poll only every 'PollingIntervalSeconds' seconds if (DateTime.Now > lastPolled.AddSeconds(PollingIntervalSeconds)) { // Is finished? try { if (_Client.IsFinished()) { // Last step is held (page 61) when program ends. Client will never finish by itself. AddEventLog("Client finished, but task did not!"); _Status = TaskStatus.Interrupted; // Profile did not finish, client did continue; } } catch { } // Always continue and keep trying #region Taskprogress try { double taskRunTime = (DateTime.Now - _startThread).TotalMinutes; double pTest = Math.Min(100, Math.Floor(taskRunTime / _Profile.DurationMin * 100)); double taskTimeRemain = _Profile.DurationMin - taskRunTime; double taskTimeRemainHrs = Math.Floor(taskTimeRemain / 60); double taskTimeRemainMin = Math.Floor(taskTimeRemain - 60 * taskTimeRemainHrs); double currentStepRuntime = (DateTime.Now - startOfCurrentProgram).TotalMinutes; double pStep = Math.Min(100, Math.Floor(currentStepRuntime / currentStep.DurationMin * 100)); _TaskProgress = String.Format("Step #{0:0}/{1:0} progress {2:0}%, test progress {3:0}%, remaining test time {4:0}h{5:00}m", iCurrentSerialStep + 1,_SerSteps.Count, pStep, pTest, taskTimeRemainHrs, taskTimeRemainMin); if (iCurrentSerialStep + 1 == _SerSteps.Count && pTest > 99.99) _TaskProgress = "Profile executed"; } catch { _TaskProgress = "n/a"; } #endregion Taskprogress lastPolled = DateTime.Now; } System.Threading.Thread.Sleep(200); _isKicking = true; } if (_Status == TaskStatus.AbortRequested) { try { if (_Client.Stop()) _Status = TaskStatus.Aborted; } catch { } } _isKicking = false; } private void RestartClient(Double DurationMin, Double StartT, Double TargetT, Double StartRH, Double TargetRH) { // Stop client try { AddEventLog("Info: Stopping client"); if (!_Client.Stop()) { _Status = TaskStatus.Interrupted; AddEventLog("Task interrupted while trying to stop client!"); return; } } catch (Exception ex) { _Status = TaskStatus.ExceptionOccured; _TaskProgress = string.Format("Client Stop() exception: {0}", ex.Message); AddEventLog(_TaskProgress); return; } // Wait to finish try { Boolean timedOut = true; DateTime startWait = DateTime.Now; while (DateTime.Now < startWait.AddSeconds(60)) { System.Threading.Thread.Sleep(1000); if (_Client.IsFinished()) { timedOut = false; break; } } if (timedOut) { _Status = TaskStatus.Interrupted; AddEventLog("Time out (60 s) in RestartClient.WaitForFinish"); return; } } catch (Exception ex) { _Status = TaskStatus.ExceptionOccured; _TaskProgress = string.Format("Client WaitForFinish exception: {0}", ex.Message); AddEventLog(_TaskProgress); return; } AddEventLog("Info: Client stopped"); // Start client try { AddEventLog("Info: Starting client"); if (!((PLxKPH_Client)_Client).Start(DurationMin, StartT, TargetT, StartRH, TargetRH)) { // Try to start again after 10 sec AddEventLog("First attempt to start client failed!"); System.Threading.Thread.Sleep(10000); if (!((PLxKPH_Client)_Client).Start(DurationMin, StartT, TargetT, StartRH, TargetRH)) { _Status = TaskStatus.Interrupted; AddEventLog("Task interrupted while trying to start client!"); return; } } } catch (Exception ex) { _Status = TaskStatus.ExceptionOccured; _TaskProgress = string.Format("Client Start() exception: {0}", ex.Message); AddEventLog(_TaskProgress); return; } AddEventLog("Info: Client started"); } } }