tdaq-develop-2025-02-12
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__;
83  pluginType = CorePropertySupervisorBase::getSupervisorProperty(
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 
510  __SUP_COUT__ << "" << __E__;
511 } // end handleRequest()
512 
513 //==============================================================================
514 void SlowControlsDashboardSupervisor::Poll(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
515 {
516  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
517  std::set<std::string> channels;
518  StringMacros::getSetFromString(channelList, channels);
519 
520  xmlOut.addTextElementToData("JSON", PollChannels_(channels));
521 } //end Poll()
522 
523 //==============================================================================
524 void SlowControlsDashboardSupervisor::Poll(cgicc::Cgicc& /*cgiIn*/,
525  HttpXmlDocument& xmlOut,
526  std::string UID)
527 {
528  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
529  << "Polling on UID:" << UID << __E__;
530 
531  std::map<int, std::set<std::string>>::iterator mapReference;
532 
533  if(UID != "" && (mapReference = channelDependencyLookupMap_.find(std::stoi(UID))) !=
534  channelDependencyLookupMap_
535  .end()) // We have their current list of Channel Dependencies
536  {
537  uidPollTimeMap_.at(std::stoi(UID)) = std::time(NULL);
538 
539  xmlOut.addTextElementToData(
540  "JSON", PollChannels_(mapReference->second)); // add to response
541  }
542  else // UID is not in our map so force them to generate a new one
543  {
544  xmlOut.addTextElementToData("JSON",
545  "{ \"message\": \"NOT_FOUND\"}"); // add to response
546  }
547 } //end Poll()
548 
549 //==============================================================================
550 std::string SlowControlsDashboardSupervisor::PollChannels_(
551  std::set<std::string>& channels, bool resubscibe /*=true*/)
552 {
553  std::string JSONMessage = "{ ";
554 
555  for(auto channel : channels)
556  {
557  // channel = channel.substr(0, channel.find(":"));
558 
559  __SUP_COUT__ << channel << __E__;
560 
561  std::array<std::string, 4> channelInformation =
562  interface_->getCurrentValue(channel);
563 
564  __SUP_COUT__ << channel << ": " << channelInformation[1] << " : "
565  << channelInformation[3] << __E__;
566 
567  if(channelInformation[0] != "NO_CHANGE")
568  {
569  //__SUP_COUT__ << "Reached" << __E__;
570  JSONMessage += "\"" + channel + "\": {";
571  JSONMessage += "\"Timestamp\":\"" + channelInformation[0] + "\",";
572  JSONMessage += "\"Value\":\"" + channelInformation[1] + "\",";
573  JSONMessage += "\"Status\":\"" + channelInformation[2] + "\",";
574  JSONMessage += "\"Severity\":\"" + channelInformation[3] + "\"},";
575  }
576  else
577  {
578  __SUP_COUT__ << "No change in value since last poll: " << channel << __E__;
579  }
580 
581  // Handle Channels that disconnect, etc
582  if(channelInformation[3] == "INVALID" && resubscibe)
583  {
584  interface_->unsubscribe(channel);
585  interface_->subscribe(channel);
586  }
587  }
588 
589  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
590  JSONMessage += "}";
591  __SUP_COUT__ << JSONMessage << __E__;
592  return JSONMessage;
593 } //end PollChannels_()
594 
595 //==============================================================================
596 void SlowControlsDashboardSupervisor::GetChannelSettings(cgicc::Cgicc& cgiIn,
597  HttpXmlDocument& xmlOut)
598 {
599  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
600 
601  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
602  << "Getting settings for " << channelList << __E__;
603 
604  std::string JSONMessage = "{ ";
605 
606  __SUP_COUT__ << "**********************" << channelList.size() << __E__;
607  if(channelList.size() > 0)
608  {
609  std::string channel;
610  size_t pos = 0;
611  size_t nextPos;
612  while((nextPos = channelList.find(",", pos)) != std::string::npos)
613  {
614  channel = channelList.substr(pos, nextPos - pos);
615 
616  __SUP_COUT__ << channel << __E__;
617 
618  std::array<std::string, 9> channelSettings = interface_->getSettings(channel);
619 
620  JSONMessage += "\"" + channel + "\": {";
621  JSONMessage += "\"Units\": \"" + channelSettings[0] + "\",";
622  JSONMessage += "\"Upper_Display_Limit\": \"" + channelSettings[1] + "\",";
623  JSONMessage += "\"Lower_Display_Limit\": \"" + channelSettings[2] + "\",";
624  JSONMessage += "\"Upper_Alarm_Limit\": \"" + channelSettings[3] + "\",";
625  JSONMessage += "\"Upper_Warning_Limit\": \"" + channelSettings[4] + "\",";
626  JSONMessage += "\"Lower_Warning_Limit\": \"" + channelSettings[5] + "\",";
627  JSONMessage += "\"Lower_Alarm_Limit\": \"" + channelSettings[6] + "\",";
628  JSONMessage += "\"Upper_Control_Limit\": \"" + channelSettings[7] + "\",";
629  JSONMessage += "\"Lower_Control_Limit\": \"" + channelSettings[8] + "\"},";
630 
631  pos = nextPos + 1;
632  }
633 
634  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
635  JSONMessage += "}";
636 
637  __SUP_COUT__ << JSONMessage << __E__;
638  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
639  }
640  else
641  {
642  __SUP_COUT__ << "Did not find any settings because Channel list is length zero!"
643  << __E__;
644 
645  xmlOut.addTextElementToData(
646  "JSON", "{ \"message\": \"GetPVSettings\"}"); // add to response
647  }
648 } //end GetChannelSettings()
649 
650 //==============================================================================
651 void SlowControlsDashboardSupervisor::GetChannelArchiverData(cgicc::Cgicc& cgiIn,
652  HttpXmlDocument& xmlOut)
653 {
654  __SUP_COUT__ << "Requesting archived data!" << __E__;
655 
656  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
657  int startTime = stoi(CgiDataUtilities::postData(cgiIn, "startTime"));
658  int endTime = stoi(CgiDataUtilities::postData(cgiIn, "endTime"));
659 
660  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
661  << "Getting History for " << channelList << " start time: " << startTime
662  << " end time: " << endTime << __E__;
663 
664  __SUP_COUT__ << "channelList.size(): " << channelList.size() << __E__;
665  if(channelList.size() > 0 && startTime > 0 && endTime > 0)
666  {
667  std::string channel;
668  size_t pos = 0;
669  size_t nextPos;
670  while((nextPos = channelList.find(",", pos)) != std::string::npos)
671  {
672  channel = channelList.substr(pos, nextPos - pos);
673 
674  __SUP_COUT__ << "Getting History for " << channel << __E__;
675 
676  std::vector<std::vector<std::string>> channelInformation =
677  interface_->getChannelHistory(channel, startTime, endTime);
678 
679  for(auto channelData : channelInformation)
680  {
681  std::string JSONMessage = "{ ";
682  JSONMessage += "\"" + channel + "\": {";
683  JSONMessage += "\"Timestamp\":\"" + channelData[0] + "\",";
684  JSONMessage += "\"Value\":\"" + channelData[1] + "\",";
685  JSONMessage += "\"Status\":\"" + channelData[2] + "\",";
686  JSONMessage += "\"Severity\":\"" + channelData[3] + "\"},";
687 
688  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
689  JSONMessage += "}";
690  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
691  }
692  //__SUP_COUT__ << JSONMessage << __E__;
693  pos = nextPos + 1;
694  }
695  }
696  else
697  {
698  __SUP_COUT__ << "Did not find any data because Channel list is length zero!"
699  << __E__;
700 
701  xmlOut.addTextElementToData(
702  "JSON", "{ \"message\": \"GetChannelArchiverData\"}"); // add to response
703  }
704 } // end GetChannelArchiverData()
705 
706 //==============================================================================
707 void SlowControlsDashboardSupervisor::GetLastAlarmsData(cgicc::Cgicc& cgiIn,
708  HttpXmlDocument& xmlOut)
709 {
710  __SUP_COUT__ << "Requesting last alarms data!" << __E__;
711 
712  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
713 
714  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
715  << "Getting last Alarms for " << channelList << __E__;
716  __SUP_COUT__ << "channelList.size(): " << channelList.size() << __E__;
717 
718  std::vector<std::vector<std::string>> alarms;
719 
720  // create lambda function to fill JSONMessage
721  std::function<void(HttpXmlDocument&, std::vector<std::vector<std::string>>&)>
722  jsonFiller = [](HttpXmlDocument& xmlOut,
723  std::vector<std::vector<std::string>>& alarms) {
724  if(alarms.size())
725  for(auto& alarmRow : alarms)
726  {
727  std::string JSONMessage = "{ ";
728  JSONMessage += "\"id\":\"" + alarmRow[0] + "\",";
729  JSONMessage += "\"pvName\":\"" + alarmRow[1] + "\",";
730  JSONMessage += "\"pvDescription\":\"" + alarmRow[2] + "\",";
731  JSONMessage += "\"pvValue\":\"" + alarmRow[3] + "\",";
732  JSONMessage += "\"pvStatus\":\"" + alarmRow[4] + "\",";
733  JSONMessage += "\"pvSeverity\":\"" + alarmRow[5] + "\",";
734  JSONMessage += "\"pvTime\":\"" + alarmRow[6] + "\",";
735 
736  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
737  JSONMessage += "}";
738  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
739  // __SUP_COUT__ << JSONMessage << __E__;
740  }
741  };
742 
743  if(channelList.size() > 0)
744  {
745  std::string channel;
746  size_t pos = 0;
747  size_t nextPos;
748  while((nextPos = channelList.find(",", pos)) != std::string::npos)
749  {
750  channel = channelList.substr(pos, nextPos - pos);
751 
752  alarms = interface_->getLastAlarms(channel);
753  __SUP_COUT__ << "get Last Alarms for channel: " << channel << __E__;
754  jsonFiller(xmlOut, alarms);
755  pos = nextPos + 1;
756  }
757  }
758  else
759  {
760  alarms = interface_->getLastAlarms("");
761  __SUP_COUT__ << "get Last Alarms for all channels" << __E__;
762  jsonFiller(xmlOut, alarms);
763  }
764 } // end GetLastAlarmsData()
765 
766 //==============================================================================
767 void SlowControlsDashboardSupervisor::GetAlarmsCheck(HttpXmlDocument& xmlOut)
768 {
769  __SUP_COUT__ << "Requesting alarms check cache data!" << __E__;
770 
771  std::string JSONMessage = "{ ";
772  JSONMessage += "\"last_check\":" +
773  std::to_string(std::chrono::duration_cast<std::chrono::seconds>(
774  alarms_timestamp_.time_since_epoch())
775  .count()) +
776  ",";
777  JSONMessage += "\"total\":" + std::to_string(alarms_.size()) + ",";
778  JSONMessage += "\"alarms\": [";
779  unsigned int nactive = 0;
780  if(alarms_.size())
781  {
782  for(auto& alarmRow : alarms_)
783  {
784  JSONMessage += "{ ";
785  JSONMessage += "\"name\":\"" + alarmRow[0] + "\",";
786  if(alarmRow.size() > 9)
787  { // alarm present
788  ++nactive;
789  JSONMessage += "\"time\":\"" + alarmRow[1] + "\",";
790  JSONMessage += "\"value\":\"" + alarmRow[2] + "\",";
791  JSONMessage += "\"status\":\"" + alarmRow[3] + "\",";
792  JSONMessage += "\"severity\":\"" + alarmRow[4] + "\",";
793  }
794  JSONMessage =
795  JSONMessage.substr(0, JSONMessage.length() - 1); // get rid of last ,
796  JSONMessage += "},";
797  } //end alarm loop
798  JSONMessage =
799  JSONMessage.substr(0, JSONMessage.length() - 1); // get rid of last ,
800  }
801  JSONMessage += "], \"nactive\": " + std::to_string(nactive);
802  JSONMessage += "}";
803  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
804 } // end GetAlarmsCheck()
805 
806 //==============================================================================
807 void SlowControlsDashboardSupervisor::GetAlarmsLogData(cgicc::Cgicc& cgiIn,
808  HttpXmlDocument& xmlOut)
809 {
810  __SUP_COUT__ << "Requesting alarms log data!" << __E__;
811 
812  std::string channelList = CgiDataUtilities::postData(cgiIn, "pvList");
813 
814  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
815  << "Getting Alarms Log for " << channelList << __E__;
816  __SUP_COUT__ << "channelList.size(): " << channelList.size() << __E__;
817 
818  std::vector<std::vector<std::string>> alarmsLog;
819 
820  // create lambda function to fill JSONMessage
821  std::function<void(HttpXmlDocument&, std::vector<std::vector<std::string>>&)>
822  jsonFiller = [](HttpXmlDocument& xmlOut,
823  std::vector<std::vector<std::string>>& alarmsLog) {
824  if(alarmsLog.size())
825  for(auto& alarmRow : alarmsLog)
826  {
827  std::string JSONMessage = "{ ";
828  JSONMessage += "\"id\":\"" + alarmRow[0] + "\",";
829  JSONMessage += "\"pvName\":\"" + alarmRow[1] + "\",";
830  JSONMessage += "\"pvValue\":\"" + alarmRow[2] + "\",";
831  JSONMessage += "\"pvStatus\":\"" + alarmRow[3] + "\",";
832  JSONMessage += "\"pvSeverity\":\"" + alarmRow[4] + "\",";
833  JSONMessage += "\"pvTime\":\"" + alarmRow[5] + "\",";
834 
835  JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
836  JSONMessage += "}";
837  xmlOut.addTextElementToData("JSON", JSONMessage); // add to response
838  // __SUP_COUT__ << JSONMessage << __E__;
839  }
840  };
841 
842  if(channelList.size() > 0)
843  {
844  std::string channel;
845  size_t pos = 0;
846  size_t nextPos;
847  while((nextPos = channelList.find(",", pos)) != std::string::npos)
848  {
849  channel = channelList.substr(pos, nextPos - pos);
850 
851  alarmsLog = interface_->getAlarmsLog(channel);
852  __SUP_COUT__ << "get Alarms Log for channel: " << channel << __E__;
853  jsonFiller(xmlOut, alarmsLog);
854  pos = nextPos + 1;
855  }
856  }
857  else
858  {
859  alarmsLog = interface_->getAlarmsLog("");
860  __SUP_COUT__ << "get Alarms Log for all channels" << __E__;
861  jsonFiller(xmlOut, alarmsLog);
862  }
863 } // end GetAlarmsLogData()
864 
865 //==============================================================================
866 void SlowControlsDashboardSupervisor::GetUserPermissions(
867  cgicc::Cgicc& /*cgiIn*/,
868  HttpXmlDocument& /*xmlOut*/,
869  const WebUsers::RequestUserInfo& /*userInfo*/)
870 {
871  return;
872 }
873 
874 //==============================================================================
875 void SlowControlsDashboardSupervisor::GenerateUID(cgicc::Cgicc& /*cgiIn*/,
876  HttpXmlDocument& xmlOut,
877  std::string channelList)
878 {
879  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " "
880  << "Generating UID" << __E__;
881 
882  std::set<std::string> channelDependencies;
883  StringMacros::getSetFromString(channelList, channelDependencies);
884 
885  // make entry for new UID_ in UID-to-channel map
886  channelDependencyLookupMap_.insert(
887  std::pair<int, std::set<std::string>>(++UID_, channelDependencies));
888 
889  uidPollTimeMap_.insert(std::pair<int, long int>(UID_, std::time(NULL)));
890 
891  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() << " NEW UID: " << UID_
892  << " maps to " << channelDependencies.size() << " channels" << __E__;
893 
894  xmlOut.addTextElementToData("JSON",
895  std::string("{ \"message\": \"") + std::to_string(UID_) +
896  "\"}"); // add to response
897 } // end GenerateUID()
898 
899 //==============================================================================
900 void SlowControlsDashboardSupervisor::GetList(cgicc::Cgicc& /*cgiIn*/,
901  HttpXmlDocument& xmlOut)
902 {
903  if(interface_ != NULL)
904  {
905  __SUP_COUT__ << "Interface is defined! Attempting to get list!" << __E__;
906  // __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
907  // __E__;
908  std::string list;
909  try
910  {
911  list = interface_->getList("JSON");
912  }
913  catch(std::runtime_error& e)
914  {
915  __SUP_SS__ << "Channel list request failed: " << e.what() << __E__;
916  __SUP_SS_THROW__;
917  }
918 
919  __SUP_COUT__ << " " << list << __E__;
920 
921  xmlOut.addTextElementToData("JSON", list); // add to response
922  }
923  else
924  {
925  __SUP_COUT__ << "Interface undefined! Failed to get list!" << __E__;
926  xmlOut.addTextElementToData("JSON", "[\"None\"]");
927  }
928 } // end GetList()
929 
930 //==============================================================================
931 void SlowControlsDashboardSupervisor::GetPages(cgicc::Cgicc& /*cgiIn*/,
932  HttpXmlDocument& xmlOut)
933 {
934  std::vector<std::string> pages;
935 
936  listFiles("", true, &pages);
937 
938  std::string returnJSON = "[";
939  for(auto it = pages.begin(); it != pages.end(); it++)
940  {
941  if(*it != "." && *it != "..")
942  returnJSON += "\"" + *it + "\", ";
943  }
944  if(returnJSON.size() > 2 && returnJSON.compare("[") != 0)
945  {
946  __SUP_COUT__ << "Found pages on server!" << __E__;
947  returnJSON.resize(returnJSON.size() - 2);
948  returnJSON += "]";
949  }
950  else
951  {
952  // No pages on the server
953  __SUP_COUT__ << "No pages found on server!" << __E__;
954  returnJSON = "[\"None\"]";
955  }
956  __SUP_COUT__ << returnJSON << __E__;
957 
958  xmlOut.addTextElementToData("JSON", returnJSON); // add to response
959 } // end GetPages()
960 
961 //==============================================================================
962 void SlowControlsDashboardSupervisor::loadPage(
963  cgicc::Cgicc& /*cgiIn*/,
964  HttpXmlDocument& xmlOut,
965  std::string page,
966  const WebUsers::RequestUserInfo& /*userInfo*/)
967 {
968  page = StringMacros::decodeURIComponent(page);
969 
970  // FIXME Filter out malicious attacks i.e. ../../../../../ stuff
971  struct stat buffer;
972  if(page.find("..") != std::string::npos)
973  {
974  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
975  << "Error! Request using '..': " << page << __E__;
976  }
977  else if(page.find("~") != std::string::npos)
978  {
979  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
980  << "Error! Request using '~': " << page << __E__;
981  }
982  else if(!(stat(page.c_str(), &buffer) == 0))
983  {
984  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
985  << "Error! File not found: " << page << __E__;
986  }
987  // Remove double / in path
988 
989  __SUP_COUT__ << page << __E__;
990 
991  if(page.at(0) == '/')
992  {
993  __SUP_COUT__ << "First character is '/'" << __E__;
994  page.erase(page.begin(), page.begin() + 1);
995  __SUP_COUT__ << page << __E__;
996  }
997 
998  std::string file = PAGES_DIRECTORY;
999  file += page;
1000  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1001  << "Trying to load page: " << page << __E__;
1002  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1003  << "Trying to load page: " << file << __E__;
1004  // read file
1005  // for each line in file
1006 
1007  std::ifstream infile(file);
1008  if(infile.fail())
1009  {
1010  __SUP_COUT__ << "Failed reading file: " << file << __E__;
1011 
1012  xmlOut.addTextElementToData("Time", "[\"Not Found\"]"); // add to response
1013  xmlOut.addTextElementToData("Notes", "[\"Not Found\"]"); // add to response
1014  xmlOut.addTextElementToData(
1015  "Page", StringMacros::encodeURIComponent(page)); // add to response
1016  return;
1017  }
1018  __SUP_COUT__ << "Reading file" << __E__;
1019 
1020  std::string time = "";
1021  std::string notes = "";
1022  std::string controlsPage = "";
1023 
1024  for(std::string line; getline(infile, line);)
1025  {
1026  __SUP_COUT__ << line << __E__;
1027  if(!line.substr(0, 5).compare("Time:"))
1028  {
1029  time = line.substr(6);
1030  }
1031  else if(!line.substr(0, 6).compare("Notes:"))
1032  {
1033  notes = line.substr(7);
1034  }
1035  else if(!line.substr(0, 5).compare("Page:"))
1036  {
1037  controlsPage = line.substr(6);
1038  }
1039  }
1040  __SUP_COUT__ << "Finished reading file" << __E__;
1041  __SUP_COUTV__(time);
1042  __SUP_COUTV__(notes);
1043  __SUP_COUTV__(controlsPage);
1044 
1045  xmlOut.addTextElementToData("Time", time); // add to response
1046  xmlOut.addTextElementToData("Notes", notes); // add to response
1047  xmlOut.addTextElementToData("Page", controlsPage); // add to response
1048 } // end loadPage()
1049 
1050 //==============================================================================
1051 void SlowControlsDashboardSupervisor::loadPhoebusPage(
1052  cgicc::Cgicc& /*cgiIn*/,
1053  HttpXmlDocument& xmlOut,
1054  std::string page,
1055  const WebUsers::RequestUserInfo& /*userInfo*/)
1056 {
1057  page = StringMacros::decodeURIComponent(page);
1058 
1059  // FIXME Filter out malicious attacks i.e. ../../../../../ stuff
1060  struct stat buffer;
1061  if(page.find("..") != std::string::npos)
1062  {
1063  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1064  << "Error! Request using '..': " << page << __E__;
1065  }
1066  else if(page.find("~") != std::string::npos)
1067  {
1068  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1069  << "Error! Request using '~': " << page << __E__;
1070  }
1071  else if(!(stat(page.c_str(), &buffer) == 0))
1072  {
1073  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1074  << "Error! File not found: " << page << __E__;
1075  }
1076  // Remove double / in path
1077 
1078  __SUP_COUT__ << page << __E__;
1079 
1080  if(page.at(0) == '/')
1081  {
1082  __SUP_COUT__ << "First character is '/'" << __E__;
1083  page.erase(page.begin(), page.begin() + 1);
1084  __SUP_COUT__ << page << __E__;
1085  }
1086 
1087  std::string file = PAGES_DIRECTORY;
1088  file += page;
1089  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1090  << "Trying to load page: " << page << __E__;
1091  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1092  << "Trying to load page: " << file << __E__;
1093 
1094  // read file
1095  __SUP_COUT__ << "Reading file" << __E__;
1096  std::ifstream infile(file);
1097  if(infile.fail())
1098  {
1099  __SUP_COUT__ << "Failed reading file: " << file << __E__;
1100  xmlOut.addTextElementToData(
1101  "Page", StringMacros::encodeURIComponent(page)); // add to response
1102  return;
1103  }
1104 
1105  std::string xml;
1106  for(std::string line; getline(infile, line);)
1107  {
1108  xml += line + "\n";
1109  }
1110  __SUP_COUT__ << xml << __E__;
1111  xmlOut.addTextElementToData("PHOEBUS", xml);
1112 
1113 } // end loadPhoebusPage()
1114 
1115 //==============================================================================
1116 void SlowControlsDashboardSupervisor::SaveControlsPage(
1117  cgicc::Cgicc& cgiIn,
1118  HttpXmlDocument& /*xmlOut*/,
1119  const WebUsers::RequestUserInfo& /*userInfo*/)
1120 {
1121  __SUP_COUT__ << "ControlsDashboard wants to create a Controls Page!" << __E__;
1122 
1123  std::string controlsPageName = CgiDataUtilities::postData(cgiIn, "Name");
1124  std::string pageString = CgiDataUtilities::postData(cgiIn, "Page");
1125  std::string Time = CgiDataUtilities::postData(cgiIn, "Time");
1126  std::string Notes =
1127  StringMacros::decodeURIComponent(CgiDataUtilities::postData(cgiIn, "Notes"));
1128  std::string isControlsPagePublic = CgiDataUtilities::postData(cgiIn, "isPublic");
1129 
1130  __SUP_COUTV__(controlsPageName);
1131  __SUP_COUTV__(pageString);
1132  __SUP_COUTV__(Notes);
1133  __SUP_COUTV__(Time);
1134  __SUP_COUTV__(isControlsPagePublic);
1135 
1136  if(controlsPageName == "")
1137  return;
1138 
1139  std::string fullPath;
1140  if(isControlsPagePublic == "true")
1141  fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1142  else
1143  fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1144 
1145  __SUP_COUTV__(fullPath);
1146 
1147  std::string file = fullPath + controlsPageName;
1148 
1149  __SUP_COUTV__("Saving Controls Page to: " + file);
1150 
1151  std::string extension = file.substr(file.length() - 4, 4);
1152  if(extension != ".dat")
1153  {
1154  __SUP_COUT__ << "Extension : " << extension << __E__;
1155  file += std::string(".dat");
1156  }
1157  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1158  << "Trying to save page: " << controlsPageName << __E__;
1159  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1160  << "Trying to save page as: " << file << __E__;
1161  // read file
1162  // for each line in file
1163 
1164  std::ofstream outputFile;
1165  outputFile.open(file);
1166  if(!outputFile.is_open())
1167  {
1168  __SUP_SS__ << "Failed to open file for writing: " << file << __E__;
1169  __SUP_SS_THROW__;
1170  }
1171  outputFile << "Time: " << Time << "\n";
1172  outputFile << "Notes: " << Notes << "\n";
1173  outputFile << "Page: " << pageString;
1174  outputFile.close();
1175 
1176  __SUP_COUT__ << "Finished writing file" << __E__;
1177 
1178  return;
1179 }
1180 
1181 //==============================================================================
1182 void SlowControlsDashboardSupervisor::SavePhoebusControlsPage(
1183  cgicc::Cgicc& cgiIn,
1184  HttpXmlDocument& /*xmlOut*/,
1185  const WebUsers::RequestUserInfo& /*userInfo*/)
1186 {
1187  __SUP_COUT__ << "ControlsDashboard wants to create a Controls Page!" << __E__;
1188 
1189  std::string controlsPageName = CgiDataUtilities::postData(cgiIn, "Name");
1190  std::string pageString = CgiDataUtilities::postData(cgiIn, "Page");
1191  std::string isControlsPagePublic = CgiDataUtilities::postData(cgiIn, "isPublic");
1192 
1193  __SUP_COUTV__(controlsPageName);
1194  __SUP_COUTV__(pageString);
1195  __SUP_COUTV__(isControlsPagePublic);
1196 
1197  if(controlsPageName == "")
1198  return;
1199 
1200  std::string fullPath;
1201  if(isControlsPagePublic == "true")
1202  fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1203  else
1204  fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1205 
1206  __SUP_COUTV__(fullPath);
1207 
1208  std::string file = fullPath + controlsPageName;
1209 
1210  __SUP_COUTV__("Saving Controls Page to: " + file);
1211 
1212  std::string extension = file.substr(file.length() - 4, 4);
1213  if(extension != ".bob")
1214  {
1215  __SUP_COUT__ << "Extension : " << extension << __E__;
1216  file += std::string(".bob");
1217  }
1218  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1219  << "Trying to save page: " << controlsPageName << __E__;
1220  __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1221  << "Trying to save page as: " << file << __E__;
1222  // read file
1223  // for each line in file
1224 
1225  std::ofstream outputFile;
1226  outputFile.open(file);
1227  if(!outputFile.is_open())
1228  {
1229  __SUP_SS__ << "Failed to open file for writing: " << file << __E__;
1230  __SUP_SS_THROW__;
1231  }
1232  outputFile << pageString << "\n";
1233  outputFile.close();
1234 
1235  __SUP_COUT__ << "Finished writing file" << __E__;
1236 
1237  return;
1238 }
1239 
1240 //==============================================================================
1241 void SlowControlsDashboardSupervisor::saveImageFile(
1242  cgicc::Cgicc& cgiIn,
1243  HttpXmlDocument& /*xmlOut*/,
1244  const WebUsers::RequestUserInfo& /*userInfo*/)
1245 {
1246  __SUP_COUT__ << "ControlsDashboard wants to save the image file uploaded!" << __E__;
1247 
1248  std::string isImagePublic = cgiIn("isPublic");
1249  const std::vector<cgicc::FormFile>& files = cgiIn.getFiles();
1250  std::string filename;
1251  std::ofstream myfile;
1252  std::string fullPath;
1253 
1254  __SUP_COUTV__(files.size());
1255  __SUP_COUTV__(isImagePublic);
1256 
1257  if(isImagePublic == "true")
1258  fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1259  else
1260  fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1261 
1262  for(unsigned int i = 0; i < files.size(); ++i)
1263  {
1264  filename = files[i].getFilename();
1265  filename = fullPath + filename;
1266  __COUT__ << "file " << i << " - " << filename << std::endl;
1267 
1268  myfile.open(filename.c_str());
1269  if(myfile.is_open())
1270  {
1271  files[i].writeToStream(myfile);
1272  myfile.close();
1273  __SUP_COUT__ << "Finished writing image file" << __E__;
1274  }
1275  }
1276 
1277  return;
1278 }
1279 
1280 //==============================================================================
1281 void SlowControlsDashboardSupervisor::Subscribe(cgicc::Cgicc& /*cgiIn*/,
1282  HttpXmlDocument& /*xmlOut*/)
1283 {
1284 }
1285 
1286 //==============================================================================
1287 void SlowControlsDashboardSupervisor::Unsubscribe(cgicc::Cgicc& /*cgiIn*/,
1288  HttpXmlDocument& /*xmlOut*/)
1289 {
1290 }
1291 
1292 //==============================================================================
1293 //==============================================================================
1294 //================================================== UTILITIES
1295 //===========================================================
1296 //==============================================================================
1298 {
1299  struct stat fileInfo;
1300  stat(dir.c_str(), &fileInfo);
1301  if(S_ISDIR(fileInfo.st_mode))
1302  {
1303  return true;
1304  }
1305  else
1306  {
1307  return false;
1308  }
1309 }
1310 
1311 //==============================================================================
1312 void SlowControlsDashboardSupervisor::listFiles(std::string innerDir,
1313  bool recursive,
1314  std::vector<std::string>* pages)
1315 {
1316  std::string baseDir = PAGES_DIRECTORY;
1317  baseDir += innerDir;
1318  DIR* dp;
1319  struct dirent* dirp;
1320  if((dp = opendir(baseDir.c_str())) == NULL)
1321  {
1322  __SUP_COUT__ << "[ERROR: " << errno << " ] Couldn't open " << baseDir << "."
1323  << __E__;
1324  return;
1325  }
1326  else
1327  {
1328  while((dirp = readdir(dp)) != NULL)
1329  {
1330  if(dirp->d_name != std::string(".") && dirp->d_name != std::string(".."))
1331  {
1332  if(isDir(baseDir + dirp->d_name) == true && recursive == true)
1333  {
1334  // pages->push_back(baseDir + dirp->d_name);
1335  __SUP_COUT__ << "[DIR]\t" << baseDir << dirp->d_name << "/" << __E__;
1336  listFiles(std::string("") + dirp->d_name + "/", true, pages);
1337  }
1338  else
1339  {
1340  pages->push_back(innerDir + dirp->d_name);
1341  __SUP_COUT__ << "[FILE]\t" << baseDir << innerDir << dirp->d_name
1342  << __E__;
1343  }
1344  }
1345  }
1346  closedir(dp);
1347  }
1348 }
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.