using System; using System.Collections.Generic; using System.Linq; using System.Text; using ChamChat.Models; namespace ChamChat { public class LHL113_Task : Task { public LHL113_Task(Client Client, Profile Profile) : base(Client, Profile) { _Profile = Profile; _Client = Client; _SerSteps = _Profile.SerializedStepList; } private const Int32 PollingIntervalSeconds = 10; private List _SerSteps; // To do public override Boolean IsControlledProgrammable(Profile profile) { #warning LHL113_Task to implement: IsControlledProgrammable(Profile profile) return true; _NewProfileDuration = 0; _ProfileNumOfSerialSteps = 1; List profiles = new List(); int k = 0; while( k < _SerSteps.Count) { Profile p = GetProfile(k); profiles.Add(p); k += _ProfileNumOfSerialSteps; } // for (int i = 0; i < _SerSteps.Count; i++) //profiles.Add(GetProfile(i)); foreach (Profile p in profiles) if (!_Client.IsProgrammable(p)) return false; // In cases below, overheat/overcool alarm will sound immediately. // Limits can be set to 50 °C from temperature. for (int i = 1; i < _SerSteps.Count; i++) { Step step1 = _SerSteps[i - 1]; Step step2 = _SerSteps[i]; if (step1.T < 40 && step2.T < 40) if (step2.T > step1.T + 50) return false; if (step1.T > 40 && step2.T > 40) if (step2.T < step1.T - 50) return false; } return true; } 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 { _TaskProgress = _Client.Progress(); } catch { _TaskProgress = "Progress could not be retrieved from client."; } lastPolled = DateTime.Now; } System.Threading.Thread.Sleep(100); if (_Status == TaskStatus.AbortRequested) { try { if (_Client.Stop()) _Status = TaskStatus.Aborted; } catch { } } _isKicking = true; } _isKicking = false; } private Double _NewProfileDuration = 0; // Duration of new profile in minutes private int _ProfileNumOfSerialSteps = 1; // Number of steps from serial step list performed in new profile. 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; _NewProfileDuration = 0; _ProfileNumOfSerialSteps = 1; while (_Status == TaskStatus.IsRunning) { if (DateTime.Now > endOfCurrentProgram) { iCurrentSerialStep += _ProfileNumOfSerialSteps; // Last step has been performed? if (iCurrentSerialStep > _SerSteps.Count - 1) { _Client.Stop(); _Status = TaskStatus.Finished; AddEventLog("Last step performed"); continue; } currentStep = _SerSteps[iCurrentSerialStep]; Profile newProfile = GetProfile(iCurrentSerialStep); if (_ProfileNumOfSerialSteps > 1) { if(newProfile.Loops.Count == 1 ) AddEventLog("Program : " + string.Format("{0:0} serial steps, loop {1}", _ProfileNumOfSerialSteps, newProfile.Loops[0].ToString())); else AddEventLog("Program : " + string.Format("{0:0} serial steps, no loops", _ProfileNumOfSerialSteps)); } else AddEventLog("Single step : " + currentStep.ToString()); RestartClient(newProfile); if (_Status != TaskStatus.IsRunning) continue; // Update variables startOfCurrentProgram = DateTime.Now; endOfCurrentProgram = DateTime.Now.AddMinutes(_NewProfileDuration); lastPolled = DateTime.Now; } // Poll only every 'PollingIntervalSeconds' seconds if (DateTime.Now > lastPolled.AddSeconds(PollingIntervalSeconds)) { // Is finished? try { if (_Client.IsFinished()) { _Status = TaskStatus.Interrupted; // Profile did not finish, client did continue; } } catch { } try { double taskRunTime = (DateTime.Now - _startThread).TotalMinutes; double pTest = Math.Min(100, Math.Floor(taskRunTime / _Profile.DurationMin * 100)); double stepRuntime = (DateTime.Now - startOfCurrentProgram).TotalMinutes; double pStep = Math.Min(100,Math.Floor(stepRuntime / _NewProfileDuration * 100)); double taskTimeRemain = _Profile.DurationMin - taskRunTime; double taskTimeRemainHrs = Math.Floor(taskTimeRemain / 60); double taskTimeRemainMin = Math.Floor(taskTimeRemain - 60 * taskTimeRemainHrs); _TaskProgress = String.Format("Step #{0:00}/{1:00} progress {2:0}%, test progress {3:0}%, remaining test time {4:0}h{5:00}m", iCurrentSerialStep + 1, _Profile.SerializedStepList.Count, pStep, pTest, taskTimeRemainHrs, taskTimeRemainMin); } catch { _TaskProgress = "Progress could not be calculated."; } lastPolled = DateTime.Now; } System.Threading.Thread.Sleep(200); if (_Status == TaskStatus.AbortRequested) { try { if (_Client.Stop()) _Status = TaskStatus.Aborted; } catch { } } _isKicking = true; } _isKicking = false; } private void RestartClient(Profile newProfile) { // Stop client try { if (!_Client.Stop()) { _Status = TaskStatus.Interrupted; return; } } catch (Exception ex) { _Status = TaskStatus.ExceptionOccured; _TaskProgress = string.Format("Client Stop() exception: {0}", ex.Message); AddEventLog(_TaskProgress); return; } System.Threading.Thread.Sleep(1000); // 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; } // Write profile try { if (!_Client.WriteProfile(newProfile)) { _Status = TaskStatus.Interrupted; return; } } catch (Exception ex) { _Status = TaskStatus.ExceptionOccured; _TaskProgress = string.Format("Client WriteProfile() exception: {0}", ex.Message); AddEventLog(_TaskProgress); return; } // Start client try { //AddEventLog("RestartClient.Start"); if (!_Client.Start()) { _Status = TaskStatus.Interrupted; return; } } catch (Exception ex) { _Status = TaskStatus.ExceptionOccured; _TaskProgress = string.Format("Client Start() exception: {0}", ex.Message); AddEventLog(_TaskProgress); return; } } private Profile GetProfile(int iStep) { Step step = _SerSteps[iStep].DeepClone(); // Duration of programmed step is 15 minutes longer than profile step.DurationMin += 15; _NewProfileDuration = _SerSteps[iStep].DurationMin; _ProfileNumOfSerialSteps = 1; List steps = new List(); steps.Add(step); // Loops List loops = new List(); // Options List options = new List(); options.Add(ProfileOption.LHL113_EndModeOff); // Shut down client for safety // Create profile return new Profile(_Profile.Title, steps, loops, options); } } }