otsdaq-utilities  3.03.02
SlowControlsDashboardSupervisor.cc
1 #include "otsdaq-utilities/SlowControlsDashboard/SlowControlsDashboardSupervisor.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/SlowControlsCore/MakeSlowControls.h"
7 #include "otsdaq/SlowControlsCore/SlowControlsVInterface.h"
8 
9 #include <boost/regex.hpp>
10 
11 using namespace ots;
12 
13 #define CONTROLS_SUPERVISOR_DATA_PATH \
14  std::string(__ENV__("SERVICE_DATA_PATH")) + "/ControlsDashboardData/"
15 #define PAGES_DIRECTORY CONTROLS_SUPERVISOR_DATA_PATH + "pages/"
16 #define PAGES_PUBLIC_DIRECTORY CONTROLS_SUPERVISOR_DATA_PATH + "pages/public/"
17 #define PAGES_PRIVATE_DIRECTORY CONTROLS_SUPERVISOR_DATA_PATH + "pages/private/"
18 
19 XDAQ_INSTANTIATOR_IMPL(SlowControlsDashboardSupervisor)
20 
21 //==============================================================================
22 SlowControlsDashboardSupervisor::SlowControlsDashboardSupervisor(
23  xdaq::ApplicationStub* stub)
24  : CoreSupervisorBase(stub), alarms_(), alarms_timestamp_()
25 {
26  __SUP_COUT__ << "Constructor." << __E__;
27 
28  INIT_MF("." /*directory used is USER_DATA/LOG/.*/);
29 
30  // make controls dashboard supervisor directories in case they don't exist
31  mkdir(((std::string)(CONTROLS_SUPERVISOR_DATA_PATH)).c_str(), 0755);
32  mkdir(((std::string)(PAGES_DIRECTORY)).c_str(), 0755);
33  mkdir(((std::string)(PAGES_PUBLIC_DIRECTORY)).c_str(), 0755);
34  mkdir(((std::string)(PAGES_PRIVATE_DIRECTORY)).c_str(), 0755);
35 
36  interface_ = NULL;
37  alarmNotifyRefreshRate_ = 60; // seconds
38 
39  init();
40 
41  __SUP_COUT__ << "Constructed." << __E__;
42 } // end constructor
43 
44 //==============================================================================
45 SlowControlsDashboardSupervisor::~SlowControlsDashboardSupervisor(void)
46 {
47  __SUP_COUT__ << "Destructor." << __E__;
48  destroy();
49  __SUP_COUT__ << "Destructed." << __E__;
50 } // end destructor()
51 
52 //==============================================================================
53 void SlowControlsDashboardSupervisor::destroy(void)
54 {
55  // called by destructor
56  delete interface_;
57 } // end destroy()
58 
59 //==============================================================================
62 {
63  UID_ = 0;
64 
65  __SUP_COUT__ << __E__;
66  ConfigurationTree node = CorePropertySupervisorBase::getSupervisorTableNode();
67  std::string pluginType;
68 
69  try
70  {
71  pluginType =
72  node.getNode("SlowControlsInterfacePluginType").getValue<std::string>();
73  }
74  catch(...)
75  {
76  // failed to get plugin type through supervisor table link, so try app property
77  __SUP_COUT__ << "Pluging type was not definded through supervisor table, trying "
78  "supervisor property..."
79  << __E__;
81  "ControlsInterfacePluginType");
82  }
83 
84  try
85  {
86  alarmNotifyRefreshRate_ = node.getNode("AlarmCheckRefreshPeriod").getValue<int>();
87  __SUP_COUTV__(alarmNotifyRefreshRate_);
88  }
89  catch(...)
90  {
91  __COUT_WARN__ << "Couldn't find `AlarmCheckRefreshPeriod`. Default "
92  "alarmNotifyRefreshRate = "
93  << alarmNotifyRefreshRate_ << " seconds." << __E__;
94  }
95 
96  __COUTV__(pluginType);
97 
98  try
99  {
100  interface_ = makeSlowControls(
101  pluginType,
102  CorePropertySupervisorBase::getSupervisorUID(),
103  CorePropertySupervisorBase::getContextTreeNode(),
104  CorePropertySupervisorBase::getSupervisorConfigurationPath());
105  }
106  catch(...)
107  {
108  }
109 
110  if(interface_ == nullptr)
111  {
112  __SS__ << "Slow Control interface plugin construction failed of type "
113  << pluginType << __E__;
114  __SS_THROW__;
115  }
116 
117  interface_->setNewAlarmCallback(
118  std::bind(&SlowControlsDashboardSupervisor::handleNewAlarms, this));
119 
120  //
121  // interface_->initialize();
122  std::thread(
124  // lockout the messages array for the remainder of the scope
125  // this guarantees the reading thread can safely access the messages
126  std::lock_guard<std::mutex> lock(cs->pluginBusyMutex_);
127 
128  cs->interface_->initialize();
129  },
130  this)
131  .detach(); // thread completes after creating, subscribing, and getting
132  // // parameters for all channels
133 
134  //
135  // checkSubscription
136  std::thread(
138  // lockout the messages array for the remainder of the scope
139  // this guarantees the reading thread can safely access the messages
140  // std::lock_guard<std::mutex> lock(cs->pluginBusyMutex_);
141  // cs->checkSubscriptions(cs);
142  cs->checkSlowControlsAlarms(cs);
143  },
144  this)
145  .detach(); // thread check EPICS slow controls alarms
146 
147  __SUP_COUT__ << "Finished init() w/ interface: " << pluginType << __E__;
148 
149  // add interface plugin to state machine list
150  CoreSupervisorBase::theStateMachineImplementation_.push_back(interface_);
151 } //end init()
152 
153 //==============================================================================
154 void SlowControlsDashboardSupervisor::handleNewAlarms()
155 {
156  __COUT__ << "DEBUG handleNewAlarms" << __E__;
157 } //end handleNewAlarms()
158 
159 //==============================================================================
163 {
164  { //create mutex scope
165  std::lock_guard<std::mutex> lock(cs->alarmCheckThreadErrorMutex_);
166  cs->alarmCheckThreadError_ = "";
167  }
168 
169  while(true)
170  {
171  alarms_ =
172  cs->interface_
173  ->checkAlarmNotifications(); // note: this calls is potential expensive since it probes the interface every time
174  alarms_timestamp_ = std::chrono::system_clock::now();
175  if(alarms_.size())
176  __COUT__ << "checkSlowControlsAlarms() found count = " << alarms_.size()
177  << __E__;
178 
179  try
180  {
181  for(const auto& alarm : alarms_)
182  {
183  if(alarm.size() > 8)
184  {
185  time_t rawtime = static_cast<time_t>(std::stoi(alarm[1]));
186  char* dt = ctime(&rawtime);
187  std::string subject = "Slow Control Alarm Notification";
188  std::string message = "PV: " + alarm[0] + "\n" + " at time: " + dt +
189  "\n" + " value: " + alarm[2] + "" +
190  " status: " + alarm[3] + "" +
191  " severity: " + alarm[4];
192 
193  __COUTT__ << "checkSlowControlsAlarms() subject '" << subject
194  << "' message '" << message << "' alarm name '" << alarm[5]
195  << "' notify to '" << alarm[8] << "' at '" << alarm[6]
196  << "' send mail " << alarm[7] << __E__;
197 
198  // toList can be "*", or "Tracker:10", "Ryan, Antonio"
199  // theRemoteWebUsers_.sendSystemMessage(
200  // "*" /*toList*/, "Subject", "Message", false /*doEmail*/);
201  theRemoteWebUsers_.sendSystemMessage(
202  alarm[6], subject, message, alarm[7] == "Yes" ? true : false);
203  }
204  }
205  }
206  catch(const std::runtime_error& e)
207  {
208  __SS__ << e.what() << '\n';
209  std::lock_guard<std::mutex> lock(cs->alarmCheckThreadErrorMutex_);
210  cs->alarmCheckThreadError_ = ss.str();
211  __COUT_ERR__ << ss.str();
212  }
213  catch(const std::exception& e)
214  {
215  __SS__ << e.what() << '\n';
216  std::lock_guard<std::mutex> lock(cs->alarmCheckThreadErrorMutex_);
217  cs->alarmCheckThreadError_ = ss.str();
218  __COUT_ERR__ << ss.str();
219  }
220  catch(...)
221  {
222  __SS__ << "checkSlowControlsAlarms() ERROR While sendin alarm messages"
223  << __E__;
224  try
225  {
226  throw;
227  } //one more try to printout extra info
228  catch(const std::exception& e)
229  {
230  ss << "Exception message: " << e.what();
231  }
232  catch(...)
233  {
234  }
235  std::lock_guard<std::mutex> lock(cs->alarmCheckThreadErrorMutex_);
236  cs->alarmCheckThreadError_ = ss.str();
237  __COUT_ERR__ << ss.str();
238  }
239 
240  sleep(alarmNotifyRefreshRate_);
241  } //end primary loop
242 } // end checkSlowControlsAlarms()
243 
244 //==============================================================================
248 {
249  __COUT__ << "checkSubscriptions() initializing..." << __E__;
250  std::vector<std::string> channelList;
251  std::vector<int> channelRefreshRates;
252  while(true)
253  {
254  channelList = {"FIRST VALUE"};
255  channelRefreshRates = {};
256  std::map<int, std::set<std::string>>::iterator mapReference =
257  cs->channelDependencyLookupMap_.begin();
258  while(mapReference !=
259  cs->channelDependencyLookupMap_
260  .end()) // We have here current list of Channel Dependencies
261  {
262  for(auto channel : mapReference->second)
263  {
264  int refreshRate = 15; // seconds
265  channelRefreshRates.push_back(refreshRate);
266 
267  __COUT__ << "THREAD actual time: " << std::time(NULL)
268  << "; uidPollTimeMap + 10 * refreshTime: "
269  << cs->uidPollTimeMap_.at(mapReference->first) + 10 * refreshRate
270  << " seconds" << __E__;
271  if(std::time(NULL) >
272  cs->uidPollTimeMap_.at(mapReference->first) + 10 * refreshRate)
273  {
274  try
275  {
276  cs->channelDependencyLookupMap_.erase(mapReference->first);
277  continue;
278  }
279  catch(const std::exception& e)
280  {
281  continue;
282  }
283  }
284 
285  std::vector<std::string>::iterator it =
286  find(channelList.begin(), channelList.end(), channel);
287  if(it == channelList.end())
288  {
289  // cs->interface_->unsubscribe(channel);
290  // cs->interface_->subscribe(channel);
291  channelList.push_back(channel);
292  __COUT__ << "Channel: " << channel << " refreshRate: " << refreshRate
293  << " seconds" << __E__;
294  __COUT__ << "channelDependencyLookupMap_.size(): "
295  << cs->channelDependencyLookupMap_.size()
296  << " UID: " << mapReference->first
297  << " mapReference->second.size(): "
298  << mapReference->second.size() << __E__;
299  }
300 
301  sleep(1);
302  }
303  mapReference++;
304  }
305  int minTime = 30; // seconds
306  if(channelRefreshRates.size() > 0)
307  minTime =
308  *min_element(channelRefreshRates.begin(), channelRefreshRates.end());
309  sleep(minTime);
310  __COUT__ << "Loop over channels subscribing - waiting time: " << minTime
311  << " seconds" << __E__;
312  }
313 }
314 
315 //==============================================================================
320 {
321  CorePropertySupervisorBase::setSupervisorProperty(
322  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.CheckUserLockRequestTypes, "*");
323 
324 } // end setSupervisorPropertyDefaults()
325 
326 //==============================================================================
330 {
331  CorePropertySupervisorBase::setSupervisorProperty(
332  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes, "poll");
333 
334  if(CorePropertySupervisorBase::isReadOnly())
335  {
336  CorePropertySupervisorBase::setSupervisorProperty(
337  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold,
338  "*=0 | getPages=1 | loadPhoebusPage=1 | getList=1 | getPVSettings=1 | getPvArchiverData=1 | generateUID=1 | getUserPermissions=1 |\
339  userActivityHeartbeat=1 | poll=1 | uid=1 | isUserAdmin=1 | getLastAlarmsData=1 | getAlarmsLogData=1 | getAlarmsCheck=1 | getPvData=1 "); // block users from writing if no write access
340  __COUT_INFO__ << "readOnly true in setSupervisorProperty" << __E__;
341  }
342 } //end forceSupervisorPropertyValues()
343 
344 //==============================================================================
345 void SlowControlsDashboardSupervisor::request(const std::string& requestType,
346  cgicc::Cgicc& cgiIn,
347  HttpXmlDocument& xmlOut,
348  const WebUsers::RequestUserInfo& userInfo)
349 {
350  try
351  {
352  if(requestType != "getPages" && !pluginBusyMutex_.try_lock())
353  {
354  __SUP_SS__ << "Controls plugin is still initializing. Please try again in a "
355  "few minutes!"
356  << __E__;
357  __SUP_SS_THROW__;
358  }
359 
360  __SUP_COUT__ << "User name is " << userInfo.username_ << "." << __E__;
361  __SUP_COUT__ << "User permission level for request '" << requestType << "' is "
362  << unsigned(userInfo.permissionLevel_)
363  << "(isAdmin=" << (userInfo.isAdmin() ? "Yes" : "No") << ")."
364  << __E__;
365 
366  // handle request per requestType
367  handleRequest(requestType, xmlOut, cgiIn, userInfo);
368  }
369  catch(const std::runtime_error& e)
370  {
371  __SUP_SS__ << "Error occurred handling request '" << requestType
372  << "': " << e.what() << __E__;
373  __SUP_COUT__ << ss.str();
374  xmlOut.addTextElementToData("Error", ss.str());
375  }
376  catch(...)
377  {
378  __SS__ << "Unknown error occurred handling request '" << requestType << "!'"
379  << __E__;
380  try
381  {
382  throw;
383  } //one more try to printout extra info
384  catch(const std::exception& e)
385  {
386  ss << "Exception message: " << e.what();
387  }
388  catch(...)
389  {
390  }
391  __SUP_COUT__ << ss.str();
392  xmlOut.addTextElementToData("Error", ss.str());
393  }
394 
395  pluginBusyMutex_.unlock();
396  __SUP_COUT__ << __E__;
397 } // end request()
398 
399 //==============================================================================
400 void SlowControlsDashboardSupervisor::handleRequest(
401  const std::string Command,
402  HttpXmlDocument& xmlOut,
403  cgicc::Cgicc& cgiIn,
404  const WebUsers::RequestUserInfo& userInfo)
405 {
406  // return xml doc holding server response
407  __SUP_COUT__ << __E__;
408 
409  if(Command == "poll")
410  {
411  std::string uid = CgiDataUtilities::getOrPostData(cgiIn, "uid");
412  Poll(cgiIn, xmlOut, uid);
413  }
414  else if(Command == "getPvData")
415  {
416  Poll(cgiIn, xmlOut);
417  }
418  else if(Command == "userActivityHeartbeat")
419  {
420  // web client code should call this while user is building
421  // in Edit Mode.
422  // Do nothing, just keep login alive
423  }
424  else if(Command == "generateUID")
425  {
426  std::string channelList = CgiDataUtilities::getOrPostData(cgiIn, "pvList");
427  GenerateUID(cgiIn, xmlOut, channelList);
428  }
429  else if(Command == "isUserAdmin")
430  {
431  std::string json = std::string("{ \"message\": \"");
432  json += (userInfo.isAdmin() ? "Yes" : "No");
433  json += "\"}";
434  xmlOut.addTextElementToData("JSON", json.c_str());
435  }
436  else if(Command == "getUserPermissions")
437  {
438  GetUserPermissions(cgiIn, xmlOut, userInfo);
439  }
440  else if(Command == "getPVSettings")
441  {
442  __SUP_COUT__ << "Channel settings requested from server! " << __E__;
443  GetChannelSettings(cgiIn, xmlOut);
444  xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id"));
445  }
446  else if(Command == "getPvArchiverData")
447  {
448  __SUP_COUT__ << "Archived Channel data requested from server! " << __E__;
449  GetChannelArchiverData(cgiIn, xmlOut);
450  xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id"));
451  }
452  else if(Command == "getList")
453  {
454  __SUP_COUT__ << "Channel List requested from server! " << __E__;
455  GetList(cgiIn, xmlOut);
456  }
457  else if(Command == "getPages")
458  {
459  __SUP_COUT__ << "Requesting pages from server! " << __E__;
460  GetPages(cgiIn, xmlOut);
461  }
462  else if(Command == "loadPage")
463  {
464  std::string page = CgiDataUtilities::getData(cgiIn, "Page");
465  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << page
466  << __E__;
467 
468  loadPage(cgiIn, xmlOut, page, userInfo);
469  }
470  else if(Command == "loadPhoebusPage")
471  {
472  std::string page = CgiDataUtilities::getData(cgiIn, "Page");
473  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << page
474  << __E__;
475 
476  loadPhoebusPage(cgiIn, xmlOut, page, userInfo);
477  }
478  else if(Command == "createControlsPage")
479  {
480  SaveControlsPage(cgiIn, xmlOut, userInfo);
481  }
482  else if(Command == "createPhoebusControlsPage")
483  {
484  SavePhoebusControlsPage(cgiIn, xmlOut, userInfo);
485  }
486  else if(Command == "getLastAlarmsData")
487  {
488  __SUP_COUT__ << "Last Alarms Data requested from server! " << __E__;
489  GetLastAlarmsData(cgiIn, xmlOut);
490  xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id"));
491  }
492  else if(Command == "getAlarmsLogData")
493  {
494  __SUP_COUT__ << "Alarms Log Data requested from server! " << __E__;
495  GetAlarmsLogData(cgiIn, xmlOut);
496  xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id"));
497  }
498  else if(Command == "getAlarmsCheck")
499  {
500  __SUP_COUT__ << "Alarms Data requested from server! " << __E__;
501  GetAlarmsCheck(xmlOut);
502  }
503  else if(Command == "saveImageFile")
504  {
505  saveImageFile(cgiIn, xmlOut, userInfo);
506  }
507  else
508  {
509  __SUP_SS__ << "Request, " << Command
510  << ", not recognized by the Slow Controls Dashboard Supervisor (was "
511  "it intended for another Supervisor?)."
512  << __E__;
513  __SUP_SS_THROW__;
514  }
515 
516  __SUP_COUT__ << "" << __E__;
517 } // end handleRequest()
518 
519 //==============================================================================
520 void SlowControlsDashboardSupervisor::Poll(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
521 {
522  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
523  std::set<std::string> channels;
524  StringMacros::getSetFromString(channelList, channels);
525 
526  xmlOut.addTextElementToData("JSON", PollChannels_(channels));
527 } //end Poll()
528 
529 //==============================================================================
530 void SlowControlsDashboardSupervisor::Poll(cgicc::Cgicc& /*cgiIn*/,
531  HttpXmlDocument& xmlOut,
532  std::string UID)
533 {
534  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
535  << "Polling on UID:" << UID << __E__;
536 
537  std::map<int, std::set<std::string>>::iterator mapReference;
538 
539  if(UID != "" && (mapReference = channelDependencyLookupMap_.find(std::stoi(UID))) !=
540  channelDependencyLookupMap_
541  .end()) // We have their current list of Channel Dependencies
542  {
543  uidPollTimeMap_.at(std::stoi(UID)) = std::time(NULL);
544 
545  xmlOut.addTextElementToData(
546  "JSON", PollChannels_(mapReference->second)); // add to response
547  }
548  else // UID is not in our map so force them to generate a new one
549  {
550  xmlOut.addTextElementToData("JSON",
551  "{ \"message\": \"NOT_FOUND\"}"); // add to response
552  }
553 } //end Poll()
554 
555 //==============================================================================
556 std::string SlowControlsDashboardSupervisor::PollChannels_(
557  std::set<std::string>& channels, bool resubscibe /*=true*/)
558 {
559  std::string JSONMessage = "{ ";
560 
561  for(auto channel : channels)
562  {
563  // channel = channel.substr(0, channel.find(":"));
564 
565  __SUP_COUT__ << channel << __E__;
566 
567  std::array<std::string, 4> channelInformation =
568  interface_->getCurrentValue(channel);
569 
570  __SUP_COUT__ << channel << ": " << channelInformation[1] << " : "
571  << channelInformation[3] << __E__;
572 
573  if(channelInformation[0] != "NO_CHANGE")
574  {
575  //__SUP_COUT__ << "Reached" << __E__;
576  JSONMessage += "\"" + channel + "\": {";
577  JSONMessage += "\"Timestamp\":\"" + channelInformation[0] + "\",";
578  JSONMessage += "\"Value\":\"" + channelInformation[1] + "\",";
579  JSONMessage += "\"Status\":\"" + channelInformation[2] + "\",";
580  JSONMessage += "\"Severity\":\"" + channelInformation[3] + "\"},";
581  }
582  else
583  {
584  __SUP_COUT__ << "No change in value since last poll: " << channel << __E__;
585  }
586 
587  // Handle Channels that disconnect, etc
588  if(channelInformation[3] == "INVALID" && resubscibe)
589  {
590  interface_->unsubscribe(channel);
591  interface_->subscribe(channel);
592  }
593  }
594 
595  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
596  JSONMessage += "}";
597  __SUP_COUT__ << JSONMessage << __E__;
598  return JSONMessage;
599 } //end PollChannels_()
600 
601 //==============================================================================
602 void SlowControlsDashboardSupervisor::GetChannelSettings(cgicc::Cgicc& cgiIn,
603  HttpXmlDocument& xmlOut)
604 {
605  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
606 
607  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
608  << "Getting settings for " << channelList << __E__;
609 
610  std::string JSONMessage = "{ ";
611 
612  __SUP_COUT__ << "**********************" << channelList.size() << __E__;
613  if(channelList.size() > 0)
614  {
615  std::string channel;
616  size_t pos = 0;
617  size_t nextPos;
618  while((nextPos = channelList.find(",", pos)) != std::string::npos)
619  {
620  channel = channelList.substr(pos, nextPos - pos);
621 
622  __SUP_COUT__ << channel << __E__;
623 
624  std::array<std::string, 9> channelSettings = interface_->getSettings(channel);
625 
626  JSONMessage += "\"" + channel + "\": {";
627  JSONMessage += "\"Units\": \"" + channelSettings[0] + "\",";
628  JSONMessage += "\"Upper_Display_Limit\": \"" + channelSettings[1] + "\",";
629  JSONMessage += "\"Lower_Display_Limit\": \"" + channelSettings[2] + "\",";
630  JSONMessage += "\"Upper_Alarm_Limit\": \"" + channelSettings[3] + "\",";
631  JSONMessage += "\"Upper_Warning_Limit\": \"" + channelSettings[4] + "\",";
632  JSONMessage += "\"Lower_Warning_Limit\": \"" + channelSettings[5] + "\",";
633  JSONMessage += "\"Lower_Alarm_Limit\": \"" + channelSettings[6] + "\",";
634  JSONMessage += "\"Upper_Control_Limit\": \"" + channelSettings[7] + "\",";
635  JSONMessage += "\"Lower_Control_Limit\": \"" + channelSettings[8] + "\"},";
636 
637  pos = nextPos + 1;
638  }
639 
640  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
641  JSONMessage += "}";
642 
643  __SUP_COUT__ << JSONMessage << __E__;
644  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
645  }
646  else
647  {
648  __SUP_COUT__ << "Did not find any settings because Channel list is length zero!"
649  << __E__;
650 
651  xmlOut.addTextElementToData(
652  "JSON", "{ \"message\": \"GetPVSettings\"}"); // add to response
653  }
654 } //end GetChannelSettings()
655 
656 //==============================================================================
657 void SlowControlsDashboardSupervisor::GetChannelArchiverData(cgicc::Cgicc& cgiIn,
658  HttpXmlDocument& xmlOut)
659 {
660  __SUP_COUT__ << "Requesting archived data!" << __E__;
661 
662  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
663  int startTime = stoi(CgiDataUtilities::postData(cgiIn, "startTime"));
664  int endTime = stoi(CgiDataUtilities::postData(cgiIn, "endTime"));
665 
666  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
667  << "Getting History for " << channelList << " start time: " << startTime
668  << " end time: " << endTime << __E__;
669 
670  __SUP_COUT__ << "channelList.size(): " << channelList.size() << __E__;
671  if(channelList.size() > 0 && startTime > 0 && endTime > 0)
672  {
673  std::string channel;
674  size_t pos = 0;
675  size_t nextPos;
676  while((nextPos = channelList.find(",", pos)) != std::string::npos)
677  {
678  channel = channelList.substr(pos, nextPos - pos);
679 
680  __SUP_COUT__ << "Getting History for " << channel << __E__;
681 
682  std::vector<std::vector<std::string>> channelInformation =
683  interface_->getChannelHistory(channel, startTime, endTime);
684 
685  for(auto channelData : channelInformation)
686  {
687  std::string JSONMessage = "{ ";
688  JSONMessage += "\"" + channel + "\": {";
689  JSONMessage += "\"Timestamp\":\"" + channelData[0] + "\",";
690  JSONMessage += "\"Value\":\"" + channelData[1] + "\",";
691  JSONMessage += "\"Status\":\"" + channelData[2] + "\",";
692  JSONMessage += "\"Severity\":\"" + channelData[3] + "\"},";
693 
694  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
695  JSONMessage += "}";
696  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
697  }
698  //__SUP_COUT__ << JSONMessage << __E__;
699  pos = nextPos + 1;
700  }
701  }
702  else
703  {
704  __SUP_COUT__ << "Did not find any data because Channel list is length zero!"
705  << __E__;
706 
707  xmlOut.addTextElementToData(
708  "JSON", "{ \"message\": \"GetChannelArchiverData\"}"); // add to response
709  }
710 } // end GetChannelArchiverData()
711 
712 //==============================================================================
713 void SlowControlsDashboardSupervisor::GetLastAlarmsData(cgicc::Cgicc& cgiIn,
714  HttpXmlDocument& xmlOut)
715 {
716  __SUP_COUT__ << "Requesting last alarms data!" << __E__;
717 
718  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
719 
720  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
721  << "Getting last Alarms for " << channelList << __E__;
722  __SUP_COUT__ << "channelList.size(): " << channelList.size() << __E__;
723 
724  std::vector<std::vector<std::string>> alarms;
725 
726  // create lambda function to fill JSONMessage
727  std::function<void(HttpXmlDocument&, std::vector<std::vector<std::string>>&)>
728  jsonFiller = [](HttpXmlDocument& xmlOut,
729  std::vector<std::vector<std::string>>& alarms) {
730  if(alarms.size())
731  for(auto& alarmRow : alarms)
732  {
733  std::string JSONMessage = "{ ";
734  JSONMessage += "\"id\":\"" + alarmRow[0] + "\",";
735  JSONMessage += "\"pvName\":\"" + alarmRow[1] + "\",";
736  JSONMessage += "\"pvDescription\":\"" + alarmRow[2] + "\",";
737  JSONMessage += "\"pvValue\":\"" + alarmRow[3] + "\",";
738  JSONMessage += "\"pvStatus\":\"" + alarmRow[4] + "\",";
739  JSONMessage += "\"pvSeverity\":\"" + alarmRow[5] + "\",";
740  JSONMessage += "\"pvTime\":\"" + alarmRow[6] + "\",";
741 
742  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
743  JSONMessage += "}";
744  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
745  // __SUP_COUT__ << JSONMessage << __E__;
746  }
747  };
748 
749  if(channelList.size() > 0)
750  {
751  std::string channel;
752  size_t pos = 0;
753  size_t nextPos;
754  while((nextPos = channelList.find(",", pos)) != std::string::npos)
755  {
756  channel = channelList.substr(pos, nextPos - pos);
757 
758  alarms = interface_->getLastAlarms(channel);
759  __SUP_COUT__ << "get Last Alarms for channel: " << channel << __E__;
760  jsonFiller(xmlOut, alarms);
761  pos = nextPos + 1;
762  }
763  }
764  else
765  {
766  alarms = interface_->getLastAlarms("");
767  __SUP_COUT__ << "get Last Alarms for all channels" << __E__;
768  jsonFiller(xmlOut, alarms);
769  }
770 } // end GetLastAlarmsData()
771 
772 //==============================================================================
773 void SlowControlsDashboardSupervisor::GetAlarmsCheck(HttpXmlDocument& xmlOut)
774 {
775  __SUP_COUT__ << "Requesting alarms check cache data!" << __E__;
776 
777  std::string JSONMessage = "{ ";
778  JSONMessage += "\"last_check\":" +
779  std::to_string(std::chrono::duration_cast<std::chrono::seconds>(
780  alarms_timestamp_.time_since_epoch())
781  .count()) +
782  ",";
783  JSONMessage += "\"total\":" + std::to_string(alarms_.size()) + ",";
784  JSONMessage += "\"alarms\": [";
785  unsigned int nactive = 0;
786  if(alarms_.size())
787  {
788  for(auto& alarmRow : alarms_)
789  {
790  JSONMessage += "{ ";
791  JSONMessage += "\"name\":\"" + alarmRow[0] + "\",";
792  if(alarmRow.size() > 9)
793  { // alarm present
794  ++nactive;
795  JSONMessage += "\"time\":\"" + alarmRow[1] + "\",";
796  JSONMessage += "\"value\":\"" + alarmRow[2] + "\",";
797  JSONMessage += "\"status\":\"" + alarmRow[3] + "\",";
798  JSONMessage += "\"severity\":\"" + alarmRow[4] + "\",";
799  }
800  JSONMessage =
801  JSONMessage.substr(0, JSONMessage.length() - 1); // get rid of last ,
802  JSONMessage += "},";
803  } //end alarm loop
804  JSONMessage =
805  JSONMessage.substr(0, JSONMessage.length() - 1); // get rid of last ,
806  }
807  JSONMessage += "], \"nactive\": " + std::to_string(nactive);
808  JSONMessage += "}";
809  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
810 } // end GetAlarmsCheck()
811 
812 //==============================================================================
813 void SlowControlsDashboardSupervisor::GetAlarmsLogData(cgicc::Cgicc& cgiIn,
814  HttpXmlDocument& xmlOut)
815 {
816  __SUP_COUT__ << "Requesting alarms log data!" << __E__;
817 
818  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
819 
820  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
821  << "Getting Alarms Log for " << channelList << __E__;
822  __SUP_COUT__ << "channelList.size(): " << channelList.size() << __E__;
823 
824  std::vector<std::vector<std::string>> alarmsLog;
825 
826  // create lambda function to fill JSONMessage
827  std::function<void(HttpXmlDocument&, std::vector<std::vector<std::string>>&)>
828  jsonFiller = [](HttpXmlDocument& xmlOut,
829  std::vector<std::vector<std::string>>& alarmsLog) {
830  if(alarmsLog.size())
831  for(auto& alarmRow : alarmsLog)
832  {
833  std::string JSONMessage = "{ ";
834  JSONMessage += "\"id\":\"" + alarmRow[0] + "\",";
835  JSONMessage += "\"pvName\":\"" + alarmRow[1] + "\",";
836  JSONMessage += "\"pvValue\":\"" + alarmRow[2] + "\",";
837  JSONMessage += "\"pvStatus\":\"" + alarmRow[3] + "\",";
838  JSONMessage += "\"pvSeverity\":\"" + alarmRow[4] + "\",";
839  JSONMessage += "\"pvTime\":\"" + alarmRow[5] + "\",";
840 
841  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
842  JSONMessage += "}";
843  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
844  // __SUP_COUT__ << JSONMessage << __E__;
845  }
846  };
847 
848  if(channelList.size() > 0)
849  {
850  std::string channel;
851  size_t pos = 0;
852  size_t nextPos;
853  while((nextPos = channelList.find(",", pos)) != std::string::npos)
854  {
855  channel = channelList.substr(pos, nextPos - pos);
856 
857  alarmsLog = interface_->getAlarmsLog(channel);
858  __SUP_COUT__ << "get Alarms Log for channel: " << channel << __E__;
859  jsonFiller(xmlOut, alarmsLog);
860  pos = nextPos + 1;
861  }
862  }
863  else
864  {
865  alarmsLog = interface_->getAlarmsLog("");
866  __SUP_COUT__ << "get Alarms Log for all channels" << __E__;
867  jsonFiller(xmlOut, alarmsLog);
868  }
869 } // end GetAlarmsLogData()
870 
871 //==============================================================================
872 void SlowControlsDashboardSupervisor::GetUserPermissions(
873  cgicc::Cgicc& /*cgiIn*/,
874  HttpXmlDocument& /*xmlOut*/,
875  const WebUsers::RequestUserInfo& /*userInfo*/)
876 {
877  return;
878 }
879 
880 //==============================================================================
881 void SlowControlsDashboardSupervisor::GenerateUID(cgicc::Cgicc& /*cgiIn*/,
882  HttpXmlDocument& xmlOut,
883  std::string channelList)
884 {
885  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
886  << "Generating UID" << __E__;
887 
888  std::set<std::string> channelDependencies;
889  StringMacros::getSetFromString(channelList, channelDependencies);
890 
891  // make entry for new UID_ in UID-to-channel map
892  channelDependencyLookupMap_.insert(
893  std::pair<int, std::set<std::string>>(++UID_, channelDependencies));
894 
895  uidPollTimeMap_.insert(std::pair<int, long int>(UID_, std::time(NULL)));
896 
897  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " NEW UID: " << UID_
898  << " maps to " << channelDependencies.size() << " channels" << __E__;
899 
900  xmlOut.addTextElementToData("JSON",
901  std::string("{ \"message\": \"") + std::to_string(UID_) +
902  "\"}"); // add to response
903 } // end GenerateUID()
904 
905 //==============================================================================
906 void SlowControlsDashboardSupervisor::GetList(cgicc::Cgicc& /*cgiIn*/,
907  HttpXmlDocument& xmlOut)
908 {
909  if(interface_ != NULL)
910  {
911  __SUP_COUT__ << "Interface is defined! Attempting to get list!" << __E__;
912  // __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
913  // __E__;
914  std::string list;
915  try
916  {
917  list = interface_->getList("JSON");
918  }
919  catch(std::runtime_error& e)
920  {
921  __SUP_SS__ << "Channel list request failed: " << e.what() << __E__;
922  __SUP_SS_THROW__;
923  }
924 
925  __SUP_COUT__ << " " << list << __E__;
926 
927  xmlOut.addTextElementToData("JSON", list); // add to response
928  }
929  else
930  {
931  __SUP_COUT__ << "Interface undefined! Failed to get list!" << __E__;
932  xmlOut.addTextElementToData("JSON", "[\"None\"]");
933  }
934 } // end GetList()
935 
936 //==============================================================================
937 void SlowControlsDashboardSupervisor::GetPages(cgicc::Cgicc& /*cgiIn*/,
938  HttpXmlDocument& xmlOut)
939 {
940  std::vector<std::string> pages;
941 
942  listFiles("", true, &pages);
943 
944  std::string returnJSON = "[";
945  for(auto it = pages.begin(); it != pages.end(); it++)
946  {
947  if(*it != "." && *it != "..")
948  returnJSON += "\"" + *it + "\", ";
949  }
950  if(returnJSON.size() > 2 && returnJSON.compare("[") != 0)
951  {
952  __SUP_COUT__ << "Found pages on server!" << __E__;
953  returnJSON.resize(returnJSON.size() - 2);
954  returnJSON += "]";
955  }
956  else
957  {
958  // No pages on the server
959  __SUP_COUT__ << "No pages found on server!" << __E__;
960  returnJSON = "[\"None\"]";
961  }
962  __SUP_COUT__ << returnJSON << __E__;
963 
964  xmlOut.addTextElementToData("JSON", returnJSON); // add to response
965 } // end GetPages()
966 
967 //==============================================================================
968 void SlowControlsDashboardSupervisor::loadPage(
969  cgicc::Cgicc& /*cgiIn*/,
970  HttpXmlDocument& xmlOut,
971  std::string page,
972  const WebUsers::RequestUserInfo& /*userInfo*/)
973 {
975 
976  // FIXME Filter out malicious attacks i.e. ../../../../../ stuff
977  struct stat buffer;
978  if(page.find("..") != std::string::npos)
979  {
980  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
981  << "Error! Request using '..': " << page << __E__;
982  }
983  else if(page.find("~") != std::string::npos)
984  {
985  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
986  << "Error! Request using '~': " << page << __E__;
987  }
988  else if(!(stat(page.c_str(), &buffer) == 0))
989  {
990  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
991  << "Error! File not found: " << page << __E__;
992  }
993  // Remove double / in path
994 
995  __SUP_COUT__ << page << __E__;
996 
997  if(page.at(0) == '/')
998  {
999  __SUP_COUT__ << "First character is '/'" << __E__;
1000  page.erase(page.begin(), page.begin() + 1);
1001  __SUP_COUT__ << page << __E__;
1002  }
1003 
1004  std::string file = PAGES_DIRECTORY;
1005  file += page;
1006  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1007  << "Trying to load page: " << page << __E__;
1008  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1009  << "Trying to load page: " << file << __E__;
1010  // read file
1011  // for each line in file
1012 
1013  std::ifstream infile(file);
1014  if(infile.fail())
1015  {
1016  __SUP_COUT__ << "Failed reading file: " << file << __E__;
1017 
1018  xmlOut.addTextElementToData("Time", "[\"Not Found\"]"); // add to response
1019  xmlOut.addTextElementToData("Notes", "[\"Not Found\"]"); // add to response
1020  xmlOut.addTextElementToData(
1021  "Page", StringMacros::encodeURIComponent(page)); // add to response
1022  return;
1023  }
1024  __SUP_COUT__ << "Reading file" << __E__;
1025 
1026  std::string time = "";
1027  std::string notes = "";
1028  std::string controlsPage = "";
1029 
1030  for(std::string line; getline(infile, line);)
1031  {
1032  __SUP_COUT__ << line << __E__;
1033  if(!line.substr(0, 5).compare("Time:"))
1034  {
1035  time = line.substr(6);
1036  }
1037  else if(!line.substr(0, 6).compare("Notes:"))
1038  {
1039  notes = line.substr(7);
1040  }
1041  else if(!line.substr(0, 5).compare("Page:"))
1042  {
1043  controlsPage = line.substr(6);
1044  }
1045  }
1046  __SUP_COUT__ << "Finished reading file" << __E__;
1047  __SUP_COUTV__(time);
1048  __SUP_COUTV__(notes);
1049  __SUP_COUTV__(controlsPage);
1050 
1051  xmlOut.addTextElementToData("Time", time); // add to response
1052  xmlOut.addTextElementToData("Notes", notes); // add to response
1053  xmlOut.addTextElementToData("Page", controlsPage); // add to response
1054 } // end loadPage()
1055 
1056 //==============================================================================
1057 void SlowControlsDashboardSupervisor::loadPhoebusPage(
1058  cgicc::Cgicc& /*cgiIn*/,
1059  HttpXmlDocument& xmlOut,
1060  std::string page,
1061  const WebUsers::RequestUserInfo& /*userInfo*/)
1062 {
1063  page = StringMacros::decodeURIComponent(page);
1064 
1065  // FIXME Filter out malicious attacks i.e. ../../../../../ stuff
1066  struct stat buffer;
1067  if(page.find("..") != std::string::npos)
1068  {
1069  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1070  << "Error! Request using '..': " << page << __E__;
1071  }
1072  else if(page.find("~") != std::string::npos)
1073  {
1074  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1075  << "Error! Request using '~': " << page << __E__;
1076  }
1077  else if(!(stat(page.c_str(), &buffer) == 0))
1078  {
1079  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1080  << "Error! File not found: " << page << __E__;
1081  }
1082  // Remove double / in path
1083 
1084  __SUP_COUT__ << page << __E__;
1085 
1086  if(page.at(0) == '/')
1087  {
1088  __SUP_COUT__ << "First character is '/'" << __E__;
1089  page.erase(page.begin(), page.begin() + 1);
1090  __SUP_COUT__ << page << __E__;
1091  }
1092 
1093  std::string file = PAGES_DIRECTORY;
1094  file += page;
1095  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1096  << "Trying to load page: " << page << __E__;
1097  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1098  << "Trying to load page: " << file << __E__;
1099 
1100  // read file
1101  __SUP_COUT__ << "Reading file" << __E__;
1102  std::ifstream infile(file);
1103  if(infile.fail())
1104  {
1105  __SUP_COUT__ << "Failed reading file: " << file << __E__;
1106  xmlOut.addTextElementToData(
1107  "Page", StringMacros::encodeURIComponent(page)); // add to response
1108  return;
1109  }
1110 
1111  std::string xml;
1112  for(std::string line; getline(infile, line);)
1113  {
1114  xml += line + "\n";
1115  }
1116  __SUP_COUT__ << xml << __E__;
1117  xmlOut.addTextElementToData("PHOEBUS", xml);
1118 
1119 } // end loadPhoebusPage()
1120 
1121 //==============================================================================
1122 void SlowControlsDashboardSupervisor::SaveControlsPage(
1123  cgicc::Cgicc& cgiIn,
1124  HttpXmlDocument& /*xmlOut*/,
1125  const WebUsers::RequestUserInfo& /*userInfo*/)
1126 {
1127  __SUP_COUT__ << "ControlsDashboard wants to create a Controls Page!" << __E__;
1128 
1129  std::string controlsPageName = CgiDataUtilities::postData(cgiIn, "Name");
1130  std::string pageString = CgiDataUtilities::postData(cgiIn, "Page");
1131  std::string Time = CgiDataUtilities::postData(cgiIn, "Time");
1132  std::string Notes =
1134  std::string isControlsPagePublic = CgiDataUtilities::postData(cgiIn, "isPublic");
1135 
1136  __SUP_COUTV__(controlsPageName);
1137  __SUP_COUTV__(pageString);
1138  __SUP_COUTV__(Notes);
1139  __SUP_COUTV__(Time);
1140  __SUP_COUTV__(isControlsPagePublic);
1141 
1142  if(controlsPageName == "")
1143  return;
1144 
1145  std::string fullPath;
1146  if(isControlsPagePublic == "true")
1147  fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1148  else
1149  fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1150 
1151  __SUP_COUTV__(fullPath);
1152 
1153  std::string file = fullPath + controlsPageName;
1154 
1155  __SUP_COUTV__("Saving Controls Page to: " + file);
1156 
1157  std::string extension = file.substr(file.length() - 4, 4);
1158  if(extension != ".dat")
1159  {
1160  __SUP_COUT__ << "Extension : " << extension << __E__;
1161  file += std::string(".dat");
1162  }
1163  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1164  << "Trying to save page: " << controlsPageName << __E__;
1165  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1166  << "Trying to save page as: " << file << __E__;
1167  // read file
1168  // for each line in file
1169 
1170  std::ofstream outputFile;
1171  outputFile.open(file);
1172  if(!outputFile.is_open())
1173  {
1174  __SUP_SS__ << "Failed to open file for writing: " << file << __E__;
1175  __SUP_SS_THROW__;
1176  }
1177  outputFile << "Time: " << Time << "\n";
1178  outputFile << "Notes: " << Notes << "\n";
1179  outputFile << "Page: " << pageString;
1180  outputFile.close();
1181 
1182  __SUP_COUT__ << "Finished writing file" << __E__;
1183 
1184  return;
1185 }
1186 
1187 //==============================================================================
1188 void SlowControlsDashboardSupervisor::SavePhoebusControlsPage(
1189  cgicc::Cgicc& cgiIn,
1190  HttpXmlDocument& /*xmlOut*/,
1191  const WebUsers::RequestUserInfo& /*userInfo*/)
1192 {
1193  __SUP_COUT__ << "ControlsDashboard wants to create a Controls Page!" << __E__;
1194 
1195  std::string controlsPageName = CgiDataUtilities::postData(cgiIn, "Name");
1196  std::string pageString = CgiDataUtilities::postData(cgiIn, "Page");
1197  std::string isControlsPagePublic = CgiDataUtilities::postData(cgiIn, "isPublic");
1198 
1199  __SUP_COUTV__(controlsPageName);
1200  __SUP_COUTV__(pageString);
1201  __SUP_COUTV__(isControlsPagePublic);
1202 
1203  if(controlsPageName == "")
1204  return;
1205 
1206  std::string fullPath;
1207  if(isControlsPagePublic == "true")
1208  fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1209  else
1210  fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1211 
1212  __SUP_COUTV__(fullPath);
1213 
1214  std::string file = fullPath + controlsPageName;
1215 
1216  __SUP_COUTV__("Saving Controls Page to: " + file);
1217 
1218  std::string extension = file.substr(file.length() - 4, 4);
1219  if(extension != ".bob")
1220  {
1221  __SUP_COUT__ << "Extension : " << extension << __E__;
1222  file += std::string(".bob");
1223  }
1224  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1225  << "Trying to save page: " << controlsPageName << __E__;
1226  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1227  << "Trying to save page as: " << file << __E__;
1228  // read file
1229  // for each line in file
1230 
1231  std::ofstream outputFile;
1232  outputFile.open(file);
1233  if(!outputFile.is_open())
1234  {
1235  __SUP_SS__ << "Failed to open file for writing: " << file << __E__;
1236  __SUP_SS_THROW__;
1237  }
1238  outputFile << pageString << "\n";
1239  outputFile.close();
1240 
1241  __SUP_COUT__ << "Finished writing file" << __E__;
1242 
1243  return;
1244 }
1245 
1246 //==============================================================================
1247 void SlowControlsDashboardSupervisor::saveImageFile(
1248  cgicc::Cgicc& cgiIn,
1249  HttpXmlDocument& /*xmlOut*/,
1250  const WebUsers::RequestUserInfo& /*userInfo*/)
1251 {
1252  __SUP_COUT__ << "ControlsDashboard wants to save the image file uploaded!" << __E__;
1253 
1254  std::string isImagePublic = cgiIn("isPublic");
1255  const std::vector<cgicc::FormFile>& files = cgiIn.getFiles();
1256  std::string filename;
1257  std::ofstream myfile;
1258  std::string fullPath;
1259 
1260  __SUP_COUTV__(files.size());
1261  __SUP_COUTV__(isImagePublic);
1262 
1263  if(isImagePublic == "true")
1264  fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1265  else
1266  fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1267 
1268  for(unsigned int i = 0; i < files.size(); ++i)
1269  {
1270  filename = files[i].getFilename();
1271  filename = fullPath + filename;
1272  __COUT__ << "file " << i << " - " << filename << std::endl;
1273 
1274  myfile.open(filename.c_str());
1275  if(myfile.is_open())
1276  {
1277  files[i].writeToStream(myfile);
1278  myfile.close();
1279  __SUP_COUT__ << "Finished writing image file" << __E__;
1280  }
1281  }
1282 
1283  return;
1284 }
1285 
1286 //==============================================================================
1287 void SlowControlsDashboardSupervisor::Subscribe(cgicc::Cgicc& /*cgiIn*/,
1288  HttpXmlDocument& /*xmlOut*/)
1289 {
1290 }
1291 
1292 //==============================================================================
1293 void SlowControlsDashboardSupervisor::Unsubscribe(cgicc::Cgicc& /*cgiIn*/,
1294  HttpXmlDocument& /*xmlOut*/)
1295 {
1296 }
1297 
1298 //==============================================================================
1299 //==============================================================================
1300 //================================================== UTILITIES
1301 //===========================================================
1302 //==============================================================================
1304 {
1305  struct stat fileInfo;
1306  stat(dir.c_str(), &fileInfo);
1307  if(S_ISDIR(fileInfo.st_mode))
1308  {
1309  return true;
1310  }
1311  else
1312  {
1313  return false;
1314  }
1315 }
1316 
1317 //==============================================================================
1318 void SlowControlsDashboardSupervisor::listFiles(std::string innerDir,
1319  bool recursive,
1320  std::vector<std::string>* pages)
1321 {
1322  std::string baseDir = PAGES_DIRECTORY;
1323  baseDir += innerDir;
1324  DIR* dp;
1325  struct dirent* dirp;
1326  if((dp = opendir(baseDir.c_str())) == NULL)
1327  {
1328  __SUP_COUT__ << "[ERROR: " << errno << " ] Couldn't open " << baseDir << "."
1329  << __E__;
1330  return;
1331  }
1332  else
1333  {
1334  while((dirp = readdir(dp)) != NULL)
1335  {
1336  if(dirp->d_name != std::string(".") && dirp->d_name != std::string(".."))
1337  {
1338  if(isDir(baseDir + dirp->d_name) == true && recursive == true)
1339  {
1340  // pages->push_back(baseDir + dirp->d_name);
1341  __SUP_COUT__ << "[DIR]\t" << baseDir << dirp->d_name << "/" << __E__;
1342  listFiles(std::string("") + dirp->d_name + "/", true, pages);
1343  }
1344  else
1345  {
1346  pages->push_back(innerDir + dirp->d_name);
1347  __SUP_COUT__ << "[FILE]\t" << baseDir << innerDir << dirp->d_name
1348  << __E__;
1349  }
1350  }
1351  }
1352  closedir(dp);
1353  }
1354 }
static std::string postData(cgicc::Cgicc &cgi, const std::string &needle)
static std::string getOrPostData(cgicc::Cgicc &cgi, const std::string &needle)
static std::string getData(cgicc::Cgicc &cgi, const std::string &needle)
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
void getValue(T &value) const
std::string getSupervisorProperty(const std::string &propertyName)
bool isDir(std::string dir)
Utilities, eventually to be moved.
void checkSubscriptions(SlowControlsDashboardSupervisor *cs)
Manage channel subscriptions to Interface.
void checkSlowControlsAlarms(SlowControlsDashboardSupervisor *cs)
Manage channel subscriptions to Interface.
SlowControlsVInterface * makeSlowControls(const std::string &slowControlsPluginName, const std::string &slowControlsUID, const ConfigurationTree &configurationTree, const std::string &pathToControlsConfiguration)
void INIT_MF(const char *name)
static void getSetFromString(const std::string &inputString, std::set< std::string > &setToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
static std::string decodeURIComponent(const std::string &data)