$treeview $search $mathjax $extrastylesheet
otsdaq_utilities
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "otsdaq-utilities/ControlsDashboard/ControlsDashboardSupervisor.h" 00002 #include <sys/stat.h> //for stat() quickly checking if file exists 00003 #include <dirent.h> //for DIR 00004 #include <dirent.h> //for DIR 00005 #include <sys/stat.h> //for stat() quickly checking if file exists 00006 00007 #include "otsdaq-core/SlowControlsCore/SlowControlsVInterface.h" 00008 #include "otsdaq-core/PluginMakers/MakeSlowControls.h" 00009 00010 using namespace ots; 00011 00012 #define PAGES_DIRECTORY \ 00013 std::string(getenv("SERVICE_DATA_PATH")) + "/ControlsDashboardData/pages/"; 00014 00015 XDAQ_INSTANTIATOR_IMPL(ControlsDashboardSupervisor) 00016 00017 //======================================================================================================================== 00018 ControlsDashboardSupervisor::ControlsDashboardSupervisor(xdaq::ApplicationStub* stub) 00019 : CoreSupervisorBase(stub) 00020 { 00021 __SUP_COUT__ << "Constructor." << __E__; 00022 00023 INIT_MF("ControlsDashboardSupervisor"); 00024 00025 init(); 00026 00027 __SUP_COUT__ << "Constructed." << __E__; 00028 } //end constructor 00029 00030 //======================================================================================================================== 00031 ControlsDashboardSupervisor::~ControlsDashboardSupervisor(void) 00032 { 00033 __SUP_COUT__ << "Destructor." << __E__; 00034 destroy(); 00035 __SUP_COUT__ << "Destructed." << __E__; 00036 } // end destructor() 00037 00038 //======================================================================================================================== 00039 void ControlsDashboardSupervisor::destroy(void) 00040 { 00041 // called by destructor 00042 delete interface_; 00043 } // end destroy() 00044 00045 //======================================================================================================================== 00046 void ControlsDashboardSupervisor::init(void) 00047 // called by constructor 00048 { 00049 UID_ = 0; 00050 00051 __COUT__ << std::endl; 00052 ConfigurationTree node = CorePropertySupervisorBase::getSupervisorTableNode(); 00053 std::string pluginType = node.getNode("ControlsInterfacePluginType").getValue(); 00054 __COUTV__(pluginType); 00055 00056 interface_ = makeSlowControls( 00057 pluginType 00058 , node.getUIDAsString() 00059 , CorePropertySupervisorBase::getContextTreeNode() 00060 , CorePropertySupervisorBase::getSupervisorConfigurationPath()); 00061 __COUT__ << std::endl; 00062 00063 __COUT__ << "Finished init() w/ interface: " << pluginType << std::endl; 00064 00065 //interface_->initialize(); 00066 //std::thread([&](){interface_->initialize();}).detach(); //thread completes after creating, subscribing, and getting parameters for all pvs 00067 00068 } //end init() 00069 00070 //======================================================================================================================== 00071 // setSupervisorPropertyDefaults 00072 // override to set defaults for supervisor property values (before user settings 00073 // override) 00074 void ControlsDashboardSupervisor::setSupervisorPropertyDefaults() 00075 { 00076 CorePropertySupervisorBase::setSupervisorProperty( 00077 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.CheckUserLockRequestTypes, "*"); 00078 } 00079 00080 //======================================================================================================================== 00081 // forceSupervisorPropertyValues 00082 // override to force supervisor property values (and ignore user settings) 00083 void ControlsDashboardSupervisor::forceSupervisorPropertyValues() 00084 { 00085 CorePropertySupervisorBase::setSupervisorProperty( 00086 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes, "poll"); 00087 } 00088 00089 //======================================================================================================================== 00090 void ControlsDashboardSupervisor::request(const std::string& requestType, cgicc::Cgicc& cgiIn, 00091 HttpXmlDocument& xmlOut, const WebUsers::RequestUserInfo& userInfo) 00092 { 00093 // __COUT__ << std::endl; 00094 // cgicc::Cgicc cgi(in); 00095 // __COUT__ << std::endl; 00096 // std::string requestType = CgiDataUtilities::getData(cgi,"RequestType"); 00097 // __COUT__ << request << std::endl; 00098 // __COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << requestType << " : end"<< std::endl; 00099 00100 00101 // if(requestType == "") 00102 // { 00103 // Default(in, out); 00104 // return; 00105 // } 00106 // 00107 // HttpXmlDocument xmldoc; 00108 // uint64_t activeSessionIndex; 00109 // std::string user; 00110 // uint8_t userPermissions; 00111 // 00112 // //**** start LOGIN GATEWAY CODE ***// 00113 // { 00114 // bool automaticCommand = requestType == "poll"; //automatic commands should not refresh cookie code.. only user initiated commands should! 00115 // bool checkLock = true; 00116 // bool getUser = false; 00117 // bool requireLock = false; 00118 // 00119 // if(!theRemoteWebUsers_.xmlRequestToGateway( 00120 // cgi, 00121 // out, 00122 // &xmldoc, 00123 // allSupervisorInfo_, 00124 // &userPermissions, //acquire user's access level (optionally null pointer) 00125 // !automaticCommand, //true/false refresh cookie code 00126 // 1, //set access level requirement to pass gateway 00127 // checkLock, //true/false enable check that system is unlocked or this user has the lock 00128 // requireLock, //true/false requires this user has the lock to proceed 00129 // 0,//&userWithLock, //acquire username with lock (optionally null pointer) 00130 // //(getUser?&user:0), //acquire username of this user (optionally null pointer) 00131 // &username, 00132 // 0, //acquire user's Display Name 00133 // &activeSessionIndex //acquire user's session index associated with the cookieCode 00134 // )) 00135 // { //failure 00136 // __COUT__ << "Failed Login Gateway: " << 00137 // out->str() << std::endl; //print out return string on failure 00138 // return; 00139 // } 00140 // } 00141 // //**** end LOGIN GATEWAY CODE ***// 00142 // 00143 // 00144 try 00145 { 00146 __SUP_COUT__ << "User name is " << userInfo.username_ << "." << __E__; 00147 __SUP_COUT__ << "User permission level for request '" << requestType << "' is " << 00148 unsigned(userInfo.permissionLevel_) << "." << __E__; 00149 00150 00151 //handle request per requestType 00152 handleRequest(requestType,xmlOut,cgiIn,userInfo.username_); 00153 } 00154 catch(const std::runtime_error& e) 00155 { 00156 __SS__ << "Error occurred handling request '" << requestType << 00157 "': " << e.what() << __E__; 00158 __SUP_COUT__ << ss.str(); 00159 xmlOut.addTextElementToData("Error",ss.str()); 00160 } 00161 catch(...) 00162 { 00163 __SS__ << "Unknown error occurred handling request '" << requestType << 00164 "!'" << __E__; 00165 __SUP_COUT__ << ss.str(); 00166 xmlOut.addTextElementToData("Error",ss.str()); 00167 } 00168 00169 } //end request() 00170 //======================================================================================================================== 00171 void ControlsDashboardSupervisor::handleRequest(const std::string Command, 00172 HttpXmlDocument& xmlOut, cgicc::Cgicc& cgiIn, 00173 const std::string &username) 00174 { 00175 //return xml doc holding server response 00176 __COUT__ << std::endl; 00177 00178 if(Command == "poll") 00179 { 00180 std::string uid = CgiDataUtilities::getOrPostData(cgiIn, "uid"); 00181 Poll(cgiIn, xmlOut, uid); 00182 } 00183 else if(Command == "generateUID") 00184 { 00185 std::string pvList = CgiDataUtilities::getOrPostData(cgiIn, "PVList"); 00186 GenerateUID(cgiIn, xmlOut, pvList); 00187 } 00188 else if(Command == "GetPVSettings") 00189 { 00190 std::string pvList = CgiDataUtilities::getOrPostData(cgiIn, "PVList"); 00191 GetPVSettings(cgiIn, xmlOut, pvList); 00192 xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn, "id")); 00193 } 00194 else if(Command == "getList") 00195 { 00196 GetList(cgiIn, xmlOut); 00197 } 00198 else if(Command == "getPages") 00199 { 00200 __COUT__ << "Requesting pages from server! " << std::endl; 00201 GetPages(cgiIn, xmlOut); 00202 } 00203 else if(Command == "loadPage") 00204 { 00205 std::string page = CgiDataUtilities::getData(cgiIn, "Page"); 00206 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << page 00207 << std::endl; 00208 00209 loadPage(cgiIn, xmlOut, page); 00210 } 00211 __COUT__ << std::endl; 00212 00213 // xmlOut.outputXmlDocument((std::ostringstream*) out, true); 00214 } //end handleRequest 00215 00216 00217 //======================================================================================================================== 00218 void ControlsDashboardSupervisor::Poll(cgicc::Cgicc& cgiIn, 00219 HttpXmlDocument& xmlOut, 00220 std::string UID) 00221 { 00222 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " " 00223 << "Polling on UID:" << UID << std::endl; 00224 00225 std::map<int, std::set<std::string>>::iterator mapReference; 00226 00227 if(UID != "" && 00228 (mapReference = pvDependencyLookupMap_.find(std::stoi(UID))) != 00229 pvDependencyLookupMap_.end()) // We have their current list of PV Dependencies 00230 { 00231 std::string JSONMessage = "{ "; 00232 00233 for(auto pv : mapReference->second) 00234 { 00235 __COUT__ << pv << std::endl; 00236 // PVInfo * pvInfo = interface_->mapOfPVInfo_.find(pv)->second; 00237 //__COUT__ << pv << ":" << (pvInfo?"Good":"Bad") << std::endl; 00238 // interface_->getCurrentPVValue(pv); 00239 std::array<std::string, 4> pvInformation = interface_->getCurrentValue(pv); 00240 00241 __COUT__ << pv << ": " << pvInformation[1] << " : " << pvInformation[3] 00242 << std::endl; 00243 00244 if(pvInformation[0] != "NO_CHANGE") 00245 { 00246 //__COUT__ << "Reached" << std::endl; 00247 JSONMessage += "\"" + pv + "\": {"; 00248 00249 /*if(pvInfo->mostRecentBufferIndex - 1 < 0) 00250 { 00251 std::string value = pvInfo->dataCache[pvInfo->dataCache.size()].second 00252 std::string time = 00253 }*/ 00254 00255 JSONMessage += "\"Timestamp\" : \"" + pvInformation[0] + "\","; 00256 JSONMessage += "\"Value\" : \"" + pvInformation[1] + "\","; 00257 JSONMessage += "\"Status\" : \"" + pvInformation[2] + "\","; 00258 JSONMessage += "\"Severity\" : \"" + pvInformation[3] + "\"},"; 00259 } 00260 else 00261 { 00262 __COUT__ << "No change in value since last poll: " << pv << std::endl; 00263 } 00264 00265 // Handle Channels that disconnect, etc 00266 if(pvInformation[3] == "INVALID") 00267 { 00268 interface_->subscribe(pv); 00269 } 00270 00271 //__COUT__ << pv << ":" << (pvInfo?"Good":"Bad") << std::endl; 00272 //__COUT__ << pv << ":" << pvInfo->mostRecentBufferIndex -1 << std::endl; 00273 //__COUT__ << pv << " : " << pvInfo->dataCache[(pvInfo->mostRecentBufferIndex 00274 //-1)].second << std::endl; 00275 } 00276 00277 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1); 00278 JSONMessage += "}"; 00279 __COUT__ << JSONMessage << std::endl; 00280 xmlOut.addTextElementToData("JSON", JSONMessage); // add to response 00281 00282 /*for (std::set<unsigned long>::iterator it = mapReference->second->begin(); it != 00283 mapReference->second.end(); ++it) 00284 { 00285 //__COUT__ << this->getApplicationDescriptor()->getLocalId() << it << 00286 std::endl; 00287 00288 00289 }*/ 00290 /*std::string fakeData = std::string("{") 00291 + "\"Mu2e_CompStatus_daq01/system_temperature\": 00292 \"40.5\"," 00293 + "\"Mu2e_CompStatus_daq01/load_one\": \"378.2\"," 00294 + "\"Mu2e_Weather_2/timestamp\": \"11.14.45.2016.4.8\"," 00295 + "\"Mu2e_CompStatus_daq01/system_temperature\": 00296 \"43.4\"," 00297 + "\"Mu2e_CompStatus_daq01/load_one\":\"80\"," 00298 + "\"Mu2e_Weather_2/timestamp\": \"11.14.45.2016.4.8\"" 00299 + "}"; 00300 xmlOut.addTextElementToData("JSON", fakeData); //add to response*/ 00301 } 00302 else // UID is not in our map so force them to generate a new one 00303 { 00304 xmlOut.addTextElementToData("JSON", 00305 "{ \"message\": \"NOT_FOUND\"}"); // add to response 00306 } 00307 } 00308 //======================================================================================================================== 00309 void ControlsDashboardSupervisor::GetPVSettings(cgicc::Cgicc& cgiIn, 00310 HttpXmlDocument& xmlOut, 00311 std::string pvList) 00312 { 00313 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " " 00314 << "Getting settings for " << pvList << std::endl; 00315 00316 std::string JSONMessage = "{ "; 00317 00318 std::string pv; 00319 size_t pos = 0; 00320 size_t nextPos; 00321 size_t lastIndex = pvList.find_last_of(","); 00322 std::cout << "**********************" << pvList.size() << std::endl; 00323 if(pvList.size() > 0) 00324 { 00325 while((nextPos = pvList.find(",", pos)) != std::string::npos) 00326 { 00327 pv = pvList.substr(pos, nextPos - pos); 00328 00329 __COUT__ << pv << std::endl; 00330 00331 std::array<std::string, 9> pvSettings = interface_->getSettings(pv); 00332 00333 JSONMessage += "\"" + pv + "\": {"; 00334 JSONMessage += "\"Units \": \"" + pvSettings[0] + "\","; 00335 JSONMessage += "\"Upper_Display_Limit\": \"" + pvSettings[1] + "\","; 00336 JSONMessage += "\"Lower_Display_Limit\": \"" + pvSettings[2] + "\","; 00337 JSONMessage += "\"Upper_Alarm_Limit \": \"" + pvSettings[3] + "\","; 00338 JSONMessage += "\"Upper_Warning_Limit\": \"" + pvSettings[4] + "\","; 00339 JSONMessage += "\"Lower_Warning_Limit\": \"" + pvSettings[5] + "\","; 00340 JSONMessage += "\"Lower_Alarm_Limit \": \"" + pvSettings[6] + "\","; 00341 JSONMessage += "\"Upper_Control_Limit\": \"" + pvSettings[7] + "\","; 00342 JSONMessage += "\"Lower_Control_Limit\": \"" + pvSettings[8] + "\"},"; 00343 00344 pos = nextPos + 1; 00345 } 00346 00347 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1); 00348 JSONMessage += "}"; 00349 00350 __COUT__ << JSONMessage << std::endl; 00351 xmlOut.addTextElementToData("JSON", JSONMessage); // add to response 00352 } 00353 else 00354 { 00355 xmlOut.addTextElementToData( 00356 "JSON", "{ \"message\": \"GetPVSettings\"}"); // add to response 00357 } 00358 } 00359 //======================================================================================================================== 00360 void ControlsDashboardSupervisor::GenerateUID(cgicc::Cgicc& cgiIn, 00361 HttpXmlDocument& xmlOut, 00362 std::string pvlist) 00363 { 00364 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " " 00365 << "Generating UID" << std::endl; 00366 00367 std::set<std::string> pvDependencies; 00368 std::string uid; 00369 std::string pv; 00370 size_t pos = 0; 00371 size_t nextPos; 00372 size_t lastIndex = pvlist.find_last_of(","); 00373 00374 if(pvlist.size() > 0) 00375 { 00376 // pvlist.substr(2); 00377 __COUT__ << pvlist << std::endl; 00378 00379 while((nextPos = pvlist.find(",", pos)) != std::string::npos) 00380 { 00381 pv = pvlist.substr(pos, nextPos - pos); 00382 //__COUT__ << UID_ << ":" << pos << "-" << nextPos << " ->" << pv << 00383 // std::endl; 00384 pvDependencies.insert(pv); 00385 pos = nextPos + 1; 00386 } 00387 00388 pvDependencyLookupMap_.insert( 00389 std::pair<int, std::set<std::string>>(++UID_, pvDependencies)); 00390 00391 uid = (std::string("{ \"message\": \"") + std::to_string(UID_) + "\"}"); 00392 } 00393 else 00394 { 00395 __COUT__ << this->getApplicationDescriptor()->getLocalId() 00396 << " PVList invalid: " << pvlist << std::endl; 00397 uid = "{ \"message\": \"-1\"}"; 00398 } 00399 00400 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " NEW UID: " << UID_ 00401 << std::endl; 00402 00403 xmlOut.addTextElementToData("JSON", uid); // add to response 00404 } 00405 //======================================================================================================================== 00406 void ControlsDashboardSupervisor::GetList(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut) 00407 { 00408 00409 if(interface_ != NULL) 00410 { 00411 00412 __COUT__ << "Interface is defined! Attempting to get list!" << std::endl; 00413 __COUT__ << this->getApplicationDescriptor()->getLocalId() << std::endl; 00414 std::cout << " " << interface_->getList("JSON") << std::endl; 00415 00416 xmlOut.addTextElementToData("JSON", interface_->getList("JSON")); //add to response 00417 } 00418 else 00419 { 00420 __COUT__ << "Interface undefined! Failed to get list!" << std::endl; 00421 xmlOut.addTextElementToData("JSON","[\"None\"]"); 00422 } 00423 } 00424 //======================================================================================================================== 00425 void ControlsDashboardSupervisor::GetPages(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut) 00426 { 00427 /*DIR * dir; 00428 struct dirent * ent; 00429 std::string pathToPages = PAGES_DIRECTORY; 00430 00431 std::vector<std::string> pages; 00432 00433 __COUT__ << this->getApplicationDescriptor()->getLocalId() << "Path to pages: " << 00434 pathToPages << std::endl; if((dir = opendir (pathToPages.c_str())) != NULL) 00435 { 00436 while((ent = readdir(dir)) != NULL) 00437 { 00438 pages.push_back(ent->d_name); 00439 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " GetPages" 00440 << ent->d_name << std::endl; 00441 } 00442 closedir(dir); 00443 } 00444 else 00445 { 00446 __COUT__ << this->getApplicationDescriptor()->getLocalId() << "Could not open 00447 directory: " << pathToPages << std::endl; return; 00448 }*/ 00449 std::vector<std::string> pages; 00450 00451 listFiles("", true, &pages); 00452 00453 std::string returnJSON = "["; 00454 for(auto it = pages.begin(); it != pages.end(); it++) 00455 { 00456 if(*it != "." && *it != "..") 00457 returnJSON += "\"" + *it + "\", "; 00458 } 00459 if(returnJSON.size() > 2 && returnJSON.compare("[") != 0) 00460 { 00461 __COUT__ << "Found pages on server!" << std::endl; 00462 returnJSON.resize(returnJSON.size() - 2); 00463 returnJSON += "]"; 00464 } 00465 else 00466 { 00467 // No pages on the server 00468 __COUT__ << "No pages found on server!" << std::endl; 00469 returnJSON = "[\"None\"]"; 00470 } 00471 std::cout << returnJSON << std::endl; 00472 00473 xmlOut.addTextElementToData("JSON", returnJSON); // add to response 00474 } 00475 //======================================================================================================================== 00476 void ControlsDashboardSupervisor::loadPage(cgicc::Cgicc& cgiIn, 00477 HttpXmlDocument& xmlOut, 00478 std::string page) 00479 { 00480 // FIXME Filter out malicious attacks i.e. ../../../../../ stuff 00481 struct stat buffer; 00482 if(page.find("..") != std::string::npos) 00483 { 00484 __COUT__ << this->getApplicationDescriptor()->getLocalId() 00485 << "Error! Request using '..': " << page << std::endl; 00486 } 00487 else if(page.find("~") != std::string::npos) 00488 { 00489 __COUT__ << this->getApplicationDescriptor()->getLocalId() 00490 << "Error! Request using '~': " << page << std::endl; 00491 } 00492 else if(!(stat(page.c_str(), &buffer) == 0)) 00493 { 00494 __COUT__ << this->getApplicationDescriptor()->getLocalId() 00495 << "Error! File not found: " << page << std::endl; 00496 } 00497 00498 std::string file = PAGES_DIRECTORY file += "/" + page; 00499 __COUT__ << this->getApplicationDescriptor()->getLocalId() 00500 << "Trying to load page: " << page << std::endl; 00501 __COUT__ << this->getApplicationDescriptor()->getLocalId() 00502 << "Trying to load page: " << file << std::endl; 00503 // read file 00504 // for each line in file 00505 00506 std::ifstream infile(file); 00507 std::cout << "Reading file" << std::endl; 00508 std::string JSONpage = ""; 00509 for(std::string line; getline(infile, line);) 00510 { 00511 std::cout << line << std::endl; 00512 JSONpage += line; 00513 } 00514 std::cout << "Finished reading file" << std::endl; 00515 00516 xmlOut.addTextElementToData("JSON", JSONpage); // add to response 00517 } 00518 //======================================================================================================================== 00519 void ControlsDashboardSupervisor::Subscribe(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut) 00520 { 00521 } 00522 //======================================================================================================================== 00523 void ControlsDashboardSupervisor::Unsubscribe(cgicc::Cgicc& cgiIn, 00524 HttpXmlDocument& xmlOut) 00525 { 00526 } 00527 //======================================================================================================================== 00528 //======================================================================================================================== 00529 //================================================== UTILITIES 00530 //=========================================================== 00531 //======================================================================================================================== 00532 bool ControlsDashboardSupervisor::isDir(std::string dir) 00533 { 00534 struct stat fileInfo; 00535 stat(dir.c_str(), &fileInfo); 00536 if(S_ISDIR(fileInfo.st_mode)) 00537 { 00538 return true; 00539 } 00540 else 00541 { 00542 return false; 00543 } 00544 } 00545 //======================================================================================================================== 00546 void ControlsDashboardSupervisor::listFiles(std::string baseDir, 00547 bool recursive, 00548 std::vector<std::string>* pages) 00549 { 00550 std::string base = PAGES_DIRECTORY; 00551 base += baseDir; 00552 00553 DIR* dp; 00554 struct dirent* dirp; 00555 if((dp = opendir(base.c_str())) == NULL) 00556 { 00557 std::cout << "[ERROR: " << errno << " ] Couldn't open " << base << "." 00558 << std::endl; 00559 return; 00560 } 00561 else 00562 { 00563 while((dirp = readdir(dp)) != NULL) 00564 { 00565 if(dirp->d_name != std::string(".") && dirp->d_name != std::string("..")) 00566 { 00567 if(isDir(base + dirp->d_name) == true && recursive == true) 00568 { 00569 // pages->push_back(baseDir + dirp->d_name); 00570 std::cout << "[DIR]\t" << baseDir << dirp->d_name << "/" << std::endl; 00571 listFiles(baseDir + dirp->d_name + "/", true, pages); 00572 } 00573 else 00574 { 00575 pages->push_back(baseDir + dirp->d_name); 00576 std::cout << "[FILE]\t" << baseDir << dirp->d_name << std::endl; 00577 } 00578 } 00579 } 00580 closedir(dp); 00581 } 00582 }