otsdaq_utilities  v2_04_02
ControlsDashboardSupervisor.cc
1 #include "otsdaq-utilities/ControlsDashboard/ControlsDashboardSupervisor.h"
2 #include <dirent.h> //for DIR
3 #include <sys/stat.h> //for stat() quickly checking if file exists
4 #include <thread> //for std::thread
5 
6 #include "otsdaq/PluginMakers/MakeSlowControls.h"
7 #include "otsdaq/SlowControlsCore/SlowControlsVInterface.h"
8 
9 using namespace ots;
10 
11 #define CONTROLS_SUPERVISOR_DATA_PATH \
12  std::string(__ENV__("SERVICE_DATA_PATH")) + "/ControlsDashboardData/"
13 #define PAGES_DIRECTORY CONTROLS_SUPERVISOR_DATA_PATH + "pages/"
14 
15 XDAQ_INSTANTIATOR_IMPL(ControlsDashboardSupervisor)
16 
17 //========================================================================================================================
18 ControlsDashboardSupervisor::ControlsDashboardSupervisor(xdaq::ApplicationStub* stub)
19  : CoreSupervisorBase(stub)
20 {
21  __SUP_COUT__ << "Constructor." << __E__;
22 
23  INIT_MF("ControlsDashboardSupervisor");
24 
25  // make controls dashboard supervisor directories in case they don't exist
26  mkdir(((std::string)(CONTROLS_SUPERVISOR_DATA_PATH)).c_str(), 0755);
27  mkdir(((std::string)(PAGES_DIRECTORY)).c_str(), 0755);
28 
29  interface_ = NULL;
30 
31  init();
32 
33  // interface_ = NULL;
34 
35  __SUP_COUT__ << "Constructed." << __E__;
36 } // end constructor
37 
38 //========================================================================================================================
39 ControlsDashboardSupervisor::~ControlsDashboardSupervisor(void)
40 {
41  __SUP_COUT__ << "Destructor." << __E__;
42  destroy();
43  __SUP_COUT__ << "Destructed." << __E__;
44 } // end destructor()
45 
46 //========================================================================================================================
47 void ControlsDashboardSupervisor::destroy(void)
48 {
49  // called by destructor
50  delete interface_;
51 } // end destroy()
52 
53 //========================================================================================================================
54 void ControlsDashboardSupervisor::init(void)
55 // called by constructor
56 {
57  UID_ = 0;
58 
59  __SUP_COUT__ << std::endl;
60  ConfigurationTree node = CorePropertySupervisorBase::getSupervisorTableNode();
61  std::string pluginType =
62  CorePropertySupervisorBase::getSupervisorProperty("ControlsInterfacePluginType");
63 
64  std::string supervisorConfigurationPath =
65  "/" + CorePropertySupervisorBase::getContextUID() + "/LinkToApplicationTable/" +
66  CorePropertySupervisorBase::getSupervisorUID();
67  //
68  interface_ = makeSlowControls(pluginType,
69  CorePropertySupervisorBase::getSupervisorUID(),
70  CorePropertySupervisorBase::getContextTreeNode(),
71  supervisorConfigurationPath);
72  __COUT__ << std::endl;
73  //
74  //
75  // interface_->initialize();
76  std::thread(
78 
79  // lockout the messages array for the remainder of the scope
80  // this guarantees the reading thread can safely access the messages
81  std::lock_guard<std::mutex> lock(cs->pluginBusyMutex_);
82 
83  cs->interface_->initialize();
84 
85  },
86  this)
87  .detach(); // thread completes after creating, subscribing, and getting
88  // // parameters for all pvs
89  __SUP_COUT__ << "Finished init() w/ interface: " << pluginType << std::endl;
90 
91 } // end init()
92 
93 //========================================================================================================================
94 // setSupervisorPropertyDefaults
95 // override to set defaults for supervisor property values (before user settings
96 // override)
97 void ControlsDashboardSupervisor::setSupervisorPropertyDefaults()
98 {
99  CorePropertySupervisorBase::setSupervisorProperty(
100  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.CheckUserLockRequestTypes, "*");
101 }
102 
103 //========================================================================================================================
104 // forceSupervisorPropertyValues
105 // override to force supervisor property values (and ignore user settings)
106 void ControlsDashboardSupervisor::forceSupervisorPropertyValues()
107 {
108  CorePropertySupervisorBase::setSupervisorProperty(
109  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes, "poll");
110 }
111 
112 //========================================================================================================================
113 void ControlsDashboardSupervisor::request(const std::string& requestType,
114  cgicc::Cgicc& cgiIn,
115  HttpXmlDocument& xmlOut,
116  const WebUsers::RequestUserInfo& userInfo)
117 {
118  try
119  {
120  if(requestType != "getPages" && !pluginBusyMutex_.try_lock())
121  {
122  __SUP_SS__ << "Controls plugin is still initializing. Please try again in a "
123  "few minutes!"
124  << __E__;
125  __SUP_SS_THROW__;
126  }
127 
128  __SUP_COUT__ << "User name is " << userInfo.username_ << "." << __E__;
129  __SUP_COUT__ << "User permission level for request '" << requestType << "' is "
130  << unsigned(userInfo.permissionLevel_)
131  << "(isAdmin=" << (userInfo.isAdmin() ? "Yes" : "No") << ")."
132  << __E__;
133 
134  // handle request per requestType
135  handleRequest(requestType, xmlOut, cgiIn, userInfo);
136  }
137  catch(const std::runtime_error& e)
138  {
139  __SUP_SS__ << "Error occurred handling request '" << requestType
140  << "': " << e.what() << __E__;
141  __SUP_COUT__ << ss.str();
142  xmlOut.addTextElementToData("Error", ss.str());
143  }
144  catch(...)
145  {
146  __SS__ << "Unknown error occurred handling request '" << requestType << "!'"
147  << __E__;
148  __SUP_COUT__ << ss.str();
149  xmlOut.addTextElementToData("Error", ss.str());
150  }
151 
152  pluginBusyMutex_.unlock();
153 
154 } // end request()
155 
156 //========================================================================================================================
157 void ControlsDashboardSupervisor::handleRequest(const std::string Command,
158  HttpXmlDocument& xmlOut,
159  cgicc::Cgicc& cgiIn,
160  const WebUsers::RequestUserInfo& userInfo)
161 {
162  // return xml doc holding server response
163  __SUP_COUT__ << std::endl;
164 
165  if(Command == "poll")
166  {
167  std::string uid = CgiDataUtilities::getOrPostData(cgiIn, "uid");
168  Poll(cgiIn, xmlOut, uid);
169  }
170  else if(Command == "generateUID")
171  {
172  std::string pvList = CgiDataUtilities::getOrPostData(cgiIn, "PVList");
173  GenerateUID(cgiIn, xmlOut, pvList);
174  }
175  else if(Command == "isUserAdmin")
176  {
177  std::string json = std::string("{ \"message\": \"");
178  json += (userInfo.isAdmin() ? "Yes" : "No");
179  json += "\"}";
180  xmlOut.addTextElementToData("JSON", json.c_str());
181  }
182  else if(Command == "getUserPermissions")
183  {
184  GetUserPermissions(cgiIn, xmlOut, userInfo);
185  }
186  else if(Command == "getPVSettings")
187  {
188  __SUP_COUT__ << "PV settings requested from server! " << std::endl;
189  GetPVSettings(cgiIn, xmlOut);
190  xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id"));
191  }
192  else if(Command == "getPVArchiverData")
193  {
194  __SUP_COUT__ << "Archived PV data requested from server! " << std::endl;
195  GetPVArchiverData(cgiIn, xmlOut);
196  }
197  else if(Command == "getList")
198  {
199  __SUP_COUT__ << "PV List requested from server! " << std::endl;
200  GetList(cgiIn, xmlOut);
201  }
202  else if(Command == "getPages")
203  {
204  __SUP_COUT__ << "Requesting pages from server! " << std::endl;
205  GetPages(cgiIn, xmlOut);
206  }
207  else if(Command == "loadPage")
208  {
209  std::string page = CgiDataUtilities::getData(cgiIn, "Page");
210  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << page
211  << std::endl;
212 
213  loadPage(cgiIn, xmlOut, page, userInfo);
214  }
215  else if(Command == "createControlsPage")
216  {
217  SaveControlsPage(cgiIn, xmlOut, userInfo);
218  }
219  // else if(Command == "savePage")
220  // {
221  // std::string pageName = CgiDataUtilities::getData(cgiIn, "PageName");
222  // std::string page = CgiDataUtilities::getOrPostData(cgiIn, "Page");
223  // SavePage(cgiIn, xmlOut, pageName, page);
224  // }
225 
226  __SUP_COUT__ << "" << std::endl;
227 
228  // xmlOut.outputXmlDocument((std::ostringstream*) out, true);
229 } // end handleRequest
230 
231 //========================================================================================================================
232 void ControlsDashboardSupervisor::Poll(cgicc::Cgicc& cgiIn,
233  HttpXmlDocument& xmlOut,
234  std::string UID)
235 {
236  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
237  << "Polling on UID:" << UID << std::endl;
238 
239  std::map<int, std::set<std::string>>::iterator mapReference;
240 
241  if(UID != "" &&
242  (mapReference = pvDependencyLookupMap_.find(std::stoi(UID))) !=
243  pvDependencyLookupMap_.end()) // We have their current list of PV Dependencies
244  {
245  std::string JSONMessage = "{ ";
246 
247  for(auto pv : mapReference->second)
248  {
249  __SUP_COUT__ << pv << std::endl;
250  // PVInfo * pvInfo = interface_->mapOfPVInfo_.find(pv)->second;
251  //__SUP_COUT__ << pv << ":" << (pvInfo?"Good":"Bad") << std::endl;
252  // interface_->getCurrentPVValue(pv);
253  std::array<std::string, 4> pvInformation = interface_->getCurrentValue(pv);
254  __SUP_COUT__ << pv << ": " << pvInformation[1] << " : " << pvInformation[3]
255  << std::endl;
256 
257  if(pvInformation[0] != "NO_CHANGE")
258  {
259  //__SUP_COUT__ << "Reached" << std::endl;
260  JSONMessage += "\"" + pv + "\": {";
261 
262  /*if(pvInfo->mostRecentBufferIndex - 1 < 0)
263  {
264  std::string value = pvInfo->dataCache[pvInfo->dataCache.size()].second
265  std::string time =
266  }*/
267 
268  JSONMessage += "\"Timestamp\":\"" + pvInformation[0] + "\",";
269  JSONMessage += "\"Value\":\"" + pvInformation[1] + "\",";
270  JSONMessage += "\"Status\":\"" + pvInformation[2] + "\",";
271  JSONMessage += "\"Severity\":\"" + pvInformation[3] + "\"},";
272  }
273  else
274  {
275  __SUP_COUT__ << "No change in value since last poll: " << pv << std::endl;
276  }
277 
278  // Handle Channels that disconnect, etc
279  if(pvInformation[3] == "INVALID")
280  {
281  interface_->subscribe(pv);
282  }
283 
284  //__SUP_COUT__ << pv << ":" << (pvInfo?"Good":"Bad") << std::endl;
285  //__SUP_COUT__ << pv << ":" << pvInfo->mostRecentBufferIndex -1 << std::endl;
286  //__SUP_COUT__ << pv << " : " <<
287  // pvInfo->dataCache[(pvInfo->mostRecentBufferIndex -1)].second << std::endl;
288  }
289 
290  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
291  JSONMessage += "}";
292  __SUP_COUT__ << JSONMessage << std::endl;
293  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
294 
295  /*for (std::set<unsigned long>::iterator it = mapReference->second->begin(); it !=
296  mapReference->second.end(); ++it)
297  {
298  //__SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << it <<
299  std::endl;
300 
301 
302  }*/
303  /*std::string fakeData = std::string("{")
304  + "\"Mu2e_CompStatus_daq01/system_temperature\":
305  \"40.5\","
306  + "\"Mu2e_CompStatus_daq01/load_one\": \"378.2\","
307  + "\"Mu2e_Weather_2/timestamp\": \"11.14.45.2016.4.8\","
308  + "\"Mu2e_CompStatus_daq01/system_temperature\":
309  \"43.4\","
310  + "\"Mu2e_CompStatus_daq01/load_one\":\"80\","
311  + "\"Mu2e_Weather_2/timestamp\": \"11.14.45.2016.4.8\""
312  + "}";
313  xmlOut.addTextElementToData("JSON", fakeData); //add to response*/
314  }
315  else // UID is not in our map so force them to generate a new one
316  {
317  xmlOut.addTextElementToData("JSON",
318  "{ \"message\": \"NOT_FOUND\"}"); // add to response
319  }
320 }
321 //========================================================================================================================
322 void ControlsDashboardSupervisor::GetPVSettings(cgicc::Cgicc& cgiIn,
323  HttpXmlDocument& xmlOut)
324 {
325  std::string pvList = CgiDataUtilities::postData(cgiIn, "PVList");
326 
327  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
328  << "Getting settings for " << pvList << std::endl;
329 
330  std::string JSONMessage = "{ ";
331 
332  std::string pv;
333  size_t pos = 0;
334  size_t nextPos;
335  size_t lastIndex = pvList.find_last_of(",");
336  std::cout << "**********************" << pvList.size() << std::endl;
337  if(pvList.size() > 0)
338  {
339  while((nextPos = pvList.find(",", pos)) != std::string::npos)
340  {
341  pv = pvList.substr(pos, nextPos - pos);
342 
343  __SUP_COUT__ << pv << std::endl;
344 
345  std::array<std::string, 9> pvSettings = interface_->getSettings(pv);
346 
347  JSONMessage += "\"" + pv + "\": {";
348  JSONMessage += "\"Units\": \"" + pvSettings[0] + "\",";
349  JSONMessage += "\"Upper_Display_Limit\": \"" + pvSettings[1] + "\",";
350  JSONMessage += "\"Lower_Display_Limit\": \"" + pvSettings[2] + "\",";
351  JSONMessage += "\"Upper_Alarm_Limit\": \"" + pvSettings[3] + "\",";
352  JSONMessage += "\"Upper_Warning_Limit\": \"" + pvSettings[4] + "\",";
353  JSONMessage += "\"Lower_Warning_Limit\": \"" + pvSettings[5] + "\",";
354  JSONMessage += "\"Lower_Alarm_Limit\": \"" + pvSettings[6] + "\",";
355  JSONMessage += "\"Upper_Control_Limit\": \"" + pvSettings[7] + "\",";
356  JSONMessage += "\"Lower_Control_Limit\": \"" + pvSettings[8] + "\"},";
357 
358  pos = nextPos + 1;
359  }
360 
361  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
362  JSONMessage += "}";
363 
364  __SUP_COUT__ << JSONMessage << std::endl;
365  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
366  }
367  else
368  {
369  __SUP_COUT__ << "Did not find any settings because PV list is length zero!"
370  << std::endl;
371 
372  xmlOut.addTextElementToData(
373  "JSON", "{ \"message\": \"GetPVSettings\"}"); // add to response
374  }
375 }
376 
377 //========================================================================================================================
378 void ControlsDashboardSupervisor::GetPVArchiverData(cgicc::Cgicc& cgiIn,
379  HttpXmlDocument& xmlOut)
380 {
381  __SUP_COUT__ << "Requesting archived data!" << std::endl;
382 
383  // FAKE NEWS RESPONSE
384  // xmlOut.addTextElementToData(
385  // "JSON",
386  // "{ \"ROOM:LI30:1:OUTSIDE_TEMP\": {
387  // \"nanos\": 823158037,
388  // \"secs\": 1540229999,
389  // \"severity\": 0,
390  // \"status\": 0,
391  // \"val\": 60.358551025390625
392  // },
393  // \"VPIO:IN20:111:VRAW\": {
394  // \"nanos\": 754373158,
395  // \"secs\": 1540229999,
396  // \"severity\": 0,
397  // \"status\": 0,
398  // \"val\": 5.529228687286377
399  // },
400  // \"YAGS:UND1:1005:Y_BM_CTR\": {
401  // \"nanos\": 164648807,
402  // \"secs\": 1537710595,
403  // \"severity\": 0,
404  // \"status\": 0,
405  // \"val\": 0.008066000000000002
406  // }
407  // }"); // add to response
408 
409  return;
410 
411  // Where parameters
412  std::string data_retrieval_url = "";
413  std::string data_retrieval_servlet = "";
414  std::string mime_type = ".json";
415 
416  // What/when paramaeters
417  std::string pv, from, to;
418 
419  // Optional parameters
420  // boolean fetchLatestMetadata, donotchunk;
421  // std::string timeranges;
422  // int ca_count, ca_how;
423 
424  std::string req = data_retrieval_url + data_retrieval_servlet + mime_type + "?" +
425  "pv=" + pv + "&from=" + from + "&to=" + to;
426 
427  std::string response = "";
428 
429  return;
430 
431 } // end GetPVArchiverData()
432 //========================================================================================================================
433 void ControlsDashboardSupervisor::GetUserPermissions(
434  cgicc::Cgicc& cgiIn,
435  HttpXmlDocument& xmlOut,
436  const WebUsers::RequestUserInfo& userInfo)
437 {
438  return;
439 }
440 //========================================================================================================================
441 void ControlsDashboardSupervisor::GenerateUID(cgicc::Cgicc& cgiIn,
442  HttpXmlDocument& xmlOut,
443  std::string pvlist)
444 {
445  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
446  << "Generating UID" << std::endl;
447 
448  std::set<std::string> pvDependencies;
449  std::string uid;
450  std::string pv;
451  size_t pos = 0;
452  size_t nextPos;
453  size_t lastIndex = pvlist.find_last_of(",");
454 
455  if(pvlist.size() > 0)
456  {
457  // pvlist.substr(2);
458  __SUP_COUT__ << pvlist << std::endl;
459 
460  while((nextPos = pvlist.find(",", pos)) != std::string::npos)
461  {
462  pv = pvlist.substr(pos, nextPos - pos);
463  //__SUP_COUT__ << UID_ << ":" << pos << "-" << nextPos << " ->" << pv <<
464  // std::endl;
465  pvDependencies.insert(pv);
466  pos = nextPos + 1;
467  }
468 
469  pvDependencyLookupMap_.insert(
470  std::pair<int, std::set<std::string>>(++UID_, pvDependencies));
471 
472  uid = (std::string("{ \"message\": \"") + std::to_string(UID_) + "\"}");
473  }
474  else
475  {
476  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
477  << " PVList invalid: " << pvlist << std::endl;
478  uid = "{ \"message\": \"-1\"}";
479  }
480 
481  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " NEW UID: " << UID_
482  << std::endl;
483 
484  xmlOut.addTextElementToData("JSON", uid); // add to response
485 } // end GenerateUID()
486 
487 //========================================================================================================================
488 void ControlsDashboardSupervisor::GetList(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
489 {
490  if(interface_ != NULL)
491  {
492  __SUP_COUT__ << "Interface is defined! Attempting to get list!" << std::endl;
493  // __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << std::endl;
494  std::cout << " " << interface_->getList("JSON") << std::endl;
495 
496  xmlOut.addTextElementToData("JSON",
497  interface_->getList("JSON")); // add to response
498  }
499  else
500  {
501  __SUP_COUT__ << "Interface undefined! Failed to get list!" << std::endl;
502  xmlOut.addTextElementToData("JSON", "[\"None\"]");
503  }
504 } // end GetList()
505 
506 //========================================================================================================================
507 void ControlsDashboardSupervisor::GetPages(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
508 {
509  /*DIR * dir;
510  struct dirent * ent;
511  std::string pathToPages = CONTROLS_SUPERVISOR_DATA_PATH;
512 
513  std::vector<std::string> pages;
514 
515  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << "Path to pages: " <<
516  pathToPages << std::endl; if((dir = opendir (pathToPages.c_str())) != NULL)
517  {
518  while((ent = readdir(dir)) != NULL)
519  {
520  pages.push_back(ent->d_name);
521  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " GetPages"
522  << ent->d_name << std::endl;
523  }
524  closedir(dir);
525  }
526  else
527  {
528  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << "Could not open
529  directory: " << pathToPages << std::endl; return;
530  }
531  */
532  std::vector<std::string> pages;
533 
534  listFiles("", true, &pages);
535 
536  std::string returnJSON = "[";
537  for(auto it = pages.begin(); it != pages.end(); it++)
538  {
539  if(*it != "." && *it != "..")
540  returnJSON += "\"" + *it + "\", ";
541  }
542  if(returnJSON.size() > 2 && returnJSON.compare("[") != 0)
543  {
544  __SUP_COUT__ << "Found pages on server!" << std::endl;
545  returnJSON.resize(returnJSON.size() - 2);
546  returnJSON += "]";
547  }
548  else
549  {
550  // No pages on the server
551  __SUP_COUT__ << "No pages found on server!" << std::endl;
552  returnJSON = "[\"None\"]";
553  }
554  std::cout << returnJSON << std::endl;
555 
556  xmlOut.addTextElementToData("JSON", returnJSON); // add to response
557 } // end GetPages()
558 
559 //========================================================================================================================
560 void ControlsDashboardSupervisor::loadPage(cgicc::Cgicc& cgiIn,
561  HttpXmlDocument& xmlOut,
562  std::string page,
563  const WebUsers::RequestUserInfo& userInfo)
564 {
565  page = StringMacros::decodeURIComponent(page);
566 
567  // FIXME Filter out malicious attacks i.e. ../../../../../ stuff
568  struct stat buffer;
569  if(page.find("..") != std::string::npos)
570  {
571  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
572  << "Error! Request using '..': " << page << std::endl;
573  }
574  else if(page.find("~") != std::string::npos)
575  {
576  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
577  << "Error! Request using '~': " << page << std::endl;
578  }
579  else if(!(stat(page.c_str(), &buffer) == 0))
580  {
581  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
582  << "Error! File not found: " << page << std::endl;
583  }
584  // Remove double / in path
585 
586  __SUP_COUT__ << page << std::endl;
587 
588  if(page.at(0) == '/')
589  {
590  __SUP_COUT__ << "First character is '/'" << std::endl;
591  page.erase(page.begin(), page.begin() + 1);
592  __SUP_COUT__ << page << std::endl;
593  }
594 
595  std::string file = CONTROLS_SUPERVISOR_DATA_PATH;
596  file += page;
597  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
598  << "Trying to load page: " << page << std::endl;
599  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
600  << "Trying to load page: " << file << std::endl;
601  // read file
602  // for each line in file
603 
604  std::ifstream infile(file);
605  if(infile.fail())
606  {
607  std::cout << "Failed reading file: " << file << std::endl;
608 
609  xmlOut.addTextElementToData("Time", "[\"Not Found\"]"); // add to response
610  xmlOut.addTextElementToData("Notes", "[\"Not Found\"]"); // add to response
611  xmlOut.addTextElementToData(
612  "Page", StringMacros::encodeURIComponent(page)); // add to response
613  return;
614  }
615  std::cout << "Reading file" << std::endl;
616 
617  std::string time = "";
618  std::string notes = "";
619  std::string controlsPage = "";
620 
621  for(std::string line; getline(infile, line);)
622  {
623  std::cout << line << std::endl;
624  if(!line.substr(0, 5).compare("Time:"))
625  {
626  time = line.substr(6);
627  }
628  else if(!line.substr(0, 6).compare("Notes:"))
629  {
630  notes = line.substr(7);
631  }
632  else if(!line.substr(0, 5).compare("Page:"))
633  {
634  controlsPage = line.substr(6);
635  }
636  }
637  std::cout << "Finished reading file" << std::endl;
638  __SUP_COUTV__(time);
639  __SUP_COUTV__(notes);
640  __SUP_COUTV__(controlsPage);
641 
642  xmlOut.addTextElementToData("Time", time); // add to response
643  xmlOut.addTextElementToData("Notes", notes); // add to response
644  xmlOut.addTextElementToData("Page", controlsPage); // add to response
645 } // end loadPage()
646 
647 //========================================================================================================================
648 void ControlsDashboardSupervisor::SaveControlsPage(
649  cgicc::Cgicc& cgiIn,
650  HttpXmlDocument& xmlOut,
651  const WebUsers::RequestUserInfo& userInfo)
652 {
653  __SUP_COUT__ << "ControlsDashboard wants to create a Controls Page!" << __E__;
654 
655  std::string controlsPageName = CgiDataUtilities::postData(cgiIn, "Name");
656  std::string pageString = CgiDataUtilities::postData(cgiIn, "Page");
657  std::string Time = CgiDataUtilities::postData(cgiIn, "Time");
658  std::string Notes =
659  StringMacros::decodeURIComponent(CgiDataUtilities::postData(cgiIn, "Notes"));
660  std::string isControlsPagePublic = CgiDataUtilities::postData(cgiIn, "isPublic");
661 
662  __SUP_COUTV__(controlsPageName);
663  __SUP_COUTV__(pageString);
664  __SUP_COUTV__(Notes);
665  __SUP_COUTV__(Time);
666  __SUP_COUTV__(isControlsPagePublic);
667 
668  if(controlsPageName == "")
669  return;
670 
671  __SUP_COUTV__(CONTROLS_SUPERVISOR_DATA_PATH);
672 
673  std::string fullPath;
674  if(isControlsPagePublic == "true")
675  fullPath = (std::string)CONTROLS_SUPERVISOR_DATA_PATH + "public/";
676  else
677  fullPath = (std::string)CONTROLS_SUPERVISOR_DATA_PATH + "private/";
678 
679  __SUP_COUTV__(fullPath);
680 
681  std::string file = fullPath + controlsPageName;
682 
683  __SUP_COUTV__("Saving Controls Page to: " + file);
684 
685  std::string extension = file.substr(file.length() - 4, 4);
686  if(extension != ".dat")
687  {
688  __SUP_COUT__ << "Extension : " << extension << std::endl;
689  file += std::string(".dat");
690  }
691  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
692  << "Trying to save page: " << controlsPageName << std::endl;
693  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
694  << "Trying to save page as: " << file << std::endl;
695  // read file
696  // for each line in file
697 
698  std::ofstream outputFile;
699  outputFile.open(file);
700  outputFile << "Time: " << Time << "\n";
701  outputFile << "Notes: " << Notes << "\n";
702  outputFile << "Page: " << pageString;
703  outputFile.close();
704 
705  std::cout << "Finished writing file" << std::endl;
706 
707  return;
708 }
709 
710 //========================================================================================================================
711 void ControlsDashboardSupervisor::Subscribe(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
712 {
713 }
714 
715 //========================================================================================================================
716 void ControlsDashboardSupervisor::Unsubscribe(cgicc::Cgicc& cgiIn,
717  HttpXmlDocument& xmlOut)
718 {
719 }
720 
721 //========================================================================================================================
722 //========================================================================================================================
723 //================================================== UTILITIES
724 //===========================================================
725 //========================================================================================================================
726 bool ControlsDashboardSupervisor::isDir(std::string dir)
727 {
728  struct stat fileInfo;
729  stat(dir.c_str(), &fileInfo);
730  if(S_ISDIR(fileInfo.st_mode))
731  {
732  return true;
733  }
734  else
735  {
736  return false;
737  }
738 }
739 //========================================================================================================================
740 void ControlsDashboardSupervisor::listFiles(std::string baseDir,
741  bool recursive,
742  std::vector<std::string>* pages)
743 {
744  std::string base = CONTROLS_SUPERVISOR_DATA_PATH;
745  base += baseDir;
746 
747  DIR* dp;
748  struct dirent* dirp;
749  if((dp = opendir(base.c_str())) == NULL)
750  {
751  std::cout << "[ERROR: " << errno << " ] Couldn't open " << base << "."
752  << std::endl;
753  return;
754  }
755  else
756  {
757  while((dirp = readdir(dp)) != NULL)
758  {
759  if(dirp->d_name != std::string(".") && dirp->d_name != std::string(".."))
760  {
761  if(isDir(base + dirp->d_name) == true && recursive == true)
762  {
763  // pages->push_back(baseDir + dirp->d_name);
764  std::cout << "[DIR]\t" << baseDir << dirp->d_name << "/" << std::endl;
765  listFiles(baseDir + dirp->d_name + "/", true, pages);
766  }
767  else
768  {
769  pages->push_back(baseDir + dirp->d_name);
770  std::cout << "[FILE]\t" << baseDir << dirp->d_name << std::endl;
771  }
772  }
773  }
774  closedir(dp);
775  }
776 }