1 #include "otsdaq-utilities/ControlsDashboard/ControlsDashboardSupervisor.h"
8 #include "otsdaq-core/PluginMakers/MakeSlowControls.h"
9 #include "otsdaq-core/SlowControlsCore/SlowControlsVInterface.h"
13 #define CONTROLS_SUPERVISOR_DATA_PATH \
14 std::string(__ENV__("SERVICE_DATA_PATH")) + "/ControlsDashboardData/"
15 #define PAGES_DIRECTORY CONTROLS_SUPERVISOR_DATA_PATH + "pages/"
21 : CoreSupervisorBase(stub)
23 __SUP_COUT__ <<
"Constructor." << __E__;
25 INIT_MF(
"ControlsDashboardSupervisor");
28 mkdir(((std::string)(CONTROLS_SUPERVISOR_DATA_PATH)).c_str(), 0755);
29 mkdir(((std::string)(PAGES_DIRECTORY)).c_str(), 0755);
33 __SUP_COUT__ <<
"Constructed." << __E__;
37 ControlsDashboardSupervisor::~ControlsDashboardSupervisor(
void)
39 __SUP_COUT__ <<
"Destructor." << __E__;
41 __SUP_COUT__ <<
"Destructed." << __E__;
45 void ControlsDashboardSupervisor::destroy(
void)
52 void ControlsDashboardSupervisor::init(
void)
57 __SUP_COUT__ << std::endl;
58 ConfigurationTree node = CorePropertySupervisorBase::getSupervisorTableNode();
59 std::string pluginType = node.getNode(
"ControlsInterfacePluginType").getValue();
60 __SUP_COUTV__(pluginType);
63 makeSlowControls(pluginType,
64 node.getUIDAsString(),
65 CorePropertySupervisorBase::getContextTreeNode(),
66 CorePropertySupervisorBase::getSupervisorConfigurationPath());
67 __COUT__ << std::endl;
69 __SUP_COUT__ <<
"Finished init() w/ interface: " << pluginType << std::endl;
77 std::lock_guard<std::mutex> lock(cs->pluginBusyMutex_);
79 cs->interface_->initialize();
92 void ControlsDashboardSupervisor::setSupervisorPropertyDefaults()
94 CorePropertySupervisorBase::setSupervisorProperty(
95 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.CheckUserLockRequestTypes,
"*");
101 void ControlsDashboardSupervisor::forceSupervisorPropertyValues()
103 CorePropertySupervisorBase::setSupervisorProperty(
104 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
"poll");
108 void ControlsDashboardSupervisor::request(
const std::string& requestType,
110 HttpXmlDocument& xmlOut,
111 const WebUsers::RequestUserInfo& userInfo)
169 if(requestType !=
"getPages" && !pluginBusyMutex_.try_lock())
171 __SUP_SS__ <<
"Controls plugin is still initializing. Please try again in a "
177 __SUP_COUT__ <<
"User name is " << userInfo.username_ <<
"." << __E__;
178 __SUP_COUT__ <<
"User permission level for request '" << requestType <<
"' is "
179 << unsigned(userInfo.permissionLevel_) <<
"." << __E__;
182 handleRequest(requestType, xmlOut, cgiIn, userInfo.username_);
184 catch(
const std::runtime_error& e)
186 __SUP_SS__ <<
"Error occurred handling request '" << requestType
187 <<
"': " << e.what() << __E__;
188 __SUP_COUT__ << ss.str();
189 xmlOut.addTextElementToData(
"Error", ss.str());
193 __SS__ <<
"Unknown error occurred handling request '" << requestType <<
"!'"
195 __SUP_COUT__ << ss.str();
196 xmlOut.addTextElementToData(
"Error", ss.str());
199 pluginBusyMutex_.unlock();
203 void ControlsDashboardSupervisor::handleRequest(
const std::string Command,
204 HttpXmlDocument& xmlOut,
206 const std::string& username)
209 __SUP_COUT__ << std::endl;
211 if(Command ==
"poll")
213 std::string uid = CgiDataUtilities::getOrPostData(cgiIn,
"uid");
214 Poll(cgiIn, xmlOut, uid);
216 else if(Command ==
"generateUID")
218 std::string pvList = CgiDataUtilities::getOrPostData(cgiIn,
"PVList");
219 GenerateUID(cgiIn, xmlOut, pvList);
221 else if(Command ==
"GetPVSettings")
223 std::string pvList = CgiDataUtilities::getOrPostData(cgiIn,
"PVList");
224 GetPVSettings(cgiIn, xmlOut, pvList);
225 xmlOut.addTextElementToData(
"id", CgiDataUtilities::getData(cgiIn,
"id"));
227 else if(Command ==
"getList")
229 __SUP_COUT__ <<
"PV List requested from server! " << std::endl;
230 GetList(cgiIn, xmlOut);
232 else if(Command ==
"getPages")
234 __SUP_COUT__ <<
"Requesting pages from server! " << std::endl;
235 GetPages(cgiIn, xmlOut);
237 else if(Command ==
"loadPage")
239 std::string page = CgiDataUtilities::getData(cgiIn,
"Page");
240 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" " << page
243 loadPage(cgiIn, xmlOut, page);
245 else if(Command ==
"savePage")
247 std::string pageName = CgiDataUtilities::getData(cgiIn,
"PageName");
248 std::string page = CgiDataUtilities::getOrPostData(cgiIn,
"Page");
249 SavePage(cgiIn, xmlOut, pageName, page);
251 __SUP_COUT__ <<
"" << std::endl;
257 void ControlsDashboardSupervisor::Poll(cgicc::Cgicc& cgiIn,
258 HttpXmlDocument& xmlOut,
261 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
262 <<
"Polling on UID:" << UID << std::endl;
264 std::map<int, std::set<std::string>>::iterator mapReference;
267 (mapReference = pvDependencyLookupMap_.find(std::stoi(UID))) !=
268 pvDependencyLookupMap_.end())
270 std::string JSONMessage =
"{ ";
272 for(
auto pv : mapReference->second)
274 __SUP_COUT__ << pv << std::endl;
278 std::array<std::string, 4> pvInformation = interface_->getCurrentValue(pv);
279 __SUP_COUT__ << pv <<
": " << pvInformation[1] <<
" : " << pvInformation[3]
282 if(pvInformation[0] !=
"NO_CHANGE")
285 JSONMessage +=
"\"" + pv +
"\": {";
293 JSONMessage +=
"\"Timestamp\":\"" + pvInformation[0] +
"\",";
294 JSONMessage +=
"\"Value\":\"" + pvInformation[1] +
"\",";
295 JSONMessage +=
"\"Status\":\"" + pvInformation[2] +
"\",";
296 JSONMessage +=
"\"Severity\":\"" + pvInformation[3] +
"\"},";
300 __SUP_COUT__ <<
"No change in value since last poll: " << pv << std::endl;
304 if(pvInformation[3] ==
"INVALID")
306 interface_->subscribe(pv);
315 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
317 __SUP_COUT__ << JSONMessage << std::endl;
318 xmlOut.addTextElementToData(
"JSON", JSONMessage);
342 xmlOut.addTextElementToData(
"JSON",
343 "{ \"message\": \"NOT_FOUND\"}");
347 void ControlsDashboardSupervisor::GetPVSettings(cgicc::Cgicc& cgiIn,
348 HttpXmlDocument& xmlOut,
351 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
352 <<
"Getting settings for " << pvList << std::endl;
354 std::string JSONMessage =
"{ ";
359 size_t lastIndex = pvList.find_last_of(
",");
360 std::cout <<
"**********************" << pvList.size() << std::endl;
361 if(pvList.size() > 0)
363 while((nextPos = pvList.find(
",", pos)) != std::string::npos)
365 pv = pvList.substr(pos, nextPos - pos);
367 __SUP_COUT__ << pv << std::endl;
369 std::array<std::string, 9> pvSettings = interface_->getSettings(pv);
371 JSONMessage +=
"\"" + pv +
"\": {";
372 JSONMessage +=
"\"Units \": \"" + pvSettings[0] +
"\",";
373 JSONMessage +=
"\"Upper_Display_Limit\": \"" + pvSettings[1] +
"\",";
374 JSONMessage +=
"\"Lower_Display_Limit\": \"" + pvSettings[2] +
"\",";
375 JSONMessage +=
"\"Upper_Alarm_Limit \": \"" + pvSettings[3] +
"\",";
376 JSONMessage +=
"\"Upper_Warning_Limit\": \"" + pvSettings[4] +
"\",";
377 JSONMessage +=
"\"Lower_Warning_Limit\": \"" + pvSettings[5] +
"\",";
378 JSONMessage +=
"\"Lower_Alarm_Limit \": \"" + pvSettings[6] +
"\",";
379 JSONMessage +=
"\"Upper_Control_Limit\": \"" + pvSettings[7] +
"\",";
380 JSONMessage +=
"\"Lower_Control_Limit\": \"" + pvSettings[8] +
"\"},";
385 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
388 __SUP_COUT__ << JSONMessage << std::endl;
389 xmlOut.addTextElementToData(
"JSON", JSONMessage);
393 xmlOut.addTextElementToData(
394 "JSON",
"{ \"message\": \"GetPVSettings\"}");
398 void ControlsDashboardSupervisor::GenerateUID(cgicc::Cgicc& cgiIn,
399 HttpXmlDocument& xmlOut,
402 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
403 <<
"Generating UID" << std::endl;
405 std::set<std::string> pvDependencies;
410 size_t lastIndex = pvlist.find_last_of(
",");
412 if(pvlist.size() > 0)
415 __SUP_COUT__ << pvlist << std::endl;
417 while((nextPos = pvlist.find(
",", pos)) != std::string::npos)
419 pv = pvlist.substr(pos, nextPos - pos);
422 pvDependencies.insert(pv);
426 pvDependencyLookupMap_.insert(
427 std::pair<
int, std::set<std::string>>(++UID_, pvDependencies));
429 uid = (std::string(
"{ \"message\": \"") + std::to_string(UID_) +
"\"}");
433 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
434 <<
" PVList invalid: " << pvlist << std::endl;
435 uid =
"{ \"message\": \"-1\"}";
438 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" NEW UID: " << UID_
441 xmlOut.addTextElementToData(
"JSON", uid);
444 void ControlsDashboardSupervisor::GetList(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
446 if(interface_ != NULL)
448 __SUP_COUT__ <<
"Interface is defined! Attempting to get list!" << std::endl;
450 std::cout <<
" " << interface_->getList(
"JSON") << std::endl;
452 xmlOut.addTextElementToData(
"JSON",
453 interface_->getList(
"JSON"));
457 __SUP_COUT__ <<
"Interface undefined! Failed to get list!" << std::endl;
458 xmlOut.addTextElementToData(
"JSON",
"[\"None\"]");
462 void ControlsDashboardSupervisor::GetPages(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
486 std::vector<std::string> pages;
488 listFiles(
"",
true, &pages);
490 std::string returnJSON =
"[";
491 for(
auto it = pages.begin(); it != pages.end(); it++)
493 if(*it !=
"." && *it !=
"..")
494 returnJSON +=
"\"" + *it +
"\", ";
496 if(returnJSON.size() > 2 && returnJSON.compare(
"[") != 0)
498 __SUP_COUT__ <<
"Found pages on server!" << std::endl;
499 returnJSON.resize(returnJSON.size() - 2);
505 __SUP_COUT__ <<
"No pages found on server!" << std::endl;
506 returnJSON =
"[\"None\"]";
508 std::cout << returnJSON << std::endl;
510 xmlOut.addTextElementToData(
"JSON", returnJSON);
513 void ControlsDashboardSupervisor::loadPage(cgicc::Cgicc& cgiIn,
514 HttpXmlDocument& xmlOut,
519 if(page.find(
"..") != std::string::npos)
521 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
522 <<
"Error! Request using '..': " << page << std::endl;
524 else if(page.find(
"~") != std::string::npos)
526 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
527 <<
"Error! Request using '~': " << page << std::endl;
529 else if(!(stat(page.c_str(), &buffer) == 0))
531 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
532 <<
"Error! File not found: " << page << std::endl;
535 std::string file = PAGES_DIRECTORY;
537 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
538 <<
"Trying to load page: " << page << std::endl;
539 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
540 <<
"Trying to load page: " << file << std::endl;
544 std::ifstream infile(file);
545 std::cout <<
"Reading file" << std::endl;
546 std::string JSONpage =
"";
547 for(std::string line; getline(infile, line);)
549 std::cout << line << std::endl;
552 std::cout <<
"Finished reading file" << std::endl;
554 xmlOut.addTextElementToData(
"JSON", JSONpage);
557 void ControlsDashboardSupervisor::SavePage(cgicc::Cgicc& cgiIn,
558 HttpXmlDocument& xmlOut,
559 std::string pageName,
562 std::string file = PAGES_DIRECTORY;
565 std::string extension = file.substr(file.length() - 4, 4);
566 if(extension !=
".dat")
568 __SUP_COUT__ <<
"Extension : " << extension << std::endl;
569 file += std::string(
".dat");
571 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
572 <<
"Trying to save page: " << page << std::endl;
573 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
574 <<
"Trying to save page as: " << file << std::endl;
578 std::ofstream outputFile;
579 outputFile.open(file);
584 std::cout <<
"Finished writing file" << std::endl;
589 void ControlsDashboardSupervisor::Subscribe(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
593 void ControlsDashboardSupervisor::Unsubscribe(cgicc::Cgicc& cgiIn,
594 HttpXmlDocument& xmlOut)
602 bool ControlsDashboardSupervisor::isDir(std::string dir)
604 struct stat fileInfo;
605 stat(dir.c_str(), &fileInfo);
606 if(S_ISDIR(fileInfo.st_mode))
616 void ControlsDashboardSupervisor::listFiles(std::string baseDir,
618 std::vector<std::string>* pages)
620 std::string base = PAGES_DIRECTORY;
625 if((dp = opendir(base.c_str())) == NULL)
627 std::cout <<
"[ERROR: " << errno <<
" ] Couldn't open " << base <<
"."
633 while((dirp = readdir(dp)) != NULL)
635 if(dirp->d_name != std::string(
".") && dirp->d_name != std::string(
".."))
637 if(isDir(base + dirp->d_name) ==
true && recursive ==
true)
640 std::cout <<
"[DIR]\t" << baseDir << dirp->d_name <<
"/" << std::endl;
641 listFiles(baseDir + dirp->d_name +
"/",
true, pages);
645 pages->push_back(baseDir + dirp->d_name);
646 std::cout <<
"[FILE]\t" << baseDir << dirp->d_name << std::endl;