1 #include "otsdaq/FECore/FEVInterface.h"
2 #include "otsdaq/CoreSupervisors/CoreSupervisorBase.h"
3 #include "otsdaq/FECore/FEVInterfacesManager.h"
4 #include "otsdaq/NetworkUtilities/UDPDataStreamerBase.h"
13 FEVInterface::FEVInterface(
const std::string& interfaceUID,
const ConfigurationTree& theXDAQContextConfigTree,
const std::string& configurationPath)
15 ,
Configurable(theXDAQContextConfigTree, configurationPath)
17 , slowControlsWorkLoop_(interfaceUID +
"-SlowControls", this)
18 , interfaceUID_(interfaceUID)
19 , mfSubject_(interfaceUID)
29 __GEN_COUT__ <<
"Constructed." << __E__;
33 FEVInterface::~FEVInterface(
void)
38 __GEN_COUT__ <<
"Destructed." << __E__;
42 void FEVInterface::configureSlowControls(
void)
45 if(metricMan && !metricMan->Running() && metricMan->Initialized())
47 __GEN_COUT__ <<
"Metric manager starting..." << __E__;
48 metricMan->do_start();
49 __GEN_COUT__ <<
"Metric manager started." << __E__;
51 else if(!metricMan || !metricMan->Initialized())
52 __GEN_COUT__ <<
"Metric manager could not be started! metricMan: " << metricMan <<
" Initialized()= " << metricMan->Initialized() << __E__;
54 __GEN_COUT__ <<
"Metric manager already started." << __E__;
56 mapOfSlowControlsChannels_.clear();
58 addSlowControlsChannels(theXDAQContextConfigTree_.getBackNode(theConfigurationPath_).getNode(
"LinkToSlowControlsChannelTable"),
60 &mapOfSlowControlsChannels_);
68 void FEVInterface::addSlowControlsChannels(
ConfigurationTree slowControlsGroupLink,
69 const std::string& subInterfaceID,
70 std::map<std::string /* ROC UID*/, FESlowControlsChannel>* mapOfSlowControlsChannels)
72 if(slowControlsGroupLink.isDisconnected())
74 __FE_COUT__ <<
"slowControlsGroupLink is disconnected, so done configuring slow controls." << __E__;
77 __FE_COUT__ <<
"slowControlsGroupLink is valid! Adding slow controls channels..." << __E__;
79 std::vector<std::pair<std::string, ConfigurationTree> > groupLinkChildren = slowControlsGroupLink.getChildren();
80 for(
auto& groupLinkChild : groupLinkChildren)
83 if(!(groupLinkChild.second.getNode(TableViewColumnInfo::COL_NAME_STATUS).getValue<
bool>()))
86 __FE_COUT__ <<
"Channel:" << getInterfaceUID() << subInterfaceID <<
"/" << groupLinkChild.first
87 <<
"\t Type:" << groupLinkChild.second.getNode(
"ChannelDataType") << __E__;
89 mapOfSlowControlsChannels->insert(std::pair<std::string, FESlowControlsChannel>(
93 groupLinkChild.second.getNode(
"ChannelDataType").getValue<std::string>(),
95 universalAddressSize_,
96 groupLinkChild.second.getNode(
"UniversalInterfaceAddress").getValue<std::string>(),
97 groupLinkChild.second.getNode(
"UniversalDataBitOffset").getValue<
unsigned int>(),
98 groupLinkChild.second.getNode(
"ReadAccess").getValue<
bool>(),
99 groupLinkChild.second.getNode(
"WriteAccess").getValue<
bool>(),
100 groupLinkChild.second.getNode(
"MonitoringEnabled").getValue<
bool>(),
101 groupLinkChild.second.getNode(
"RecordChangesOnly").getValue<
bool>(),
102 groupLinkChild.second.getNode(
"DelayBetweenSamplesInSeconds").getValue<time_t>(),
103 groupLinkChild.second.getNode(
"LocalSavingEnabled").getValue<
bool>(),
104 groupLinkChild.second.getNode(
"LocalFilePath").getValue<std::string>(),
105 groupLinkChild.second.getNode(
"RadixFileName").getValue<std::string>(),
106 groupLinkChild.second.getNode(
"SaveBinaryFile").getValue<
bool>(),
107 groupLinkChild.second.getNode(
"AlarmsEnabled").getValue<
bool>(),
108 groupLinkChild.second.getNode(
"LatchAlarms").getValue<
bool>(),
109 groupLinkChild.second.getNode(
"LowLowThreshold").getValue<std::string>(),
110 groupLinkChild.second.getNode(
"LowThreshold").getValue<std::string>(),
111 groupLinkChild.second.getNode(
"HighThreshold").getValue<std::string>(),
112 groupLinkChild.second.getNode(
"HighHighThreshold").getValue<std::string>())));
118 void FEVInterface::resetSlowControlsChannelIterator(
void)
120 slowControlsChannelsIterator_ = mapOfSlowControlsChannels_.begin();
127 if(slowControlsChannelsIterator_ == mapOfSlowControlsChannels_.end())
130 return &((slowControlsChannelsIterator_++)->second);
137 readValue.resize(universalDataSize_);
138 universalRead(channel.getUniversalAddress(), &readValue[0]);
143 unsigned int FEVInterface::getSlowControlsChannelCount(
void) {
return mapOfSlowControlsChannels_.size(); }
146 bool FEVInterface::slowControlsRunning(
void)
try
148 __FE_COUT__ <<
"slowControlsRunning" << __E__;
150 if(getSlowControlsChannelCount() == 0)
152 __FE_COUT__ <<
"No slow controls channels to monitor, exiting slow controls workloop." << __E__;
156 readVal.resize(universalDataSize_);
160 const unsigned int txBufferSz = 1500;
161 const unsigned int txBufferFullThreshold = 750;
162 std::string txBuffer;
163 txBuffer.reserve(txBufferSz);
165 ConfigurationTree FEInterfaceNode = theXDAQContextConfigTree_.getBackNode(theConfigurationPath_);
168 std::unique_ptr<UDPDataStreamerBase> slowContrlolsTxSocket;
169 std::string slowControlsSupervisorIPAddress =
"", slowControlsSelfIPAddress =
"";
170 int slowControlsSupervisorPort = 0, slowControlsSelfPort = 0;
173 ConfigurationTree slowControlsInterfaceLink = FEInterfaceNode.getNode(
"LinkToSlowControlsSupervisorTable");
175 if(slowControlsInterfaceLink.isDisconnected())
177 __FE_SS__ <<
"slowControlsInterfaceLink is disconnected, so no socket made." << __E__;
181 slowControlsSelfIPAddress = FEInterfaceNode.getNode(
"SlowControlsTxSocketIPAddress").getValue<std::string>();
182 slowControlsSelfPort = FEInterfaceNode.getNode(
"SlowControlsTxSocketPort").getValue<
int>();
183 slowControlsSupervisorIPAddress = slowControlsInterfaceLink.getNode(
"IPAddress").getValue<std::string>();
184 slowControlsSupervisorPort = slowControlsInterfaceLink.getNode(
"Port").getValue<
int>();
188 __FE_COUT__ <<
"Link to slow controls supervisor is missing, so no socket made." << __E__;
191 if(slowControlsSupervisorPort && slowControlsSelfPort && slowControlsSupervisorIPAddress !=
"" && slowControlsSelfIPAddress !=
"")
193 __FE_COUT__ <<
"slowControlsInterfaceLink is valid! Create tx socket..." << __E__;
194 slowContrlolsTxSocket.reset(
195 new UDPDataStreamerBase(slowControlsSelfIPAddress, slowControlsSelfPort, slowControlsSupervisorIPAddress, slowControlsSupervisorPort));
199 __FE_COUT__ <<
"Invalid Slow Controls socket parameters, so no socket made." << __E__;
205 bool aggregateFileIsBinaryFormat =
false;
208 if(FEInterfaceNode.getNode(
"SlowControlsLocalAggregateSavingEnabled").getValue<
bool>())
210 aggregateFileIsBinaryFormat = FEInterfaceNode.getNode(
"SlowControlsSaveBinaryFile").getValue<
bool>();
212 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned On BinaryFormat=" << aggregateFileIsBinaryFormat << __E__;
214 std::string saveFullFileName = FEInterfaceNode.getNode(
"SlowControlsLocalFilePath").getValue<std::string>() +
"/" +
215 FEInterfaceNode.getNode(
"SlowControlsRadixFileName").getValue<std::string>() +
"-" +
216 FESlowControlsChannel::underscoreString(getInterfaceUID()) +
"-" + std::to_string(time(0)) +
217 (aggregateFileIsBinaryFormat ?
".dat" :
".txt");
219 fp = fopen(saveFullFileName.c_str(), aggregateFileIsBinaryFormat ?
"ab" :
"a");
222 __FE_COUT_ERR__ <<
"Failed to open slow controls channel file: " << saveFullFileName << __E__;
226 __FE_COUT_INFO__ <<
"Slow controls aggregate file opened: " << saveFullFileName << __E__;
233 if(!aggregateFileIsBinaryFormat)
234 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned off." << __E__;
236 time_t timeCounter = 0;
238 unsigned int numOfReadAccessChannels = 0;
239 bool firstTime =
true;
241 while(slowControlsWorkLoop_.getContinueWorkLoop())
243 __FE_COUT__ <<
"..." << __E__;
249 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
256 resetSlowControlsChannelIterator();
257 while((channel = getNextSlowControlsChannel()) !=
nullptr)
260 if(!channel->readAccess_)
264 ++numOfReadAccessChannels;
267 if(timeCounter % channel->delayBetweenSamples_)
270 __FE_COUT__ <<
"Reading Channel:" << channel->fullChannelName_ << __E__;
272 getSlowControlsValue(*channel, readVal);
284 channel->handleSample(readVal, txBuffer, fp, aggregateFileIsBinaryFormat);
286 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
289 if(channel->monitoringEnabled_ && metricMan && metricMan->Running() &&
290 universalAddressSize_ <= 8)
293 for(
size_t ii = 0; ii < universalAddressSize_; ++ii)
294 val += (uint8_t)readVal[ii] << (ii * 4);
296 __FE_COUT__ <<
"Sending sample to Metric Manager..." << __E__;
297 metricMan->sendMetric(channel->fullChannelName_, val,
"", 3, artdaq::MetricMode::LastPoint);
300 __FE_COUT__ <<
"Skipping sample to Metric Manager: " <<
301 " channel->monitoringEnabled_=" << channel->monitoringEnabled_ <<
302 " metricMan=" << metricMan <<
303 " metricMan->Running()=" << (metricMan && metricMan->Running()) << __E__;
307 if(txBuffer.size() > txBufferSz)
309 __FE_SS__ <<
"This should never happen hopefully!" << __E__;
314 if(slowContrlolsTxSocket && txBuffer.size() > txBufferFullThreshold)
316 __FE_COUT__ <<
"Sending now! txBufferFullThreshold=" << txBufferFullThreshold << __E__;
317 slowContrlolsTxSocket->send(txBuffer);
323 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
326 if(slowContrlolsTxSocket && txBuffer.size())
328 __FE_COUT__ <<
"Sending now!" << __E__;
329 slowContrlolsTxSocket->send(txBuffer);
337 if(numOfReadAccessChannels == 0)
339 __MCOUT_WARN__(
"There are no slow controls channels with read access!" << __E__);
343 __COUT__ <<
"There are " << getSlowControlsChannelCount() <<
" slow controls channels total. " << numOfReadAccessChannels
344 <<
" with read access enabled." << __E__;
352 __FE_COUT__ <<
"Slow controls workloop done." << __E__;
361 bool isSoftError =
false;
369 ss <<
"SOFT Error was caught during slow controls running thread: " << e.what() << std::endl;
372 catch(
const std::runtime_error& e)
374 ss <<
"Caught an error during slow controls running thread of FE Interface '" << Configurable::theConfigurationRecordName_ <<
"': " << e.what()
379 ss <<
"Caught an unknown error during slow controls running thread." << __E__;
387 __FE_COUT_ERR__ << ss.str();
390 [](
FEVInterface* fe,
const std::string errorMessage,
bool isSoftError) { FEVInterface::sendAsyncErrorToGateway(fe, errorMessage, isSoftError); },
408 void FEVInterface::sendAsyncErrorToGateway(
FEVInterface* fe,
const std::string& errorMessage,
bool isSoftError)
try
410 std::stringstream feHeader;
411 feHeader <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID() <<
":" << fe->theConfigurationRecordName_ <<
"\t";
415 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async SOFT Running Error... \n" << errorMessage << __E__;
416 fe->VStateMachine::parentSupervisor_->setAsyncSoftErrorMessage(errorMessage);
419 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async Running Error... \n" << errorMessage << __E__;
421 XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor = fe->VStateMachine::parentSupervisor_->allSupervisorInfo_.getGatewayInfo().getDescriptor();
424 parameters.addParameter(
"ErrorMessage", errorMessage);
426 xoap::MessageReference replyMessage =
427 fe->VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(gatewaySupervisor, isSoftError ?
"AsyncSoftError" :
"AsyncError", parameters);
429 std::stringstream replyMessageSStream;
430 replyMessageSStream << SOAPUtilities::translate(replyMessage);
431 __COUT__ << feHeader.str() <<
"Received... " << replyMessageSStream.str() << std::endl;
433 if(replyMessageSStream.str().find(
"Fault") != std::string::npos)
435 __COUT_ERR__ << feHeader.str() <<
"Failure to indicate fault to Gateway..." << __E__;
439 catch(
const xdaq::exception::Exception& e)
442 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running SOFT "
443 "error back to Gateway: "
444 << e.what() << __E__;
446 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running "
447 "error back to Gateway: "
448 << e.what() << __E__;
454 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
455 "SOFT error back to Gateway."
458 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
459 "error back to Gateway."
467 bool FEVInterface::workLoopThread(toolbox::task::WorkLoop* )
471 continueWorkLoop_ = running();
478 bool isSoftError =
false;
486 ss <<
"SOFT Error was caught while running: " << e.what() << std::endl;
489 catch(
const std::runtime_error& e)
491 ss <<
"Caught an error during running at FE Interface '" << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
495 ss <<
"Caught an unknown error during running." << __E__;
503 __FE_COUT_ERR__ << ss.str();
506 [](
FEVInterface* fe,
const std::string errorMessage,
bool isSoftError) { FEVInterface::sendAsyncErrorToGateway(fe, errorMessage, isSoftError); },
516 return continueWorkLoop_;
527 void FEVInterface::registerFEMacroFunction(
const std::string& feMacroName,
528 frontEndMacroFunction_t feMacroFunction,
529 const std::vector<std::string>& namesOfInputArgs,
530 const std::vector<std::string>& namesOfOutputArgs,
531 uint8_t requiredUserPermissions,
532 const std::string& allowedCallingFEs)
534 if(mapOfFEMacroFunctions_.find(feMacroName) != mapOfFEMacroFunctions_.end())
536 __FE_SS__ <<
"feMacroName '" << feMacroName <<
"' already exists! Not allowed." << __E__;
537 __FE_COUT_ERR__ <<
"\n" << ss.str();
541 mapOfFEMacroFunctions_.insert(std::pair<std::string, frontEndMacroStruct_t>(
542 feMacroName, frontEndMacroStruct_t(feMacroName, feMacroFunction, namesOfInputArgs, namesOfOutputArgs, requiredUserPermissions, allowedCallingFEs)));
550 const std::string& FEVInterface::getFEMacroConstArgument(frontEndMacroConstArgs_t& args,
const std::string& argName)
552 for(
const frontEndMacroArg_t& pair : args)
554 if(pair.first == argName)
556 __COUT__ <<
"argName : " << pair.second << __E__;
560 __SS__ <<
"Requested input argument not found with name '" << argName <<
"'" << __E__;
568 std::string ots::getFEMacroConstArgumentValue<std::string>(FEVInterface::frontEndMacroConstArgs_t& args,
const std::string& argName)
570 return FEVInterface::getFEMacroConstArgument(args, argName);
577 std::string ots::getFEMacroArgumentValue<std::string>(FEVInterface::frontEndMacroArgs_t& args,
const std::string& argName)
579 return FEVInterface::getFEMacroArgument(args, argName);
587 std::string& FEVInterface::getFEMacroArgument(frontEndMacroArgs_t& args,
const std::string& argName)
589 for(std::pair<const std::string /* output arg name */, std::string /* arg output value */>& pair : args)
591 if(pair.first == argName)
594 __SS__ <<
"Requested argument not found with name '" << argName <<
"'" << __E__;
603 void FEVInterface::runSequenceOfCommands(
const std::string& treeLinkName)
605 std::map<uint64_t, uint64_t> writeHistory;
606 uint64_t writeAddress, writeValue, bitMask;
609 std::string writeBuffer;
610 std::string readBuffer;
612 bool ignoreError =
true;
617 ConfigurationTree configSeqLink = theXDAQContextConfigTree_.getNode(theConfigurationPath_).getNode(treeLinkName);
622 if(configSeqLink.isDisconnected())
623 __FE_COUT__ <<
"Disconnected configure sequence" << __E__;
626 __FE_COUT__ <<
"Handling configure sequence." << __E__;
627 auto childrenMap = configSeqLink.getChildrenMap();
628 for(
const auto& child : childrenMap)
632 writeAddress = child.second.getNode(
"WriteAddress").getValue<uint64_t>();
633 writeValue = child.second.getNode(
"WriteValue").getValue<uint64_t>();
634 bitPosition = child.second.getNode(
"StartingBitPosition").getValue<uint8_t>();
635 bitMask = (1 << child.second.getNode(
"BitFieldSize").getValue<uint8_t>()) - 1;
637 writeValue &= bitMask;
638 writeValue <<= bitPosition;
639 bitMask = ~(bitMask << bitPosition);
642 if(writeHistory.find(writeAddress) == writeHistory.end())
643 writeHistory[writeAddress] = 0;
645 writeHistory[writeAddress] &= bitMask;
646 writeHistory[writeAddress] |= writeValue;
649 "\t Writing %s: \t %ld(0x%lX) \t %ld(0x%lX)",
653 writeHistory[writeAddress],
654 writeHistory[writeAddress]);
656 __FE_COUT__ << msg << __E__;
658 universalWrite((
char*)&writeAddress, (
char*)&(writeHistory[writeAddress]));
673 __FE_COUT__ <<
"Unable to access sequence of commands through configuration tree. "
674 <<
"Assuming no sequence. " << __E__;
686 void FEVInterface::runSelfFrontEndMacro(
const std::string& feMacroName,
689 const std::vector<FEVInterface::frontEndMacroArg_t>& argsIn,
690 std::vector<FEVInterface::frontEndMacroArg_t>& argsOut)
693 auto FEMacroIt = this->getMapOfFEMacroFunctions().find(feMacroName);
694 if(FEMacroIt == this->getMapOfFEMacroFunctions().end())
696 __CFG_SS__ <<
"FE Macro '" << feMacroName <<
"' of interfaceID '" << getInterfaceUID() <<
"' was not found!" << __E__;
697 __CFG_COUT_ERR__ <<
"\n" << ss.str();
703 for(
unsigned int i = 0; i < argsIn.size(); ++i)
704 if(argsIn[i].first != feMacro.namesOfInputArguments_[i])
706 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '" << getInterfaceUID() <<
"' was attempted with a mismatch in"
707 <<
" a name of an input argument. " << argsIn[i].first <<
" was given. " << feMacro.namesOfInputArguments_[i] <<
" expected." << __E__;
708 __CFG_COUT_ERR__ <<
"\n" << ss.str();
713 if(feMacro.namesOfInputArguments_.size() != argsIn.size())
715 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '" << getInterfaceUID() <<
"' was attempted with a mismatch in"
716 <<
" number of input arguments. " << argsIn.size() <<
" were given. " << feMacro.namesOfInputArguments_.size() <<
" expected." << __E__;
717 __CFG_COUT_ERR__ <<
"\n" << ss.str();
721 __CFG_COUT__ <<
"# of input args = " << argsIn.size() << __E__;
722 for(
auto& argIn : argsIn)
723 __CFG_COUT__ << argIn.first <<
": " << argIn.second << __E__;
725 __CFG_COUT__ <<
"Launching FE Macro '" << feMacro.feMacroName_ <<
"' ..." << __E__;
728 for(
unsigned int i = 0; i < feMacro.namesOfOutputArguments_.size(); ++i)
729 argsOut.push_back(FEVInterface::frontEndMacroArg_t(feMacro.namesOfOutputArguments_[i],
"DEFAULT"));
732 (this->*(feMacro.macroFunction_))(feMacro, argsIn, argsOut);
734 __CFG_COUT__ <<
"FE Macro complete!" << __E__;
736 __CFG_COUT__ <<
"# of output args = " << argsOut.size() << __E__;
737 for(
const auto& arg : argsOut)
738 __CFG_COUT__ << arg.first <<
": " << arg.second << __E__;
746 void FEVInterface::runFrontEndMacro(
const std::string& targetInterfaceID,
747 const std::string& feMacroName,
748 const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs,
749 std::vector<FEVInterface::frontEndMacroArg_t>& outputArgs)
const
751 __FE_COUTV__(targetInterfaceID);
752 __FE_COUTV__(VStateMachine::parentSupervisor_);
754 std::string inputArgsStr = StringMacros::vectorToString(inputArgs,
";" ,
"," );
756 __FE_COUTV__(inputArgsStr);
758 xoap::MessageReference message = SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
761 parameters.addParameter(
"type",
"feMacro");
762 parameters.addParameter(
"requester", FEVInterface::interfaceUID_);
763 parameters.addParameter(
"targetInterfaceID", targetInterfaceID);
764 parameters.addParameter(
"feMacroName", feMacroName);
765 parameters.addParameter(
"inputArgs", inputArgsStr);
766 SOAPUtilities::addParameters(message, parameters);
768 __FE_COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message) << __E__;
770 xoap::MessageReference replyMessage = VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
771 VStateMachine::parentSupervisor_->allSupervisorInfo_.getAllMacroMakerTypeSupervisorInfo().begin()->second.getDescriptor(), message);
773 __FE_COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage) << __E__;
776 rxParameters.addParameter(
"Error");
777 SOAPUtilities::receive(replyMessage, rxParameters);
779 std::string error = rxParameters.getValue(
"Error");
784 __FE_SS__ <<
"Error transmitting request to target interface '" << targetInterfaceID <<
"' from '" << FEVInterface::interfaceUID_ <<
".' " << error
791 argsOutParameter.addParameter(
"outputArgs");
792 SOAPUtilities::receive(replyMessage, argsOutParameter);
794 std::string outputArgsStr = argsOutParameter.getValue(
"outputArgs");
795 std::set<char> pairDelimiter({
';'}), nameValueDelimiter({
','});
797 std::map<std::string, std::string> mapToReturn;
798 StringMacros::getMapFromString(outputArgsStr, mapToReturn, pairDelimiter, nameValueDelimiter);
801 for(
auto& mapPair : mapToReturn)
802 outputArgs.push_back(mapPair);
811 void FEVInterface::receiveFromFrontEnd(
const std::string& requester, std::string& retValue,
unsigned int timeoutInSeconds)
const
813 __FE_COUTV__(requester);
814 __FE_COUTV__(parentSupervisor_);
816 std::string data =
"0";
822 std::lock_guard<std::mutex> lock(parentInterfaceManager_->frontEndCommunicationReceiveMutex_);
824 auto receiveBuffersForTargetIt = parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.find(FEVInterface::interfaceUID_);
825 if(receiveBuffersForTargetIt != parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.end())
827 __FE_COUT__ <<
"Number of source buffers found for front-end '" << FEVInterface::interfaceUID_
828 <<
"': " << receiveBuffersForTargetIt->second.size() << __E__;
830 for(
auto& buffPair : receiveBuffersForTargetIt->second)
831 __FE_COUTV__(buffPair.first);
834 std::string sourceBufferId =
"";
835 std::queue<std::string >& sourceBuffer =
836 StringMacros::getWildCardMatchFromMap(requester, receiveBuffersForTargetIt->second, &sourceBufferId);
838 __FE_COUT__ <<
"Found source buffer '" << sourceBufferId <<
"' with size " << sourceBuffer.size() << __E__;
840 if(sourceBuffer.size())
842 __FE_COUT__ <<
"Found a value in queue of size " << sourceBuffer.size() << __E__;
845 retValue = sourceBuffer.front();
850 __FE_COUT__ <<
"Source buffer empty for '" << requester <<
"'" << __E__;
856 if(!timeoutInSeconds)
858 __FE_SS__ <<
"Timeout (" << timeoutInSeconds <<
" s) waiting for front-end communication from " << requester <<
"." << __E__;
866 __FE_COUT__ <<
"Waiting for front-end communication from " << requester <<
" for " << timeoutInSeconds <<
" more seconds..." << __E__;
880 std::string FEVInterface::receiveFromFrontEnd(
const std::string& requester,
unsigned int timeoutInSeconds)
const
882 std::string retValue;
883 FEVInterface::receiveFromFrontEnd(requester, retValue, timeoutInSeconds);
889 FEVInterface::macroStruct_t::macroStruct_t(
const std::string& macroString)
891 __COUTV__(macroString);
897 std::vector<std::string> extractVec;
898 StringMacros::getVectorFromString(macroString, extractVec, {
'"'});
900 __COUTV__(StringMacros::vectorToString(extractVec,
" ||| "));
904 MACRONAME_NAME_INDEX = 1,
905 MACRONAME_VALUE_INDEX = 3,
906 SEQUENCE_NAME_INDEX = 5,
907 SEQUENCE_VALUE_INDEX = 7,
908 LSBF_NAME_INDEX = 17,
909 LSFBF_VALUE_INDEX = 19,
913 if(MACRONAME_NAME_INDEX >= extractVec.size() || extractVec[MACRONAME_NAME_INDEX] !=
"name")
915 __SS__ <<
"Invalid sequence, 'name' expected in position " << MACRONAME_NAME_INDEX << __E__;
918 if(SEQUENCE_NAME_INDEX >= extractVec.size() || extractVec[SEQUENCE_NAME_INDEX] !=
"sequence")
920 __SS__ <<
"Invalid sequence, 'sequence' expected in position " << SEQUENCE_NAME_INDEX << __E__;
923 if(LSBF_NAME_INDEX >= extractVec.size() || extractVec[LSBF_NAME_INDEX] !=
"LSBF")
925 __SS__ <<
"Invalid sequence, 'LSBF' expected in position " << LSBF_NAME_INDEX << __E__;
928 macroName_ = extractVec[MACRONAME_VALUE_INDEX];
929 __COUTV__(macroName_);
930 lsbf_ = extractVec[LSFBF_VALUE_INDEX] ==
"false" ?
false :
true;
932 std::string& sequence = extractVec[SEQUENCE_VALUE_INDEX];
935 std::vector<std::string> sequenceCommands;
936 StringMacros::getVectorFromString(sequence, sequenceCommands, {
','});
938 __COUTV__(StringMacros::vectorToString(sequenceCommands,
" ### "));
940 for(
auto& command : sequenceCommands)
947 std::vector<std::string> commandPieces;
948 StringMacros::getVectorFromString(command, commandPieces, {
':'});
950 __COUTV__(StringMacros::vectorToString(commandPieces,
" ### "));
952 __COUTV__(commandPieces.size());
963 if(commandPieces.size() < 3 || commandPieces.size() > 4 || commandPieces[1].size() != 1)
965 __SS__ <<
"Invalid command type specified in command string: " << command << __E__;
971 std::function<bool(
const std::string&
973 localIsVariable = [](
const std::string& fieldValue) {
975 std::string mfSubject_ =
"isVar";
976 __GEN_COUTV__(fieldValue);
979 for(
const auto& c : fieldValue)
980 if(!((c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f') || (c >=
'A' && c <=
'F')))
986 if(commandPieces[1][0] ==
'r' && commandPieces.size() == 4)
988 __COUT__ <<
"Read type found." << __E__;
992 operations_.push_back(std::make_pair(macroStruct_t::OP_TYPE_READ, readOps_.size()));
994 readOps_.push_back(macroStruct_t::readOp_t());
995 readOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
996 readOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
998 if(!readOps_.back().addressIsVar_)
1002 std::string lsbfData =
"";
1005 commandPieces[2] =
"0" + commandPieces[2];
1006 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1008 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1010 lsbfData += commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1011 lsbfData += commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1012 __COUTV__(lsbfData);
1014 __COUTV__(lsbfData);
1015 StringMacros::getNumber(
"0x" + lsbfData, readOps_.back().address_);
1018 StringMacros::getNumber(
"0x" + commandPieces[2], readOps_.back().address_);
1022 readOps_.back().addressVarName_ = commandPieces[2];
1023 __COUTV__(readOps_.back().addressVarName_);
1025 namesOfInputArguments_.emplace(readOps_.back().addressVarName_);
1028 if(readOps_.back().dataIsVar_)
1030 readOps_.back().dataVarName_ = commandPieces[3];
1031 __COUTV__(readOps_.back().dataVarName_);
1033 namesOfOutputArguments_.emplace(readOps_.back().dataVarName_);
1036 else if(commandPieces[1][0] ==
'w' && commandPieces.size() == 4)
1038 __COUT__ <<
"Write type found." << __E__;
1042 operations_.push_back(std::make_pair(macroStruct_t::OP_TYPE_WRITE, writeOps_.size()));
1044 writeOps_.push_back(macroStruct_t::writeOp_t());
1045 writeOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1046 writeOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1048 if(!writeOps_.back().addressIsVar_)
1052 std::string lsbfData =
"";
1055 commandPieces[2] =
"0" + commandPieces[2];
1056 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1058 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1060 lsbfData += commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1061 lsbfData += commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1062 __COUTV__(lsbfData);
1064 __COUTV__(lsbfData);
1065 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().address_);
1068 StringMacros::getNumber(
"0x" + commandPieces[2], writeOps_.back().address_);
1072 writeOps_.back().addressVarName_ = commandPieces[2];
1073 __COUTV__(writeOps_.back().addressVarName_);
1075 namesOfInputArguments_.emplace(writeOps_.back().addressVarName_);
1078 if(!writeOps_.back().dataIsVar_)
1082 std::string lsbfData =
"";
1085 commandPieces[2] =
"0" + commandPieces[3];
1086 for(
unsigned int i = 0; i < commandPieces[3].size() / 2; ++i)
1088 __COUTV__(commandPieces[3].size() - 2 * (i + 1));
1090 lsbfData += commandPieces[3][commandPieces[3].size() - 2 * (i + 1)];
1091 lsbfData += commandPieces[3][commandPieces[3].size() - 2 * (i + 1) + 1];
1092 __COUTV__(lsbfData);
1094 __COUTV__(lsbfData);
1095 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().data_);
1098 StringMacros::getNumber(
"0x" + commandPieces[3], writeOps_.back().data_);
1102 writeOps_.back().dataVarName_ = commandPieces[3];
1103 __COUTV__(writeOps_.back().dataVarName_);
1105 namesOfInputArguments_.emplace(writeOps_.back().dataVarName_);
1108 else if(commandPieces[1][0] ==
'd' && commandPieces.size() == 3)
1110 __COUT__ <<
"Delay type found." << __E__;
1113 operations_.push_back(std::make_pair(macroStruct_t::OP_TYPE_DELAY, delayOps_.size()));
1115 delayOps_.push_back(macroStruct_t::delayOp_t());
1116 delayOps_.back().delayIsVar_ = localIsVariable(commandPieces[2]);
1118 if(!delayOps_.back().delayIsVar_)
1119 StringMacros::getNumber(
"0x" + commandPieces[2], delayOps_.back().delay_);
1122 delayOps_.back().delayVarName_ = commandPieces[2];
1123 __COUTV__(delayOps_.back().delayVarName_);
1125 namesOfInputArguments_.emplace(delayOps_.back().delayVarName_);
1130 __SS__ <<
"Invalid command type '" << commandPieces[1][0] <<
"' specified with " << commandPieces.size() <<
" components." << __E__;
1136 __COUT__ << operations_.size() <<
" operations extracted: \n\t" << readOps_.size() <<
" reads \n\t" << writeOps_.size() <<
" writes \n\t"
1137 << delayOps_.size() <<
" delays" << __E__;
1139 __COUT__ <<
"Input arguments: " << __E__;
1140 for(
const auto& inputArg : namesOfInputArguments_)
1141 __COUT__ <<
"\t" << inputArg << __E__;
1143 __COUT__ <<
"Output arguments: " << __E__;
1144 for(
const auto& outputArg : namesOfOutputArguments_)
1145 __COUT__ <<
"\t" << outputArg << __E__;
1155 __FE_COUT__ <<
"Running Macro '" << macro.macroName_ <<
"' of " << macro.operations_.size() <<
" operations." << __E__;
1157 for(
auto& op : macro.operations_)
1159 if(op.first == macroStruct_t::OP_TYPE_READ)
1161 __FE_COUT__ <<
"Doing read op..." << __E__;
1162 macroStruct_t::readOp_t& readOp = macro.readOps_[op.second];
1163 if(readOp.addressIsVar_)
1165 __FE_COUTV__(readOp.addressVarName_);
1166 readOp.address_ = variableMap.at(readOp.addressVarName_);
1169 uint64_t dataValue = 0;
1171 __FE_COUT__ << std::hex <<
"Read address: \t 0x" << readOp.address_ << __E__ << std::dec;
1173 universalRead((
char*)&readOp.address_, (
char*)&dataValue);
1175 __FE_COUT__ << std::hex <<
"Read data: \t 0x" << dataValue << __E__ << std::dec;
1177 if(readOp.dataIsVar_)
1179 __FE_COUTV__(readOp.dataVarName_);
1180 variableMap.at(readOp.dataVarName_) = dataValue;
1184 else if(op.first == macroStruct_t::OP_TYPE_WRITE)
1186 __FE_COUT__ <<
"Doing write op..." << __E__;
1187 macroStruct_t::writeOp_t& writeOp = macro.writeOps_[op.second];
1188 if(writeOp.addressIsVar_)
1190 __FE_COUTV__(writeOp.addressVarName_);
1191 writeOp.address_ = variableMap.at(writeOp.addressVarName_);
1193 if(writeOp.dataIsVar_)
1195 __FE_COUTV__(writeOp.dataVarName_);
1196 writeOp.data_ = variableMap.at(writeOp.dataVarName_);
1199 __FE_COUT__ << std::hex <<
"Write address: \t 0x" << writeOp.address_ << __E__ << std::dec;
1200 __FE_COUT__ << std::hex <<
"Write data: \t 0x" << writeOp.data_ << __E__ << std::dec;
1202 universalWrite((
char*)&writeOp.address_, (
char*)&writeOp.data_);
1205 else if(op.first == macroStruct_t::OP_TYPE_DELAY)
1207 __FE_COUT__ <<
"Doing delay op..." << __E__;
1209 macroStruct_t::delayOp_t& delayOp = macro.delayOps_[op.second];
1210 if(delayOp.delayIsVar_)
1212 __FE_COUTV__(delayOp.delayVarName_);
1213 delayOp.delay_ = variableMap.at(delayOp.delayVarName_);
1216 __FE_COUT__ << std::dec <<
"Delay ms: \t " << delayOp.delay_ << __E__;
1218 usleep(delayOp.delay_ * 1000);
1223 __FE_SS__ <<
"Invalid command type '" << op.first <<
"!'" << __E__;