00001 #include "otsdaq-utilities/ControlsDashboard/ControlsDashboardSupervisor.h"
00002
00003 #include <sys/stat.h>
00004 #include <dirent.h>
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "otsdaq-core/ControlsCore/ControlsVInterface.h"
00029 #include "otsdaq-core/PluginMakers/MakeControls.h"
00030
00031
00032
00033 using namespace ots;
00034
00035
00036 #define PAGES_DIRECTORY std::string(getenv("SERVICE_DATA_PATH")) + "/ControlsDashboardData/pages/";
00037
00038
00039 XDAQ_INSTANTIATOR_IMPL(ControlsDashboardSupervisor)
00040
00041
00042 ControlsDashboardSupervisor::ControlsDashboardSupervisor(xdaq::ApplicationStub* stub)
00043 : CoreSupervisorBase(stub)
00044 {
00045 INIT_MF("ControlsDashboardSupervisor");
00046
00047 init();
00048
00049 }
00050
00051
00052 ControlsDashboardSupervisor::~ControlsDashboardSupervisor(void)
00053 {
00054 destroy();
00055 }
00056
00057
00058
00059
00060 void ControlsDashboardSupervisor::setSupervisorPropertyDefaults()
00061 {
00062 CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.CheckUserLockRequestTypes,
00063 "*");
00064 }
00065
00066
00067
00068
00069 void ControlsDashboardSupervisor::forceSupervisorPropertyValues()
00070 {
00071 CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
00072 "poll");
00073 }
00074
00075
00076 void ControlsDashboardSupervisor::request(const std::string& requestType, cgicc::Cgicc& cgiIn,
00077 HttpXmlDocument& xmlOut, const WebUsers::RequestUserInfo& userInfo)
00078 {
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 __COUT__ << std::endl;
00134
00135 if(requestType == "poll")
00136 {
00137 std::string uid = CgiDataUtilities::getOrPostData(cgiIn,"uid");
00138 Poll(cgiIn, xmlOut, uid);
00139 }
00140 else if(requestType == "generateUID")
00141 {
00142 std::string pvList = CgiDataUtilities::getOrPostData(cgiIn,"PVList");
00143 GenerateUID(cgiIn, xmlOut, pvList);
00144 }
00145 else if(requestType == "GetPVSettings")
00146 {
00147 std::string pvList = CgiDataUtilities::getOrPostData(cgiIn,"PVList");
00148 GetPVSettings(cgiIn, xmlOut, pvList);
00149 xmlOut.addTextElementToData("id", CgiDataUtilities::getData(cgiIn,"id"));
00150 }
00151 else if(requestType == "getList")
00152 {
00153 GetList(cgiIn, xmlOut);
00154 }
00155 else if(requestType == "getPages")
00156 {
00157 GetPages(cgiIn, xmlOut);
00158 }
00159 else if(requestType == "loadPage")
00160 {
00161 std::string page = CgiDataUtilities::getData(cgiIn,"Page");
00162 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << page << std::endl;
00163
00164 loadPage(cgiIn, xmlOut, page);
00165 }
00166 __COUT__ << std::endl;
00167
00168
00169
00170
00171
00172 }
00173
00174 void ControlsDashboardSupervisor::init(void)
00175
00176 {
00177 UID_= 0;
00178
00179 __COUT__ << std::endl;
00180 std::string t = "test";
00181 std::string nodeName = theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getConfigurationName();
00182 __COUT__ << nodeName << std::endl;
00183 ConfigurationTree node = theConfigurationManager_->getNode(nodeName);
00184 __COUT__ << node << std::endl;
00185
00186 interface_ = makeControls(
00187 "ControlsOtsInterface"
00188 , t
00189 , node
00190 , nodeName);
00191 __COUT__ << std::endl;
00192
00193
00194
00195 }
00196
00197 void ControlsDashboardSupervisor::destroy(void)
00198 {
00199
00200 delete interface_;
00201 }
00202
00203
00204 void ControlsDashboardSupervisor::Poll(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut, std::string UID )
00205 {
00206
00207 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << "Polling on UID:" << UID << std::endl;
00208
00209 std::map<int, std::set<std::string>>::iterator mapReference;
00210
00211 if( UID != "" && (mapReference = pvDependencyLookupMap_.find(std::stoi(UID))) != pvDependencyLookupMap_.end())
00212 {
00213 std::string JSONMessage = "{ ";
00214
00215 for(auto pv : mapReference->second)
00216 {
00217 __COUT__ << pv << std::endl;
00218
00219
00220
00221 std::array<std::string, 4> pvInformation = interface_->getCurrentValue(pv);
00222
00223 __COUT__ << pv << ": " << pvInformation[1] << " : " << pvInformation[3] << std::endl;
00224
00225
00226 if(pvInformation[0] != "NO_CHANGE")
00227 {
00228
00229 JSONMessage += "\"" + pv + "\": {";
00230
00231
00232
00233
00234
00235
00236
00237 JSONMessage += "\"Timestamp\" : \"" + pvInformation[0] + "\",";
00238 JSONMessage += "\"Value\" : \"" + pvInformation[1] + "\",";
00239 JSONMessage += "\"Status\" : \"" + pvInformation[2] + "\",";
00240 JSONMessage += "\"Severity\" : \"" + pvInformation[3] + "\"},";
00241
00242 }
00243 else
00244 {
00245 __COUT__ << "No change in value since last poll: " << pv << std::endl;
00246 }
00247
00248
00249 if(pvInformation[3] == "INVALID")
00250 {
00251 interface_->subscribe(pv);
00252 }
00253
00254
00255
00256
00257
00258
00259 }
00260
00261 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
00262 JSONMessage += "}";
00263 __COUT__ << JSONMessage << std::endl;
00264 xmlOut.addTextElementToData("JSON", JSONMessage);
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 }
00287 else
00288 {
00289 xmlOut.addTextElementToData("JSON", "{ \"message\": \"NOT_FOUND\"}");
00290 }
00291 }
00292
00293 void ControlsDashboardSupervisor::GetPVSettings(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut, std::string pvList )
00294 {
00295 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << "Getting settings for " << pvList << std::endl;
00296
00297 std::string JSONMessage = "{ ";
00298
00299 std::string pv;
00300 size_t pos = 0;
00301 size_t nextPos;
00302 size_t lastIndex = pvList.find_last_of(",");
00303 std::cout << "**********************" << pvList.size() << std::endl;
00304 if(pvList.size() > 0)
00305 {
00306
00307 while((nextPos = pvList.find(",", pos)) != std::string::npos)
00308 {
00309 pv = pvList.substr(pos, nextPos-pos);
00310
00311
00312 __COUT__ << pv << std::endl;
00313
00314 std::array<std::string, 9> pvSettings = interface_->getSettings(pv);
00315
00316
00317 JSONMessage += "\"" + pv + "\": {";
00318 JSONMessage += "\"Units \": \"" + pvSettings[0] + "\",";
00319 JSONMessage += "\"Upper_Display_Limit\": \"" + pvSettings[1] + "\",";
00320 JSONMessage += "\"Lower_Display_Limit\": \"" + pvSettings[2] + "\",";
00321 JSONMessage += "\"Upper_Alarm_Limit \": \"" + pvSettings[3] + "\",";
00322 JSONMessage += "\"Upper_Warning_Limit\": \"" + pvSettings[4] + "\",";
00323 JSONMessage += "\"Lower_Warning_Limit\": \"" + pvSettings[5] + "\",";
00324 JSONMessage += "\"Lower_Alarm_Limit \": \"" + pvSettings[6] + "\",";
00325 JSONMessage += "\"Upper_Control_Limit\": \"" + pvSettings[7] + "\",";
00326 JSONMessage += "\"Lower_Control_Limit\": \"" + pvSettings[8] + "\"},";
00327
00328 pos = nextPos + 1;
00329 }
00330
00331 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
00332 JSONMessage += "}";
00333
00334 __COUT__ << JSONMessage << std::endl;
00335 xmlOut.addTextElementToData("JSON", JSONMessage);
00336
00337 }
00338 else
00339 {
00340 xmlOut.addTextElementToData("JSON", "{ \"message\": \"GetPVSettings\"}");
00341 }
00342
00343
00344
00345
00346 }
00347
00348 void ControlsDashboardSupervisor::GenerateUID(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut, std::string pvlist )
00349 {
00350
00351 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " " << "Generating UID" << std::endl;
00352
00353 std::set<std::string> pvDependencies;
00354 std::string uid;
00355 std::string pv;
00356 size_t pos = 0;
00357 size_t nextPos;
00358 size_t lastIndex = pvlist.find_last_of(",");
00359
00360 if(pvlist.size() > 0)
00361 {
00362
00363 __COUT__ << pvlist << std::endl;
00364
00365 while((nextPos = pvlist.find(",", pos)) != std::string::npos)
00366 {
00367 pv = pvlist.substr(pos, nextPos-pos);
00368
00369 pvDependencies.insert(pv);
00370 pos = nextPos + 1;
00371 }
00372
00373 pvDependencyLookupMap_.insert(std::pair<int, std::set<std::string>> (++UID_, pvDependencies) );
00374
00375 uid = (std::string("{ \"message\": \"") + std::to_string(UID_) +"\"}");
00376 }else
00377 {
00378 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " PVList invalid: " << pvlist << std::endl;
00379 uid = "{ \"message\": \"-1\"}";
00380 }
00381
00382
00383 __COUT__ << this->getApplicationDescriptor()->getLocalId() << " NEW UID: " << UID_ << std::endl;
00384
00385 xmlOut.addTextElementToData("JSON", uid);
00386
00387
00388 }
00389
00390 void ControlsDashboardSupervisor::GetList(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
00391 {
00392
00393 __COUT__ << this->getApplicationDescriptor()->getLocalId() << std::endl;
00394 std::cout << " " << interface_->getList("JSON") << std::endl;
00395
00396 xmlOut.addTextElementToData("JSON", interface_->getList("JSON"));
00397
00398 }
00399
00400 void ControlsDashboardSupervisor::GetPages(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
00401 {
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 std::vector<std::string> pages;
00424
00425 listFiles("", true, &pages);
00426
00427 std::string returnJSON = "[";
00428 for(auto it = pages.begin(); it != pages.end(); it++)
00429 {
00430 if(*it != "." && *it != "..")
00431 returnJSON += "\"" + *it + "\", ";
00432 }
00433 if(returnJSON.size() > 2 && returnJSON.compare("[") != 0)
00434 {
00435 __COUT__ << "Found pages on server!" << std::endl;
00436 returnJSON.resize(returnJSON.size()-2);
00437 returnJSON += "]";
00438 }
00439 else
00440 {
00441
00442 __COUT__ << "No pages found on server!" << std::endl;
00443 returnJSON = "[\"None\"]";
00444 }
00445 std::cout << returnJSON << std::endl;
00446
00447 xmlOut.addTextElementToData("JSON", returnJSON);
00448
00449 }
00450
00451 void ControlsDashboardSupervisor::loadPage(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut, std::string page )
00452 {
00453
00454 struct stat buffer;
00455 if(page.find("..") != std::string::npos)
00456 {
00457 __COUT__ << this->getApplicationDescriptor()->getLocalId() << "Error! Request using '..': " << page << std::endl;
00458 }
00459 else if (page.find("~") != std::string::npos)
00460 {
00461 __COUT__ << this->getApplicationDescriptor()->getLocalId() << "Error! Request using '~': " << page << std::endl;
00462 }
00463 else if(!(stat(page.c_str(), &buffer) == 0))
00464 {
00465 __COUT__ << this->getApplicationDescriptor()->getLocalId() << "Error! File not found: " << page << std::endl;
00466 }
00467
00468 std::string file = PAGES_DIRECTORY
00469 file += "/" + page;
00470 __COUT__ << this->getApplicationDescriptor()->getLocalId() << "Trying to load page: " << page << std::endl;
00471 __COUT__ << this->getApplicationDescriptor()->getLocalId() << "Trying to load page: " << file << std::endl;
00472
00473
00474
00475 std::ifstream infile(file);
00476 std::cout << "Reading file" << std::endl;
00477 std::string JSONpage = "";
00478 for(std::string line; getline(infile, line);)
00479 {
00480 std::cout << line << std::endl;
00481 JSONpage += line;
00482 }
00483 std::cout << "Finished reading file" << std::endl;
00484
00485 xmlOut.addTextElementToData("JSON", JSONpage);
00486
00487 }
00488
00489 void ControlsDashboardSupervisor::Subscribe(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
00490 {
00491
00492
00493 }
00494
00495 void ControlsDashboardSupervisor::Unsubscribe(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
00496 {
00497
00498
00499 }
00500
00501
00502
00503
00504 bool ControlsDashboardSupervisor::isDir(std::string dir)
00505 {
00506 struct stat fileInfo;
00507 stat(dir.c_str(), &fileInfo);
00508 if (S_ISDIR(fileInfo.st_mode))
00509 {
00510 return true;
00511 }
00512 else
00513 {
00514 return false;
00515 }
00516 }
00517
00518 void ControlsDashboardSupervisor::listFiles(std::string baseDir, bool recursive, std::vector<std::string> * pages )
00519 {
00520 std::string base = PAGES_DIRECTORY;
00521 base += baseDir;
00522
00523 DIR *dp;
00524 struct dirent *dirp;
00525 if ((dp = opendir(base.c_str())) == NULL) {
00526 std::cout << "[ERROR: " << errno << " ] Couldn't open " << base << "." << std::endl;
00527 return;
00528 }
00529 else
00530 {
00531 while ((dirp = readdir(dp)) != NULL) {
00532 if (dirp->d_name != std::string(".") && dirp->d_name != std::string(".."))
00533 {
00534 if (isDir(base + dirp->d_name) == true && recursive == true)
00535 {
00536
00537 std::cout << "[DIR]\t" << baseDir << dirp->d_name << "/" << std::endl;
00538 listFiles(baseDir + dirp->d_name + "/", true, pages);
00539 }
00540 else
00541 {
00542 pages->push_back(baseDir + dirp->d_name);
00543 std::cout << "[FILE]\t" << baseDir << dirp->d_name << std::endl;
00544 }
00545 }
00546 }
00547 closedir(dp);
00548 }
00549 }
00550
00551
00552