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"
23 const std::function<void(
unsigned int)>& callback;
27 const std::function<
void(
unsigned int)>& callback_)
28 : source(source_), callback(callback_), previous(active)
37 const std::string FEVInterface::UNKNOWN_TYPE =
"UNKNOWN";
39 TableViewColumnInfo::DATATYPE_STRING_ALT_DEFAULT;
42 FEVInterface::FEVInterface(
const std::string& interfaceUID,
44 const std::string& configurationPath)
46 ,
Configurable(theXDAQContextConfigTree, configurationPath)
48 , slowControlsWorkLoop_(interfaceUID +
"-SlowControls", this)
49 , interfaceUID_(interfaceUID)
51 , mfSubject_(interfaceUID)
57 VStateMachine::parentSupervisor_ =
nullptr;
61 interfaceType_ = theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
62 .getNode(
"FEInterfacePluginName")
63 .getValue<std::string>();
68 <<
"FEInterface type could not be determined in base class from "
69 "configuration tree path; "
70 "the type may be defined subsequently by the inheriting class (e.g. to "
71 "take advantage of Slow Controls caching functionality, "
72 "the FEInterface type should be defined for all frontend interfaces)"
78 registerFEMacroFunction(
79 "Slow Controls Pause/Resume",
81 &FEVInterface::PauseResumeSlowControls),
82 std::vector<std::string>{
"Pause Slow Controls (Default = false)"},
83 std::vector<std::string>{
"Result"},
86 "This FE Macro is used to Pause or Resume the Slow Controls workloop, which "
87 "could be valuable while debugging front-ends.");
90 __GEN_COUT__ <<
"Constructed." << __E__;
97 VStateMachine::parentSupervisor_ = supervisor;
98 parentInterfaceManager_ = manager;
102 FEVInterface::~FEVInterface(
void)
107 __GEN_COUT__ <<
"Destructed." << __E__;
111 void FEVInterface::PauseResumeSlowControls(__ARGS__)
113 slowControlsWorkLoopShouldRun_ =
114 !__GET_ARG_IN__(
"Pause Slow Controls (Default = false)",
bool,
false);
115 __FE_COUTV__(slowControlsWorkLoopShouldRun_);
117 std::stringstream outss;
118 outss <<
"Slow Controls workloop is "
119 << (slowControlsWorkLoopShouldRun_ ?
"active." :
"paused.");
121 __SET_ARG_OUT__(
"Result", outss.str());
125 void FEVInterface::configureSlowControls(
void)
129 __COUT__ <<
"configureSlowControls path=" << theConfigurationPath_ << __E__;
132 if(metricMan && !metricMan->Running() && metricMan->Initialized())
134 __COUT__ <<
"Metric manager starting..." << __E__;
135 metricMan->do_start();
136 __COUT__ <<
"Metric manager started." << __E__;
138 else if(!metricMan || !metricMan->Initialized())
139 __COUT__ <<
"Metric manager could not be started! metricMan: " << metricMan
140 <<
" Initialized()= " << (metricMan ? metricMan->Initialized() : 0)
143 __COUT__ <<
"Metric manager already started." << __E__;
145 mapOfSlowControlsChannels_.clear();
152 std::string errMessage;
156 theXDAQContextConfigTree_.
getNode(theConfigurationPath_)
157 .
getNode(
"LinkToSlowControlsChannelTable");
166 addSlowControlsChannels(
167 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
168 .getNode(
"LinkToSlowControlsChannelTable"),
169 &mapOfSlowControlsChannels_);
174 addSlowControlsChannels(
175 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
176 .getNode(
"LinkToSlowControlsChannelTable"),
177 &mapOfSlowControlsChannels_);
179 catch(
const std::runtime_error& e)
181 __SS__ <<
"Configuring slow controls channels encountered an error: "
188 catch(
const std::runtime_error& e)
190 __SS__ <<
"Error was caught while configuring slow controls: " << e.what() << __E__;
195 __SS__ <<
"Unknown error was caught while configuring slow controls." << __E__;
200 catch(
const std::exception& e)
202 ss <<
"Exception message: " << e.what();
214 void FEVInterface::addSlowControlsChannels(
216 std::map<std::string /* ROC UID*/, FESlowControlsChannel>* mapOfSlowControlsChannels)
221 <<
"slowControlsGroupLink is disconnected, so done configuring slow controls."
225 __FE_COUT__ <<
"slowControlsGroupLink is valid! Adding slow controls channels..."
228 std::vector<std::pair<std::string, ConfigurationTree> > groupLinkChildren =
230 for(
auto& groupLinkChild : groupLinkChildren)
233 if(!(groupLinkChild.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
237 __FE_COUT__ <<
"Channel:" << slowControlsGroupLink.
getTableName() <<
"/"
238 << getInterfaceUID() <<
"/" << groupLinkChild.first
239 <<
"\t Type:" << groupLinkChild.second.getNode(
"ChannelDataType")
243 std::string transformation =
"";
247 groupLinkChild.second.getNode(
"Transformation").getValue<std::string>();
251 __FE_COUT__ <<
"Slow controls 'Transformation' setting not found." << __E__;
254 mapOfSlowControlsChannels->insert(std::pair<std::string, FESlowControlsChannel>(
255 groupLinkChild.first,
258 groupLinkChild.first,
259 groupLinkChild.second.getNode(
"ChannelDataType").getValue<std::string>(),
260 groupLinkChild.second.getNode(
"UniversalInterfaceAddress")
261 .getValue<std::string>(),
262 groupLinkChild.second.getNode(
"Transformation").getValue<std::string>(),
263 groupLinkChild.second.getNode(
"UniversalDataBitOffset")
264 .getValue<
unsigned int>(),
265 groupLinkChild.second.getNode(
"ReadAccess").getValue<
bool>(),
266 groupLinkChild.second.getNode(
"WriteAccess").getValue<
bool>(),
267 groupLinkChild.second.getNode(
"MonitoringEnabled").getValue<
bool>(),
268 groupLinkChild.second.getNode(
"RecordChangesOnly").getValue<
bool>(),
269 groupLinkChild.second.getNode(
"DelayBetweenSamplesInSeconds")
271 groupLinkChild.second.getNode(
"LocalSavingEnabled").getValue<
bool>(),
272 groupLinkChild.second.getNode(
"LocalFilePath").getValue<std::string>(),
273 groupLinkChild.second.getNode(
"RadixFileName").getValue<std::string>(),
274 groupLinkChild.second.getNode(
"SaveBinaryFile").getValue<
bool>(),
275 groupLinkChild.second.getNode(
"AlarmsEnabled").getValue<
bool>(),
276 groupLinkChild.second.getNode(
"LatchAlarms").getValue<
bool>(),
277 groupLinkChild.second.getNode(
"LowLowThreshold").getValue<std::string>(),
278 groupLinkChild.second.getNode(
"LowThreshold").getValue<std::string>(),
279 groupLinkChild.second.getNode(
"HighThreshold").getValue<std::string>(),
280 groupLinkChild.second.getNode(
"HighHighThreshold")
281 .getValue<std::string>())));
283 __FE_COUT__ <<
"Added " << mapOfSlowControlsChannels->size()
284 <<
" slow controls channels." << __E__;
290 void FEVInterface::resetSlowControlsChannelIterator(
void)
292 slowControlsChannelsIterator_ = mapOfSlowControlsChannels_.begin();
299 if(slowControlsChannelsIterator_ == mapOfSlowControlsChannels_.end())
303 (slowControlsChannelsIterator_++)->second);
308 unsigned int FEVInterface::getSlowControlsChannelCount(
void)
310 return mapOfSlowControlsChannels_.size();
314 bool FEVInterface::slowControlsRunning(
void)
317 __FE_COUT__ <<
"slowControlsRunning" << __E__;
319 if(getSlowControlsChannelCount() == 0)
322 <<
"No slow controls channels to monitor, exiting slow controls workloop."
329 const unsigned int txBufferSz = 1500;
330 const unsigned int txBufferFullThreshold = 750;
331 std::string txBuffer;
332 txBuffer.reserve(txBufferSz);
335 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_);
338 std::unique_ptr<UDPDataStreamerBase> slowContrlolsTxSocket;
339 std::string slowControlsSupervisorIPAddress =
"", slowControlsSelfIPAddress =
"";
340 int slowControlsSupervisorPort = 0, slowControlsSelfPort = 0;
344 FEInterfaceNode.
getNode(
"LinkToSlowControlsSupervisorTable");
348 __FE_SS__ <<
"slowControlsInterfaceLink is disconnected, so no socket made."
353 slowControlsSelfIPAddress =
354 FEInterfaceNode.
getNode(
"SlowControlsTxSocketIPAddress")
356 slowControlsSelfPort =
358 slowControlsSupervisorIPAddress =
359 slowControlsInterfaceLink.
getNode(
"IPAddress").
getValue<std::string>();
360 slowControlsSupervisorPort =
365 __FE_COUT__ <<
"Link to slow controls supervisor is missing, so no socket made."
369 bool txBufferUsed =
false;
370 if(slowControlsSupervisorPort && slowControlsSelfPort &&
371 slowControlsSupervisorIPAddress !=
"" && slowControlsSelfIPAddress !=
"")
373 __FE_COUT__ <<
"slowControlsInterfaceLink is valid! Create tx socket..." << __E__;
374 slowContrlolsTxSocket.reset(
376 slowControlsSelfPort,
377 slowControlsSupervisorIPAddress,
378 slowControlsSupervisorPort));
383 __FE_COUT__ <<
"Invalid Slow Controls socket parameters, so no socket made."
390 bool aggregateFileIsBinaryFormat =
false;
393 if(FEInterfaceNode.
getNode(
"SlowControlsLocalAggregateSavingEnabled")
396 aggregateFileIsBinaryFormat =
397 FEInterfaceNode.
getNode(
"SlowControlsSaveBinaryFile").
getValue<
bool>();
399 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned On BinaryFormat="
400 << aggregateFileIsBinaryFormat << __E__;
402 std::string saveFullFileName =
403 FEInterfaceNode.
getNode(
"SlowControlsLocalFilePath")
406 FEInterfaceNode.
getNode(
"SlowControlsRadixFileName")
408 "-" + FESlowControlsChannel::underscoreString(getInterfaceUID()) +
"-" +
409 std::to_string(time(0)) + (aggregateFileIsBinaryFormat ?
".dat" :
".txt");
412 fopen(saveFullFileName.c_str(), aggregateFileIsBinaryFormat ?
"ab" :
"a");
416 <<
"Failed to open slow controls channel file: " << saveFullFileName
422 <<
"Slow controls aggregate file opened: " << saveFullFileName
430 if(!aggregateFileIsBinaryFormat)
431 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned off." << __E__;
433 time_t timeCounter = 0;
435 unsigned int numOfReadAccessChannels = 0;
436 bool firstTime =
true;
437 while(slowControlsWorkLoop_.getContinueWorkLoop())
443 if(!slowControlsWorkLoopShouldRun_)
446 <<
"Skipping slow controls loop... slowControlsWorkLoopShouldRun_ = "
447 << slowControlsWorkLoopShouldRun_ << __E__;
450 __COUTT__ <<
"Starting slow controls loop... slowControlsWorkLoopShouldRun_ = "
451 << slowControlsWorkLoopShouldRun_ << __E__;
454 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
461 resetSlowControlsChannelIterator();
462 while((channel = getNextSlowControlsChannel()) !=
nullptr)
465 if(!channel->readAccess_)
469 ++numOfReadAccessChannels;
472 if(timeCounter % channel->delayBetweenSamples_)
475 __FE_COUT__ <<
"Reading Channel:" << channel->fullChannelName
476 <<
" at t=" << time(0) << __E__;
479 bool usingBufferedValue =
false;
480 if(channel->getInterfaceType() != FEVInterface::UNKNOWN_TYPE)
482 resetSlowControlsChannelIterator();
484 while((channelToCopy = getNextSlowControlsChannel()) != channel &&
485 channelToCopy !=
nullptr)
487 __FE_COUTT__ <<
"Looking for buffered value at "
488 << BinaryStringMacros::binaryNumberToHexString(
489 channelToCopy->getUniversalAddress(),
"0x",
" ")
490 <<
" " << channelToCopy->getReadSizeBytes() <<
" "
491 << time(0) - channelToCopy->getLastSampleTime() << __E__;
493 __FE_COUTTV__(channel->getInterfaceUID());
494 __FE_COUTTV__(channelToCopy->getInterfaceUID());
495 __FE_COUTTV__(channel->getInterfaceType());
496 __FE_COUTTV__(channelToCopy->getInterfaceType());
498 if(!usingBufferedValue &&
499 channelToCopy->getInterfaceUID() == channel->getInterfaceUID() &&
500 channelToCopy->getInterfaceType() == channel->getInterfaceType() &&
501 BinaryStringMacros::binaryNumberToHexString(
502 channelToCopy->getUniversalAddress(),
"0x",
" ") ==
503 BinaryStringMacros::binaryNumberToHexString(
504 channel->getUniversalAddress(),
"0x",
" ") &&
505 channelToCopy->getReadSizeBytes() == channel->getReadSizeBytes() &&
506 time(0) - channelToCopy->getLastSampleTime() <
509 usingBufferedValue =
true;
511 <<
"Using buffered " << channelToCopy->getReadSizeBytes()
512 <<
"-byte value at address:"
513 << BinaryStringMacros::binaryNumberToHexString(
514 channelToCopy->getUniversalAddress(),
"0x",
" ")
519 << BinaryStringMacros::binaryNumberToHexString(
520 channelToCopy->getLastSampleReadValue(),
"0x",
" ")
521 <<
" at t=" << time(0) << __E__;
522 channel->
handleSample(channelToCopy->getLastSampleReadValue(),
525 aggregateFileIsBinaryFormat,
527 __FE_COUT__ <<
"Copied: "
528 << BinaryStringMacros::binaryNumberToHexString(
529 channel->getSample(),
"0x",
" ")
530 <<
" at t=" << time(0) << __E__;
538 if(!usingBufferedValue)
540 std::string readValInst;
541 std::string& readVal = readValInst;
542 readVal.resize(universalDataSize_);
545 channel->doRead(readVal);
547 catch(
const std::exception& e)
549 __FE_COUT_WARN__ <<
"DCS slow controls read failed for channel '"
550 << channel->fullChannelName <<
"': " << e.what()
551 <<
" -- skipping this sample." << __E__;
556 __FE_COUT_WARN__ <<
"DCS slow controls read failed for channel '"
557 << channel->fullChannelName
558 <<
"' with an unknown error -- skipping this sample."
563 readVal, txBuffer, fp, aggregateFileIsBinaryFormat, txBufferUsed);
564 __FE_COUT__ <<
"Have: "
565 << BinaryStringMacros::binaryNumberToHexString(
566 channel->getSample(),
"0x",
" ")
567 <<
" at t=" << time(0) << __E__;
571 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
574 if(channel->monitoringEnabled && metricMan && metricMan->Running() &&
575 universalAddressSize_ <= 8)
578 for(
size_t ii = 0; ii < channel->getSample().size(); ++ii)
579 val += (uint8_t)channel->getSample()[ii] << (ii * 8);
582 if((channel->transformation).size() >
585 __FE_COUT__ <<
"Transformation formula = " << channel->transformation
588 TFormula transformationFormula(
"transformationFormula",
589 (channel->transformation).c_str());
590 double transformedVal = transformationFormula.Eval(val);
592 if(!std::isnan(transformedVal))
594 __FE_COUT__ <<
"Transformed " << val <<
" into " << transformedVal
596 __FE_COUT__ <<
"Sending \"" << channel->fullChannelName
597 <<
"\" transformed sample to Metric Manager..."
599 metricMan->sendMetric(channel->fullChannelName,
603 artdaq::MetricMode::LastPoint);
607 __FE_SS__ <<
"Transformed value is NaN!" << __E__;
613 __FE_COUT__ <<
"Sending \"" << channel->fullChannelName
614 <<
"\" sample to Metric Manager..." << __E__;
615 metricMan->sendMetric(channel->fullChannelName,
619 artdaq::MetricMode::LastPoint);
624 __FE_COUT__ <<
"Skipping \"" << channel->fullChannelName
625 <<
"\" sample to Metric Manager... "
626 <<
" channel->monitoringEnabled="
627 << channel->monitoringEnabled <<
" metricMan=" << metricMan
628 <<
" metricMan->Running()="
629 << (metricMan && metricMan->Running()) << __E__;
633 if(txBuffer.size() > txBufferSz)
635 __FE_SS__ <<
"This should never happen hopefully!" << __E__;
639 if(!slowContrlolsTxSocket && txBufferUsed)
643 if(slowContrlolsTxSocket && txBuffer.size() > txBufferFullThreshold)
645 __FE_COUT__ <<
"Sending now! txBufferFullThreshold="
646 << txBufferFullThreshold << __E__;
647 slowContrlolsTxSocket->send(txBuffer);
653 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
656 if(slowContrlolsTxSocket && txBuffer.size())
658 __FE_COUT__ <<
"Sending now!" << __E__;
659 slowContrlolsTxSocket->send(txBuffer);
667 if(numOfReadAccessChannels == 0)
670 <<
"There are no slow controls channels with read access!" << __E__;
674 __FE_COUT__ <<
"There are " << getSlowControlsChannelCount()
675 <<
" slow controls channels total. "
676 << numOfReadAccessChannels <<
" with read access enabled."
685 __FE_COUT__ <<
"Slow controls workloop done." << __E__;
694 bool isPauseException =
false;
695 bool isStopException =
false;
703 ss <<
"PAUSE Exception was caught during slow controls running thread: "
704 << e.what() << std::endl;
705 isPauseException =
true;
709 ss <<
"STOP Exception was caught during slow controls running thread: "
710 << e.what() << std::endl;
711 isStopException =
true;
713 catch(
const std::runtime_error& e)
715 ss <<
"Caught an error during slow controls running thread of FE Interface '"
716 << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
720 ss <<
"Caught an unknown error during slow controls running thread." << __E__;
725 catch(
const std::exception& e)
727 ss <<
"Exception message: " << e.what();
739 __FE_COUT_ERR__ << ss.str();
743 const std::string errorMessage,
744 bool isPauseException,
745 bool isStopException) {
746 FEVInterface::sendAsyncExceptionToGateway(
747 fe, errorMessage, isPauseException, isStopException);
768 const std::string& errorMessage,
769 bool isPauseException,
770 bool isStopException)
773 std::stringstream feHeader;
774 feHeader <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID() <<
":"
775 << fe->theConfigurationRecordName_ <<
"\t";
779 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async STOP Running Exception... \n"
780 << errorMessage << __E__;
781 fe->VStateMachine::parentSupervisor_->setAsyncPauseExceptionMessage(errorMessage);
783 else if(isPauseException)
785 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async PAUSE Running Exception... \n"
786 << errorMessage << __E__;
787 fe->VStateMachine::parentSupervisor_->setAsyncStopExceptionMessage(errorMessage);
790 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async Running Error... \n"
791 << errorMessage << __E__;
793 XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
794 fe->VStateMachine::parentSupervisor_->allSupervisorInfo_.getGatewayInfo()
798 parameters.addParameter(
"ErrorMessage", errorMessage);
800 xoap::MessageReference replyMessage =
801 fe->VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
803 isPauseException ?
"AsyncPauseException" :
"AsyncError",
806 std::stringstream replyMessageSStream;
807 replyMessageSStream << SOAPUtilities::translate(replyMessage);
808 __COUT__ << feHeader.str() <<
"Received... " << replyMessageSStream.str()
811 if(replyMessageSStream.str().find(
"Fault") != std::string::npos)
813 __COUT_ERR__ << feHeader.str() <<
"Failure to indicate fault to Gateway..."
818 catch(
const xdaq::exception::Exception& e)
821 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running SOFT "
822 "error back to Gateway: "
823 << e.what() << __E__;
825 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running "
826 "error back to Gateway: "
827 << e.what() << __E__;
833 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
834 "SOFT error back to Gateway."
837 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
838 "error back to Gateway."
846 bool FEVInterface::workLoopThread(toolbox::task::WorkLoop* )
858 bool isPauseException =
false;
859 bool isStopException =
false;
867 ss <<
"SOFT Exception was caught while running: " << e.what() << std::endl;
868 isPauseException =
true;
872 ss <<
"STOP Exception was caught while running: " << e.what() << std::endl;
873 isStopException =
true;
875 catch(
const std::runtime_error& e)
877 ss <<
"Caught an error during running at FE Interface '"
878 << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
882 ss <<
"Caught an unknown error during running." << __E__;
887 catch(
const std::exception& e)
889 ss <<
"Exception message: " << e.what();
901 __FE_COUT_ERR__ << ss.str();
905 const std::string errorMessage,
906 bool isPauseException,
907 bool isStopException) {
908 FEVInterface::sendAsyncExceptionToGateway(
909 fe, errorMessage, isPauseException, isStopException);
921 return continueWorkLoop_;
932 void FEVInterface::registerFEMacroFunction(
933 const std::string& feMacroName,
935 const std::vector<std::string>& namesOfInputArgs,
936 const std::vector<std::string>& namesOfOutputArgs,
937 uint8_t requiredUserPermissions,
938 const std::string& allowedCallingFEs,
939 const std::string& feMacroTooltip)
941 registerFEMacroFunction(feMacroName,
945 std::to_string(requiredUserPermissions),
949 void FEVInterface::registerFEMacroFunction(
950 const std::string& feMacroName,
951 frontEndMacroFunction_t feMacroFunction,
952 const std::vector<std::string>& namesOfInputArgs,
953 const std::vector<std::string>& namesOfOutputArgs,
954 const std::string& requiredUserPermissions,
955 const std::string& allowedCallingFEs,
956 const std::string& feMacroTooltip)
958 if(mapOfFEMacroFunctions_.find(feMacroName) != mapOfFEMacroFunctions_.end())
960 __FE_SS__ <<
"feMacroName '" << feMacroName <<
"' already exists! Not allowed."
962 __FE_COUT_ERR__ <<
"\n" << ss.str();
966 __FE_COUTT__ <<
"Registering FE Macro Function: '" << feMacroName
967 <<
"' with requiredUserPermissions=" << requiredUserPermissions
968 <<
" allowedCallingFEs=" << allowedCallingFEs << __E__;
970 mapOfFEMacroFunctions_.insert(std::pair<std::string, frontEndMacroStruct_t>(
972 frontEndMacroStruct_t(feMacroName,
976 requiredUserPermissions,
988 const std::string& FEVInterface::getFEMacroConstArgument(frontEndMacroConstArgs_t& args,
989 const std::string& argName)
991 for(
const frontEndMacroArg_t& pair : args)
994 if(pair.first.substr(0, pair.first.find(
'(')) ==
995 argName.substr(0, argName.find(
'(')))
997 __COUT__ << argName <<
": " << pair.second << __E__;
1001 __SS__ <<
"Requested input argument '" << argName
1002 <<
"' not found in list of arguments." << __E__;
1003 ss <<
"\nHere is the list of arguments: \n";
1004 for(
const frontEndMacroArg_t& pair : args)
1005 ss <<
"\t - " << pair.first <<
"\n";
1013 std::string ots::getFEMacroConstArgumentValue<std::string>(
1014 FEVInterface::frontEndMacroConstArgs_t& args,
1015 const std::string& argName,
1016 const std::string& defaultValue)
1018 const std::string& data = FEVInterface::getFEMacroConstArgument(args, argName);
1021 if(data ==
"Default" || data ==
"DEFAULT")
1022 return defaultValue;
1030 std::string ots::getFEMacroArgumentValue<std::string>(
1031 FEVInterface::frontEndMacroArgs_t& args,
const std::string& argName)
1033 return FEVInterface::getFEMacroArgument(args, argName);
1041 std::string& FEVInterface::getFEMacroArgument(frontEndMacroArgs_t& args,
1042 const std::string& argName)
1044 for(std::pair<
const std::string ,
1045 std::string >& pair : args)
1047 if(pair.first == argName)
1050 __SS__ <<
"Requested argument not found with name '" << argName <<
"'" << __E__;
1059 void FEVInterface::runSequenceOfCommands(
const std::string& treeLinkName)
1061 std::map<uint64_t, uint64_t> writeHistory;
1062 uint64_t writeAddress, writeValue, bitMask;
1063 uint8_t bitPosition;
1065 std::string writeBuffer;
1066 std::string readBuffer;
1068 bool ignoreError =
true;
1074 theXDAQContextConfigTree_.
getNode(theConfigurationPath_)
1081 __FE_COUT__ <<
"Disconnected configure sequence" << __E__;
1084 __FE_COUT__ <<
"Handling configure sequence." << __E__;
1086 for(
const auto& child : childrenMap)
1091 child.second.getNode(
"WriteAddress").getValue<uint64_t>();
1092 writeValue = child.second.getNode(
"WriteValue").getValue<uint64_t>();
1094 child.second.getNode(
"StartingBitPosition").getValue<uint8_t>();
1096 (1 << child.second.getNode(
"BitFieldSize").getValue<uint8_t>()) -
1099 writeValue &= bitMask;
1100 writeValue <<= bitPosition;
1101 bitMask = ~(bitMask << bitPosition);
1104 if(writeHistory.find(writeAddress) == writeHistory.end())
1105 writeHistory[writeAddress] = 0;
1107 writeHistory[writeAddress] &= bitMask;
1108 writeHistory[writeAddress] |= writeValue;
1111 "\t Writing %s: \t %ld(0x%lX) \t %ld(0x%lX)",
1112 child.first.c_str(),
1115 writeHistory[writeAddress],
1116 writeHistory[writeAddress]);
1118 __FE_COUT__ << msg << __E__;
1120 universalWrite((
char*)&writeAddress,
1121 (
char*)&(writeHistory[writeAddress]));
1127 ignoreError =
false;
1137 <<
"Unable to access sequence of commands through configuration tree. "
1138 <<
"Assuming no sequence. " << __E__;
1150 void FEVInterface::runSelfFrontEndMacro(
1151 const std::string& name,
1152 const std::vector<frontEndMacroArg_t>& inputs,
1153 std::vector<frontEndMacroArg_t>& outputs,
1154 const std::function<
void(
unsigned int)>& onProgress)
1156 FEMacroProgressForwarder scope(
this, onProgress);
1157 const auto threadID = std::this_thread::get_id();
1158 clearFEMacroPercentDone(threadID);
1161 setFEMacroPercentDone(0);
1162 runSelfFrontEndMacro(name, inputs, outputs);
1163 setFEMacroPercentDone(100);
1167 clearFEMacroPercentDone(threadID);
1170 clearFEMacroPercentDone(threadID);
1173 void FEVInterface::runSelfFrontEndMacro(
1174 const std::string& feMacroName,
1177 const std::vector<FEVInterface::frontEndMacroArg_t>& argsIn,
1178 std::vector<FEVInterface::frontEndMacroArg_t>& argsOut)
1181 auto FEMacroIt = this->getMapOfFEMacroFunctions().find(feMacroName);
1182 if(FEMacroIt == this->getMapOfFEMacroFunctions().end())
1184 __CFG_SS__ <<
"FE Macro '" << feMacroName <<
"' of interfaceID '"
1185 << getInterfaceUID() <<
"' was not found!" << __E__;
1186 __CFG_COUT_ERR__ <<
"\n" << ss.str();
1192 for(
unsigned int i = 0;
1193 i < argsIn.size() && i < feMacro.namesOfInputArguments_.size();
1195 if(argsIn[i].first != feMacro.namesOfInputArguments_[i])
1197 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
1198 << getInterfaceUID() <<
"' was attempted with a mismatch in"
1199 <<
" a name of an input argument. " << argsIn[i].first
1200 <<
" was given. " << feMacro.namesOfInputArguments_[i]
1201 <<
" expected." << __E__;
1202 __CFG_COUT_ERR__ <<
"\n" << ss.str();
1207 if(feMacro.namesOfInputArguments_.size() != argsIn.size())
1209 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
1210 << getInterfaceUID() <<
"' was attempted with a mismatch in"
1211 <<
" number of input arguments. " << argsIn.size() <<
" were given. "
1212 << feMacro.namesOfInputArguments_.size() <<
" expected." << __E__;
1213 __CFG_COUT_ERR__ <<
"\n" << ss.str();
1217 __CFG_COUT__ <<
"# of input args = " << argsIn.size() << __E__;
1218 for(
auto& argIn : argsIn)
1219 __CFG_COUT__ << argIn.first <<
": " << argIn.second << __E__;
1221 __CFG_COUT__ <<
"Launching FE Macro '" << feMacro.feMacroName_ <<
"' ..." << __E__;
1224 for(
unsigned int i = 0; i < feMacro.namesOfOutputArguments_.size(); ++i)
1225 argsOut.push_back(FEVInterface::frontEndMacroArg_t(
1226 feMacro.namesOfOutputArguments_[i],
"DEFAULT"));
1231 __CFG_COUT__ <<
"FE Macro complete!" << __E__;
1233 __CFG_COUT__ <<
"# of output args = " << argsOut.size() << __E__;
1234 for(
const auto& arg : argsOut)
1235 __CFG_COUT__ << arg.first <<
": " << arg.second << __E__;
1243 void FEVInterface::runFrontEndMacro(
1244 const std::string& targetInterfaceID,
1245 const std::string& feMacroName,
1246 const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs,
1247 std::vector<FEVInterface::frontEndMacroArg_t>& outputArgs)
const
1249 __FE_COUTV__(targetInterfaceID);
1250 __FE_COUTV__(VStateMachine::parentSupervisor_);
1251 __FE_COUTV__(VStateMachine::parentSupervisor_->getSupervisorUID());
1253 auto MacroMakerSupervisors = VStateMachine::parentSupervisor_->allSupervisorInfo_
1254 .getAllMacroMakerTypeSupervisorInfo();
1255 __FE_COUTV__(MacroMakerSupervisors.size());
1257 if(!MacroMakerSupervisors.size())
1259 __FE_SS__ <<
"No MacroMakerSupervisors found! Notify admins." << __E__;
1263 std::vector<FEVInterface::frontEndMacroArg_t> encodedInputArgs;
1264 for(
auto& arg : inputArgs)
1266 __FE_COUT__ << arg.first <<
": " << arg.second << __E__;
1267 encodedInputArgs.push_back(
1268 std::make_pair(StringMacros::encodeURIComponent(arg.first),
1269 StringMacros::encodeURIComponent(arg.second)));
1272 std::string inputArgsStr = StringMacros::vectorToString(
1273 encodedInputArgs,
";" ,
"," );
1275 __FE_COUTV__(inputArgsStr);
1277 xoap::MessageReference message =
1278 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
1281 parameters.addParameter(
"type",
"feMacro");
1282 parameters.addParameter(
"requester", FEVInterface::interfaceUID_);
1283 parameters.addParameter(
"targetInterfaceID", targetInterfaceID);
1284 parameters.addParameter(
"feMacroName", feMacroName);
1285 parameters.addParameter(
"inputArgs", inputArgsStr);
1286 SOAPUtilities::addParameters(message, parameters);
1288 __FE_COUT__ <<
"DIAG ms=" << StringMacros::nowEpochMs()
1289 <<
" Sending FE communication: " << SOAPUtilities::translate(message)
1292 xoap::MessageReference replyMessage =
1293 VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
1294 MacroMakerSupervisors.begin()->second.getDescriptor(), message);
1296 std::string replyCommand = SOAPUtilities::translate(replyMessage).getCommand();
1297 __FE_COUT__ <<
"DIAG ms=" << StringMacros::nowEpochMs()
1298 <<
" Response received: " << replyCommand << __E__;
1300 if(replyCommand ==
"Fault")
1302 std::string faultDetail;
1305 replyMessage->writeTo(faultDetail);
1310 __FE_SS__ <<
"SOAP Fault received from target interface '" << targetInterfaceID
1311 <<
"' requested by '" << FEVInterface::interfaceUID_
1312 <<
"': " << faultDetail << __E__;
1317 rxParameters.addParameter(
"Error");
1318 SOAPUtilities::receive(replyMessage, rxParameters);
1320 std::string error = rxParameters.getValue(
"Error");
1325 __FE_SS__ <<
"Error transmitting request to target interface '"
1326 << targetInterfaceID <<
"' from '" << FEVInterface::interfaceUID_
1327 <<
".' " << error << __E__;
1333 argsOutParameter.addParameter(
"outputArgs");
1334 SOAPUtilities::receive(replyMessage, argsOutParameter);
1336 std::string outputArgsStr = argsOutParameter.getValue(
"outputArgs");
1337 std::set<char> pairDelimiter({
';'}), nameValueDelimiter({
','});
1339 std::map<std::string, std::string> mapToReturn;
1340 StringMacros::getMapFromString(
1348 for(
auto& mapPair : mapToReturn)
1349 outputArgs.push_back(
1350 std::make_pair(StringMacros::decodeURIComponent(mapPair.first),
1351 StringMacros::decodeURIComponent(mapPair.second)));
1360 void FEVInterface::receiveFromFrontEnd(
const std::string& requester,
1361 std::string& retValue,
1362 unsigned int timeoutInSeconds)
const
1364 __FE_COUTV__(requester);
1365 __FE_COUTV__(parentSupervisor_);
1367 std::string data =
"0";
1373 std::lock_guard<std::mutex> lock(
1374 parentInterfaceManager_->frontEndCommunicationReceiveMutex_);
1376 auto receiveBuffersForTargetIt =
1377 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.find(
1378 FEVInterface::interfaceUID_);
1379 if(receiveBuffersForTargetIt !=
1380 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.end())
1382 __FE_COUT__ <<
"Number of source buffers found for front-end '"
1383 << FEVInterface::interfaceUID_
1384 <<
"': " << receiveBuffersForTargetIt->second.size() << __E__;
1386 for(
auto& buffPair : receiveBuffersForTargetIt->second)
1387 __FE_COUTV__(buffPair.first);
1390 std::string sourceBufferId =
"";
1391 std::queue<std::string >& sourceBuffer =
1392 StringMacros::getWildCardMatchFromMap(
1393 requester, receiveBuffersForTargetIt->second, &sourceBufferId);
1395 __FE_COUT__ <<
"Found source buffer '" << sourceBufferId <<
"' with size "
1396 << sourceBuffer.size() << __E__;
1398 if(sourceBuffer.size())
1400 __FE_COUT__ <<
"Found a value in queue of size "
1401 << sourceBuffer.size() << __E__;
1404 retValue = sourceBuffer.front();
1409 __FE_COUT__ <<
"Source buffer empty for '" << requester <<
"'"
1416 if(!timeoutInSeconds)
1418 __FE_SS__ <<
"Timeout (" << timeoutInSeconds
1419 <<
" s) waiting for front-end communication from " << requester
1428 __FE_COUT__ <<
"Waiting for front-end communication from " << requester <<
" for "
1429 << timeoutInSeconds <<
" more seconds..." << __E__;
1443 std::string FEVInterface::receiveFromFrontEnd(
const std::string& requester,
1444 unsigned int timeoutInSeconds)
const
1446 std::string retValue;
1447 FEVInterface::receiveFromFrontEnd(requester, retValue, timeoutInSeconds);
1453 FEVInterface::macroStruct_t::macroStruct_t(
const std::string& macroString)
1455 __COUTVS__(20, macroString);
1461 std::vector<std::string> extractVec;
1462 StringMacros::getVectorFromString(macroString, extractVec, {
'"'});
1464 __COUTVS__(20, StringMacros::vectorToString(extractVec,
" ||| "));
1468 MACRONAME_NAME_INDEX = 1,
1469 MACRONAME_VALUE_INDEX = 3,
1470 SEQUENCE_NAME_INDEX = 5,
1471 SEQUENCE_VALUE_INDEX = 7,
1472 LSBF_NAME_INDEX = 17,
1473 LSFBF_VALUE_INDEX = 19,
1477 if(MACRONAME_NAME_INDEX >= extractVec.size() ||
1478 extractVec[MACRONAME_NAME_INDEX] !=
"name")
1480 __SS__ <<
"Invalid sequence, 'name' expected in position " << MACRONAME_NAME_INDEX
1484 if(SEQUENCE_NAME_INDEX >= extractVec.size() ||
1485 extractVec[SEQUENCE_NAME_INDEX] !=
"sequence")
1487 __SS__ <<
"Invalid sequence, 'sequence' expected in position "
1488 << SEQUENCE_NAME_INDEX << __E__;
1491 if(LSBF_NAME_INDEX >= extractVec.size() || extractVec[LSBF_NAME_INDEX] !=
"LSBF")
1493 __SS__ <<
"Invalid sequence, 'LSBF' expected in position " << LSBF_NAME_INDEX
1497 macroName_ = extractVec[MACRONAME_VALUE_INDEX];
1498 __COUTVS__(20, macroName_);
1499 lsbf_ = extractVec[LSFBF_VALUE_INDEX] ==
"false" ? false :
true;
1500 __COUTVS__(20, lsbf_);
1501 std::string& sequence = extractVec[SEQUENCE_VALUE_INDEX];
1502 __COUTVS__(20, sequence);
1504 std::vector<std::string> sequenceCommands;
1505 StringMacros::getVectorFromString(sequence, sequenceCommands, {
','});
1507 __COUTVS__(20, StringMacros::vectorToString(sequenceCommands,
" ### "));
1509 for(
auto& command : sequenceCommands)
1511 __COUTVS__(20, command);
1516 std::vector<std::string> commandPieces;
1517 StringMacros::getVectorFromString(command, commandPieces, {
':'});
1519 __COUTVS__(20, StringMacros::vectorToString(commandPieces,
" ### "));
1521 __COUTVS__(20, commandPieces.size());
1532 if(commandPieces.size() < 3 || commandPieces.size() > 4 ||
1533 commandPieces[1].size() != 1)
1535 __SS__ <<
"Invalid command type specified in command string: " << command
1542 std::function<bool(
const std::string&
1544 localIsVariable = [](
const std::string& fieldValue) {
1546 std::string mfSubject_ =
"isVar";
1547 __GEN_COUTVS__(20, fieldValue);
1550 for(
const auto& c : fieldValue)
1551 if(!((c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f') ||
1552 (c >=
'A' && c <=
'F')))
1557 if(commandPieces[1][0] ==
'r' && commandPieces.size() == 4)
1559 TLOG_DEBUG(20) << __COUT_HDR__ <<
"Read type found." << __E__;
1563 operations_.push_back(
1564 std::make_pair(macroStruct_t::OP_TYPE_READ, readOps_.size()));
1567 readOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1568 readOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1570 if(!readOps_.back().addressIsVar_)
1574 std::string lsbfData =
"";
1577 commandPieces[2] =
"0" + commandPieces[2];
1578 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1580 __COUTVS__(20, commandPieces[2].size() - 2 * (i + 1));
1583 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1585 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1586 __COUTV__(lsbfData);
1588 __COUTVS__(20, lsbfData);
1589 StringMacros::getNumber(
"0x" + lsbfData, readOps_.back().address_);
1592 StringMacros::getNumber(
"0x" + commandPieces[2],
1593 readOps_.back().address_);
1597 readOps_.back().addressVarName_ = commandPieces[2];
1598 __COUTVS__(20, readOps_.back().addressVarName_);
1600 namesOfInputArguments_.emplace(readOps_.back().addressVarName_);
1603 if(readOps_.back().dataIsVar_)
1605 readOps_.back().dataVarName_ = commandPieces[3];
1606 __COUTVS__(20, readOps_.back().dataVarName_);
1608 namesOfOutputArguments_.emplace(readOps_.back().dataVarName_);
1611 else if(commandPieces[1][0] ==
'w' && commandPieces.size() == 4)
1613 TLOG_DEBUG(20) << __COUT_HDR__ <<
"Write type found." << __E__;
1617 operations_.push_back(
1618 std::make_pair(macroStruct_t::OP_TYPE_WRITE, writeOps_.size()));
1621 writeOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1622 writeOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1624 if(!writeOps_.back().addressIsVar_)
1628 std::string lsbfData =
"";
1631 commandPieces[2] =
"0" + commandPieces[2];
1632 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1634 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1637 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1639 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1640 __COUTV__(lsbfData);
1642 __COUTVS__(20, lsbfData);
1643 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().address_);
1646 StringMacros::getNumber(
"0x" + commandPieces[2],
1647 writeOps_.back().address_);
1651 writeOps_.back().addressVarName_ = commandPieces[2];
1652 __COUTVS__(20, writeOps_.back().addressVarName_);
1654 namesOfInputArguments_.emplace(writeOps_.back().addressVarName_);
1657 if(!writeOps_.back().dataIsVar_)
1661 std::string lsbfData =
"";
1664 commandPieces[2] =
"0" + commandPieces[3];
1665 for(
unsigned int i = 0; i < commandPieces[3].size() / 2; ++i)
1667 __COUTVS__(20, commandPieces[3].size() - 2 * (i + 1));
1670 commandPieces[3][commandPieces[3].size() - 2 * (i + 1)];
1672 commandPieces[3][commandPieces[3].size() - 2 * (i + 1) + 1];
1673 __COUTVS__(20, lsbfData);
1675 __COUTV__(lsbfData);
1676 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().data_);
1679 StringMacros::getNumber(
"0x" + commandPieces[3],
1680 writeOps_.back().data_);
1684 writeOps_.back().dataVarName_ = commandPieces[3];
1685 __COUTVS__(20, writeOps_.back().dataVarName_);
1687 namesOfInputArguments_.emplace(writeOps_.back().dataVarName_);
1690 else if(commandPieces[1][0] ==
'd' && commandPieces.size() == 3)
1692 TLOG_DEBUG(20) << __COUT_HDR__ <<
"Delay type found." << __E__;
1695 operations_.push_back(
1696 std::make_pair(macroStruct_t::OP_TYPE_DELAY, delayOps_.size()));
1699 delayOps_.back().delayIsVar_ = localIsVariable(commandPieces[2]);
1701 if(!delayOps_.back().delayIsVar_)
1702 StringMacros::getNumber(
"0x" + commandPieces[2], delayOps_.back().delay_);
1705 delayOps_.back().delayVarName_ = commandPieces[2];
1706 __COUTVS__(20, delayOps_.back().delayVarName_);
1708 namesOfInputArguments_.emplace(delayOps_.back().delayVarName_);
1713 __SS__ <<
"Invalid command type '" << commandPieces[1][0]
1714 <<
"' specified with " << commandPieces.size() <<
" components."
1721 __COUTT__ << operations_.size() <<
" operations extracted: \n\t" << readOps_.size()
1722 <<
" reads \n\t" << writeOps_.size() <<
" writes \n\t" << delayOps_.size()
1723 <<
" delays" << __E__;
1725 __COUTT__ <<
"Input arguments: " << __E__;
1726 for(
const auto& inputArg : namesOfInputArguments_)
1727 __COUTT__ <<
"\t" << inputArg << __E__;
1729 __COUTT__ <<
"Output arguments: " << __E__;
1730 for(
const auto& outputArg : namesOfOutputArguments_)
1731 __COUTT__ <<
"\t" << outputArg << __E__;
1737 void FEVInterface::runMacro(
1739 std::map<std::string /*name*/, uint64_t /*value*/>& variableMap)
1743 __FE_COUT__ <<
"Running Macro '" << macro.macroName_ <<
"' of "
1744 << macro.operations_.size() <<
" operations." << __E__;
1746 for(
auto& op : macro.operations_)
1748 if(op.first == macroStruct_t::OP_TYPE_READ)
1750 __FE_COUT__ <<
"Doing read op..." << __E__;
1752 if(readOp.addressIsVar_)
1754 __FE_COUTV__(readOp.addressVarName_);
1755 readOp.address_ = variableMap.at(readOp.addressVarName_);
1758 uint64_t dataValue = 0;
1760 __FE_COUT__ << std::hex <<
"Read address: \t 0x" << readOp.address_ << __E__
1763 universalRead((
char*)&readOp.address_, (
char*)&dataValue);
1765 __FE_COUT__ << std::hex <<
"Read data: \t 0x" << dataValue << __E__
1768 if(readOp.dataIsVar_)
1770 __FE_COUTV__(readOp.dataVarName_);
1771 variableMap.at(readOp.dataVarName_) = dataValue;
1775 else if(op.first == macroStruct_t::OP_TYPE_WRITE)
1777 __FE_COUT__ <<
"Doing write op..." << __E__;
1779 if(writeOp.addressIsVar_)
1781 __FE_COUTV__(writeOp.addressVarName_);
1782 writeOp.address_ = variableMap.at(writeOp.addressVarName_);
1784 if(writeOp.dataIsVar_)
1786 __FE_COUTV__(writeOp.dataVarName_);
1787 writeOp.data_ = variableMap.at(writeOp.dataVarName_);
1790 __FE_COUT__ << std::hex <<
"Write address: \t 0x" << writeOp.address_ << __E__
1792 __FE_COUT__ << std::hex <<
"Write data: \t 0x" << writeOp.data_ << __E__
1795 universalWrite((
char*)&writeOp.address_, (
char*)&writeOp.data_);
1798 else if(op.first == macroStruct_t::OP_TYPE_DELAY)
1800 __FE_COUT__ <<
"Doing delay op..." << __E__;
1803 if(delayOp.delayIsVar_)
1805 __FE_COUTV__(delayOp.delayVarName_);
1806 delayOp.
delay_ = variableMap.at(delayOp.delayVarName_);
1809 __FE_COUT__ << std::dec <<
"Delay ms: \t " << delayOp.
delay_ << __E__;
1811 usleep(delayOp.
delay_ * 1000);
1816 __FE_SS__ <<
"Invalid command type '" << op.first <<
"!'" << __E__;
1825 void FEVInterface::setFEMacroPercentDone(
unsigned int percentDone)
1827 const unsigned int percent = percentDone > 100 ? 100 : percentDone;
1829 std::lock_guard<std::mutex> lock(feMacroPercentDoneMutex_);
1830 feMacroPercentDoneMap_[std::this_thread::get_id()] =
static_cast<int>(percent);
1832 for(
auto* route = FEMacroProgressForwarder::active; route; route = route->previous)
1833 if(route->source ==
this)
1836 route->callback(percent);
1842 int FEVInterface::getFEMacroPercentDone(std::thread::id threadID)
const
1844 std::lock_guard<std::mutex> lock(feMacroPercentDoneMutex_);
1845 auto it = feMacroPercentDoneMap_.find(threadID);
1846 if(it == feMacroPercentDoneMap_.end())
1852 void FEVInterface::clearFEMacroPercentDone(std::thread::id threadID)
1854 std::lock_guard<std::mutex> lock(feMacroPercentDoneMutex_);
1855 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)
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)
static const std::string DEFAULT
end Slow Controls
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