1 #include "otsdaq-utilities/ControlsDashboard/ControlsDashboardSupervisor.h"
6 #include "otsdaq-core/PluginMakers/MakeSlowControls.h"
7 #include "otsdaq-core/SlowControlsCore/SlowControlsVInterface.h"
11 #define CONTROLS_SUPERVISOR_DATA_PATH \
12 std::string(__ENV__("SERVICE_DATA_PATH")) + "/ControlsDashboardData/"
13 #define PAGES_DIRECTORY CONTROLS_SUPERVISOR_DATA_PATH + "pages/"
19 : CoreSupervisorBase(stub)
21 __SUP_COUT__ <<
"Constructor." << __E__;
23 INIT_MF(
"ControlsDashboardSupervisor");
26 mkdir(((std::string)(CONTROLS_SUPERVISOR_DATA_PATH)).c_str(), 0755);
27 mkdir(((std::string)(PAGES_DIRECTORY)).c_str(), 0755);
31 __SUP_COUT__ <<
"Constructed." << __E__;
35 ControlsDashboardSupervisor::~ControlsDashboardSupervisor(
void)
37 __SUP_COUT__ <<
"Destructor." << __E__;
39 __SUP_COUT__ <<
"Destructed." << __E__;
43 void ControlsDashboardSupervisor::destroy(
void)
50 void ControlsDashboardSupervisor::init(
void)
55 __SUP_COUT__ << std::endl;
56 ConfigurationTree node = CorePropertySupervisorBase::getSupervisorTableNode();
57 std::string pluginType = node.getNode(
"ControlsInterfacePluginType").getValue();
58 __SUP_COUTV__(pluginType);
61 makeSlowControls(pluginType,
62 node.getUIDAsString(),
63 CorePropertySupervisorBase::getContextTreeNode(),
64 CorePropertySupervisorBase::getSupervisorConfigurationPath());
65 __COUT__ << std::endl;
67 __SUP_COUT__ <<
"Finished init() w/ interface: " << pluginType << std::endl;
75 std::lock_guard<std::mutex> lock(cs->pluginBusyMutex_);
77 cs->interface_->initialize();
90 void ControlsDashboardSupervisor::setSupervisorPropertyDefaults()
92 CorePropertySupervisorBase::setSupervisorProperty(
93 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.CheckUserLockRequestTypes,
"*");
99 void ControlsDashboardSupervisor::forceSupervisorPropertyValues()
101 CorePropertySupervisorBase::setSupervisorProperty(
102 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
"poll");
106 void ControlsDashboardSupervisor::request(
const std::string& requestType,
108 HttpXmlDocument& xmlOut,
109 const WebUsers::RequestUserInfo& userInfo)
166 if(requestType !=
"getPages" && !pluginBusyMutex_.try_lock())
168 __SUP_SS__ <<
"Controls plugin is still initializing. Please try again in a "
174 __SUP_COUT__ <<
"User name is " << userInfo.username_ <<
"." << __E__;
175 __SUP_COUT__ <<
"User permission level for request '" << requestType <<
"' is "
176 << unsigned(userInfo.permissionLevel_) <<
"." << __E__;
179 handleRequest(requestType, xmlOut, cgiIn, userInfo.username_);
181 catch(
const std::runtime_error& e)
183 __SUP_SS__ <<
"Error occurred handling request '" << requestType
184 <<
"': " << e.what() << __E__;
185 __SUP_COUT__ << ss.str();
186 xmlOut.addTextElementToData(
"Error", ss.str());
190 __SS__ <<
"Unknown error occurred handling request '" << requestType <<
"!'"
192 __SUP_COUT__ << ss.str();
193 xmlOut.addTextElementToData(
"Error", ss.str());
196 pluginBusyMutex_.unlock();
200 void ControlsDashboardSupervisor::handleRequest(
const std::string Command,
201 HttpXmlDocument& xmlOut,
203 const std::string& username)
206 __SUP_COUT__ << std::endl;
208 if(Command ==
"poll")
210 std::string uid = CgiDataUtilities::getOrPostData(cgiIn,
"uid");
211 Poll(cgiIn, xmlOut, uid);
213 else if(Command ==
"generateUID")
215 std::string pvList = CgiDataUtilities::getOrPostData(cgiIn,
"PVList");
216 GenerateUID(cgiIn, xmlOut, pvList);
218 else if(Command ==
"GetPVSettings")
220 std::string pvList = CgiDataUtilities::getOrPostData(cgiIn,
"PVList");
221 GetPVSettings(cgiIn, xmlOut, pvList);
222 xmlOut.addTextElementToData(
"id", CgiDataUtilities::getData(cgiIn,
"id"));
224 else if(Command ==
"getList")
226 __SUP_COUT__ <<
"PV List requested from server! " << std::endl;
227 GetList(cgiIn, xmlOut);
229 else if(Command ==
"getPages")
231 __SUP_COUT__ <<
"Requesting pages from server! " << std::endl;
232 GetPages(cgiIn, xmlOut);
234 else if(Command ==
"loadPage")
236 std::string page = CgiDataUtilities::getData(cgiIn,
"Page");
237 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" " << page
240 loadPage(cgiIn, xmlOut, page);
242 else if(Command ==
"savePage")
244 std::string pageName = CgiDataUtilities::getData(cgiIn,
"PageName");
245 std::string page = CgiDataUtilities::getOrPostData(cgiIn,
"Page");
246 SavePage(cgiIn, xmlOut, pageName, page);
248 __SUP_COUT__ <<
"" << std::endl;
254 void ControlsDashboardSupervisor::Poll(cgicc::Cgicc& cgiIn,
255 HttpXmlDocument& xmlOut,
258 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
259 <<
"Polling on UID:" << UID << std::endl;
261 std::map<int, std::set<std::string>>::iterator mapReference;
264 (mapReference = pvDependencyLookupMap_.find(std::stoi(UID))) !=
265 pvDependencyLookupMap_.end())
267 std::string JSONMessage =
"{ ";
269 for(
auto pv : mapReference->second)
271 __SUP_COUT__ << pv << std::endl;
275 std::array<std::string, 4> pvInformation = interface_->getCurrentValue(pv);
276 __SUP_COUT__ << pv <<
": " << pvInformation[1] <<
" : " << pvInformation[3]
279 if(pvInformation[0] !=
"NO_CHANGE")
282 JSONMessage +=
"\"" + pv +
"\": {";
290 JSONMessage +=
"\"Timestamp\":\"" + pvInformation[0] +
"\",";
291 JSONMessage +=
"\"Value\":\"" + pvInformation[1] +
"\",";
292 JSONMessage +=
"\"Status\":\"" + pvInformation[2] +
"\",";
293 JSONMessage +=
"\"Severity\":\"" + pvInformation[3] +
"\"},";
297 __SUP_COUT__ <<
"No change in value since last poll: " << pv << std::endl;
301 if(pvInformation[3] ==
"INVALID")
303 interface_->subscribe(pv);
312 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
314 __SUP_COUT__ << JSONMessage << std::endl;
315 xmlOut.addTextElementToData(
"JSON", JSONMessage);
339 xmlOut.addTextElementToData(
"JSON",
340 "{ \"message\": \"NOT_FOUND\"}");
344 void ControlsDashboardSupervisor::GetPVSettings(cgicc::Cgicc& cgiIn,
345 HttpXmlDocument& xmlOut,
348 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
349 <<
"Getting settings for " << pvList << std::endl;
351 std::string JSONMessage =
"{ ";
356 size_t lastIndex = pvList.find_last_of(
",");
357 std::cout <<
"**********************" << pvList.size() << std::endl;
358 if(pvList.size() > 0)
360 while((nextPos = pvList.find(
",", pos)) != std::string::npos)
362 pv = pvList.substr(pos, nextPos - pos);
364 __SUP_COUT__ << pv << std::endl;
366 std::array<std::string, 9> pvSettings = interface_->getSettings(pv);
368 JSONMessage +=
"\"" + pv +
"\": {";
369 JSONMessage +=
"\"Units \": \"" + pvSettings[0] +
"\",";
370 JSONMessage +=
"\"Upper_Display_Limit\": \"" + pvSettings[1] +
"\",";
371 JSONMessage +=
"\"Lower_Display_Limit\": \"" + pvSettings[2] +
"\",";
372 JSONMessage +=
"\"Upper_Alarm_Limit \": \"" + pvSettings[3] +
"\",";
373 JSONMessage +=
"\"Upper_Warning_Limit\": \"" + pvSettings[4] +
"\",";
374 JSONMessage +=
"\"Lower_Warning_Limit\": \"" + pvSettings[5] +
"\",";
375 JSONMessage +=
"\"Lower_Alarm_Limit \": \"" + pvSettings[6] +
"\",";
376 JSONMessage +=
"\"Upper_Control_Limit\": \"" + pvSettings[7] +
"\",";
377 JSONMessage +=
"\"Lower_Control_Limit\": \"" + pvSettings[8] +
"\"},";
382 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
385 __SUP_COUT__ << JSONMessage << std::endl;
386 xmlOut.addTextElementToData(
"JSON", JSONMessage);
390 xmlOut.addTextElementToData(
391 "JSON",
"{ \"message\": \"GetPVSettings\"}");
395 void ControlsDashboardSupervisor::GenerateUID(cgicc::Cgicc& cgiIn,
396 HttpXmlDocument& xmlOut,
399 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
400 <<
"Generating UID" << std::endl;
402 std::set<std::string> pvDependencies;
407 size_t lastIndex = pvlist.find_last_of(
",");
409 if(pvlist.size() > 0)
412 __SUP_COUT__ << pvlist << std::endl;
414 while((nextPos = pvlist.find(
",", pos)) != std::string::npos)
416 pv = pvlist.substr(pos, nextPos - pos);
419 pvDependencies.insert(pv);
423 pvDependencyLookupMap_.insert(
424 std::pair<
int, std::set<std::string>>(++UID_, pvDependencies));
426 uid = (std::string(
"{ \"message\": \"") + std::to_string(UID_) +
"\"}");
430 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
431 <<
" PVList invalid: " << pvlist << std::endl;
432 uid =
"{ \"message\": \"-1\"}";
435 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" NEW UID: " << UID_
438 xmlOut.addTextElementToData(
"JSON", uid);
441 void ControlsDashboardSupervisor::GetList(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
443 if(interface_ != NULL)
445 __SUP_COUT__ <<
"Interface is defined! Attempting to get list!" << std::endl;
447 std::cout <<
" " << interface_->getList(
"JSON") << std::endl;
449 xmlOut.addTextElementToData(
"JSON",
450 interface_->getList(
"JSON"));
454 __SUP_COUT__ <<
"Interface undefined! Failed to get list!" << std::endl;
455 xmlOut.addTextElementToData(
"JSON",
"[\"None\"]");
459 void ControlsDashboardSupervisor::GetPages(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
483 std::vector<std::string> pages;
485 listFiles(
"",
true, &pages);
487 std::string returnJSON =
"[";
488 for(
auto it = pages.begin(); it != pages.end(); it++)
490 if(*it !=
"." && *it !=
"..")
491 returnJSON +=
"\"" + *it +
"\", ";
493 if(returnJSON.size() > 2 && returnJSON.compare(
"[") != 0)
495 __SUP_COUT__ <<
"Found pages on server!" << std::endl;
496 returnJSON.resize(returnJSON.size() - 2);
502 __SUP_COUT__ <<
"No pages found on server!" << std::endl;
503 returnJSON =
"[\"None\"]";
505 std::cout << returnJSON << std::endl;
507 xmlOut.addTextElementToData(
"JSON", returnJSON);
510 void ControlsDashboardSupervisor::loadPage(cgicc::Cgicc& cgiIn,
511 HttpXmlDocument& xmlOut,
516 if(page.find(
"..") != std::string::npos)
518 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
519 <<
"Error! Request using '..': " << page << std::endl;
521 else if(page.find(
"~") != std::string::npos)
523 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
524 <<
"Error! Request using '~': " << page << std::endl;
526 else if(!(stat(page.c_str(), &buffer) == 0))
528 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
529 <<
"Error! File not found: " << page << std::endl;
532 std::string file = PAGES_DIRECTORY;
534 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
535 <<
"Trying to load page: " << page << std::endl;
536 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
537 <<
"Trying to load page: " << file << std::endl;
541 std::ifstream infile(file);
542 std::cout <<
"Reading file" << std::endl;
543 std::string JSONpage =
"";
544 for(std::string line; getline(infile, line);)
546 std::cout << line << std::endl;
549 std::cout <<
"Finished reading file" << std::endl;
551 xmlOut.addTextElementToData(
"JSON", JSONpage);
554 void ControlsDashboardSupervisor::SavePage(cgicc::Cgicc& cgiIn,
555 HttpXmlDocument& xmlOut,
556 std::string pageName,
559 std::string file = PAGES_DIRECTORY;
562 std::string extension = file.substr(file.length() - 4, 4);
563 if(extension !=
".dat")
565 __SUP_COUT__ <<
"Extension : " << extension << std::endl;
566 file += std::string(
".dat");
568 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
569 <<
"Trying to save page: " << page << std::endl;
570 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
571 <<
"Trying to save page as: " << file << std::endl;
575 std::ofstream outputFile;
576 outputFile.open(file);
581 std::cout <<
"Finished writing file" << std::endl;
586 void ControlsDashboardSupervisor::Subscribe(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
590 void ControlsDashboardSupervisor::Unsubscribe(cgicc::Cgicc& cgiIn,
591 HttpXmlDocument& xmlOut)
599 bool ControlsDashboardSupervisor::isDir(std::string dir)
601 struct stat fileInfo;
602 stat(dir.c_str(), &fileInfo);
603 if(S_ISDIR(fileInfo.st_mode))
613 void ControlsDashboardSupervisor::listFiles(std::string baseDir,
615 std::vector<std::string>* pages)
617 std::string base = PAGES_DIRECTORY;
622 if((dp = opendir(base.c_str())) == NULL)
624 std::cout <<
"[ERROR: " << errno <<
" ] Couldn't open " << base <<
"."
630 while((dirp = readdir(dp)) != NULL)
632 if(dirp->d_name != std::string(
".") && dirp->d_name != std::string(
".."))
634 if(isDir(base + dirp->d_name) ==
true && recursive ==
true)
637 std::cout <<
"[DIR]\t" << baseDir << dirp->d_name <<
"/" << std::endl;
638 listFiles(baseDir + dirp->d_name +
"/",
true, pages);
642 pages->push_back(baseDir + dirp->d_name);
643 std::cout <<
"[FILE]\t" << baseDir << dirp->d_name << std::endl;