otsdaq-utilities  3.05.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  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::
337  setSupervisorProperty( // block users from writing if no write access
338  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES
339  .UserPermissionsThreshold,
340  "*=0 | getPages=1 | loadPhoebusPage=1 | getList=1 | getPVSettings=1 | getPvArchiverData=1 | generateUID=1 | getUserPermissions=1 |\
341  userActivityHeartbeat=1 | poll=1 | uid=1 | isUserAdmin=1 | getLastAlarmsData=1 | getAlarmsLogData=1 | getAlarmsCheck=1 | getPvData=1 ");
342 
343  CorePropertySupervisorBase::
344  setSupervisorProperty( // allow no login on certain requests (i.e. standAloneMode pages)
345  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES
346  .AllowNoLoginRequestTypes,
347  "getPages | getList | loadPhoebusPage | generateUID | poll | "
348  "getPVSettings");
349  __COUT_INFO__ << "readOnly true in setSupervisorProperty" << __E__;
350  }
351 } //end forceSupervisorPropertyValues()
352 
353 //==============================================================================
354 void SlowControlsDashboardSupervisor::request(const std::string& requestType,
355  cgicc::Cgicc& cgiIn,
356  HttpXmlDocument& xmlOut,
357  const WebUsers::RequestUserInfo& userInfo)
358 {
359  __SUP_COUT__ << "requestType: " << requestType << ", "
360  << "userInfo.username_: " << userInfo.username_ << __E__;
361  try
362  {
363  if(requestType != "getPages" && !pluginBusyMutex_.try_lock())
364  {
365  __SUP_SS__ << "Controls plugin is still initializing. Please try again in a "
366  "few minutes!"
367  << __E__;
368  __SUP_SS_THROW__;
369  }
370 
371  __SUP_COUT__ << "User name is " << userInfo.username_ << "." << __E__;
372  __SUP_COUT__ << "User permission level for request '" << requestType << "' is "
373  << unsigned(userInfo.permissionLevel_)
374  << "(isAdmin=" << (userInfo.isAdmin() ? "Yes" : "No") << ")."
375  << __E__;
376 
377  // handle request per requestType
378  handleRequest(requestType, xmlOut, cgiIn, userInfo);
379  }
380  catch(const std::runtime_error& e)
381  {
382  __SUP_SS__ << "Error occurred handling request '" << requestType
383  << "': " << e.what() << __E__;
384  __SUP_COUT__ << ss.str();
385  xmlOut.addTextElementToData("Error", ss.str());
386  }
387  catch(...)
388  {
389  __SS__ << "Unknown error occurred handling request '" << requestType << "!'"
390  << __E__;
391  try
392  {
393  throw;
394  } //one more try to printout extra info
395  catch(const std::exception& e)
396  {
397  ss << "Exception message: " << e.what();
398  }
399  catch(...)
400  {
401  }
402  __SUP_COUT__ << ss.str();
403  xmlOut.addTextElementToData("Error", ss.str());
404  }
405 
406  pluginBusyMutex_.unlock();
407  __SUP_COUT__ << __E__;
408 } // end request()
409 
410 //==============================================================================
411 void SlowControlsDashboardSupervisor::handleRequest(
412  const std::string Command,
413  HttpXmlDocument& xmlOut,
414  cgicc::Cgicc& cgiIn,
415  const WebUsers::RequestUserInfo& userInfo)
416 {
417  // return xml doc holding server response
418  __SUP_COUT__ << __E__;
419 
420  if(Command == "poll")
421  {
422  std::string uid = CgiDataUtilities::getOrPostData(cgiIn, "uid");
423  Poll(cgiIn, xmlOut, uid);
424  }
425  else if(Command == "getPvData")
426  {
427  Poll(cgiIn, xmlOut);
428  }
429  else if(Command == "userActivityHeartbeat")
430  {
431  // web client code should call this while user is building
432  // in Edit Mode.
433  // Do nothing, just keep login alive
434  }
435  else if(Command == "generateUID")
436  {
437  std::string channelList = CgiDataUtilities::getOrPostData(cgiIn, "pvList");
438  GenerateUID(cgiIn, xmlOut, channelList);
439  }
440  else if(Command == "isUserAdmin")
441  {
442  std::string json = std::string("{ \"message\": \"");
443  json += (userInfo.isAdmin() ? "Yes" : "No");
444  json += "\"}";
445  xmlOut.addTextElementToData("JSON", json.c_str());
446  }
447  else if(Command == "getUserPermissions")
448  {
449  GetUserPermissions(cgiIn, xmlOut, userInfo);
450  }
451  else if(Command == "getPVSettings")
452  {
453  __SUP_COUT__ << "Channel settings requested from server! " << __E__;
454  GetChannelSettings(cgiIn, xmlOut);
455  xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id"));
456  }
457  else if(Command == "getPvArchiverData")
458  {
459  __SUP_COUT__ << "Archived Channel data requested from server! " << __E__;
460  GetChannelArchiverData(cgiIn, xmlOut);
461  xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id"));
462  }
463  else if(Command == "getList")
464  {
465  __SUP_COUT__ << "Channel List requested from server! " << __E__;
466  GetList(cgiIn, xmlOut);
467  }
468  else if(Command == "getPages")
469  {
470  __SUP_COUT__ << "Requesting pages from server! " << __E__;
471  GetPages(cgiIn, xmlOut);
472  }
473  else if(Command == "loadPage")
474  {
475  std::string page = CgiDataUtilities::getData(cgiIn, "Page");
476  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << page
477  << __E__;
478 
479  loadPage(cgiIn, xmlOut, page, userInfo);
480  }
481  else if(Command == "loadPhoebusPage")
482  {
483  std::string page = CgiDataUtilities::getData(cgiIn, "Page");
484  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << page
485  << __E__;
486 
487  loadPhoebusPage(cgiIn, xmlOut, page, userInfo);
488  }
489  else if(Command == "createControlsPage")
490  {
491  SaveControlsPage(cgiIn, xmlOut, userInfo);
492  }
493  else if(Command == "createPhoebusControlsPage")
494  {
495  SavePhoebusControlsPage(cgiIn, xmlOut, userInfo);
496  }
497  else if(Command == "getLastAlarmsData")
498  {
499  __SUP_COUT__ << "Last Alarms Data requested from server! " << __E__;
500  GetLastAlarmsData(cgiIn, xmlOut);
501  xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id"));
502  }
503  else if(Command == "getAlarmsLogData")
504  {
505  __SUP_COUT__ << "Alarms Log Data requested from server! " << __E__;
506  GetAlarmsLogData(cgiIn, xmlOut);
507  xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id"));
508  }
509  else if(Command == "getAlarmsCheck")
510  {
511  __SUP_COUT__ << "Alarms Data requested from server! " << __E__;
512  GetAlarmsCheck(xmlOut);
513  }
514  else if(Command == "saveImageFile")
515  {
516  saveImageFile(cgiIn, xmlOut, userInfo);
517  }
518  else
519  {
520  __SUP_SS__ << "Request, " << Command
521  << ", not recognized by the Slow Controls Dashboard Supervisor (was "
522  "it intended for another Supervisor?)."
523  << __E__;
524  __SUP_SS_THROW__;
525  }
526 
527  __SUP_COUT__ << "" << __E__;
528 } // end handleRequest()
529 
530 //==============================================================================
531 void SlowControlsDashboardSupervisor::Poll(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
532 {
533  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
534  std::set<std::string> channels;
535  StringMacros::getSetFromString(channelList, channels);
536 
537  xmlOut.addTextElementToData("JSON", PollChannels_(channels));
538 } //end Poll()
539 
540 //==============================================================================
541 void SlowControlsDashboardSupervisor::Poll(cgicc::Cgicc& /*cgiIn*/,
542  HttpXmlDocument& xmlOut,
543  std::string UID)
544 {
545  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
546  << "Polling on UID:" << UID << __E__;
547 
548  std::map<int, std::set<std::string>>::iterator mapReference;
549 
550  if(UID != "" && (mapReference = channelDependencyLookupMap_.find(std::stoi(UID))) !=
551  channelDependencyLookupMap_
552  .end()) // We have their current list of Channel Dependencies
553  {
554  uidPollTimeMap_.at(std::stoi(UID)) = std::time(NULL);
555 
556  xmlOut.addTextElementToData(
557  "JSON", PollChannels_(mapReference->second)); // add to response
558  }
559  else // UID is not in our map so force them to generate a new one
560  {
561  xmlOut.addTextElementToData("JSON",
562  "{ \"message\": \"NOT_FOUND\"}"); // add to response
563  }
564 } //end Poll()
565 
566 //==============================================================================
567 std::string SlowControlsDashboardSupervisor::PollChannels_(
568  std::set<std::string>& channels, bool resubscibe /*=true*/)
569 {
570  std::string JSONMessage = "{ ";
571 
572  for(auto channel : channels)
573  {
574  // channel = channel.substr(0, channel.find(":"));
575 
576  __SUP_COUT__ << channel << __E__;
577 
578  std::array<std::string, 4> channelInformation =
579  interface_->getCurrentValue(channel);
580 
581  __SUP_COUT__ << channel << ": " << channelInformation[1] << " : "
582  << channelInformation[3] << __E__;
583 
584  if(channelInformation[0] != "NO_CHANGE")
585  {
586  //__SUP_COUT__ << "Reached" << __E__;
587  JSONMessage += "\"" + channel + "\": {";
588  JSONMessage += "\"Timestamp\":\"" + channelInformation[0] + "\",";
589  JSONMessage += "\"Value\":\"" + channelInformation[1] + "\",";
590  JSONMessage += "\"Status\":\"" + channelInformation[2] + "\",";
591  JSONMessage += "\"Severity\":\"" + channelInformation[3] + "\"},";
592  }
593  else
594  {
595  __SUP_COUT__ << "No change in value since last poll: " << channel << __E__;
596  }
597 
598  // Handle Channels that disconnect, etc
599  if(channelInformation[3] == "INVALID" && resubscibe)
600  {
601  interface_->unsubscribe(channel);
602  interface_->subscribe(channel);
603  }
604  }
605 
606  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
607  JSONMessage += "}";
608  __SUP_COUT__ << JSONMessage << __E__;
609  return JSONMessage;
610 } //end PollChannels_()
611 
612 //==============================================================================
613 void SlowControlsDashboardSupervisor::GetChannelSettings(cgicc::Cgicc& cgiIn,
614  HttpXmlDocument& xmlOut)
615 {
616  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
617 
618  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
619  << "Getting settings for " << channelList << __E__;
620 
621  std::string JSONMessage = "{ ";
622 
623  __SUP_COUT__ << "**********************" << channelList.size() << __E__;
624  if(channelList.size() > 0)
625  {
626  std::string channel;
627  size_t pos = 0;
628  size_t nextPos;
629  while((nextPos = channelList.find(",", pos)) != std::string::npos)
630  {
631  channel = channelList.substr(pos, nextPos - pos);
632 
633  __SUP_COUT__ << channel << __E__;
634 
635  std::array<std::string, 9> channelSettings = interface_->getSettings(channel);
636 
637  JSONMessage += "\"" + channel + "\": {";
638  JSONMessage += "\"Units\": \"" + channelSettings[0] + "\",";
639  JSONMessage += "\"Upper_Display_Limit\": \"" + channelSettings[1] + "\",";
640  JSONMessage += "\"Lower_Display_Limit\": \"" + channelSettings[2] + "\",";
641  JSONMessage += "\"Upper_Alarm_Limit\": \"" + channelSettings[3] + "\",";
642  JSONMessage += "\"Upper_Warning_Limit\": \"" + channelSettings[4] + "\",";
643  JSONMessage += "\"Lower_Warning_Limit\": \"" + channelSettings[5] + "\",";
644  JSONMessage += "\"Lower_Alarm_Limit\": \"" + channelSettings[6] + "\",";
645  JSONMessage += "\"Upper_Control_Limit\": \"" + channelSettings[7] + "\",";
646  JSONMessage += "\"Lower_Control_Limit\": \"" + channelSettings[8] + "\"},";
647 
648  pos = nextPos + 1;
649  }
650 
651  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
652  JSONMessage += "}";
653 
654  __SUP_COUT__ << JSONMessage << __E__;
655  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
656  }
657  else
658  {
659  __SUP_COUT__ << "Did not find any settings because Channel list is length zero!"
660  << __E__;
661 
662  xmlOut.addTextElementToData(
663  "JSON", "{ \"message\": \"GetPVSettings\"}"); // add to response
664  }
665 } //end GetChannelSettings()
666 
667 //==============================================================================
668 void SlowControlsDashboardSupervisor::GetChannelArchiverData(cgicc::Cgicc& cgiIn,
669  HttpXmlDocument& xmlOut)
670 {
671  __SUP_COUT__ << "Requesting archived data!" << __E__;
672 
673  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
674  int startTime = stoi(CgiDataUtilities::postData(cgiIn, "startTime"));
675  int endTime = stoi(CgiDataUtilities::postData(cgiIn, "endTime"));
676 
677  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
678  << "Getting History for " << channelList << " start time: " << startTime
679  << " end time: " << endTime << __E__;
680 
681  __SUP_COUT__ << "channelList.size(): " << channelList.size() << __E__;
682  if(channelList.size() > 0 && startTime > 0 && endTime > 0)
683  {
684  std::string channel;
685  size_t pos = 0;
686  size_t nextPos;
687  while((nextPos = channelList.find(",", pos)) != std::string::npos)
688  {
689  channel = channelList.substr(pos, nextPos - pos);
690 
691  __SUP_COUT__ << "Getting History for " << channel << __E__;
692 
693  std::vector<std::vector<std::string>> channelInformation =
694  interface_->getChannelHistory(channel, startTime, endTime);
695 
696  for(auto channelData : channelInformation)
697  {
698  std::string JSONMessage = "{ ";
699  JSONMessage += "\"" + channel + "\": {";
700  JSONMessage += "\"Timestamp\":\"" + channelData[0] + "\",";
701  JSONMessage += "\"Value\":\"" + channelData[1] + "\",";
702  JSONMessage += "\"Status\":\"" + channelData[2] + "\",";
703  JSONMessage += "\"Severity\":\"" + channelData[3] + "\"},";
704 
705  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
706  JSONMessage += "}";
707  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
708  }
709  //__SUP_COUT__ << JSONMessage << __E__;
710  pos = nextPos + 1;
711  }
712  }
713  else
714  {
715  __SUP_COUT__ << "Did not find any data because Channel list is length zero!"
716  << __E__;
717 
718  xmlOut.addTextElementToData(
719  "JSON", "{ \"message\": \"GetChannelArchiverData\"}"); // add to response
720  }
721 } // end GetChannelArchiverData()
722 
723 //==============================================================================
724 void SlowControlsDashboardSupervisor::GetLastAlarmsData(cgicc::Cgicc& cgiIn,
725  HttpXmlDocument& xmlOut)
726 {
727  __SUP_COUT__ << "Requesting last alarms data!" << __E__;
728 
729  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
730 
731  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
732  << "Getting last Alarms for " << channelList << __E__;
733  __SUP_COUT__ << "channelList.size(): " << channelList.size() << __E__;
734 
735  std::vector<std::vector<std::string>> alarms;
736 
737  // create lambda function to fill JSONMessage
738  std::function<void(HttpXmlDocument&, std::vector<std::vector<std::string>>&)>
739  jsonFiller = [](HttpXmlDocument& xmlOut,
740  std::vector<std::vector<std::string>>& alarms) {
741  if(alarms.size())
742  for(auto& alarmRow : alarms)
743  {
744  std::string JSONMessage = "{ ";
745  JSONMessage += "\"id\":\"" + alarmRow[0] + "\",";
746  JSONMessage += "\"pvName\":\"" + alarmRow[1] + "\",";
747  JSONMessage += "\"pvDescription\":\"" + alarmRow[2] + "\",";
748  JSONMessage += "\"pvValue\":\"" + alarmRow[3] + "\",";
749  JSONMessage += "\"pvStatus\":\"" + alarmRow[4] + "\",";
750  JSONMessage += "\"pvSeverity\":\"" + alarmRow[5] + "\",";
751  JSONMessage += "\"pvTime\":\"" + alarmRow[6] + "\",";
752 
753  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
754  JSONMessage += "}";
755  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
756  // __SUP_COUT__ << JSONMessage << __E__;
757  }
758  };
759 
760  if(channelList.size() > 0)
761  {
762  std::string channel;
763  size_t pos = 0;
764  size_t nextPos;
765  while((nextPos = channelList.find(",", pos)) != std::string::npos)
766  {
767  channel = channelList.substr(pos, nextPos - pos);
768 
769  alarms = interface_->getLastAlarms(channel);
770  __SUP_COUT__ << "get Last Alarms for channel: " << channel << __E__;
771  jsonFiller(xmlOut, alarms);
772  pos = nextPos + 1;
773  }
774  }
775  else
776  {
777  alarms = interface_->getLastAlarms("");
778  __SUP_COUT__ << "get Last Alarms for all channels" << __E__;
779  jsonFiller(xmlOut, alarms);
780  }
781 } // end GetLastAlarmsData()
782 
783 //==============================================================================
784 void SlowControlsDashboardSupervisor::GetAlarmsCheck(HttpXmlDocument& xmlOut)
785 {
786  __SUP_COUT__ << "Requesting alarms check cache data!" << __E__;
787 
788  std::string JSONMessage = "{ ";
789  JSONMessage += "\"last_check\":" +
790  std::to_string(std::chrono::duration_cast<std::chrono::seconds>(
791  alarms_timestamp_.time_since_epoch())
792  .count()) +
793  ",";
794  JSONMessage += "\"total\":" + std::to_string(alarms_.size()) + ",";
795  JSONMessage += "\"alarms\": [";
796  unsigned int nactive = 0;
797  if(alarms_.size())
798  {
799  for(auto& alarmRow : alarms_)
800  {
801  JSONMessage += "{ ";
802  JSONMessage += "\"name\":\"" + alarmRow[0] + "\",";
803  if(alarmRow.size() > 9)
804  { // alarm present
805  ++nactive;
806  JSONMessage += "\"time\":\"" + alarmRow[1] + "\",";
807  JSONMessage += "\"value\":\"" + alarmRow[2] + "\",";
808  JSONMessage += "\"status\":\"" + alarmRow[3] + "\",";
809  JSONMessage += "\"severity\":\"" + alarmRow[4] + "\",";
810  }
811  JSONMessage =
812  JSONMessage.substr(0, JSONMessage.length() - 1); // get rid of last ,
813  JSONMessage += "},";
814  } //end alarm loop
815  JSONMessage =
816  JSONMessage.substr(0, JSONMessage.length() - 1); // get rid of last ,
817  }
818  JSONMessage += "], \"nactive\": " + std::to_string(nactive);
819  JSONMessage += "}";
820  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
821 } // end GetAlarmsCheck()
822 
823 //==============================================================================
824 void SlowControlsDashboardSupervisor::GetAlarmsLogData(cgicc::Cgicc& cgiIn,
825  HttpXmlDocument& xmlOut)
826 {
827  __SUP_COUT__ << "Requesting alarms log data!" << __E__;
828 
829  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
830 
831  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
832  << "Getting Alarms Log for " << channelList << __E__;
833  __SUP_COUT__ << "channelList.size(): " << channelList.size() << __E__;
834 
835  std::vector<std::vector<std::string>> alarmsLog;
836 
837  // create lambda function to fill JSONMessage
838  std::function<void(HttpXmlDocument&, std::vector<std::vector<std::string>>&)>
839  jsonFiller = [](HttpXmlDocument& xmlOut,
840  std::vector<std::vector<std::string>>& alarmsLog) {
841  if(alarmsLog.size())
842  for(auto& alarmRow : alarmsLog)
843  {
844  std::string JSONMessage = "{ ";
845  JSONMessage += "\"id\":\"" + alarmRow[0] + "\",";
846  JSONMessage += "\"pvName\":\"" + alarmRow[1] + "\",";
847  JSONMessage += "\"pvValue\":\"" + alarmRow[2] + "\",";
848  JSONMessage += "\"pvStatus\":\"" + alarmRow[3] + "\",";
849  JSONMessage += "\"pvSeverity\":\"" + alarmRow[4] + "\",";
850  JSONMessage += "\"pvTime\":\"" + alarmRow[5] + "\",";
851 
852  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
853  JSONMessage += "}";
854  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
855  // __SUP_COUT__ << JSONMessage << __E__;
856  }
857  };
858 
859  if(channelList.size() > 0)
860  {
861  std::string channel;
862  size_t pos = 0;
863  size_t nextPos;
864  while((nextPos = channelList.find(",", pos)) != std::string::npos)
865  {
866  channel = channelList.substr(pos, nextPos - pos);
867 
868  alarmsLog = interface_->getAlarmsLog(channel);
869  __SUP_COUT__ << "get Alarms Log for channel: " << channel << __E__;
870  jsonFiller(xmlOut, alarmsLog);
871  pos = nextPos + 1;
872  }
873  }
874  else
875  {
876  alarmsLog = interface_->getAlarmsLog("");
877  __SUP_COUT__ << "get Alarms Log for all channels" << __E__;
878  jsonFiller(xmlOut, alarmsLog);
879  }
880 } // end GetAlarmsLogData()
881 
882 //==============================================================================
883 void SlowControlsDashboardSupervisor::GetUserPermissions(
884  cgicc::Cgicc& /*cgiIn*/,
885  HttpXmlDocument& /*xmlOut*/,
886  const WebUsers::RequestUserInfo& /*userInfo*/)
887 {
888  return;
889 }
890 
891 //==============================================================================
892 void SlowControlsDashboardSupervisor::GenerateUID(cgicc::Cgicc& /*cgiIn*/,
893  HttpXmlDocument& xmlOut,
894  std::string channelList)
895 {
896  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
897  << "Generating UID" << __E__;
898 
899  std::set<std::string> channelDependencies;
900  StringMacros::getSetFromString(channelList, channelDependencies);
901 
902  // make entry for new UID_ in UID-to-channel map
903  channelDependencyLookupMap_.insert(
904  std::pair<int, std::set<std::string>>(++UID_, channelDependencies));
905 
906  uidPollTimeMap_.insert(std::pair<int, long int>(UID_, std::time(NULL)));
907 
908  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " NEW UID: " << UID_
909  << " maps to " << channelDependencies.size() << " channels" << __E__;
910 
911  xmlOut.addTextElementToData("JSON",
912  std::string("{ \"message\": \"") + std::to_string(UID_) +
913  "\"}"); // add to response
914 } // end GenerateUID()
915 
916 //==============================================================================
917 void SlowControlsDashboardSupervisor::GetList(cgicc::Cgicc& /*cgiIn*/,
918  HttpXmlDocument& xmlOut)
919 {
920  if(interface_ != NULL)
921  {
922  __SUP_COUT__ << "Interface is defined! Attempting to get list!" << __E__;
923  // __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
924  // __E__;
925  std::string list;
926  try
927  {
928  list = interface_->getList("JSON");
929  }
930  catch(std::runtime_error& e)
931  {
932  __SUP_SS__ << "Channel list request failed: " << e.what() << __E__;
933  __SUP_SS_THROW__;
934  }
935 
936  __SUP_COUT__ << " " << list << __E__;
937 
938  xmlOut.addTextElementToData("JSON", list); // add to response
939  }
940  else
941  {
942  __SUP_COUT__ << "Interface undefined! Failed to get list!" << __E__;
943  xmlOut.addTextElementToData("JSON", "[\"None\"]");
944  }
945 } // end GetList()
946 
947 //==============================================================================
948 void SlowControlsDashboardSupervisor::GetPages(cgicc::Cgicc& /*cgiIn*/,
949  HttpXmlDocument& xmlOut)
950 {
951  std::vector<std::string> pages;
952 
953  listFiles("", true, &pages);
954 
955  std::string returnJSON = "[";
956  for(auto it = pages.begin(); it != pages.end(); it++)
957  {
958  if(*it != "." && *it != "..")
959  returnJSON += "\"" + *it + "\", ";
960  }
961  if(returnJSON.size() > 2 && returnJSON.compare("[") != 0)
962  {
963  __SUP_COUT__ << "Found pages on server!" << __E__;
964  returnJSON.resize(returnJSON.size() - 2);
965  returnJSON += "]";
966  }
967  else
968  {
969  // No pages on the server
970  __SUP_COUT__ << "No pages found on server!" << __E__;
971  returnJSON = "[\"None\"]";
972  }
973  __SUP_COUT__ << returnJSON << __E__;
974 
975  xmlOut.addTextElementToData("JSON", returnJSON); // add to response
976 } // end GetPages()
977 
978 //==============================================================================
979 void SlowControlsDashboardSupervisor::loadPage(
980  cgicc::Cgicc& /*cgiIn*/,
981  HttpXmlDocument& xmlOut,
982  std::string page,
983  const WebUsers::RequestUserInfo& /*userInfo*/)
984 {
986 
987  // FIXME Filter out malicious attacks i.e. ../../../../../ stuff
988  struct stat buffer;
989  if(page.find("..") != std::string::npos)
990  {
991  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
992  << "Error! Request using '..': " << page << __E__;
993  }
994  else if(page.find("~") != std::string::npos)
995  {
996  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
997  << "Error! Request using '~': " << page << __E__;
998  }
999  else if(!(stat(page.c_str(), &buffer) == 0))
1000  {
1001  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1002  << "Error! File not found: " << page << __E__;
1003  }
1004  // Remove double / in path
1005 
1006  __SUP_COUT__ << page << __E__;
1007 
1008  if(page.at(0) == '/')
1009  {
1010  __SUP_COUT__ << "First character is '/'" << __E__;
1011  page.erase(page.begin(), page.begin() + 1);
1012  __SUP_COUT__ << page << __E__;
1013  }
1014 
1015  std::string file = PAGES_DIRECTORY;
1016  file += page;
1017  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1018  << "Trying to load page: " << page << __E__;
1019  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1020  << "Trying to load page: " << file << __E__;
1021  // read file
1022  // for each line in file
1023 
1024  std::ifstream infile(file);
1025  if(infile.fail())
1026  {
1027  __SUP_COUT__ << "Failed reading file: " << file << __E__;
1028 
1029  xmlOut.addTextElementToData("Time", "[\"Not Found\"]"); // add to response
1030  xmlOut.addTextElementToData("Notes", "[\"Not Found\"]"); // add to response
1031  xmlOut.addTextElementToData(
1032  "Page", StringMacros::encodeURIComponent(page)); // add to response
1033  return;
1034  }
1035  __SUP_COUT__ << "Reading file" << __E__;
1036 
1037  std::string time = "";
1038  std::string notes = "";
1039  std::string controlsPage = "";
1040 
1041  for(std::string line; getline(infile, line);)
1042  {
1043  __SUP_COUT__ << line << __E__;
1044  if(!line.substr(0, 5).compare("Time:"))
1045  {
1046  time = line.substr(6);
1047  }
1048  else if(!line.substr(0, 6).compare("Notes:"))
1049  {
1050  notes = line.substr(7);
1051  }
1052  else if(!line.substr(0, 5).compare("Page:"))
1053  {
1054  controlsPage = line.substr(6);
1055  }
1056  }
1057  __SUP_COUT__ << "Finished reading file" << __E__;
1058  __SUP_COUTV__(time);
1059  __SUP_COUTV__(notes);
1060  __SUP_COUTV__(controlsPage);
1061 
1062  xmlOut.addTextElementToData("Time", time); // add to response
1063  xmlOut.addTextElementToData("Notes", notes); // add to response
1064  xmlOut.addTextElementToData("Page", controlsPage); // add to response
1065 } // end loadPage()
1066 
1067 //==============================================================================
1068 void SlowControlsDashboardSupervisor::loadPhoebusPage(
1069  cgicc::Cgicc& /*cgiIn*/,
1070  HttpXmlDocument& xmlOut,
1071  std::string page,
1072  const WebUsers::RequestUserInfo& /*userInfo*/)
1073 {
1074  page = StringMacros::decodeURIComponent(page);
1075 
1076  // FIXME Filter out malicious attacks i.e. ../../../../../ stuff
1077  struct stat buffer;
1078  if(page.find("..") != std::string::npos)
1079  {
1080  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1081  << "Error! Request using '..': " << page << __E__;
1082  }
1083  else if(page.find("~") != std::string::npos)
1084  {
1085  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1086  << "Error! Request using '~': " << page << __E__;
1087  }
1088  else if(!(stat(page.c_str(), &buffer) == 0))
1089  {
1090  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1091  << "Error! File not found: " << page << __E__;
1092  }
1093  // Remove double / in path
1094 
1095  __SUP_COUT__ << page << __E__;
1096 
1097  if(page.at(0) == '/')
1098  {
1099  __SUP_COUT__ << "First character is '/'" << __E__;
1100  page.erase(page.begin(), page.begin() + 1);
1101  __SUP_COUT__ << page << __E__;
1102  }
1103 
1104  std::string file = PAGES_DIRECTORY;
1105  file += page;
1106  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1107  << "Trying to load page: " << page << __E__;
1108  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1109  << "Trying to load page: " << file << __E__;
1110 
1111  // read file
1112  __SUP_COUT__ << "Reading file" << __E__;
1113  std::ifstream infile(file);
1114  if(infile.fail())
1115  {
1116  __SUP_COUT__ << "Failed reading file: " << file << __E__;
1117  xmlOut.addTextElementToData(
1118  "Page", StringMacros::encodeURIComponent(page)); // add to response
1119  return;
1120  }
1121 
1122  std::string xml;
1123  for(std::string line; getline(infile, line);)
1124  {
1125  xml += line + "\n";
1126  }
1127  __SUP_COUT__ << xml << __E__;
1128  xmlOut.addTextElementToData("PHOEBUS", xml);
1129 
1130 } // end loadPhoebusPage()
1131 
1132 //==============================================================================
1133 void SlowControlsDashboardSupervisor::SaveControlsPage(
1134  cgicc::Cgicc& cgiIn,
1135  HttpXmlDocument& /*xmlOut*/,
1136  const WebUsers::RequestUserInfo& /*userInfo*/)
1137 {
1138  __SUP_COUT__ << "ControlsDashboard wants to create a Controls Page!" << __E__;
1139 
1140  std::string controlsPageName = CgiDataUtilities::postData(cgiIn, "Name");
1141  std::string pageString = CgiDataUtilities::postData(cgiIn, "Page");
1142  std::string Time = CgiDataUtilities::postData(cgiIn, "Time");
1143  std::string Notes =
1145  std::string isControlsPagePublic = CgiDataUtilities::postData(cgiIn, "isPublic");
1146 
1147  __SUP_COUTV__(controlsPageName);
1148  __SUP_COUTV__(pageString);
1149  __SUP_COUTV__(Notes);
1150  __SUP_COUTV__(Time);
1151  __SUP_COUTV__(isControlsPagePublic);
1152 
1153  if(controlsPageName == "")
1154  return;
1155 
1156  std::string fullPath;
1157  if(isControlsPagePublic == "true")
1158  fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1159  else
1160  fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1161 
1162  __SUP_COUTV__(fullPath);
1163 
1164  std::string file = fullPath + controlsPageName;
1165 
1166  __SUP_COUTV__("Saving Controls Page to: " + file);
1167 
1168  std::string extension = file.substr(file.length() - 4, 4);
1169  if(extension != ".dat")
1170  {
1171  __SUP_COUT__ << "Extension : " << extension << __E__;
1172  file += std::string(".dat");
1173  }
1174  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1175  << "Trying to save page: " << controlsPageName << __E__;
1176  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1177  << "Trying to save page as: " << file << __E__;
1178  // read file
1179  // for each line in file
1180 
1181  std::ofstream outputFile;
1182  outputFile.open(file);
1183  if(!outputFile.is_open())
1184  {
1185  __SUP_SS__ << "Failed to open file for writing: " << file << __E__;
1186  __SUP_SS_THROW__;
1187  }
1188  outputFile << "Time: " << Time << "\n";
1189  outputFile << "Notes: " << Notes << "\n";
1190  outputFile << "Page: " << pageString;
1191  outputFile.close();
1192 
1193  __SUP_COUT__ << "Finished writing file" << __E__;
1194 
1195  return;
1196 }
1197 
1198 //==============================================================================
1199 void SlowControlsDashboardSupervisor::SavePhoebusControlsPage(
1200  cgicc::Cgicc& cgiIn,
1201  HttpXmlDocument& /*xmlOut*/,
1202  const WebUsers::RequestUserInfo& /*userInfo*/)
1203 {
1204  __SUP_COUT__ << "ControlsDashboard wants to create a Controls Page!" << __E__;
1205 
1206  std::string controlsPageName = CgiDataUtilities::postData(cgiIn, "Name");
1207  std::string pageString = CgiDataUtilities::postData(cgiIn, "Page");
1208  std::string isControlsPagePublic = CgiDataUtilities::postData(cgiIn, "isPublic");
1209 
1210  __SUP_COUTV__(controlsPageName);
1211  __SUP_COUTV__(pageString);
1212  __SUP_COUTV__(isControlsPagePublic);
1213 
1214  if(controlsPageName == "")
1215  return;
1216 
1217  std::string fullPath;
1218  if(isControlsPagePublic == "true")
1219  fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1220  else
1221  fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1222 
1223  __SUP_COUTV__(fullPath);
1224 
1225  std::string file = fullPath + controlsPageName;
1226 
1227  __SUP_COUTV__("Saving Controls Page to: " + file);
1228 
1229  std::string extension = file.substr(file.length() - 4, 4);
1230  if(extension != ".bob")
1231  {
1232  __SUP_COUT__ << "Extension : " << extension << __E__;
1233  file += std::string(".bob");
1234  }
1235  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1236  << "Trying to save page: " << controlsPageName << __E__;
1237  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1238  << "Trying to save page as: " << file << __E__;
1239  // read file
1240  // for each line in file
1241 
1242  std::ofstream outputFile;
1243  outputFile.open(file);
1244  if(!outputFile.is_open())
1245  {
1246  __SUP_SS__ << "Failed to open file for writing: " << file << __E__;
1247  __SUP_SS_THROW__;
1248  }
1249  outputFile << pageString << "\n";
1250  outputFile.close();
1251 
1252  __SUP_COUT__ << "Finished writing file" << __E__;
1253 
1254  return;
1255 }
1256 
1257 //==============================================================================
1258 void SlowControlsDashboardSupervisor::saveImageFile(
1259  cgicc::Cgicc& cgiIn,
1260  HttpXmlDocument& /*xmlOut*/,
1261  const WebUsers::RequestUserInfo& /*userInfo*/)
1262 {
1263  __SUP_COUT__ << "ControlsDashboard wants to save the image file uploaded!" << __E__;
1264 
1265  std::string isImagePublic = cgiIn("isPublic");
1266  const std::vector<cgicc::FormFile>& files = cgiIn.getFiles();
1267  std::string filename;
1268  std::ofstream myfile;
1269  std::string fullPath;
1270 
1271  __SUP_COUTV__(files.size());
1272  __SUP_COUTV__(isImagePublic);
1273 
1274  if(isImagePublic == "true")
1275  fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1276  else
1277  fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1278 
1279  for(unsigned int i = 0; i < files.size(); ++i)
1280  {
1281  filename = files[i].getFilename();
1282  filename = fullPath + filename;
1283  __COUT__ << "file " << i << " - " << filename << std::endl;
1284 
1285  myfile.open(filename.c_str());
1286  if(myfile.is_open())
1287  {
1288  files[i].writeToStream(myfile);
1289  myfile.close();
1290  __SUP_COUT__ << "Finished writing image file" << __E__;
1291  }
1292  }
1293 
1294  return;
1295 }
1296 
1297 //==============================================================================
1298 void SlowControlsDashboardSupervisor::Subscribe(cgicc::Cgicc& /*cgiIn*/,
1299  HttpXmlDocument& /*xmlOut*/)
1300 {
1301 }
1302 
1303 //==============================================================================
1304 void SlowControlsDashboardSupervisor::Unsubscribe(cgicc::Cgicc& /*cgiIn*/,
1305  HttpXmlDocument& /*xmlOut*/)
1306 {
1307 }
1308 
1309 //==============================================================================
1310 //==============================================================================
1311 //================================================== UTILITIES
1312 //===========================================================
1313 //==============================================================================
1315 {
1316  struct stat fileInfo;
1317  stat(dir.c_str(), &fileInfo);
1318  if(S_ISDIR(fileInfo.st_mode))
1319  {
1320  return true;
1321  }
1322  else
1323  {
1324  return false;
1325  }
1326 }
1327 
1328 //==============================================================================
1329 void SlowControlsDashboardSupervisor::listFiles(std::string innerDir,
1330  bool recursive,
1331  std::vector<std::string>* pages)
1332 {
1333  std::string baseDir = PAGES_DIRECTORY;
1334  baseDir += innerDir;
1335  DIR* dp;
1336  struct dirent* dirp;
1337  if((dp = opendir(baseDir.c_str())) == NULL)
1338  {
1339  __SUP_COUT__ << "[ERROR: " << errno << " ] Couldn't open " << baseDir << "."
1340  << __E__;
1341  return;
1342  }
1343  else
1344  {
1345  while((dirp = readdir(dp)) != NULL)
1346  {
1347  if(dirp->d_name != std::string(".") && dirp->d_name != std::string(".."))
1348  {
1349  if(isDir(baseDir + dirp->d_name) == true && recursive == true)
1350  {
1351  // pages->push_back(baseDir + dirp->d_name);
1352  __SUP_COUT__ << "[DIR]\t" << baseDir << dirp->d_name << "/" << __E__;
1353  listFiles(std::string("") + dirp->d_name + "/", true, pages);
1354  }
1355  else
1356  {
1357  pages->push_back(innerDir + dirp->d_name);
1358  __SUP_COUT__ << "[FILE]\t" << baseDir << innerDir << dirp->d_name
1359  << __E__;
1360  }
1361  }
1362  }
1363  closedir(dp);
1364  }
1365 }
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)