otsdaq_utilities  v2_02_00
SmartLaunch.js
1 
2 
3 
4  // Description of Smart Launch Functionality/Behavior:
5  //
6  // Checkboxes on left to select detector systems to include
7  // Giant button on right to launch
8  //
9  // Launch means:
10  // - enable associated contexts
11  // - save new context group, activate (do not alias)
12  // - save user active sessions
13  // - relaunch otsdaq normal mode
14  // - load active sessions
15  // - detect in GUI that system is back alive
16 
17 //User note:
18 // Users can define special launch context groupings by defining
19 // global variables: SmartLaunch.subsystems and SmartLaunch.systemToContextMap.
20 // This is demonstrated in otsdaq_demo/UserWebGUI/html/SmartLaunch.html
21 //
22 // In short, subsystems make up your configuration, and subsystems consist
23 // of one or many context records.
24 
25 
26 //Smart Launch desktop icon from:
27 // http://icons.iconarchive.com/icons/bokehlicia/captiva/256/rocket-icon.png
28 
29 
30 var SmartLaunch = SmartLaunch || {}; //define SmartLaunch namespace
31 
32 if (typeof Debug == 'undefined')
33  throw('ERROR: Debug is undefined! Must include Debug.js before SmartLaunch.js');
34 else if (typeof Globals == 'undefined')
35  throw('ERROR: Globals is undefined! Must include Globals.js before SmartLaunch.js');
36 
37 SmartLaunch.MENU_PRIMARY_COLOR = "rgb(220, 187, 165)";
38 SmartLaunch.MENU_SECONDARY_COLOR = "rgb(130, 51, 51)";
39 
40 
41 SmartLaunch.launcher; //this is THE SmartLaunch variable
42 SmartLaunch.doShowContexts = false; //default value for showing contexts or not
43 SmartLaunch.subsystems = [];
44 // _NAME_STRIPS,
45 // _NAME_MWPC,
46 // _NAME_NIMPLUS
47 // ];
48 SmartLaunch.systemToContextMap = {};
49 // SmartLaunch.systemToContextMap[_NAME_STRIPS] = [
50 // "StripTelescopeContext"
51 // ];
52 // SmartLaunch.systemToContextMap[_NAME_MWPC] = [
53 // "WireChamberContext",
54 // "ARTDAQBoardReader0",
55 // "ARTDAQEventBuilder0",
56 // "ARTDAQEventBuilder1",
57 // "ARTDAQAggregator0"
58 // ];
59 // SmartLaunch.systemToContextMap[_NAME_NIMPLUS] = [
60 // "NimPlusContext"
61 // ];
62 
65 //call create to create instance of a SmartLaunch
68 SmartLaunch.create = function() {
69 
70 
71  //functions:
72  //
73  // init()
74  // createElements()
75  // redrawWindow()
76  // readEnabledSubsystems()
77  // getCurrentState()
78  // - localGetStateHandler()
79  // displayState()
80  //
81  // this.launch()
82  // - localLaunch()
83  // - localSetSequenceOfRecords()
84  // this.gatewayLaunchOts()
85  // - localDelayedLaunch()
86  // -- localCountDown()
87  // this.run()
88  // - localStop()
89  // - localRun()
90  //
91  // this.toggleCheckboxDiv(i)
92  // this.handleCheckbox(c)
93 
94 
95 
96 
97  //for display
98  var _CHECKBOX_H = 40;
99  var _CHECKBOX_MIN_W = 240;
100  var _CHECKBOX_MAX_W = 540;
101  var _LAUNCH_MIN_W = 525;
102  var _MARGIN = 40;
103 
104 
105  var _needEventListeners = true;
106 
107  var _subsetBasePath = "XDAQContextConfiguration";
108 
109  var _systemStatusArray = [];
110  var _contextRecords = [];
111 
112 
113 
114  //for run state
115  var _state = "";
116  var _inTransition = false;
117  var _wasInTransition = false;
118  var _timeInState = 0;
119  var _transitionPercentComplete = 0;
120  var _runNumber;
121  var _transitionName = "";
122 
123  var _fsmName, _fsmWindowName;
124  var _getStateTimer = 0;
125  var _runFSMTimer = 0;
126 
127  var _running = false;
128  var _runStatusDiv;
129 
132  // end variable declaration
133  SmartLaunch.launcher = this;
134  Debug.log("SmartLaunch.launcher constructed");
135 
136  init();
137  Debug.log("SmartLaunch.launcher initialized");
138 
139 
140  //=====================================================================================
141  //init ~~
142  function init()
143  {
144  Debug.log("Smart Launch init ");
145  DesktopContent.tooltip("Smart Launch",
146  "Welcome to the Smart Launch user interface. "+
147  "Select which pieces of the configuration you want to enable, and then press the launch button!" +
148  "\n\n" +
149  "Once the pieces you want are enabled, press the run button!"
150  );
151 
152  //get all existing contexts
153  ConfigurationAPI.getSubsetRecords(
154  _subsetBasePath,
155  "",//filterList,
156  localGetContextRecordsHandler
157  );
158 
159  //get run state always
160  window.clearTimeout(_getStateTimer);
161  _getStateTimer = window.setTimeout(getCurrentState,1000); //in 1 sec
162 
163  return;
164 
166  function localGetContextRecordsHandler(records)
167  {
168  //extract context records
169  console.log(records);
170  _contextRecords = records;
171 
172  //proceed with rest of init
173  createElements();
174 
175  if(_needEventListeners)
176  {
177  window.addEventListener("resize",redrawWindow);
178  _needEventListeners = false;
179  }
180 
181  //redrawWindow();
182  readEnabledSubsystems();
183  }
184 
185 
186  } //end init()
187 
188  //=====================================================================================
189  //createElements ~~
190  // called initially to create checkbox and button elements
191  function createElements()
192  {
193  Debug.log("createElements");
194 
195 
196  // <!-- body content populated by javascript -->
197  // <div id='content'>
198  // <div id='refreshLink'><a onclick='init()'>Refresh</a></div>
199  //
200  // <div id='subsystemDiv'><div id='subsystemDivContainer'></div></div>
201  //
202  // <a id='launchLink' onclick='SmartLaunch.launcher.launch()'>
203  // <div id='launchDiv'>Launch</div>
204  // </a>
205  //
206  // <a id='runLink' onclick='SmartLaunch.launcher.run()'>
207  // <div id='runDiv'>Run</div>
208  // </a>
209  //
210  // <div id='runStatusDiv' style='top:10px;/*default to 10px for case when someone else has lock*/'></div>
211  //
212  // </div>
213 
214  var cel,el,al,sl;
215 
216  cel = document.getElementById("content");
217  if(!cel)
218  {
219  cel = document.createElement("div");
220  cel.setAttribute("id","content");
221  }
222 
223  //clear all elements
224  cel.innerHTML = "";
225 
226 
227  { //content div
228 
229 
230  //subsystem div
231  sl = document.createElement("div");
232  sl.setAttribute("id","subsystemDiv");
233  el = document.createElement("div");
234  el.setAttribute("id","subsystemDivContainer");
235  sl.appendChild(el);
236  cel.appendChild(sl);
237 
238 
239 
240  //launch link
241  al = document.createElement("a");
242  al.setAttribute("id","launchLink");
243  al.onclick = function()
244  {
245  Debug.log("clicked launch");
246  SmartLaunch.launcher.launch();
247  };
248 
249  el = document.createElement("div");
250  el.setAttribute("id","launchDiv");
251  el.innerHTML = "Launch";
252  al.appendChild(el);
253  cel.appendChild(al);
254 
255  //run link
256  al = document.createElement("a");
257  al.setAttribute("id","runLink");
258  al.onclick = function()
259  {
260  Debug.log("clicked run");
261  SmartLaunch.launcher.run();
262  };
263 
264  el = document.createElement("div");
265  el.setAttribute("id","runDiv");
266  el.innerHTML = "Run";
267  al.appendChild(el);
268  cel.appendChild(al);
269 
270  //run status
271  sl = document.createElement("div");
272  sl.setAttribute("id","runStatusDiv");
273  sl.style.top = "10px"; //default to 10px for case when someone else has lock
274  cel.appendChild(sl);
275 
276  }
277 
278 
279 
280 
281 
282 
283  document.body.appendChild(cel);
284 
285 
286  } //end createElements()
287 
288  //=====================================================================================
289  //readEnabledSubsystems ~~
290  // call redrawWindow when complete
291  function readEnabledSubsystems()
292  {
293  try
294  {
295  Debug.log("readEnabledSubsystems");
296 
297  var recordsArray = [];
298 
299  for(var i=0; i<SmartLaunch.subsystems.length; ++i)
300  {
301  for(var j=0; j<SmartLaunch.systemToContextMap[SmartLaunch.subsystems[i]].length; ++j)
302  recordsArray.push(SmartLaunch.systemToContextMap[SmartLaunch.subsystems[i]][j]);
303  }
304  if(SmartLaunch.doShowContexts)
305  for(var i=0; i<_contextRecords.length; ++i)
306  recordsArray.push(_contextRecords[i]);
307 
308  console.log("recordsArray",recordsArray);
309 
310  ConfigurationAPI.getFieldValuesForRecords(
311  _subsetBasePath,
312  recordsArray,
313  ["Status"],
314  localStatusForRecordsHandler
315  );
316  return;
317  }
318  catch(e)
319  {
320  Debug.log("There was error reading the status of the configuration subsystems (" +
321  "were the subsystem variables setup properly?): " +
322  e, Debug.HIGH_PRIORITY);
323  return;
324  }
325 
327  function localStatusForRecordsHandler(recFieldValues)
328  {
329  Debug.log("localStatusForRecordsHandler value-length=" + recFieldValues.length)
330  var statusArray = []; //clear
331  for(var i in recFieldValues)
332  statusArray.push(
333  recFieldValues[i].fieldValue == "On"?true:false);//recFieldValues[i].fieldUID .. recFieldValues[i].fieldPath + ": " +
334 
335  console.log("statusArray",statusArray);
336 
337  _systemStatusArray = []; //clear
338  var k=0;
339  for(var i=0; i<SmartLaunch.subsystems.length; ++i)
340  {
341  _systemStatusArray.push(true);
342  for(var j=0; j<SmartLaunch.systemToContextMap[SmartLaunch.subsystems[i]].length; ++j,++k)
343  if(!statusArray[k]) //found one off exception
344  _systemStatusArray[i] = false; //so consider entire subsystem off
345  }
346  if(SmartLaunch.doShowContexts)
347  for(var i=0; i<_contextRecords.length; ++i, ++k)
348  _systemStatusArray.push(statusArray[k]);
349 
350  console.log("_systemStatusArray",_systemStatusArray);
351 
352  redrawWindow();
353 
354  } //end localStatusForRecordsHandler()
355 
356 
357  } //end readEnabledSubsystems()
358 
359 
360  //=====================================================================================
361  //redrawWindow ~~
362  // called when page is resized
363  function redrawWindow()
364  {
365  //adjust link divs to proper size
366  // use ratio of new-size/original-size to determine proper size
367 
368  var w = window.innerWidth | 0;
369  var h = window.innerHeight | 0;
370 
371  if(w < _LAUNCH_MIN_W)
372  w = _LAUNCH_MIN_W;
373  if(h < _LAUNCH_MIN_W)
374  h = _LAUNCH_MIN_W;
375 
376  Debug.log("redrawWindow to " + w + " - " + h);
377 
378  var sdiv = document.getElementById("subsystemDiv");
379  var ldiv = document.getElementById("launchDiv");
380  var rdiv = document.getElementById("runDiv");
381  _runStatusDiv = runStatusDiv = document.getElementById("runStatusDiv");
382 
383  var chkH = _CHECKBOX_H;
384  var chkW = (w/3)|0;
385  if(chkW < _CHECKBOX_MIN_W) chkW = _CHECKBOX_MIN_W;
386  if(chkW > _CHECKBOX_MAX_W) chkW = _CHECKBOX_MAX_W;
387 
388  var sdivH = 66 + chkH*SmartLaunch.subsystems.length; //header + chkboxes
389 
390  if(SmartLaunch.doShowContexts)
391  {
392  sdivH += 66 + chkH*_contextRecords.length; //header + chkboxes
393  }
394  if(sdivH > 2/3*h)
395  sdivH = 2/3*h; //clip height
396  if(sdivH < 100)
397  sdivH = 100; //clip min
398 
399  var sdivW = chkW;
400 
401  var sdivX = _MARGIN;
402  var sdivY = (h-sdivH)/2;
403  if(sdivY < _MARGIN)
404  sdivY = _MARGIN;
405 
406 // var ldivX = _MARGIN + chkW;
407 // var ldivSz = h;
408 // if(ldivSz > w - ldivX - _MARGIN*3) //pick min of w/h
409 // ldivSz = w - ldivX - _MARGIN*3;
410 // if(ldivSz < 120) //clip min
411 // ldivSz = 120;
412 // var ldivY = (h-ldivSz)/2;
413 //
414 // var rdivX = _MARGIN + chkW;
415 // var rdivSz = ldivSz;
416 // var rdivY = ldivY + ldivSz;
417 // var rratio = 180/300;
418 
419  var ldivX = _MARGIN + chkW;
420  var ldivSz = h/2;
421  if(ldivSz > w - ldivX - _MARGIN*3) //pick min of w/h
422  ldivSz = w - ldivX - _MARGIN*3;
423  ldivSz *= 0.9;
424  var ldivY = (h-ldivSz)/2 - ldivSz/2;
425  var lratio = 180/300;
426 
427  var rdivX = _MARGIN + chkW;
428  var rdivSz = ldivSz;
429  var rdivY = ldivY + ldivSz;
430  var rratio = 180/300;
431 
432 
433  //draw checkboxes
434  {
435  var str = "";
436  var statusIndex = 0;
437 
438  var hideableSubsystems = SmartLaunch.subsystems.length && SmartLaunch.doShowContexts;
439  var hideableContexts = SmartLaunch.subsystems.length;
440 
441  if(SmartLaunch.subsystems.length)
442  {
443  if(hideableSubsystems)
444  str += "<a onclick='SmartLaunch.launcher.toggleCheckboxDiv(0);' title='Hide/Show Subsystems'>";
445  str += "<h3>Subsystems</h3>";
446  if(hideableSubsystems)
447  str += "</a>";
448 
449  str += "<div id='ssCheckboxDiv'>";
450  for(var i=0;i<SmartLaunch.subsystems.length;++i,++statusIndex)
451  {
452  str += "<div class='ssCheckbox' style='height:" + chkH + "px;" +
453  "' >";
454  str += "<div class='pretty p-icon p-round p-smooth' onclick='SmartLaunch.launcher.handleCheckbox(" +
455  statusIndex + ");' >"; //p-smooth for slow transition
456  str += " <input type='checkbox' class='subsystemCheckboxes' " +
457  (_systemStatusArray[statusIndex]?"checked":"") +
458  "/>";
459  str += "<div class='state p-success'>";
460  str += "<i class='icon mdi mdi-check'></i>";
461  str += "<label>" + SmartLaunch.subsystems[i] + "</label>";
462  str += "</div>";
463  str += "</div>";
464  str += "</div>";
465  str += "<div id='clearDiv'></div>";
466  }
467  str += "</div>";
468  }
469  else if(!SmartLaunch.doShowContexts)
470  {
471  str += "No subsystem configuration definition found.";
472  }
473 
474 
475  if(SmartLaunch.doShowContexts)
476  {
477  if(hideableContexts)
478  str += "<a onclick='SmartLaunch.launcher.toggleCheckboxDiv(1);' title='Hide/Show Contexts'>";
479  str += "<h3>Individual Contexts</h3>";
480  if(hideableContexts)
481  str += "</a>";
482 
483  if(!_contextRecords.length)
484  str += "No contexts found.";
485 
486 
487  str += "<div id='ctxCheckboxDiv'>";
488  for(var i=0; i<_contextRecords.length; ++i,++statusIndex)
489  {
490  str += "<div class='ssCheckbox' style='height:" + chkH + "px;" +
491  "' >";
492  str += "<div class='pretty p-icon p-round p-smooth' onclick='SmartLaunch.launcher.handleCheckbox(" +
493  statusIndex + ");' >"; //p-smooth for slow transition
494  str += " <input type='checkbox' class='subsystemCheckboxes' " +
495  (_systemStatusArray[statusIndex]?"checked":"") +
496  "/>";
497  str += "<div class='state p-success'>";
498  str += "<i class='icon mdi mdi-check'></i>";
499  str += "<label>" + _contextRecords[i] + "</label>";
500  str += "</div>";
501  str += "</div>";
502  str += "</div>";
503  str += "<div id='clearDiv'></div>";
504  }
505  str += "</div>"
506  }
507 
508 
509  sdiv.style.left = (sdivX-20) + "px";
510  sdiv.style.top = sdivY + "px";
511  sdiv.style.height = sdivH + "px";
512  sdiv.style.width = sdivW + "px";
513  sdiv.style.display = "block";
514 
515 
516  sdiv = document.getElementById("subsystemDivContainer");
517  sdiv.style.left = (sdivX-20) + "px";
518  sdiv.style.top = sdivY + "px";
519  sdiv.style.height = sdivH + "px";
520  sdiv.style.width = sdivW + "px";
521  sdiv.innerHTML = "";
522  sdiv.innerHTML = str;
523  sdiv.style.display = "block";
524  }
525 
526  //draw launch button
527  {
528 
529 // ldiv.style.left = (ldivX + (w - ldivX - _MARGIN*2 - ldivSz)/2) + "px";
530 // ldiv.style.top = (ldivY+((ldivSz-ldivSz*200/300)/2)) + "px";
531 //
532 // ldiv.style.width = ldivSz + "px";
533 // var fontSize = ldivSz/10;
534 // if(fontSize < 30) fontSize = 30;
535 // ldiv.style.fontSize = (fontSize) + "px";
536 // ldiv.style.paddingTop = (ldivSz*200/300/2 - (fontSize+6)/2) + "px"; //ratio of size minus font size
537 // ldiv.style.paddingBottom = (ldivSz*200/300/2- (fontSize+6)/2) + "px";
538 // ldiv.style.borderRadius = (ldivSz*300/100) + "px/" + (ldivSz*200/100) + "px";
539 //
540 // ldiv.style.display = "block";
541  ldiv.style.left = (ldivX + (w - ldivX - _MARGIN*2 - ldivSz)/2) + "px";
542  ldiv.style.top = (ldivY+((ldivSz-ldivSz*lratio)/2)) + "px";
543  //ldiv.style.height = (ldivSz*200/300) + "px";
544  ldiv.style.width = ldivSz + "px";
545  ldiv.style.paddingTop = (ldivSz*lratio/2 - 36/2) + "px"; //ratio of size minus font size
546  ldiv.style.paddingBottom = (ldivSz*lratio/2- 36/2) + "px";
547  //ldiv.style.paddingLeft = (ldivSz/2) + "px";
548  //ldiv.style.paddingRight = (ldivSz/2) + "px";
549 
550  ldiv.style.borderRadius = ldivSz + "px/" + (ldivSz*200/300) + "px";
551  ldiv.style.fontSize = ldivSz/10 + "px";
552 
553  ldiv.style.display = "block";
554  }
555 
556 
557  //draw run button
558  {
559 
560  rdiv.style.left = (rdivX + (w - rdivX - _MARGIN*2 - rdivSz)/2) + "px";
561  rdiv.style.top = (rdivY+((rdivSz-rdivSz*rratio)/2)) + "px";
562  //rdiv.style.height = (rdivSz*200/300) + "px";
563  rdiv.style.width = rdivSz + "px";
564  rdiv.style.paddingTop = (rdivSz*rratio/2 - 36/2) + "px"; //ratio of size minus font size
565  rdiv.style.paddingBottom = (rdivSz*rratio/2- 36/2) + "px";
566  //rdiv.style.paddingLeft = (rdivSz/2) + "px";
567  //rdiv.style.paddingRight = (rdivSz/2) + "px";
568 
569  rdiv.style.borderRadius = rdivSz + "px/" + (rdivSz*200/300) + "px";
570  rdiv.style.fontSize = rdivSz/10 + "px";
571 
572  rdiv.style.display = "block";
573  //ldiv.innerHTML = str;
574 
575  runStatusDiv.style.left = (rdivX + _MARGIN + (w - rdivX - _MARGIN*2 - rdivSz)/2) + "px";
576  runStatusDiv.style.top = (h/2 - 50) + "px";
577  runStatusDiv.style.width = (rdivSz + _MARGIN) + "px";
578  runStatusDiv.style.fontSize = rdivSz/15 + "px";
579  }
580 
581  } //end redrawWindow()
582 
583 
584  //=====================================================================================
585  //getCurrentState ~~
586  function getCurrentState()
587  {
588  window.clearTimeout(_getStateTimer);
589 
590  DesktopContent.XMLHttpRequest("Request?RequestType=getCurrentState" +
591  "&fsmName=" + _fsmName,
592  "",
593  localGetStateHandler,
594  0, //handler param
595  0,0,false, //progressHandler, callHandlerOnErr, showLoadingOverlay
596  true /*targetSupervisor*/, true /*ignoreSystemBlock*/);
597 
598  //===========
599  function localGetStateHandler(req,id,err)
600  {
601  if(!req) //error! stop handler
602  {
603  Debug.log("Error: " + err, Debug.HIGH_PRIORITY);
604  return;
605  }
606 
607 
608  _state = DesktopContent.getXMLValue(req,"current_state");
609  _inTransition = DesktopContent.getXMLValue(req,"in_transition") == "1";
610  _timeInState = DesktopContent.getXMLValue(req,"time_in_state") | 0;
611  _runNumber = DesktopContent.getXMLValue(req,"run_number");
612  _transitionPercentComplete = DesktopContent.getXMLValue(req,"transition_progress") | 0;
613 
614  if(_transitionPercentComplete > 100)
615  {
616  //Debug.log("???" + _transitionPercentComplete);
617  _transitionPercentComplete = 100;
618  }
619 
620 
621  //Debug.log("localGetStateHandler: " + _state + " -- " + _inTransition +
622  // " -- t" + _timeInState + " " + _transitionPercentComplete + "%");
623 
624 
625 
626  displayState();
627 
628 
629  //on success, get state again
630  window.clearTimeout(_getStateTimer);
631  _getStateTimer = window.setTimeout(getCurrentState,1000); //in 1 sec
632  }
633  } //getCurrentState
634 
635 
636  //=====================================================================================
637  //displayState ~~
638  function displayState()
639  {
640  //Debug.log("displayState");
641 
642  //update display
643 
644  //indicate running if detected
645  if(_state == "Running")
646  {
647  if(!_running)
648  {
649  _running = true;
650  document.getElementById("runDiv").innerHTML = "Stop";
651  }
652  }
653  else //not running
654  {
655  if(_running)
656  {
657  _running = false;
658  document.getElementById("runDiv").innerHTML = "Run";
659  }
660  }
661 
662 
663  let str = "";
664  str += "<table cellspacing='0' cellpadding='0'>";
665 
666  //current state display
667  if(_inTransition)
668  str += "<tr><td style='font-weight: bold; padding-right:20px;'>Transition:</td><td>" +
669  _transitionName + "</td></tr>";
670  else
671  str += "<tr><td style='font-weight: bold; padding-right:20px;'>Current State:</td><td>" +
672  _state + "</td></tr>";
673 
674 
675 
676  //current run number display
677  if(//_state == "Running" &&
678  _runNumber)
679  {
680  //extract run number components
681  let i = _runNumber.lastIndexOf(' ');
682  if(i >= 0)
683  {
684  let hdr = _runNumber.substr(0,i);
685  let num = _runNumber.substr(i+1);
686  stateStr = "Running <br>&nbsp;&nbsp;&nbsp;&nbsp;" + _runNumber;
687  str += "<tr><td style='font-weight: bold; padding-right:20px;'>" +
688  hdr + "</td><td>" +
689  num + "</td></tr>";
690  }
691  }
692 
693 
694 
695  //transitioning display
696  let progressStr = "";
697  if(_inTransition)
698  {
699  progressStr = _transitionPercentComplete + " %";
700 
701  str += "<tr><td style='font-weight: bold; padding-right:20px;'>Progress:</td><td>" +
702  progressStr + "</td></tr>";
703 
704  if(!_wasInTransition)
705  _wasInTransition = true;
706  }
707  else if(_wasInTransition)
708  {
709  //show 100% once to show some display
710  _wasInTransition = false;
711  progressStr = 100 + " %";
712 
713  str += "<tr><td style='font-weight: bold; padding-right:20px;'>Transitioning:</td><td>" +
714  progressStr + "</td></tr>";
715  }
716  else
717  {
718  //time in state display
719  let tstr = "";
720  var hours = (_timeInState/60.0/60.0)|0;
721  var mins = ((_timeInState%(60*60))/60.0)|0;
722  var secs = _timeInState%60;
723 
724  tstr += hours + ":";
725  if(mins < 10) tstr += "0"; //keep to 2 digits
726  tstr += mins + ":";
727  if(secs < 10) tstr += "0"; //keep to 2 digits
728  tstr += secs ;
729 
730  str += "<tr><td style='font-weight: bold; padding-right:20px;'>Time-in-State:</td><td>" + tstr + "</td></tr>";
731  }
732 
733  try //in case no display
734  {
735  _runStatusDiv.innerHTML = str;
736 
737  _runStatusDiv.style.display = "block";
738  }
739  catch(e) {console.log(e);}
740  } //end displayState()
741 
742  //=====================================================================================
743  //launch ~~
744  this.launch = function()
745  {
746  Debug.log("launch");
747  DesktopContent.popUpVerification(
748  "Are you sure you want to relaunch otsdaq?",
749  localLaunch,
750  0,"#efeaea",0,"#770000");
751 
752  //============
753  function localLaunch()
754  {
755  Debug.log("localLaunch");
756 
757  var checkboxes = document.getElementsByClassName('subsystemCheckboxes');
758  console.log("checkboxes",checkboxes);
759  var checkedArray = [];
760  for(var i=0;i<checkboxes.length;++i)
761  checkedArray.push(checkboxes[i].checked);
762  console.log("checkedArray",checkedArray);
763 
764  var recordsArray = [];
765  var valuesArray = [];
766 
767  //assemble records array
768 
769  if(SmartLaunch.doShowContexts)
770  {
771  //just use context checkbox settings
772  for(var i=0; i<_contextRecords.length; ++i)
773  {
774  recordsArray.push(_contextRecords[i]);
775  valuesArray.push(checkedArray[SmartLaunch.subsystems.length+i]?
776  "1":"0");
777  }
778  }
779  else
780  {
781  //extract context settings from system to context map
782  for(var i=0; i<SmartLaunch.subsystems.length; ++i)
783  {
784  for(var j=0; j<SmartLaunch.systemToContextMap[SmartLaunch.subsystems[i]].length; ++j)
785  {
786  recordsArray.push(SmartLaunch.systemToContextMap[SmartLaunch.subsystems[i]][j]);
787  valuesArray.push(checkedArray[i]?"1":"0");
788 
789  }
790  }
791  }
792  console.log("recordsArray",recordsArray);
793  console.log("valuesArray",valuesArray);
794 
795  var recordIndex = 0;
796  var localModifiedTables = undefined;
797  //sequentially send request for each record until done
798  localSetSequenceOfRecords();
799 
800  //===========================
801  function localSetSequenceOfRecords()
802  {
803  ConfigurationAPI.setFieldValuesForRecords(
804  _subsetBasePath,
805  recordsArray[recordIndex],
806  "Status", //fieldArr
807  valuesArray[recordIndex], //valueArr
808  function(modifiedTables)
809  {
810  Debug.log("recordIndex = " + recordIndex);
811 
812  if(modifiedTables.length == 0)
813  {
814  Debug.log("Something went very wrong. Notify administrators.",
815  Debug.HIGH_PRIORITY);
816  return;
817  }
818 
819  ++recordIndex;
820  if(recordIndex == recordsArray.length)
821  {
822  Debug.log("Done with sequence.");
823 
824  //proceed to save (quietly) tables, groups, aliases
825  ConfigurationAPI.saveModifiedTables(modifiedTables,
827  function(savedTables, savedGroups, savedAliases)
828  {
829  if(!savedTables.length)
830  {
831  Debug.log("Something went very wrong. Notify administrators.",
832  Debug.HIGH_PRIORITY);
833  return;
834  }
835 
836  Debug.log("Successfully applied subsystem selections!", Debug.INFO_PRIORITY);
837 
838 
839  //relaunch
840  Debug.log("Relaunching ots...");
841  SmartLaunch.launcher.gatewayLaunchOts();
842 
843 
844  }); //end saveModifiedTables handler
845  return;
846  }
847 
848  console.log("setFieldValuesForRecords modifiedTables",modifiedTables);
849  localModifiedTables = modifiedTables;
850  localSetSequenceOfRecords();
851 
852  } //end setFieldValuesForRecords handler
853  ,localModifiedTables);
854  } //end localSetSequenceOfRecords()
855  }
856  } // end launch()
857 
858  //=====================================================================================
859  //gatewayLaunchOts ~~
860  this.gatewayLaunchOts = function()
861  {
862  Debug.log("Relaunching otsdaq!",Debug.INFO_PRIORITY);
863 
864  //block checks
865  window.clearTimeout(_getStateTimer);
866 
867  //start blackout
868  DesktopContent._blockSystemCheckMailbox.innerHTML = "1";
869  window.setTimeout(localDelayedLaunch,1000); //gaurantee blackout starts
870  //now in all future requests must ignoreSystemBlock
871 
872  //===========
873  function localDelayedLaunch()
874  {
875  DesktopContent.XMLHttpRequest("Request?" +
876  "RequestType=gatewayLaunchOTS", //end get data
877  "", //end post data
878  function(req) //start handler
879  {
880  Debug.log("gatewayLaunchOts handler ");
881 
882 
883  var countDown = 10;
884  localCountDown();
885  //=================
886  function localCountDown()
887  {
888  Debug.log("Waiting " + countDown + " seconds for startup sequence...",
889  Debug.INFO_PRIORITY);
890 
891  window.setTimeout(function() {
892  Debug.log("localCountDown handler ");
893  --countDown;
894  if(countDown == 0)
895  {
896  //end blackout
897  DesktopContent._blockSystemCheckMailbox.innerHTML = "";
898  init();
899  Debug.log("And we are back!",Debug.INFO_PRIORITY);
900  return;
901  }
902  localCountDown();
903  }, //end blackout-end handler
904  1000/*ms*/);
905  }// end localCountDown
906 
907  }, //end gatewayLaunchOTS req handler
908  0, //handler param
909  0,0,true, //progressHandler, callHandlerOnErr, showLoadingOverlay
910  true /*targetSupervisor*/, true /*ignoreSystemBlock*/);
911  } // end localDelayedLaunch()
912 
913  } //end gatewayLaunchOts()
914 
915 
916  //=====================================================================================
917  //run ~~
918  this.run = function()
919  {
920  Debug.log("run");
921 
922  var timeoutCount = 0; //used to detect taking too long
923  var operativeWord = "starting";
924  var lastState = "";
925 
926  if(_running)
927  {
928  DesktopContent.popUpVerification(
929  "Are you sure you want to stop the run?",
930  localStop,
931  0,"#efeaea",0,"#770000");
932 
933  //===========
934  function localStop()
935  {
936  Debug.log("localStop");
937  //just change operative word and run (to stop)
938  operativeWord = "stopping";
939  localRun();
940  }
941  return;
942  }
943 
944  DesktopContent.popUpVerification(
945  "Are you sure you want to start a run?",
946  localRun,
947  0,"#efeaea",0,"#770000");
948 
949  //===========
950  function localRun()
951  {
952  Debug.log("localRun");
953 
954  window.clearTimeout(_runFSMTimer);
955 
956  ++timeoutCount;
957  if(timeoutCount > 60) //if it has been one minute, too long
958  {
959  Debug.log("Timeout reached! Giving up on " + operativeWord + " the run.", Debug.HIGH_PRIORITY);
960  return;
961  }
962 
963  if(_inTransition) //wait
964  {
965  window.clearTimeout(_getStateTimer);
966  _getStateTimer = window.setTimeout(getCurrentState,1000); //in 1 sec
967 
968  window.clearTimeout(_runFSMTimer);
969  _runFSMTimer = window.setTimeout(localRun,1000); //wait a sec
970  return;
971  }
972 
973  if(lastState == _state)
974  {
975  Debug.log("State machine is not progressing! Stuck in '" +
976  _state + ".' Giving up on " + operativeWord + " the run.", Debug.HIGH_PRIORITY);
977  return;
978  }
979 
980  lastState = _state;
981 
982  let transitionPostData = "";
983  //keep transitioning to Run state
984  if(_state == "Initial")
985  {
986  _transitionName = "Initialize";
987  }
988  else if(_state == "Failed")
989  {
990  if(timeoutCount > 1)
991  {
992  //if localRun activity caused failure, give up
993  Debug.log("Fault encountered! Giving up on " + operativeWord + " the run.", Debug.HIGH_PRIORITY);
994  return;
995  }
996  _transitionName = "Halt";
997  }
998  else if(_state == "Halted")
999  {
1000  _transitionName = "Configure";
1001  //FIXME -- could get system alias from somewhere (e.g. first alias in list, or icon parameter)
1002  transitionPostData = "ConfigurationAlias=" + "defaultSystemAlias";
1003  }
1004  else if(_state == "Configured")
1005  {
1006  if(operativeWord == "stopping")
1007  {
1008  //done!
1009  Debug.log("<i>otsdaq</i> has now Stopped! " +
1010  _runNumber + ".", Debug.INFO_PRIORITY);
1011  return;
1012  }
1013 
1014  _transitionName = "Start";
1015  }
1016  else if(_state == "Paused")
1017  {
1018  _transitionName = "Start";
1019  }
1020  else if(_state == "Running")
1021  {
1022  if(operativeWord == "stopping")
1023  {
1024  _transitionName = "Stop";
1025  }
1026  else //starting
1027  {
1028  //done!
1029  Debug.log("<i>otsdaq</i> is now Running! " +
1030  _runNumber + ".", Debug.INFO_PRIORITY);
1031  return;
1032  }
1033  }
1034  else
1035  {
1036  Debug.log("Unknown action for current state '" + _state + "'..." +
1037  "Giving up on " + operativeWord + " the run.", Debug.HIGH_PRIORITY);
1038  return;
1039  }
1040 
1041  _inTransition = true;
1042  _transitionPercentComplete = 0;
1043 
1044  displayState();
1045 
1046  Debug.log("_transitionName = " + _transitionName +
1047  " transitionPostData = " + transitionPostData);
1048 
1049  DesktopContent.XMLHttpRequest("StateMachineXgiHandler?StateMachine=" +
1050  _transitionName +
1051  "&fsmName=" + _fsmName +
1052  "&fsmWindowName=" + _fsmWindowName,
1053  transitionPostData,
1054  //===========
1055  function(req)
1056  {
1057 
1058  var success = DesktopContent.getXMLValue(req,"state_tranisition_attempted") == "1";
1059  if(!success)
1060  {
1061  var err = DesktopContent.getXMLValue(req,"state_tranisition_attempted_err");
1062  if(err)
1063  Debug.log(err,Debug.HIGH_PRIORITY);
1064  Debug.log("Server indicated failure to attempt state transition. " +
1065  "Giving up on " + operativeWord + " the run.",Debug.HIGH_PRIORITY);
1066  return;
1067  }
1068 
1069  //on success continue..
1070  window.clearTimeout(_runFSMTimer);
1071  _runFSMTimer = window.setTimeout(localRun,3000); //wait 3 seconds before doing anything
1072  }, // end handler
1073  0, //handler param
1074  0,0,false, //progressHandler, callHandlerOnErr, showLoadingOverlay
1075  true /*targetSupervisor*/);
1076 
1077  }
1078 
1079  } //end run()
1080 
1081  //=====================================================================================
1082  //toggleCheckboxDiv(i) ~~
1083  this.toggleCheckboxDiv = function(i)
1084  {
1085  Debug.log("toggleCheckboxDiv(i) " + i);
1086 
1087  var el;
1088  if(i == 0) //toggle subsystems
1089  {
1090  el = document.getElementById("ssCheckboxDiv");
1091  el.style.display = (el.style.display == "none")?"block":"none";
1092  }
1093  else if(i == 1) //toggle contextx
1094  {
1095  el = document.getElementById("ctxCheckboxDiv");
1096  el.style.display = (el.style.display == "none")?"block":"none";
1097  }
1098  else throw("Invalid index checkbox div " + i);
1099  } //end toggleCheckboxDiv()
1100 
1101  //=====================================================================================
1102  //handleCheckbox(i) ~~
1103  this.handleCheckbox = function(c)
1104  {
1105  Debug.log("handleCheckbox(c) " + c);
1106 
1107  var checkboxes = document.getElementsByClassName('subsystemCheckboxes');
1108  console.log("checkboxes",checkboxes);
1109  var checkedArray = [];
1110  for(var i=0;i<checkboxes.length;++i)
1111  checkedArray.push(checkboxes[i].checked);
1112  console.log("checkedArray",checkedArray);
1113 
1114  Debug.log("set to " + checkedArray[c]);
1115 
1116  //create a context map
1117  var contextEnabledMap = {}; //map to [enabled, index]
1118  for(var i=0; i<_contextRecords.length; ++i)
1119  contextEnabledMap[_contextRecords[i]] = [checkedArray[SmartLaunch.subsystems.length+i],
1120  SmartLaunch.subsystems.length+i];
1121 
1122  //update for each context that was just affected
1123  if(c < SmartLaunch.subsystems.length)
1124  {
1125  //dealing with a subsystem
1126  for(var j=0; j<SmartLaunch.systemToContextMap[SmartLaunch.subsystems[c]].length; ++j)
1127  {
1128  //update map
1129  contextEnabledMap[ //context name
1130  SmartLaunch.systemToContextMap[SmartLaunch.subsystems[c]][j]
1131  ][0] = checkedArray[c]; //set to checked value
1132  //and set checkbox
1133  checkboxes[contextEnabledMap[ //context name
1134  SmartLaunch.systemToContextMap[SmartLaunch.subsystems[c]][j]
1135  ][1]].checked = checkedArray[c];
1136  }
1137  }
1138  else
1139  {
1140  //dealing with a context
1141 
1142  //update map
1143  contextEnabledMap[_contextRecords[c - SmartLaunch.subsystems.length]][0] = checkedArray[c]; //set to checked value
1144 
1145  }
1146  console.log("contextEnabledMap",contextEnabledMap);
1147 
1148 
1149  //update all subsystems based on this change
1150  for(var i=0;i<SmartLaunch.subsystems.length;++i)
1151  {
1152  if(i==c) continue; //skip box that was changed
1153 
1154  var enabled = true;
1155  //if any member contexts are disabled then disable subsystem
1156  for(var j=0; j<SmartLaunch.systemToContextMap[SmartLaunch.subsystems[i]].length; ++j)
1157  {
1158  if(!contextEnabledMap[
1159  SmartLaunch.systemToContextMap[SmartLaunch.subsystems[i]][j]][0])
1160  {
1161  enabled = false;
1162  break;
1163  }
1164  }
1165 
1166  //set checkbox
1167  checkboxes[i].checked = enabled;
1168  }
1169 
1170 
1171  } //end handleCheckbox()
1172 
1173 
1174 } //end create() SmartLaunch instance
1175 
1176 
1177 
1178 
1179 
1180 
1181 
1182 
1183 
1184 
1185