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