1 #include "otsdaq/FECore/FEVInterface.h"
2 #include "otsdaq/CoreSupervisors/CoreSupervisorBase.h"
3 #include "otsdaq/FECore/FEVInterfacesManager.h"
4 #include "otsdaq/Macros/BinaryStringMacros.h"
5 #include "otsdaq/NetworkUtilities/UDPDataStreamerBase.h"
9 #define TRACE_NAME "FEVInterface"
16 const std::string FEVInterface::UNKNOWN_TYPE =
"UNKNOWN";
18 TableViewColumnInfo::DATATYPE_STRING_ALT_DEFAULT;
21 FEVInterface::FEVInterface(
const std::string& interfaceUID,
23 const std::string& configurationPath)
25 ,
Configurable(theXDAQContextConfigTree, configurationPath)
27 , slowControlsWorkLoop_(interfaceUID +
"-SlowControls", this)
28 , interfaceUID_(interfaceUID)
30 , mfSubject_(interfaceUID)
36 VStateMachine::parentSupervisor_ =
nullptr;
40 interfaceType_ = theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
41 .getNode(
"FEInterfacePluginName")
42 .getValue<std::string>();
47 <<
"FEInterface type could not be determined in base class from "
48 "configuration tree path; "
49 "the type may be defined subsequently by the inheriting class (e.g. to "
50 "take advantage of Slow Controls caching functionality, "
51 "the FEInterface type should be defined for all frontend interfaces)"
57 registerFEMacroFunction(
58 "Slow Controls Pause/Resume",
60 &FEVInterface::PauseResumeSlowControls),
61 std::vector<std::string>{
"Pause Slow Controls (Default = false)"},
62 std::vector<std::string>{
"Result"},
65 "This FE Macro is used to Pause or Resume the Slow Controls workloop, which "
66 "could be valuable while debugging front-ends.");
69 __GEN_COUT__ <<
"Constructed." << __E__;
77 parentInterfaceManager_ = manager;
81 FEVInterface::~FEVInterface(
void)
86 __GEN_COUT__ <<
"Destructed." << __E__;
90 void FEVInterface::PauseResumeSlowControls(__ARGS__)
92 slowControlsWorkLoopShouldRun_ =
93 !__GET_ARG_IN__(
"Pause Slow Controls (Default = false)",
bool,
false);
94 __FE_COUTV__(slowControlsWorkLoopShouldRun_);
96 std::stringstream outss;
97 outss <<
"Slow Controls workloop is "
98 << (slowControlsWorkLoopShouldRun_ ?
"active." :
"paused.");
100 __SET_ARG_OUT__(
"Result", outss.str());
108 __COUT__ <<
"configureSlowControls path=" << theConfigurationPath_ << __E__;
111 if(metricMan && !metricMan->Running() && metricMan->Initialized())
113 __COUT__ <<
"Metric manager starting..." << __E__;
114 metricMan->do_start();
115 __COUT__ <<
"Metric manager started." << __E__;
117 else if(!metricMan || !metricMan->Initialized())
118 __COUT__ <<
"Metric manager could not be started! metricMan: " << metricMan
119 <<
" Initialized()= " << (metricMan ? metricMan->Initialized() : 0)
122 __COUT__ <<
"Metric manager already started." << __E__;
131 std::string errMessage;
135 theXDAQContextConfigTree_.
getNode(theConfigurationPath_)
136 .
getNode(
"LinkToSlowControlsChannelTable");
146 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
147 .
getNode(
"LinkToSlowControlsChannelTable"),
154 theXDAQContextConfigTree_.
getNode(theConfigurationPath_)
155 .
getNode(
"LinkToSlowControlsChannelTable"),
158 catch(
const std::runtime_error& e)
160 __SS__ <<
"Configuring slow controls channels encountered an error: "
167 catch(
const std::runtime_error& e)
169 __SS__ <<
"Error was caught while configuring slow controls: " << e.what() << __E__;
174 __SS__ <<
"Unknown error was caught while configuring slow controls." << __E__;
179 catch(
const std::exception& e)
181 ss <<
"Exception message: " << e.what();
195 std::map<std::string /* ROC UID*/, FESlowControlsChannel>* mapOfSlowControlsChannels)
200 <<
"slowControlsGroupLink is disconnected, so done configuring slow controls."
204 __FE_COUT__ <<
"slowControlsGroupLink is valid! Adding slow controls channels..."
207 std::vector<std::pair<std::string, ConfigurationTree> > groupLinkChildren =
209 for(
auto& groupLinkChild : groupLinkChildren)
212 if(!(groupLinkChild.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
216 __FE_COUT__ <<
"Channel:" << slowControlsGroupLink.
getTableName() <<
"/"
217 << getInterfaceUID() <<
"/" << groupLinkChild.first
218 <<
"\t Type:" << groupLinkChild.second.getNode(
"ChannelDataType")
222 std::string transformation =
"";
226 groupLinkChild.second.getNode(
"Transformation").getValue<std::string>();
230 __FE_COUT__ <<
"Slow controls 'Transformation' setting not found." << __E__;
233 mapOfSlowControlsChannels->insert(std::pair<std::string, FESlowControlsChannel>(
234 groupLinkChild.first,
237 groupLinkChild.first,
238 groupLinkChild.second.getNode(
"ChannelDataType").getValue<std::string>(),
239 groupLinkChild.second.getNode(
"UniversalInterfaceAddress")
240 .getValue<std::string>(),
241 groupLinkChild.second.getNode(
"Transformation").getValue<std::string>(),
242 groupLinkChild.second.getNode(
"UniversalDataBitOffset")
243 .getValue<
unsigned int>(),
244 groupLinkChild.second.getNode(
"ReadAccess").getValue<
bool>(),
245 groupLinkChild.second.getNode(
"WriteAccess").getValue<
bool>(),
246 groupLinkChild.second.getNode(
"MonitoringEnabled").getValue<
bool>(),
247 groupLinkChild.second.getNode(
"RecordChangesOnly").getValue<
bool>(),
248 groupLinkChild.second.getNode(
"DelayBetweenSamplesInSeconds")
250 groupLinkChild.second.getNode(
"LocalSavingEnabled").getValue<
bool>(),
251 groupLinkChild.second.getNode(
"LocalFilePath").getValue<std::string>(),
252 groupLinkChild.second.getNode(
"RadixFileName").getValue<std::string>(),
253 groupLinkChild.second.getNode(
"SaveBinaryFile").getValue<
bool>(),
254 groupLinkChild.second.getNode(
"AlarmsEnabled").getValue<
bool>(),
255 groupLinkChild.second.getNode(
"LatchAlarms").getValue<
bool>(),
256 groupLinkChild.second.getNode(
"LowLowThreshold").getValue<std::string>(),
257 groupLinkChild.second.getNode(
"LowThreshold").getValue<std::string>(),
258 groupLinkChild.second.getNode(
"HighThreshold").getValue<std::string>(),
259 groupLinkChild.second.getNode(
"HighHighThreshold")
260 .getValue<std::string>())));
262 __FE_COUT__ <<
"Added " << mapOfSlowControlsChannels->size()
263 <<
" slow controls channels." << __E__;
282 (slowControlsChannelsIterator_++)->second);
296 __FE_COUT__ <<
"slowControlsRunning" << __E__;
301 <<
"No slow controls channels to monitor, exiting slow controls workloop."
308 const unsigned int txBufferSz = 1500;
309 const unsigned int txBufferFullThreshold = 750;
310 std::string txBuffer;
311 txBuffer.reserve(txBufferSz);
314 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_);
317 std::unique_ptr<UDPDataStreamerBase> slowContrlolsTxSocket;
318 std::string slowControlsSupervisorIPAddress =
"", slowControlsSelfIPAddress =
"";
319 int slowControlsSupervisorPort = 0, slowControlsSelfPort = 0;
323 FEInterfaceNode.
getNode(
"LinkToSlowControlsSupervisorTable");
327 __FE_SS__ <<
"slowControlsInterfaceLink is disconnected, so no socket made."
332 slowControlsSelfIPAddress =
333 FEInterfaceNode.
getNode(
"SlowControlsTxSocketIPAddress")
335 slowControlsSelfPort =
337 slowControlsSupervisorIPAddress =
338 slowControlsInterfaceLink.
getNode(
"IPAddress").
getValue<std::string>();
339 slowControlsSupervisorPort =
344 __FE_COUT__ <<
"Link to slow controls supervisor is missing, so no socket made."
348 bool txBufferUsed =
false;
349 if(slowControlsSupervisorPort && slowControlsSelfPort &&
350 slowControlsSupervisorIPAddress !=
"" && slowControlsSelfIPAddress !=
"")
352 __FE_COUT__ <<
"slowControlsInterfaceLink is valid! Create tx socket..." << __E__;
353 slowContrlolsTxSocket.reset(
355 slowControlsSelfPort,
356 slowControlsSupervisorIPAddress,
357 slowControlsSupervisorPort));
362 __FE_COUT__ <<
"Invalid Slow Controls socket parameters, so no socket made."
369 bool aggregateFileIsBinaryFormat =
false;
372 if(FEInterfaceNode.
getNode(
"SlowControlsLocalAggregateSavingEnabled")
375 aggregateFileIsBinaryFormat =
376 FEInterfaceNode.
getNode(
"SlowControlsSaveBinaryFile").
getValue<
bool>();
378 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned On BinaryFormat="
379 << aggregateFileIsBinaryFormat << __E__;
381 std::string saveFullFileName =
382 FEInterfaceNode.
getNode(
"SlowControlsLocalFilePath")
385 FEInterfaceNode.
getNode(
"SlowControlsRadixFileName")
388 std::to_string(time(0)) + (aggregateFileIsBinaryFormat ?
".dat" :
".txt");
391 fopen(saveFullFileName.c_str(), aggregateFileIsBinaryFormat ?
"ab" :
"a");
395 <<
"Failed to open slow controls channel file: " << saveFullFileName
401 <<
"Slow controls aggregate file opened: " << saveFullFileName
409 if(!aggregateFileIsBinaryFormat)
410 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned off." << __E__;
412 time_t timeCounter = 0;
414 unsigned int numOfReadAccessChannels = 0;
415 bool firstTime =
true;
416 while(slowControlsWorkLoop_.getContinueWorkLoop())
422 if(!slowControlsWorkLoopShouldRun_)
425 <<
"Skipping slow controls loop... slowControlsWorkLoopShouldRun_ = "
426 << slowControlsWorkLoopShouldRun_ << __E__;
429 __COUTT__ <<
"Starting slow controls loop... slowControlsWorkLoopShouldRun_ = "
430 << slowControlsWorkLoopShouldRun_ << __E__;
433 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
444 if(!channel->readAccess_)
448 ++numOfReadAccessChannels;
451 if(timeCounter % channel->delayBetweenSamples_)
454 __FE_COUT__ <<
"Reading Channel:" << channel->fullChannelName
455 <<
" at t=" << time(0) << __E__;
458 bool usingBufferedValue =
false;
459 if(channel->getInterfaceType() != FEVInterface::UNKNOWN_TYPE)
464 channelToCopy !=
nullptr)
466 __FE_COUTT__ <<
"Looking for buffered value at "
467 << BinaryStringMacros::binaryNumberToHexString(
468 channelToCopy->getUniversalAddress(),
"0x",
" ")
469 <<
" " << channelToCopy->getReadSizeBytes() <<
" "
470 << time(0) - channelToCopy->getLastSampleTime() << __E__;
472 __FE_COUTTV__(channel->getInterfaceUID());
473 __FE_COUTTV__(channelToCopy->getInterfaceUID());
474 __FE_COUTTV__(channel->getInterfaceType());
475 __FE_COUTTV__(channelToCopy->getInterfaceType());
477 if(!usingBufferedValue &&
478 channelToCopy->getInterfaceUID() == channel->getInterfaceUID() &&
479 channelToCopy->getInterfaceType() == channel->getInterfaceType() &&
480 BinaryStringMacros::binaryNumberToHexString(
481 channelToCopy->getUniversalAddress(),
"0x",
" ") ==
482 BinaryStringMacros::binaryNumberToHexString(
483 channel->getUniversalAddress(),
"0x",
" ") &&
484 channelToCopy->getReadSizeBytes() == channel->getReadSizeBytes() &&
485 time(0) - channelToCopy->getLastSampleTime() <
488 usingBufferedValue =
true;
490 <<
"Using buffered " << channelToCopy->getReadSizeBytes()
491 <<
"-byte value at address:"
492 << BinaryStringMacros::binaryNumberToHexString(
493 channelToCopy->getUniversalAddress(),
"0x",
" ")
498 << BinaryStringMacros::binaryNumberToHexString(
499 channelToCopy->getLastSampleReadValue(),
"0x",
" ")
500 <<
" at t=" << time(0) << __E__;
501 channel->
handleSample(channelToCopy->getLastSampleReadValue(),
504 aggregateFileIsBinaryFormat,
506 __FE_COUT__ <<
"Copied: "
507 << BinaryStringMacros::binaryNumberToHexString(
508 channel->getSample(),
"0x",
" ")
509 <<
" at t=" << time(0) << __E__;
517 if(!usingBufferedValue)
519 std::string readValInst;
520 std::string& readVal = readValInst;
521 readVal.resize(universalDataSize_);
522 channel->doRead(readVal);
524 readVal, txBuffer, fp, aggregateFileIsBinaryFormat, txBufferUsed);
525 __FE_COUT__ <<
"Have: "
526 << BinaryStringMacros::binaryNumberToHexString(
527 channel->getSample(),
"0x",
" ")
528 <<
" at t=" << time(0) << __E__;
532 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
535 if(channel->monitoringEnabled && metricMan && metricMan->Running() &&
536 universalAddressSize_ <= 8)
539 for(
size_t ii = 0; ii < channel->getSample().size(); ++ii)
540 val += (uint8_t)channel->getSample()[ii] << (ii * 8);
543 if((channel->transformation).size() >
546 __FE_COUT__ <<
"Transformation formula = " << channel->transformation
549 TFormula transformationFormula(
"transformationFormula",
550 (channel->transformation).c_str());
551 double transformedVal = transformationFormula.Eval(val);
553 if(!std::isnan(transformedVal))
555 __FE_COUT__ <<
"Transformed " << val <<
" into " << transformedVal
557 __FE_COUT__ <<
"Sending \"" << channel->fullChannelName
558 <<
"\" transformed sample to Metric Manager..."
560 metricMan->sendMetric(channel->fullChannelName,
564 artdaq::MetricMode::LastPoint);
568 __FE_SS__ <<
"Transformed value is NaN!" << __E__;
574 __FE_COUT__ <<
"Sending \"" << channel->fullChannelName
575 <<
"\" sample to Metric Manager..." << __E__;
576 metricMan->sendMetric(channel->fullChannelName,
580 artdaq::MetricMode::LastPoint);
585 __FE_COUT__ <<
"Skipping \"" << channel->fullChannelName
586 <<
"\" sample to Metric Manager... "
587 <<
" channel->monitoringEnabled="
588 << channel->monitoringEnabled <<
" metricMan=" << metricMan
589 <<
" metricMan->Running()="
590 << (metricMan && metricMan->Running()) << __E__;
594 if(txBuffer.size() > txBufferSz)
596 __FE_SS__ <<
"This should never happen hopefully!" << __E__;
600 if(!slowContrlolsTxSocket && txBufferUsed)
604 if(slowContrlolsTxSocket && txBuffer.size() > txBufferFullThreshold)
606 __FE_COUT__ <<
"Sending now! txBufferFullThreshold="
607 << txBufferFullThreshold << __E__;
608 slowContrlolsTxSocket->send(txBuffer);
614 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
617 if(slowContrlolsTxSocket && txBuffer.size())
619 __FE_COUT__ <<
"Sending now!" << __E__;
620 slowContrlolsTxSocket->send(txBuffer);
628 if(numOfReadAccessChannels == 0)
631 <<
"There are no slow controls channels with read access!" << __E__;
636 <<
" slow controls channels total. "
637 << numOfReadAccessChannels <<
" with read access enabled."
646 __FE_COUT__ <<
"Slow controls workloop done." << __E__;
655 bool isPauseException =
false;
656 bool isStopException =
false;
664 ss <<
"PAUSE Exception was caught during slow controls running thread: "
665 << e.what() << std::endl;
666 isPauseException =
true;
670 ss <<
"STOP Exception was caught during slow controls running thread: "
671 << e.what() << std::endl;
672 isStopException =
true;
674 catch(
const std::runtime_error& e)
676 ss <<
"Caught an error during slow controls running thread of FE Interface '"
677 << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
681 ss <<
"Caught an unknown error during slow controls running thread." << __E__;
686 catch(
const std::exception& e)
688 ss <<
"Exception message: " << e.what();
700 __FE_COUT_ERR__ << ss.str();
704 const std::string errorMessage,
705 bool isPauseException,
706 bool isStopException) {
708 fe, errorMessage, isPauseException, isStopException);
729 const std::string& errorMessage,
730 bool isPauseException,
731 bool isStopException)
734 std::stringstream feHeader;
735 feHeader <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID() <<
":"
736 << fe->theConfigurationRecordName_ <<
"\t";
740 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async STOP Running Exception... \n"
741 << errorMessage << __E__;
742 fe->VStateMachine::parentSupervisor_->setAsyncPauseExceptionMessage(errorMessage);
744 else if(isPauseException)
746 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async PAUSE Running Exception... \n"
747 << errorMessage << __E__;
748 fe->VStateMachine::parentSupervisor_->setAsyncStopExceptionMessage(errorMessage);
751 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async Running Error... \n"
752 << errorMessage << __E__;
754 XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
755 fe->VStateMachine::parentSupervisor_->allSupervisorInfo_.getGatewayInfo()
759 parameters.addParameter(
"ErrorMessage", errorMessage);
761 xoap::MessageReference replyMessage =
762 fe->VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
764 isPauseException ?
"AsyncPauseException" :
"AsyncError",
767 std::stringstream replyMessageSStream;
768 replyMessageSStream << SOAPUtilities::translate(replyMessage);
769 __COUT__ << feHeader.str() <<
"Received... " << replyMessageSStream.str()
772 if(replyMessageSStream.str().find(
"Fault") != std::string::npos)
774 __COUT_ERR__ << feHeader.str() <<
"Failure to indicate fault to Gateway..."
779 catch(
const xdaq::exception::Exception& e)
782 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running SOFT "
783 "error back to Gateway: "
784 << e.what() << __E__;
786 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running "
787 "error back to Gateway: "
788 << e.what() << __E__;
794 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
795 "SOFT error back to Gateway."
798 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
799 "error back to Gateway."
819 bool isPauseException =
false;
820 bool isStopException =
false;
828 ss <<
"SOFT Exception was caught while running: " << e.what() << std::endl;
829 isPauseException =
true;
833 ss <<
"STOP Exception was caught while running: " << e.what() << std::endl;
834 isStopException =
true;
836 catch(
const std::runtime_error& e)
838 ss <<
"Caught an error during running at FE Interface '"
839 << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
843 ss <<
"Caught an unknown error during running." << __E__;
848 catch(
const std::exception& e)
850 ss <<
"Exception message: " << e.what();
862 __FE_COUT_ERR__ << ss.str();
866 const std::string errorMessage,
867 bool isPauseException,
868 bool isStopException) {
870 fe, errorMessage, isPauseException, isStopException);
882 return continueWorkLoop_;
894 const std::string& feMacroName,
896 const std::vector<std::string>& namesOfInputArgs,
897 const std::vector<std::string>& namesOfOutputArgs,
898 uint8_t requiredUserPermissions,
899 const std::string& allowedCallingFEs,
900 const std::string& feMacroTooltip)
906 std::to_string(requiredUserPermissions),
911 const std::string& feMacroName,
912 frontEndMacroFunction_t feMacroFunction,
913 const std::vector<std::string>& namesOfInputArgs,
914 const std::vector<std::string>& namesOfOutputArgs,
915 const std::string& requiredUserPermissions,
916 const std::string& allowedCallingFEs,
917 const std::string& feMacroTooltip)
921 __FE_SS__ <<
"feMacroName '" << feMacroName <<
"' already exists! Not allowed."
923 __FE_COUT_ERR__ <<
"\n" << ss.str();
927 __FE_COUTT__ <<
"Registering FE Macro Function: '" << feMacroName
928 <<
"' with requiredUserPermissions=" << requiredUserPermissions
929 <<
" allowedCallingFEs=" << allowedCallingFEs << __E__;
933 frontEndMacroStruct_t(feMacroName,
937 requiredUserPermissions,
950 const std::string& argName)
952 for(
const frontEndMacroArg_t& pair : args)
955 if(pair.first.substr(0, pair.first.find(
'(')) ==
956 argName.substr(0, argName.find(
'(')))
958 __COUT__ << argName <<
": " << pair.second << __E__;
962 __SS__ <<
"Requested input argument '" << argName
963 <<
"' not found in list of arguments." << __E__;
964 ss <<
"\nHere is the list of arguments: \n";
965 for(
const frontEndMacroArg_t& pair : args)
966 ss <<
"\t - " << pair.first <<
"\n";
974 std::string ots::getFEMacroConstArgumentValue<std::string>(
975 FEVInterface::frontEndMacroConstArgs_t& args,
976 const std::string& argName,
977 const std::string& defaultValue)
982 if(data ==
"Default" || data ==
"DEFAULT")
991 std::string ots::getFEMacroArgumentValue<std::string>(
992 FEVInterface::frontEndMacroArgs_t& args,
const std::string& argName)
1003 const std::string& argName)
1005 for(std::pair<
const std::string ,
1006 std::string >& pair : args)
1008 if(pair.first == argName)
1011 __SS__ <<
"Requested argument not found with name '" << argName <<
"'" << __E__;
1022 std::map<uint64_t, uint64_t> writeHistory;
1023 uint64_t writeAddress, writeValue, bitMask;
1024 uint8_t bitPosition;
1026 std::string writeBuffer;
1027 std::string readBuffer;
1029 bool ignoreError =
true;
1035 theXDAQContextConfigTree_.
getNode(theConfigurationPath_)
1042 __FE_COUT__ <<
"Disconnected configure sequence" << __E__;
1045 __FE_COUT__ <<
"Handling configure sequence." << __E__;
1047 for(
const auto& child : childrenMap)
1052 child.second.getNode(
"WriteAddress").getValue<uint64_t>();
1053 writeValue = child.second.getNode(
"WriteValue").getValue<uint64_t>();
1055 child.second.getNode(
"StartingBitPosition").getValue<uint8_t>();
1057 (1 << child.second.getNode(
"BitFieldSize").getValue<uint8_t>()) -
1060 writeValue &= bitMask;
1061 writeValue <<= bitPosition;
1062 bitMask = ~(bitMask << bitPosition);
1065 if(writeHistory.find(writeAddress) == writeHistory.end())
1066 writeHistory[writeAddress] = 0;
1068 writeHistory[writeAddress] &= bitMask;
1069 writeHistory[writeAddress] |= writeValue;
1072 "\t Writing %s: \t %ld(0x%lX) \t %ld(0x%lX)",
1073 child.first.c_str(),
1076 writeHistory[writeAddress],
1077 writeHistory[writeAddress]);
1079 __FE_COUT__ << msg << __E__;
1081 universalWrite((
char*)&writeAddress,
1082 (
char*)&(writeHistory[writeAddress]));
1088 ignoreError =
false;
1098 <<
"Unable to access sequence of commands through configuration tree. "
1099 <<
"Assuming no sequence. " << __E__;
1112 const std::string& feMacroName,
1115 const std::vector<FEVInterface::frontEndMacroArg_t>& argsIn,
1116 std::vector<FEVInterface::frontEndMacroArg_t>& argsOut)
1119 auto FEMacroIt = this->getMapOfFEMacroFunctions().find(feMacroName);
1120 if(FEMacroIt == this->getMapOfFEMacroFunctions().end())
1122 __CFG_SS__ <<
"FE Macro '" << feMacroName <<
"' of interfaceID '"
1123 << getInterfaceUID() <<
"' was not found!" << __E__;
1124 __CFG_COUT_ERR__ <<
"\n" << ss.str();
1130 for(
unsigned int i = 0;
1131 i < argsIn.size() && i < feMacro.namesOfInputArguments_.size();
1133 if(argsIn[i].first != feMacro.namesOfInputArguments_[i])
1135 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
1136 << getInterfaceUID() <<
"' was attempted with a mismatch in"
1137 <<
" a name of an input argument. " << argsIn[i].first
1138 <<
" was given. " << feMacro.namesOfInputArguments_[i]
1139 <<
" expected." << __E__;
1140 __CFG_COUT_ERR__ <<
"\n" << ss.str();
1145 if(feMacro.namesOfInputArguments_.size() != argsIn.size())
1147 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
1148 << getInterfaceUID() <<
"' was attempted with a mismatch in"
1149 <<
" number of input arguments. " << argsIn.size() <<
" were given. "
1150 << feMacro.namesOfInputArguments_.size() <<
" expected." << __E__;
1151 __CFG_COUT_ERR__ <<
"\n" << ss.str();
1155 __CFG_COUT__ <<
"# of input args = " << argsIn.size() << __E__;
1156 for(
auto& argIn : argsIn)
1157 __CFG_COUT__ << argIn.first <<
": " << argIn.second << __E__;
1159 __CFG_COUT__ <<
"Launching FE Macro '" << feMacro.feMacroName_ <<
"' ..." << __E__;
1162 for(
unsigned int i = 0; i < feMacro.namesOfOutputArguments_.size(); ++i)
1163 argsOut.push_back(FEVInterface::frontEndMacroArg_t(
1164 feMacro.namesOfOutputArguments_[i],
"DEFAULT"));
1169 __CFG_COUT__ <<
"FE Macro complete!" << __E__;
1171 __CFG_COUT__ <<
"# of output args = " << argsOut.size() << __E__;
1172 for(
const auto& arg : argsOut)
1173 __CFG_COUT__ << arg.first <<
": " << arg.second << __E__;
1182 const std::string& targetInterfaceID,
1183 const std::string& feMacroName,
1184 const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs,
1185 std::vector<FEVInterface::frontEndMacroArg_t>& outputArgs)
const
1187 __FE_COUTV__(targetInterfaceID);
1192 .getAllMacroMakerTypeSupervisorInfo();
1193 __FE_COUTV__(MacroMakerSupervisors.size());
1195 if(!MacroMakerSupervisors.size())
1197 __FE_SS__ <<
"No MacroMakerSupervisors found! Notify admins." << __E__;
1201 std::vector<FEVInterface::frontEndMacroArg_t> encodedInputArgs;
1202 for(
auto& arg : inputArgs)
1204 __FE_COUT__ << arg.first <<
": " << arg.second << __E__;
1205 encodedInputArgs.push_back(
1206 std::make_pair(StringMacros::encodeURIComponent(arg.first),
1207 StringMacros::encodeURIComponent(arg.second)));
1211 encodedInputArgs,
";" ,
"," );
1213 __FE_COUTV__(inputArgsStr);
1215 xoap::MessageReference message =
1216 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
1219 parameters.addParameter(
"type",
"feMacro");
1220 parameters.addParameter(
"requester", FEVInterface::interfaceUID_);
1221 parameters.addParameter(
"targetInterfaceID", targetInterfaceID);
1222 parameters.addParameter(
"feMacroName", feMacroName);
1223 parameters.addParameter(
"inputArgs", inputArgsStr);
1224 SOAPUtilities::addParameters(message, parameters);
1226 __FE_COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
1229 xoap::MessageReference replyMessage =
1231 MacroMakerSupervisors.begin()->second.getDescriptor(), message);
1233 __FE_COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage)
1237 rxParameters.addParameter(
"Error");
1238 SOAPUtilities::receive(replyMessage, rxParameters);
1240 std::string error = rxParameters.getValue(
"Error");
1245 __FE_SS__ <<
"Error transmitting request to target interface '"
1246 << targetInterfaceID <<
"' from '" << FEVInterface::interfaceUID_
1247 <<
".' " << error << __E__;
1253 argsOutParameter.addParameter(
"outputArgs");
1254 SOAPUtilities::receive(replyMessage, argsOutParameter);
1256 std::string outputArgsStr = argsOutParameter.getValue(
"outputArgs");
1257 std::set<char> pairDelimiter({
';'}), nameValueDelimiter({
','});
1259 std::map<std::string, std::string> mapToReturn;
1261 outputArgsStr, mapToReturn, pairDelimiter, nameValueDelimiter);
1264 for(
auto& mapPair : mapToReturn)
1265 outputArgs.push_back(mapPair);
1275 std::string& retValue,
1276 unsigned int timeoutInSeconds)
const
1278 __FE_COUTV__(requester);
1281 std::string data =
"0";
1287 std::lock_guard<std::mutex> lock(
1290 auto receiveBuffersForTargetIt =
1291 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.find(
1292 FEVInterface::interfaceUID_);
1293 if(receiveBuffersForTargetIt !=
1294 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.end())
1296 __FE_COUT__ <<
"Number of source buffers found for front-end '"
1297 << FEVInterface::interfaceUID_
1298 <<
"': " << receiveBuffersForTargetIt->second.size() << __E__;
1300 for(
auto& buffPair : receiveBuffersForTargetIt->second)
1301 __FE_COUTV__(buffPair.first);
1304 std::string sourceBufferId =
"";
1305 std::queue<std::string >& sourceBuffer =
1307 requester, receiveBuffersForTargetIt->second, &sourceBufferId);
1309 __FE_COUT__ <<
"Found source buffer '" << sourceBufferId <<
"' with size "
1310 << sourceBuffer.size() << __E__;
1312 if(sourceBuffer.size())
1314 __FE_COUT__ <<
"Found a value in queue of size "
1315 << sourceBuffer.size() << __E__;
1318 retValue = sourceBuffer.front();
1323 __FE_COUT__ <<
"Source buffer empty for '" << requester <<
"'"
1330 if(!timeoutInSeconds)
1332 __FE_SS__ <<
"Timeout (" << timeoutInSeconds
1333 <<
" s) waiting for front-end communication from " << requester
1342 __FE_COUT__ <<
"Waiting for front-end communication from " << requester <<
" for "
1343 << timeoutInSeconds <<
" more seconds..." << __E__;
1358 unsigned int timeoutInSeconds)
const
1360 std::string retValue;
1369 __COUTVS__(20, macroString);
1375 std::vector<std::string> extractVec;
1382 MACRONAME_NAME_INDEX = 1,
1383 MACRONAME_VALUE_INDEX = 3,
1384 SEQUENCE_NAME_INDEX = 5,
1385 SEQUENCE_VALUE_INDEX = 7,
1386 LSBF_NAME_INDEX = 17,
1387 LSFBF_VALUE_INDEX = 19,
1391 if(MACRONAME_NAME_INDEX >= extractVec.size() ||
1392 extractVec[MACRONAME_NAME_INDEX] !=
"name")
1394 __SS__ <<
"Invalid sequence, 'name' expected in position " << MACRONAME_NAME_INDEX
1398 if(SEQUENCE_NAME_INDEX >= extractVec.size() ||
1399 extractVec[SEQUENCE_NAME_INDEX] !=
"sequence")
1401 __SS__ <<
"Invalid sequence, 'sequence' expected in position "
1402 << SEQUENCE_NAME_INDEX << __E__;
1405 if(LSBF_NAME_INDEX >= extractVec.size() || extractVec[LSBF_NAME_INDEX] !=
"LSBF")
1407 __SS__ <<
"Invalid sequence, 'LSBF' expected in position " << LSBF_NAME_INDEX
1411 macroName_ = extractVec[MACRONAME_VALUE_INDEX];
1412 __COUTVS__(20, macroName_);
1413 lsbf_ = extractVec[LSFBF_VALUE_INDEX] ==
"false" ? false :
true;
1414 __COUTVS__(20,
lsbf_);
1415 std::string& sequence = extractVec[SEQUENCE_VALUE_INDEX];
1416 __COUTVS__(20, sequence);
1418 std::vector<std::string> sequenceCommands;
1423 for(
auto& command : sequenceCommands)
1425 __COUTVS__(20, command);
1430 std::vector<std::string> commandPieces;
1435 __COUTVS__(20, commandPieces.size());
1446 if(commandPieces.size() < 3 || commandPieces.size() > 4 ||
1447 commandPieces[1].size() != 1)
1449 __SS__ <<
"Invalid command type specified in command string: " << command
1456 std::function<bool(
const std::string&
1458 localIsVariable = [](
const std::string& fieldValue) {
1461 __GEN_COUTVS__(20, fieldValue);
1464 for(
const auto& c : fieldValue)
1465 if(!((c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f') ||
1466 (c >=
'A' && c <=
'F')))
1471 if(commandPieces[1][0] ==
'r' && commandPieces.size() == 4)
1473 TLOG_DEBUG(20) << __COUT_HDR__ <<
"Read type found." << __E__;
1477 operations_.push_back(
1478 std::make_pair(macroStruct_t::OP_TYPE_READ, readOps_.size()));
1481 readOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1482 readOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1484 if(!readOps_.back().addressIsVar_)
1488 std::string lsbfData =
"";
1491 commandPieces[2] =
"0" + commandPieces[2];
1492 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1494 __COUTVS__(20, commandPieces[2].size() - 2 * (i + 1));
1497 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1499 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1500 __COUTV__(lsbfData);
1502 __COUTVS__(20, lsbfData);
1507 readOps_.back().address_);
1511 readOps_.back().addressVarName_ = commandPieces[2];
1512 __COUTVS__(20, readOps_.back().addressVarName_);
1514 namesOfInputArguments_.emplace(readOps_.back().addressVarName_);
1517 if(readOps_.back().dataIsVar_)
1519 readOps_.back().dataVarName_ = commandPieces[3];
1520 __COUTVS__(20, readOps_.back().dataVarName_);
1522 namesOfOutputArguments_.emplace(readOps_.back().dataVarName_);
1525 else if(commandPieces[1][0] ==
'w' && commandPieces.size() == 4)
1527 TLOG_DEBUG(20) << __COUT_HDR__ <<
"Write type found." << __E__;
1531 operations_.push_back(
1532 std::make_pair(macroStruct_t::OP_TYPE_WRITE, writeOps_.size()));
1535 writeOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1536 writeOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1538 if(!writeOps_.back().addressIsVar_)
1542 std::string lsbfData =
"";
1545 commandPieces[2] =
"0" + commandPieces[2];
1546 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1548 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1551 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1553 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1554 __COUTV__(lsbfData);
1556 __COUTVS__(20, lsbfData);
1561 writeOps_.back().address_);
1565 writeOps_.back().addressVarName_ = commandPieces[2];
1566 __COUTVS__(20, writeOps_.back().addressVarName_);
1568 namesOfInputArguments_.emplace(writeOps_.back().addressVarName_);
1571 if(!writeOps_.back().dataIsVar_)
1575 std::string lsbfData =
"";
1578 commandPieces[2] =
"0" + commandPieces[3];
1579 for(
unsigned int i = 0; i < commandPieces[3].size() / 2; ++i)
1581 __COUTVS__(20, commandPieces[3].size() - 2 * (i + 1));
1584 commandPieces[3][commandPieces[3].size() - 2 * (i + 1)];
1586 commandPieces[3][commandPieces[3].size() - 2 * (i + 1) + 1];
1587 __COUTVS__(20, lsbfData);
1589 __COUTV__(lsbfData);
1594 writeOps_.back().data_);
1598 writeOps_.back().dataVarName_ = commandPieces[3];
1599 __COUTVS__(20, writeOps_.back().dataVarName_);
1601 namesOfInputArguments_.emplace(writeOps_.back().dataVarName_);
1604 else if(commandPieces[1][0] ==
'd' && commandPieces.size() == 3)
1606 TLOG_DEBUG(20) << __COUT_HDR__ <<
"Delay type found." << __E__;
1609 operations_.push_back(
1610 std::make_pair(macroStruct_t::OP_TYPE_DELAY, delayOps_.size()));
1613 delayOps_.back().delayIsVar_ = localIsVariable(commandPieces[2]);
1615 if(!delayOps_.back().delayIsVar_)
1619 delayOps_.back().delayVarName_ = commandPieces[2];
1620 __COUTVS__(20, delayOps_.back().delayVarName_);
1622 namesOfInputArguments_.emplace(delayOps_.back().delayVarName_);
1627 __SS__ <<
"Invalid command type '" << commandPieces[1][0]
1628 <<
"' specified with " << commandPieces.size() <<
" components."
1635 __COUTT__ << operations_.size() <<
" operations extracted: \n\t" << readOps_.size()
1636 <<
" reads \n\t" << writeOps_.size() <<
" writes \n\t" << delayOps_.size()
1637 <<
" delays" << __E__;
1639 __COUTT__ <<
"Input arguments: " << __E__;
1640 for(
const auto& inputArg : namesOfInputArguments_)
1641 __COUTT__ <<
"\t" << inputArg << __E__;
1643 __COUTT__ <<
"Output arguments: " << __E__;
1644 for(
const auto& outputArg : namesOfOutputArguments_)
1645 __COUTT__ <<
"\t" << outputArg << __E__;
1653 std::map<std::string /*name*/, uint64_t /*value*/>& variableMap)
1657 __FE_COUT__ <<
"Running Macro '" << macro.macroName_ <<
"' of "
1658 << macro.operations_.size() <<
" operations." << __E__;
1660 for(
auto& op : macro.operations_)
1662 if(op.first == macroStruct_t::OP_TYPE_READ)
1664 __FE_COUT__ <<
"Doing read op..." << __E__;
1666 if(readOp.addressIsVar_)
1668 __FE_COUTV__(readOp.addressVarName_);
1669 readOp.address_ = variableMap.at(readOp.addressVarName_);
1672 uint64_t dataValue = 0;
1674 __FE_COUT__ << std::hex <<
"Read address: \t 0x" << readOp.address_ << __E__
1679 __FE_COUT__ << std::hex <<
"Read data: \t 0x" << dataValue << __E__
1682 if(readOp.dataIsVar_)
1684 __FE_COUTV__(readOp.dataVarName_);
1685 variableMap.at(readOp.dataVarName_) = dataValue;
1689 else if(op.first == macroStruct_t::OP_TYPE_WRITE)
1691 __FE_COUT__ <<
"Doing write op..." << __E__;
1693 if(writeOp.addressIsVar_)
1695 __FE_COUTV__(writeOp.addressVarName_);
1696 writeOp.address_ = variableMap.at(writeOp.addressVarName_);
1698 if(writeOp.dataIsVar_)
1700 __FE_COUTV__(writeOp.dataVarName_);
1701 writeOp.data_ = variableMap.at(writeOp.dataVarName_);
1704 __FE_COUT__ << std::hex <<
"Write address: \t 0x" << writeOp.address_ << __E__
1706 __FE_COUT__ << std::hex <<
"Write data: \t 0x" << writeOp.data_ << __E__
1709 universalWrite((
char*)&writeOp.address_, (
char*)&writeOp.data_);
1712 else if(op.first == macroStruct_t::OP_TYPE_DELAY)
1714 __FE_COUT__ <<
"Doing delay op..." << __E__;
1717 if(delayOp.delayIsVar_)
1719 __FE_COUTV__(delayOp.delayVarName_);
1720 delayOp.
delay_ = variableMap.at(delayOp.delayVarName_);
1723 __FE_COUT__ << std::dec <<
"Delay ms: \t " << delayOp.
delay_ << __E__;
1725 usleep(delayOp.
delay_ * 1000);
1730 __FE_SS__ <<
"Invalid command type '" << op.first <<
"!'" << __E__;
1741 std::lock_guard<std::mutex> lock(feMacroPercentDoneMutex_);
1742 feMacroPercentDoneMap_[std::this_thread::get_id()] =
1743 static_cast<int>(percentDone > 100 ? 100 : percentDone);
1747 int FEVInterface::getFEMacroPercentDone(std::thread::id threadID)
const
1749 std::lock_guard<std::mutex> lock(feMacroPercentDoneMutex_);
1750 auto it = feMacroPercentDoneMap_.find(threadID);
1751 if(it == feMacroPercentDoneMap_.end())
1757 void FEVInterface::clearFEMacroPercentDone(std::thread::id threadID)
1759 std::lock_guard<std::mutex> lock(feMacroPercentDoneMutex_);
1760 feMacroPercentDoneMap_.erase(threadID);
bool isDisconnected(void) const
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
navigating between nodes
const std::string & getTableName(void) const
getTableName
std::map< std::string, ConfigurationTree > getChildrenMap(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool onlyStatusTrue=false) const
void getValue(T &value) const
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool byPriority=false, bool onlyStatusTrue=false) const
void handleSample(const std::string &universalReadValue, std::string &txBuffer, FILE *fpAggregate=0, bool aggregateIsBinaryFormat=false, bool txBufferUsed=true)
static std::string underscoreString(const std::string &str)
void runMacro(FEVInterface::macroStruct_t ¯o, std::map< std::string, uint64_t > &variableMap)
runMacro
virtual void resetSlowControlsChannelIterator(void)
virtual in case channels are handled in multiple maps, for example
void(ots::FEVInterface::*)(const frontEndMacroStruct_t &feMacroStruct, FEVInterface::frontEndMacroConstArgs_t argsIn, FEVInterface::frontEndMacroArgs_t argsOut) frontEndMacroFunction_t
void function (vector-of-inputs, vector-of-outputs)
virtual void configureSlowControls(void)
end State Machine handlers
static void sendAsyncExceptionToGateway(FEVInterface *fe, const std::string &errMsg, bool isPauseException, bool isStopException)
void runSequenceOfCommands(const std::string &treeLinkName)
std::map< std::string, frontEndMacroStruct_t > mapOfFEMacroFunctions_
Map of FE Macro functions members.
static const std::string & getFEMacroConstArgument(frontEndMacroConstArgs_t args, const std::string &argName)
< for specialized access to FE Macro in/out arguments
void addSlowControlsChannels(ConfigurationTree slowControlsGroupLink, std::map< std::string, FESlowControlsChannel > *mapOfSlowControlsChannels)
static const std::string DEFAULT
end Slow Controls
std::string mfSubject_
for GEN_COUT decorations which would be safe in destructors, e.g. mirror interfaceUID_
virtual FESlowControlsChannel * getNextSlowControlsChannel(void)
virtual in case channels are handled in multiple maps, for example
void runFrontEndMacro(const std::string &targetInterfaceID, const std::string &feMacroName, const std::vector< FEVInterface::frontEndMacroArg_t > &inputArgs, std::vector< FEVInterface::frontEndMacroArg_t > &outputArgs) const
virtual void universalRead(char *address, char *returnValue)=0
throw std::runtime_error exception on error/timeout
void runSelfFrontEndMacro(const std::string &feMacroName, const std::vector< FEVInterface::frontEndMacroArg_t > &inputArgs, std::vector< FEVInterface::frontEndMacroArg_t > &outputArgs)
void setFEMacroPercentDone(unsigned int percentDone)
FE Macro progress reporting (for async macros via FESupervisor)
static std::string & getFEMacroArgument(frontEndMacroArgs_t args, const std::string &argName)
virtual bool running(void)
bool slowControlsRunning(void)
slow controls workloop calls this
virtual unsigned int getSlowControlsChannelCount(void)
virtual in case channels are handled in multiple maps, for example
void receiveFromFrontEnd(const std::string &requester, T &retValue, unsigned int timeoutInSeconds=1) const
bool workLoopThread(toolbox::task::WorkLoop *workLoop)
end FE Communication helpers //////
void registerFEMacroFunction(const std::string &feMacroName, frontEndMacroFunction_t feMacroFunction, const std::vector< std::string > &namesOfInputArgs, const std::vector< std::string > &namesOfOutputArgs, uint8_t requiredUserPermissions=1, const std::string &allowedCallingFEs="*", const std::string &feMacroTooltip="")
std::map< std::string, FESlowControlsChannel > mapOfSlowControlsChannels_
Slow Controls members.
std::mutex frontEndCommunicationReceiveMutex_
FE communication helpers.
CoreSupervisorBase * parentSupervisor_
defines used also by OtsConfigurationWizardSupervisor
< members fully define a front-end macro function
const frontEndMacroFunction_t macroFunction_
Note: must be called using this instance.
uint64_t delay_
milliseconds
macroStruct_t(const std::string ¯oString)
macroStruct_t constructor
bool lsbf_
least significant byte first
static void getVectorFromString(const std::string &inputString, std::vector< std::string > &listToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'}, std::vector< char > *listOfDelimiters=0, bool decodeURIComponents=false)
static std::string vectorToString(const std::vector< T > &setToReturn, const std::string &delimeter=", ")
vectorToString ~
static T & getWildCardMatchFromMap(const std::string &needle, std::map< std::string, T > &haystack, std::string *foundKey=0)
defined in included .icc source
static void getMapFromString(const std::string &inputString, std::map< S, T > &mapToReturn, const std::set< char > &pairPairDelimiter={',', '|', '&'}, const std::set< char > &nameValueDelimiter={'=', ':'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
getMapFromString ~
static bool getNumber(const std::string &s, T &retValue)