1 #include "otsdaq-utilities/SlowControlsDashboard/SlowControlsDashboardSupervisor.h"
6 #include "otsdaq/SlowControlsCore/MakeSlowControls.h"
7 #include "otsdaq/SlowControlsCore/SlowControlsVInterface.h"
9 #include <boost/regex.hpp>
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/"
22 SlowControlsDashboardSupervisor::SlowControlsDashboardSupervisor(
23 xdaq::ApplicationStub* stub)
24 : CoreSupervisorBase(stub), alarms_(), alarms_timestamp_()
26 __SUP_COUT__ <<
"Constructor." << __E__;
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);
37 alarmNotifyRefreshRate_ = 60;
39 readOnly_ = getSupervisorProperty(
"ReadOnly",
"1") ==
"1" ? true :
false;
40 __SUP_COUTV__(readOnly_);
44 __SUP_COUT__ <<
"Constructed." << __E__;
48 SlowControlsDashboardSupervisor::~SlowControlsDashboardSupervisor(
void)
50 __SUP_COUT__ <<
"Destructor." << __E__;
52 __SUP_COUT__ <<
"Destructed." << __E__;
56 void SlowControlsDashboardSupervisor::destroy(
void)
68 __SUP_COUT__ << __E__;
69 ConfigurationTree node = CorePropertySupervisorBase::getSupervisorTableNode();
70 std::string pluginType;
75 node.getNode(
"SlowControlsInterfacePluginType").getValue<std::string>();
80 __SUP_COUT__ <<
"Pluging type was not definded through supervisor table, trying "
81 "supervisor property..."
83 pluginType = CorePropertySupervisorBase::getSupervisorProperty(
84 "ControlsInterfacePluginType");
89 alarmNotifyRefreshRate_ = node.getNode(
"AlarmCheckRefreshPeriod").getValue<
int>();
90 __SUP_COUTV__(alarmNotifyRefreshRate_);
94 __COUT_WARN__ <<
"Couldn't find `AlarmCheckRefreshPeriod`. Default "
95 "alarmNotifyRefreshRate = "
96 << alarmNotifyRefreshRate_ <<
" seconds." << __E__;
99 __COUTV__(pluginType);
103 interface_ = makeSlowControls(
105 CorePropertySupervisorBase::getSupervisorUID(),
106 CorePropertySupervisorBase::getContextTreeNode(),
107 CorePropertySupervisorBase::getSupervisorConfigurationPath());
113 if(interface_ ==
nullptr)
115 __SS__ <<
"Slow Control interface plugin construction failed of type "
116 << pluginType << __E__;
120 interface_->setNewAlarmCallback(
121 std::bind(&SlowControlsDashboardSupervisor::handleNewAlarms,
this));
129 std::lock_guard<std::mutex> lock(cs->pluginBusyMutex_);
131 cs->interface_->initialize();
150 __SUP_COUT__ <<
"Finished init() w/ interface: " << pluginType << __E__;
153 CoreSupervisorBase::theStateMachineImplementation_.push_back(interface_);
157 void SlowControlsDashboardSupervisor::handleNewAlarms()
159 __COUT__ <<
"DEBUG handleNewAlarms" << __E__;
168 std::lock_guard<std::mutex> lock(cs->alarmCheckThreadErrorMutex_);
169 cs->alarmCheckThreadError_ =
"";
176 ->checkAlarmNotifications();
177 alarms_timestamp_ = std::chrono::system_clock::now();
179 __COUT__ <<
"checkSlowControlsAlarms() found count = " << alarms_.size()
184 for(
const auto& alarm : alarms_)
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];
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__;
204 theRemoteWebUsers_.sendSystemMessage(
205 alarm[6], subject, message, alarm[7] ==
"Yes" ?
true :
false);
209 catch(
const std::runtime_error& e)
211 __SS__ << e.what() <<
'\n';
212 std::lock_guard<std::mutex> lock(cs->alarmCheckThreadErrorMutex_);
213 cs->alarmCheckThreadError_ = ss.str();
214 __COUT_ERR__ << ss.str();
216 catch(
const std::exception& e)
218 __SS__ << e.what() <<
'\n';
219 std::lock_guard<std::mutex> lock(cs->alarmCheckThreadErrorMutex_);
220 cs->alarmCheckThreadError_ = ss.str();
221 __COUT_ERR__ << ss.str();
225 __SS__ <<
"checkSlowControlsAlarms() ERROR While sendin alarm messages"
231 catch(
const std::exception& e)
233 ss <<
"Exception message: " << e.what();
238 std::lock_guard<std::mutex> lock(cs->alarmCheckThreadErrorMutex_);
239 cs->alarmCheckThreadError_ = ss.str();
240 __COUT_ERR__ << ss.str();
243 sleep(alarmNotifyRefreshRate_);
252 __COUT__ <<
"checkSubscriptions() initializing..." << __E__;
253 std::vector<std::string> channelList;
254 std::vector<int> channelRefreshRates;
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_
265 for(
auto channel : mapReference->second)
267 int refreshRate = 15;
268 channelRefreshRates.push_back(refreshRate);
270 __COUT__ <<
"THREAD actual time: " << std::time(NULL)
271 <<
"; uidPollTimeMap + 10 * refreshTime: "
272 << cs->uidPollTimeMap_.at(mapReference->first) + 10 * refreshRate
273 <<
" seconds" << __E__;
275 cs->uidPollTimeMap_.at(mapReference->first) + 10 * refreshRate)
279 cs->channelDependencyLookupMap_.erase(mapReference->first);
282 catch(
const std::exception& e)
288 std::vector<std::string>::iterator it =
289 find(channelList.begin(), channelList.end(), channel);
290 if(it == channelList.end())
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__;
309 if(channelRefreshRates.size() > 0)
311 *min_element(channelRefreshRates.begin(), channelRefreshRates.end());
313 __COUT__ <<
"Loop over channels subscribing - waiting time: " << minTime
314 <<
" seconds" << __E__;
324 CorePropertySupervisorBase::setSupervisorProperty(
325 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.CheckUserLockRequestTypes,
"*");
334 CorePropertySupervisorBase::setSupervisorProperty(
335 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
"poll");
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 ");
347 void SlowControlsDashboardSupervisor::request(
const std::string& requestType,
349 HttpXmlDocument& xmlOut,
350 const WebUsers::RequestUserInfo& userInfo)
354 if(requestType !=
"getPages" && !pluginBusyMutex_.try_lock())
356 __SUP_SS__ <<
"Controls plugin is still initializing. Please try again in a "
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") <<
")."
369 handleRequest(requestType, xmlOut, cgiIn, userInfo);
371 catch(
const std::runtime_error& e)
373 __SUP_SS__ <<
"Error occurred handling request '" << requestType
374 <<
"': " << e.what() << __E__;
375 __SUP_COUT__ << ss.str();
376 xmlOut.addTextElementToData(
"Error", ss.str());
380 __SS__ <<
"Unknown error occurred handling request '" << requestType <<
"!'"
386 catch(
const std::exception& e)
388 ss <<
"Exception message: " << e.what();
393 __SUP_COUT__ << ss.str();
394 xmlOut.addTextElementToData(
"Error", ss.str());
397 pluginBusyMutex_.unlock();
398 __SUP_COUT__ << __E__;
402 void SlowControlsDashboardSupervisor::handleRequest(
403 const std::string Command,
404 HttpXmlDocument& xmlOut,
406 const WebUsers::RequestUserInfo& userInfo)
409 __SUP_COUT__ << __E__;
411 if(Command ==
"poll")
413 std::string uid = CgiDataUtilities::getOrPostData(cgiIn,
"uid");
414 Poll(cgiIn, xmlOut, uid);
416 else if(Command ==
"getPvData")
420 else if(Command ==
"userActivityHeartbeat")
426 else if(Command ==
"generateUID")
428 std::string channelList = CgiDataUtilities::getOrPostData(cgiIn,
"pvList");
429 GenerateUID(cgiIn, xmlOut, channelList);
431 else if(Command ==
"isUserAdmin")
433 std::string json = std::string(
"{ \"message\": \"");
434 json += (userInfo.isAdmin() ?
"Yes" :
"No");
436 xmlOut.addTextElementToData(
"JSON", json.c_str());
438 else if(Command ==
"getUserPermissions")
440 GetUserPermissions(cgiIn, xmlOut, userInfo);
442 else if(Command ==
"getPVSettings")
444 __SUP_COUT__ <<
"Channel settings requested from server! " << __E__;
445 GetChannelSettings(cgiIn, xmlOut);
446 xmlOut.addTextElementToData(
"id", CgiDataUtilities::getData(cgiIn,
"id"));
448 else if(Command ==
"getPvArchiverData")
450 __SUP_COUT__ <<
"Archived Channel data requested from server! " << __E__;
451 GetChannelArchiverData(cgiIn, xmlOut);
452 xmlOut.addTextElementToData(
"id", CgiDataUtilities::getData(cgiIn,
"id"));
454 else if(Command ==
"getList")
456 __SUP_COUT__ <<
"Channel List requested from server! " << __E__;
457 GetList(cgiIn, xmlOut);
459 else if(Command ==
"getPages")
461 __SUP_COUT__ <<
"Requesting pages from server! " << __E__;
462 GetPages(cgiIn, xmlOut);
464 else if(Command ==
"loadPage")
466 std::string page = CgiDataUtilities::getData(cgiIn,
"Page");
467 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" " << page
470 loadPage(cgiIn, xmlOut, page, userInfo);
472 else if(Command ==
"loadPhoebusPage")
474 std::string page = CgiDataUtilities::getData(cgiIn,
"Page");
475 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" " << page
478 loadPhoebusPage(cgiIn, xmlOut, page, userInfo);
480 else if(Command ==
"createControlsPage")
482 SaveControlsPage(cgiIn, xmlOut, userInfo);
484 else if(Command ==
"createPhoebusControlsPage")
486 SavePhoebusControlsPage(cgiIn, xmlOut, userInfo);
488 else if(Command ==
"getLastAlarmsData")
490 __SUP_COUT__ <<
"Last Alarms Data requested from server! " << __E__;
491 GetLastAlarmsData(cgiIn, xmlOut);
492 xmlOut.addTextElementToData(
"id", CgiDataUtilities::getData(cgiIn,
"id"));
494 else if(Command ==
"getAlarmsLogData")
496 __SUP_COUT__ <<
"Alarms Log Data requested from server! " << __E__;
497 GetAlarmsLogData(cgiIn, xmlOut);
498 xmlOut.addTextElementToData(
"id", CgiDataUtilities::getData(cgiIn,
"id"));
500 else if(Command ==
"getAlarmsCheck")
502 __SUP_COUT__ <<
"Alarms Data requested from server! " << __E__;
503 GetAlarmsCheck(xmlOut);
505 else if(Command ==
"saveImageFile")
507 saveImageFile(cgiIn, xmlOut, userInfo);
510 __SUP_COUT__ <<
"" << __E__;
514 void SlowControlsDashboardSupervisor::Poll(cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut)
516 std::string channelList = CgiDataUtilities::postData(cgiIn,
"pvList");
517 std::set<std::string> channels;
518 StringMacros::getSetFromString(channelList, channels);
520 xmlOut.addTextElementToData(
"JSON", PollChannels_(channels));
524 void SlowControlsDashboardSupervisor::Poll(cgicc::Cgicc& ,
525 HttpXmlDocument& xmlOut,
528 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
529 <<
"Polling on UID:" << UID << __E__;
531 std::map<int, std::set<std::string>>::iterator mapReference;
533 if(UID !=
"" && (mapReference = channelDependencyLookupMap_.find(std::stoi(UID))) !=
534 channelDependencyLookupMap_
537 uidPollTimeMap_.at(std::stoi(UID)) = std::time(NULL);
539 xmlOut.addTextElementToData(
540 "JSON", PollChannels_(mapReference->second));
544 xmlOut.addTextElementToData(
"JSON",
545 "{ \"message\": \"NOT_FOUND\"}");
550 std::string SlowControlsDashboardSupervisor::PollChannels_(
551 std::set<std::string>& channels,
bool resubscibe )
553 std::string JSONMessage =
"{ ";
555 for(
auto channel : channels)
559 __SUP_COUT__ << channel << __E__;
561 std::array<std::string, 4> channelInformation =
562 interface_->getCurrentValue(channel);
564 __SUP_COUT__ << channel <<
": " << channelInformation[1] <<
" : "
565 << channelInformation[3] << __E__;
567 if(channelInformation[0] !=
"NO_CHANGE")
570 JSONMessage +=
"\"" + channel +
"\": {";
571 JSONMessage +=
"\"Timestamp\":\"" + channelInformation[0] +
"\",";
572 JSONMessage +=
"\"Value\":\"" + channelInformation[1] +
"\",";
573 JSONMessage +=
"\"Status\":\"" + channelInformation[2] +
"\",";
574 JSONMessage +=
"\"Severity\":\"" + channelInformation[3] +
"\"},";
578 __SUP_COUT__ <<
"No change in value since last poll: " << channel << __E__;
582 if(channelInformation[3] ==
"INVALID" && resubscibe)
584 interface_->unsubscribe(channel);
585 interface_->subscribe(channel);
589 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
591 __SUP_COUT__ << JSONMessage << __E__;
596 void SlowControlsDashboardSupervisor::GetChannelSettings(cgicc::Cgicc& cgiIn,
597 HttpXmlDocument& xmlOut)
599 std::string channelList = CgiDataUtilities::postData(cgiIn,
"pvList");
601 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
602 <<
"Getting settings for " << channelList << __E__;
604 std::string JSONMessage =
"{ ";
606 __SUP_COUT__ <<
"**********************" << channelList.size() << __E__;
607 if(channelList.size() > 0)
612 while((nextPos = channelList.find(
",", pos)) != std::string::npos)
614 channel = channelList.substr(pos, nextPos - pos);
616 __SUP_COUT__ << channel << __E__;
618 std::array<std::string, 9> channelSettings = interface_->getSettings(channel);
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] +
"\"},";
634 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
637 __SUP_COUT__ << JSONMessage << __E__;
638 xmlOut.addTextElementToData(
"JSON", JSONMessage);
642 __SUP_COUT__ <<
"Did not find any settings because Channel list is length zero!"
645 xmlOut.addTextElementToData(
646 "JSON",
"{ \"message\": \"GetPVSettings\"}");
651 void SlowControlsDashboardSupervisor::GetChannelArchiverData(cgicc::Cgicc& cgiIn,
652 HttpXmlDocument& xmlOut)
654 __SUP_COUT__ <<
"Requesting archived data!" << __E__;
656 std::string channelList = CgiDataUtilities::postData(cgiIn,
"pvList");
657 int startTime = stoi(CgiDataUtilities::postData(cgiIn,
"startTime"));
658 int endTime = stoi(CgiDataUtilities::postData(cgiIn,
"endTime"));
660 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
661 <<
"Getting History for " << channelList <<
" start time: " << startTime
662 <<
" end time: " << endTime << __E__;
664 __SUP_COUT__ <<
"channelList.size(): " << channelList.size() << __E__;
665 if(channelList.size() > 0 && startTime > 0 && endTime > 0)
670 while((nextPos = channelList.find(
",", pos)) != std::string::npos)
672 channel = channelList.substr(pos, nextPos - pos);
674 __SUP_COUT__ <<
"Getting History for " << channel << __E__;
676 std::vector<std::vector<std::string>> channelInformation =
677 interface_->getChannelHistory(channel, startTime, endTime);
679 for(
auto channelData : channelInformation)
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] +
"\"},";
688 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
690 xmlOut.addTextElementToData(
"JSON", JSONMessage);
698 __SUP_COUT__ <<
"Did not find any data because Channel list is length zero!"
701 xmlOut.addTextElementToData(
702 "JSON",
"{ \"message\": \"GetChannelArchiverData\"}");
707 void SlowControlsDashboardSupervisor::GetLastAlarmsData(cgicc::Cgicc& cgiIn,
708 HttpXmlDocument& xmlOut)
710 __SUP_COUT__ <<
"Requesting last alarms data!" << __E__;
712 std::string channelList = CgiDataUtilities::postData(cgiIn,
"pvList");
714 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
715 <<
"Getting last Alarms for " << channelList << __E__;
716 __SUP_COUT__ <<
"channelList.size(): " << channelList.size() << __E__;
718 std::vector<std::vector<std::string>> alarms;
721 std::function<void(HttpXmlDocument&, std::vector<std::vector<std::string>>&)>
722 jsonFiller = [](HttpXmlDocument& xmlOut,
723 std::vector<std::vector<std::string>>& alarms) {
725 for(
auto& alarmRow : alarms)
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] +
"\",";
736 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
738 xmlOut.addTextElementToData(
"JSON", JSONMessage);
743 if(channelList.size() > 0)
748 while((nextPos = channelList.find(
",", pos)) != std::string::npos)
750 channel = channelList.substr(pos, nextPos - pos);
752 alarms = interface_->getLastAlarms(channel);
753 __SUP_COUT__ <<
"get Last Alarms for channel: " << channel << __E__;
754 jsonFiller(xmlOut, alarms);
760 alarms = interface_->getLastAlarms(
"");
761 __SUP_COUT__ <<
"get Last Alarms for all channels" << __E__;
762 jsonFiller(xmlOut, alarms);
767 void SlowControlsDashboardSupervisor::GetAlarmsCheck(HttpXmlDocument& xmlOut)
769 __SUP_COUT__ <<
"Requesting alarms check cache data!" << __E__;
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())
777 JSONMessage +=
"\"total\":" + std::to_string(alarms_.size()) +
",";
778 JSONMessage +=
"\"alarms\": [";
779 unsigned int nactive = 0;
782 for(
auto& alarmRow : alarms_)
785 JSONMessage +=
"\"name\":\"" + alarmRow[0] +
"\",";
786 if(alarmRow.size() > 9)
789 JSONMessage +=
"\"time\":\"" + alarmRow[1] +
"\",";
790 JSONMessage +=
"\"value\":\"" + alarmRow[2] +
"\",";
791 JSONMessage +=
"\"status\":\"" + alarmRow[3] +
"\",";
792 JSONMessage +=
"\"severity\":\"" + alarmRow[4] +
"\",";
795 JSONMessage.substr(0, JSONMessage.length() - 1);
799 JSONMessage.substr(0, JSONMessage.length() - 1);
801 JSONMessage +=
"], \"nactive\": " + std::to_string(nactive);
803 xmlOut.addTextElementToData(
"JSON", JSONMessage);
807 void SlowControlsDashboardSupervisor::GetAlarmsLogData(cgicc::Cgicc& cgiIn,
808 HttpXmlDocument& xmlOut)
810 __SUP_COUT__ <<
"Requesting alarms log data!" << __E__;
812 std::string channelList = CgiDataUtilities::postData(cgiIn,
"pvList");
814 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
815 <<
"Getting Alarms Log for " << channelList << __E__;
816 __SUP_COUT__ <<
"channelList.size(): " << channelList.size() << __E__;
818 std::vector<std::vector<std::string>> alarmsLog;
821 std::function<void(HttpXmlDocument&, std::vector<std::vector<std::string>>&)>
822 jsonFiller = [](HttpXmlDocument& xmlOut,
823 std::vector<std::vector<std::string>>& alarmsLog) {
825 for(
auto& alarmRow : alarmsLog)
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] +
"\",";
835 JSONMessage = JSONMessage.substr(0, JSONMessage.length() - 1);
837 xmlOut.addTextElementToData(
"JSON", JSONMessage);
842 if(channelList.size() > 0)
847 while((nextPos = channelList.find(
",", pos)) != std::string::npos)
849 channel = channelList.substr(pos, nextPos - pos);
851 alarmsLog = interface_->getAlarmsLog(channel);
852 __SUP_COUT__ <<
"get Alarms Log for channel: " << channel << __E__;
853 jsonFiller(xmlOut, alarmsLog);
859 alarmsLog = interface_->getAlarmsLog(
"");
860 __SUP_COUT__ <<
"get Alarms Log for all channels" << __E__;
861 jsonFiller(xmlOut, alarmsLog);
866 void SlowControlsDashboardSupervisor::GetUserPermissions(
869 const WebUsers::RequestUserInfo& )
875 void SlowControlsDashboardSupervisor::GenerateUID(cgicc::Cgicc& ,
876 HttpXmlDocument& xmlOut,
877 std::string channelList)
879 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" "
880 <<
"Generating UID" << __E__;
882 std::set<std::string> channelDependencies;
883 StringMacros::getSetFromString(channelList, channelDependencies);
886 channelDependencyLookupMap_.insert(
887 std::pair<
int, std::set<std::string>>(++UID_, channelDependencies));
889 uidPollTimeMap_.insert(std::pair<int, long int>(UID_, std::time(NULL)));
891 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId() <<
" NEW UID: " << UID_
892 <<
" maps to " << channelDependencies.size() <<
" channels" << __E__;
894 xmlOut.addTextElementToData(
"JSON",
895 std::string(
"{ \"message\": \"") + std::to_string(UID_) +
900 void SlowControlsDashboardSupervisor::GetList(cgicc::Cgicc& ,
901 HttpXmlDocument& xmlOut)
903 if(interface_ != NULL)
905 __SUP_COUT__ <<
"Interface is defined! Attempting to get list!" << __E__;
911 list = interface_->getList(
"JSON");
913 catch(std::runtime_error& e)
915 __SUP_SS__ <<
"Channel list request failed: " << e.what() << __E__;
919 __SUP_COUT__ <<
" " << list << __E__;
921 xmlOut.addTextElementToData(
"JSON", list);
925 __SUP_COUT__ <<
"Interface undefined! Failed to get list!" << __E__;
926 xmlOut.addTextElementToData(
"JSON",
"[\"None\"]");
931 void SlowControlsDashboardSupervisor::GetPages(cgicc::Cgicc& ,
932 HttpXmlDocument& xmlOut)
934 std::vector<std::string> pages;
936 listFiles(
"",
true, &pages);
938 std::string returnJSON =
"[";
939 for(
auto it = pages.begin(); it != pages.end(); it++)
941 if(*it !=
"." && *it !=
"..")
942 returnJSON +=
"\"" + *it +
"\", ";
944 if(returnJSON.size() > 2 && returnJSON.compare(
"[") != 0)
946 __SUP_COUT__ <<
"Found pages on server!" << __E__;
947 returnJSON.resize(returnJSON.size() - 2);
953 __SUP_COUT__ <<
"No pages found on server!" << __E__;
954 returnJSON =
"[\"None\"]";
956 __SUP_COUT__ << returnJSON << __E__;
958 xmlOut.addTextElementToData(
"JSON", returnJSON);
962 void SlowControlsDashboardSupervisor::loadPage(
964 HttpXmlDocument& xmlOut,
966 const WebUsers::RequestUserInfo& )
968 page = StringMacros::decodeURIComponent(page);
972 if(page.find(
"..") != std::string::npos)
974 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
975 <<
"Error! Request using '..': " << page << __E__;
977 else if(page.find(
"~") != std::string::npos)
979 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
980 <<
"Error! Request using '~': " << page << __E__;
982 else if(!(stat(page.c_str(), &buffer) == 0))
984 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
985 <<
"Error! File not found: " << page << __E__;
989 __SUP_COUT__ << page << __E__;
991 if(page.at(0) ==
'/')
993 __SUP_COUT__ <<
"First character is '/'" << __E__;
994 page.erase(page.begin(), page.begin() + 1);
995 __SUP_COUT__ << page << __E__;
998 std::string file = PAGES_DIRECTORY;
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__;
1007 std::ifstream infile(file);
1010 __SUP_COUT__ <<
"Failed reading file: " << file << __E__;
1012 xmlOut.addTextElementToData(
"Time",
"[\"Not Found\"]");
1013 xmlOut.addTextElementToData(
"Notes",
"[\"Not Found\"]");
1014 xmlOut.addTextElementToData(
1015 "Page", StringMacros::encodeURIComponent(page));
1018 __SUP_COUT__ <<
"Reading file" << __E__;
1020 std::string time =
"";
1021 std::string notes =
"";
1022 std::string controlsPage =
"";
1024 for(std::string line; getline(infile, line);)
1026 __SUP_COUT__ << line << __E__;
1027 if(!line.substr(0, 5).compare(
"Time:"))
1029 time = line.substr(6);
1031 else if(!line.substr(0, 6).compare(
"Notes:"))
1033 notes = line.substr(7);
1035 else if(!line.substr(0, 5).compare(
"Page:"))
1037 controlsPage = line.substr(6);
1040 __SUP_COUT__ <<
"Finished reading file" << __E__;
1041 __SUP_COUTV__(time);
1042 __SUP_COUTV__(notes);
1043 __SUP_COUTV__(controlsPage);
1045 xmlOut.addTextElementToData(
"Time", time);
1046 xmlOut.addTextElementToData(
"Notes", notes);
1047 xmlOut.addTextElementToData(
"Page", controlsPage);
1051 void SlowControlsDashboardSupervisor::loadPhoebusPage(
1053 HttpXmlDocument& xmlOut,
1055 const WebUsers::RequestUserInfo& )
1057 page = StringMacros::decodeURIComponent(page);
1061 if(page.find(
"..") != std::string::npos)
1063 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1064 <<
"Error! Request using '..': " << page << __E__;
1066 else if(page.find(
"~") != std::string::npos)
1068 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1069 <<
"Error! Request using '~': " << page << __E__;
1071 else if(!(stat(page.c_str(), &buffer) == 0))
1073 __SUP_COUT__ << this->getApplicationDescriptor()->getLocalId()
1074 <<
"Error! File not found: " << page << __E__;
1078 __SUP_COUT__ << page << __E__;
1080 if(page.at(0) ==
'/')
1082 __SUP_COUT__ <<
"First character is '/'" << __E__;
1083 page.erase(page.begin(), page.begin() + 1);
1084 __SUP_COUT__ << page << __E__;
1087 std::string file = PAGES_DIRECTORY;
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__;
1095 __SUP_COUT__ <<
"Reading file" << __E__;
1096 std::ifstream infile(file);
1099 __SUP_COUT__ <<
"Failed reading file: " << file << __E__;
1100 xmlOut.addTextElementToData(
1101 "Page", StringMacros::encodeURIComponent(page));
1106 for(std::string line; getline(infile, line);)
1110 __SUP_COUT__ << xml << __E__;
1111 xmlOut.addTextElementToData(
"PHOEBUS", xml);
1116 void SlowControlsDashboardSupervisor::SaveControlsPage(
1117 cgicc::Cgicc& cgiIn,
1119 const WebUsers::RequestUserInfo& )
1121 __SUP_COUT__ <<
"ControlsDashboard wants to create a Controls Page!" << __E__;
1123 std::string controlsPageName = CgiDataUtilities::postData(cgiIn,
"Name");
1124 std::string pageString = CgiDataUtilities::postData(cgiIn,
"Page");
1125 std::string Time = CgiDataUtilities::postData(cgiIn,
"Time");
1127 StringMacros::decodeURIComponent(CgiDataUtilities::postData(cgiIn,
"Notes"));
1128 std::string isControlsPagePublic = CgiDataUtilities::postData(cgiIn,
"isPublic");
1130 __SUP_COUTV__(controlsPageName);
1131 __SUP_COUTV__(pageString);
1132 __SUP_COUTV__(Notes);
1133 __SUP_COUTV__(Time);
1134 __SUP_COUTV__(isControlsPagePublic);
1136 if(controlsPageName ==
"")
1139 std::string fullPath;
1140 if(isControlsPagePublic ==
"true")
1141 fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1143 fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1145 __SUP_COUTV__(fullPath);
1147 std::string file = fullPath + controlsPageName;
1149 __SUP_COUTV__(
"Saving Controls Page to: " + file);
1151 std::string extension = file.substr(file.length() - 4, 4);
1152 if(extension !=
".dat")
1154 __SUP_COUT__ <<
"Extension : " << extension << __E__;
1155 file += std::string(
".dat");
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__;
1164 std::ofstream outputFile;
1165 outputFile.open(file);
1166 if(!outputFile.is_open())
1168 __SUP_SS__ <<
"Failed to open file for writing: " << file << __E__;
1171 outputFile <<
"Time: " << Time <<
"\n";
1172 outputFile <<
"Notes: " << Notes <<
"\n";
1173 outputFile <<
"Page: " << pageString;
1176 __SUP_COUT__ <<
"Finished writing file" << __E__;
1182 void SlowControlsDashboardSupervisor::SavePhoebusControlsPage(
1183 cgicc::Cgicc& cgiIn,
1185 const WebUsers::RequestUserInfo& )
1187 __SUP_COUT__ <<
"ControlsDashboard wants to create a Controls Page!" << __E__;
1189 std::string controlsPageName = CgiDataUtilities::postData(cgiIn,
"Name");
1190 std::string pageString = CgiDataUtilities::postData(cgiIn,
"Page");
1191 std::string isControlsPagePublic = CgiDataUtilities::postData(cgiIn,
"isPublic");
1193 __SUP_COUTV__(controlsPageName);
1194 __SUP_COUTV__(pageString);
1195 __SUP_COUTV__(isControlsPagePublic);
1197 if(controlsPageName ==
"")
1200 std::string fullPath;
1201 if(isControlsPagePublic ==
"true")
1202 fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1204 fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1206 __SUP_COUTV__(fullPath);
1208 std::string file = fullPath + controlsPageName;
1210 __SUP_COUTV__(
"Saving Controls Page to: " + file);
1212 std::string extension = file.substr(file.length() - 4, 4);
1213 if(extension !=
".bob")
1215 __SUP_COUT__ <<
"Extension : " << extension << __E__;
1216 file += std::string(
".bob");
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__;
1225 std::ofstream outputFile;
1226 outputFile.open(file);
1227 if(!outputFile.is_open())
1229 __SUP_SS__ <<
"Failed to open file for writing: " << file << __E__;
1232 outputFile << pageString <<
"\n";
1235 __SUP_COUT__ <<
"Finished writing file" << __E__;
1241 void SlowControlsDashboardSupervisor::saveImageFile(
1242 cgicc::Cgicc& cgiIn,
1244 const WebUsers::RequestUserInfo& )
1246 __SUP_COUT__ <<
"ControlsDashboard wants to save the image file uploaded!" << __E__;
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;
1254 __SUP_COUTV__(files.size());
1255 __SUP_COUTV__(isImagePublic);
1257 if(isImagePublic ==
"true")
1258 fullPath = (std::string)PAGES_PUBLIC_DIRECTORY;
1260 fullPath = (std::string)PAGES_PRIVATE_DIRECTORY;
1262 for(
unsigned int i = 0; i < files.size(); ++i)
1264 filename = files[i].getFilename();
1265 filename = fullPath + filename;
1266 __COUT__ <<
"file " << i <<
" - " << filename << std::endl;
1268 myfile.open(filename.c_str());
1269 if(myfile.is_open())
1271 files[i].writeToStream(myfile);
1273 __SUP_COUT__ <<
"Finished writing image file" << __E__;
1281 void SlowControlsDashboardSupervisor::Subscribe(cgicc::Cgicc& ,
1287 void SlowControlsDashboardSupervisor::Unsubscribe(cgicc::Cgicc& ,
1299 struct stat fileInfo;
1300 stat(dir.c_str(), &fileInfo);
1301 if(S_ISDIR(fileInfo.st_mode))
1312 void SlowControlsDashboardSupervisor::listFiles(std::string innerDir,
1314 std::vector<std::string>* pages)
1316 std::string baseDir = PAGES_DIRECTORY;
1317 baseDir += innerDir;
1319 struct dirent* dirp;
1320 if((dp = opendir(baseDir.c_str())) == NULL)
1322 __SUP_COUT__ <<
"[ERROR: " << errno <<
" ] Couldn't open " << baseDir <<
"."
1328 while((dirp = readdir(dp)) != NULL)
1330 if(dirp->d_name != std::string(
".") && dirp->d_name != std::string(
".."))
1332 if(
isDir(baseDir + dirp->d_name) ==
true && recursive ==
true)
1335 __SUP_COUT__ <<
"[DIR]\t" << baseDir << dirp->d_name <<
"/" << __E__;
1336 listFiles(std::string(
"") + dirp->d_name +
"/",
true, pages);
1340 pages->push_back(innerDir + dirp->d_name);
1341 __SUP_COUT__ <<
"[FILE]\t" << baseDir << innerDir << dirp->d_name
bool isDir(std::string dir)
Utilities, eventually to be moved.
void checkSubscriptions(SlowControlsDashboardSupervisor *cs)
Manage channel subscriptions to Interface.
virtual void forceSupervisorPropertyValues(void) override
void init(void)
called by constructor
virtual void setSupervisorPropertyDefaults(void) override
void checkSlowControlsAlarms(SlowControlsDashboardSupervisor *cs)
Manage channel subscriptions to Interface.