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";
 
   19 FEVInterface::FEVInterface(
const std::string&       interfaceUID,
 
   21                            const std::string&       configurationPath)
 
   23     , 
Configurable(theXDAQContextConfigTree, configurationPath)
 
   25     , slowControlsWorkLoop_(interfaceUID + 
"-SlowControls", this)
 
   26     , interfaceUID_(interfaceUID)
 
   28     , mfSubject_(interfaceUID)
 
   37         interfaceType_ = theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
 
   38                              .getNode(
"FEInterfacePluginName")
 
   39                              .getValue<std::string>();
 
   44             << 
"FEInterface type could not be determined in base class from " 
   45                "configuration tree path; " 
   46                "the type may be defined subsequently by the inheriting class (e.g. to " 
   47                "take advantage of Slow Controls caching functionality, " 
   48                "the FEInterface type should be defined for all frontend interfaces)" 
   52     __GEN_COUT__ << 
"Constructed." << __E__;
 
   56 FEVInterface::~FEVInterface(
void)
 
   61     __GEN_COUT__ << 
"Destructed." << __E__;
 
   69     __COUT__ << 
"configureSlowControls path=" << theConfigurationPath_ << __E__;
 
   72     if(metricMan && !metricMan->Running() && metricMan->Initialized())
 
   74         __COUT__ << 
"Metric manager starting..." << __E__;
 
   75         metricMan->do_start();
 
   76         __COUT__ << 
"Metric manager started." << __E__;
 
   78     else if(!metricMan || !metricMan->Initialized())
 
   79         __COUT__ << 
"Metric manager could not be started! metricMan: " << metricMan
 
   80                  << 
" Initialized()= " << (metricMan ? metricMan->Initialized() : 0)
 
   83         __COUT__ << 
"Metric manager already started." << __E__;
 
   92     std::string errMessage;
 
   96             theXDAQContextConfigTree_.
getNode(theConfigurationPath_)
 
   97                 .
getNode(
"LinkToSlowControlsChannelTable");
 
  107             theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
 
  108                 .
getNode(
"LinkToSlowControlsChannelTable"),
 
  115                 theXDAQContextConfigTree_.
getNode(theConfigurationPath_)
 
  116                     .
getNode(
"LinkToSlowControlsChannelTable"),
 
  119         catch(
const std::runtime_error& e)
 
  121             __SS__ << 
"Configuring slow controls channels encountered an error: " 
  128 catch(
const std::runtime_error& e)
 
  130     __SS__ << 
"Error was caught while configuring slow controls: " << e.what() << __E__;
 
  135     __SS__ << 
"Unknown error was caught while configuring slow controls." << __E__;
 
  140     catch(
const std::exception& e)
 
  142         ss << 
"Exception message: " << e.what();
 
  156     std::map<std::string /* ROC UID*/, FESlowControlsChannel>* mapOfSlowControlsChannels)
 
  161             << 
"slowControlsGroupLink is disconnected, so done configuring slow controls." 
  165     __FE_COUT__ << 
"slowControlsGroupLink is valid! Adding slow controls channels..." 
  168     std::vector<std::pair<std::string, ConfigurationTree> > groupLinkChildren =
 
  170     for(
auto& groupLinkChild : groupLinkChildren)
 
  173         if(!(groupLinkChild.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
 
  177         __FE_COUT__ << 
"Channel:" << slowControlsGroupLink.
getTableName() << 
"/" 
  178                     << getInterfaceUID() << 
"/" << groupLinkChild.first
 
  179                     << 
"\t Type:" << groupLinkChild.second.getNode(
"ChannelDataType")
 
  183         std::string transformation = 
"";
 
  187                 groupLinkChild.second.getNode(
"Transformation").getValue<std::string>();
 
  191             __FE_COUT__ << 
"Slow controls 'Transformation' setting not found." << __E__;
 
  194         mapOfSlowControlsChannels->insert(std::pair<std::string, FESlowControlsChannel>(
 
  195             groupLinkChild.first,
 
  198                 groupLinkChild.first,
 
  199                 groupLinkChild.second.getNode(
"ChannelDataType").getValue<std::string>(),
 
  200                 groupLinkChild.second.getNode(
"UniversalInterfaceAddress")
 
  201                     .getValue<std::string>(),
 
  202                 groupLinkChild.second.getNode(
"Transformation").getValue<std::string>(),
 
  203                 groupLinkChild.second.getNode(
"UniversalDataBitOffset")
 
  204                     .getValue<
unsigned int>(),
 
  205                 groupLinkChild.second.getNode(
"ReadAccess").getValue<
bool>(),
 
  206                 groupLinkChild.second.getNode(
"WriteAccess").getValue<
bool>(),
 
  207                 groupLinkChild.second.getNode(
"MonitoringEnabled").getValue<
bool>(),
 
  208                 groupLinkChild.second.getNode(
"RecordChangesOnly").getValue<
bool>(),
 
  209                 groupLinkChild.second.getNode(
"DelayBetweenSamplesInSeconds")
 
  211                 groupLinkChild.second.getNode(
"LocalSavingEnabled").getValue<
bool>(),
 
  212                 groupLinkChild.second.getNode(
"LocalFilePath").getValue<std::string>(),
 
  213                 groupLinkChild.second.getNode(
"RadixFileName").getValue<std::string>(),
 
  214                 groupLinkChild.second.getNode(
"SaveBinaryFile").getValue<
bool>(),
 
  215                 groupLinkChild.second.getNode(
"AlarmsEnabled").getValue<
bool>(),
 
  216                 groupLinkChild.second.getNode(
"LatchAlarms").getValue<
bool>(),
 
  217                 groupLinkChild.second.getNode(
"LowLowThreshold").getValue<std::string>(),
 
  218                 groupLinkChild.second.getNode(
"LowThreshold").getValue<std::string>(),
 
  219                 groupLinkChild.second.getNode(
"HighThreshold").getValue<std::string>(),
 
  220                 groupLinkChild.second.getNode(
"HighHighThreshold")
 
  221                     .getValue<std::string>())));
 
  223     __FE_COUT__ << 
"Added " << mapOfSlowControlsChannels->size()
 
  224                 << 
" slow controls channels." << __E__;
 
  243         (slowControlsChannelsIterator_++)->second);  
 
  257     __FE_COUT__ << 
"slowControlsRunning" << __E__;
 
  262             << 
"No slow controls channels to monitor, exiting slow controls workloop." 
  269     const unsigned int txBufferSz            = 1500;
 
  270     const unsigned int txBufferFullThreshold = 750;
 
  271     std::string        txBuffer;
 
  272     txBuffer.reserve(txBufferSz);
 
  275         theXDAQContextConfigTree_.getBackNode(theConfigurationPath_);
 
  278     std::unique_ptr<UDPDataStreamerBase> slowContrlolsTxSocket;
 
  279     std::string slowControlsSupervisorIPAddress = 
"", slowControlsSelfIPAddress = 
"";
 
  280     int         slowControlsSupervisorPort = 0, slowControlsSelfPort = 0;
 
  284             FEInterfaceNode.
getNode(
"LinkToSlowControlsSupervisorTable");
 
  288             __FE_SS__ << 
"slowControlsInterfaceLink is disconnected, so no socket made." 
  293         slowControlsSelfIPAddress =
 
  294             FEInterfaceNode.
getNode(
"SlowControlsTxSocketIPAddress")
 
  296         slowControlsSelfPort =
 
  298         slowControlsSupervisorIPAddress =
 
  299             slowControlsInterfaceLink.
getNode(
"IPAddress").
getValue<std::string>();
 
  300         slowControlsSupervisorPort =
 
  305         __FE_COUT__ << 
"Link to slow controls supervisor is missing, so no socket made." 
  309     bool txBufferUsed = 
false;
 
  310     if(slowControlsSupervisorPort && slowControlsSelfPort &&
 
  311        slowControlsSupervisorIPAddress != 
"" && slowControlsSelfIPAddress != 
"")
 
  313         __FE_COUT__ << 
"slowControlsInterfaceLink is valid! Create tx socket..." << __E__;
 
  314         slowContrlolsTxSocket.reset(
 
  316                                     slowControlsSelfPort,
 
  317                                     slowControlsSupervisorIPAddress,
 
  318                                     slowControlsSupervisorPort));
 
  323         __FE_COUT__ << 
"Invalid Slow Controls socket parameters, so no socket made." 
  330     bool  aggregateFileIsBinaryFormat = 
false;
 
  333         if(FEInterfaceNode.
getNode(
"SlowControlsLocalAggregateSavingEnabled")
 
  336             aggregateFileIsBinaryFormat =
 
  337                 FEInterfaceNode.
getNode(
"SlowControlsSaveBinaryFile").
getValue<
bool>();
 
  339             __FE_COUT_INFO__ << 
"Slow Controls Aggregate Saving turned On BinaryFormat=" 
  340                              << aggregateFileIsBinaryFormat << __E__;
 
  342             std::string saveFullFileName =
 
  343                 FEInterfaceNode.
getNode(
"SlowControlsLocalFilePath")
 
  346                 FEInterfaceNode.
getNode(
"SlowControlsRadixFileName")
 
  349                 std::to_string(time(0)) + (aggregateFileIsBinaryFormat ? 
".dat" : 
".txt");
 
  352                 fopen(saveFullFileName.c_str(), aggregateFileIsBinaryFormat ? 
"ab" : 
"a");
 
  356                     << 
"Failed to open slow controls channel file: " << saveFullFileName
 
  362                     << 
"Slow controls aggregate file opened: " << saveFullFileName
 
  370     if(!aggregateFileIsBinaryFormat)
 
  371         __FE_COUT_INFO__ << 
"Slow Controls Aggregate Saving turned off." << __E__;
 
  373     time_t timeCounter = 0;
 
  375     unsigned int numOfReadAccessChannels = 0;
 
  376     bool         firstTime               = 
true;
 
  378     while(slowControlsWorkLoop_.getContinueWorkLoop())
 
  386             __FE_COUT__ << 
"txBuffer sz=" << txBuffer.size() << __E__;
 
  397             if(!channel->readAccess_)
 
  401                 ++numOfReadAccessChannels;
 
  404             if(timeCounter % channel->delayBetweenSamples_)
 
  407             __FE_COUT__ << 
"Reading Channel:" << channel->fullChannelName
 
  408                         << 
" at t=" << time(0) << __E__;
 
  411             bool usingBufferedValue = 
false;
 
  412             if(channel->getInterfaceType() != FEVInterface::UNKNOWN_TYPE)
 
  417                       channelToCopy != 
nullptr)
 
  419                     __FE_COUTT__ << 
"Looking for buffered value at " 
  420                                  << BinaryStringMacros::binaryNumberToHexString(
 
  421                                         channelToCopy->getUniversalAddress(), 
"0x", 
" ")
 
  422                                  << 
" " << channelToCopy->getReadSizeBytes() << 
" " 
  423                                  << time(0) - channelToCopy->getLastSampleTime() << __E__;
 
  425                     __FE_COUTTV__(channel->getInterfaceUID());
 
  426                     __FE_COUTTV__(channelToCopy->getInterfaceUID());
 
  427                     __FE_COUTTV__(channel->getInterfaceType());
 
  428                     __FE_COUTTV__(channelToCopy->getInterfaceType());
 
  430                     if(!usingBufferedValue &&
 
  431                        channelToCopy->getInterfaceUID() == channel->getInterfaceUID() &&
 
  432                        channelToCopy->getInterfaceType() == channel->getInterfaceType() &&
 
  433                        BinaryStringMacros::binaryNumberToHexString(
 
  434                            channelToCopy->getUniversalAddress(), 
"0x", 
" ") ==
 
  435                            BinaryStringMacros::binaryNumberToHexString(
 
  436                                channel->getUniversalAddress(), 
"0x", 
" ") &&
 
  437                        channelToCopy->getReadSizeBytes() == channel->getReadSizeBytes() &&
 
  438                        time(0) - channelToCopy->getLastSampleTime() <
 
  441                         usingBufferedValue = 
true;
 
  443                             << 
"Using buffered " << channelToCopy->getReadSizeBytes()
 
  444                             << 
"-byte value at address:" 
  445                             << BinaryStringMacros::binaryNumberToHexString(
 
  446                                    channelToCopy->getUniversalAddress(), 
"0x", 
" ")
 
  451                             << BinaryStringMacros::binaryNumberToHexString(
 
  452                                    channelToCopy->getLastSampleReadValue(), 
"0x", 
" ")
 
  453                             << 
" at t=" << time(0) << __E__;
 
  454                         channel->
handleSample(channelToCopy->getLastSampleReadValue(),
 
  457                                               aggregateFileIsBinaryFormat,
 
  459                         __FE_COUT__ << 
"Copied: " 
  460                                     << BinaryStringMacros::binaryNumberToHexString(
 
  461                                            channel->getSample(), 
"0x", 
" ")
 
  462                                     << 
" at t=" << time(0) << __E__;
 
  470             if(!usingBufferedValue)
 
  472                 std::string  readValInst;
 
  473                 std::string& readVal = readValInst;
 
  474                 readVal.resize(universalDataSize_);  
 
  475                 channel->doRead(readVal);
 
  477                     readVal, txBuffer, fp, aggregateFileIsBinaryFormat, txBufferUsed);
 
  478                 __FE_COUT__ << 
"Have: " 
  479                             << BinaryStringMacros::binaryNumberToHexString(
 
  480                                    channel->getSample(), 
"0x", 
" ")
 
  481                             << 
" at t=" << time(0) << __E__;
 
  485                 __FE_COUT__ << 
"txBuffer sz=" << txBuffer.size() << __E__;
 
  488             if(channel->monitoringEnabled && metricMan && metricMan->Running() &&
 
  489                universalAddressSize_ <= 8)
 
  492                 for(
size_t ii = 0; ii < channel->getSample().size(); ++ii)
 
  493                     val += (uint8_t)channel->getSample()[ii] << (ii * 8);
 
  496                 if((channel->transformation).size() >
 
  499                     __FE_COUT__ << 
"Transformation formula = " << channel->transformation
 
  502                     TFormula transformationFormula(
"transformationFormula",
 
  503                                                    (channel->transformation).c_str());
 
  504                     double   transformedVal = transformationFormula.Eval(val);
 
  506                     if(!std::isnan(transformedVal))
 
  508                         __FE_COUT__ << 
"Transformed " << val << 
" into " << transformedVal
 
  510                         __FE_COUT__ << 
"Sending \"" << channel->fullChannelName
 
  511                                     << 
"\" transformed sample to Metric Manager..." 
  513                         metricMan->sendMetric(channel->fullChannelName,
 
  517                                               artdaq::MetricMode::LastPoint);
 
  521                         __FE_SS__ << 
"Transformed value is NaN!" << __E__;
 
  527                     __FE_COUT__ << 
"Sending \"" << channel->fullChannelName
 
  528                                 << 
"\" sample to Metric Manager..." << __E__;
 
  529                     metricMan->sendMetric(channel->fullChannelName,
 
  533                                           artdaq::MetricMode::LastPoint);
 
  538                 __FE_COUT__ << 
"Skipping  \"" << channel->fullChannelName
 
  539                             << 
"\" sample to Metric Manager... " 
  540                             << 
" channel->monitoringEnabled=" 
  541                             << channel->monitoringEnabled << 
" metricMan=" << metricMan
 
  542                             << 
" metricMan->Running()=" 
  543                             << (metricMan && metricMan->Running()) << __E__;
 
  547             if(txBuffer.size() > txBufferSz)
 
  549                 __FE_SS__ << 
"This should never happen hopefully!" << __E__;
 
  553             if(!slowContrlolsTxSocket && txBufferUsed)
 
  557             if(slowContrlolsTxSocket && txBuffer.size() > txBufferFullThreshold)
 
  559                 __FE_COUT__ << 
"Sending now! txBufferFullThreshold=" 
  560                             << txBufferFullThreshold << __E__;
 
  561                 slowContrlolsTxSocket->send(txBuffer);
 
  567             __FE_COUT__ << 
"txBuffer sz=" << txBuffer.size() << __E__;
 
  570         if(slowContrlolsTxSocket && txBuffer.size())
 
  572             __FE_COUT__ << 
"Sending now!" << __E__;
 
  573             slowContrlolsTxSocket->send(txBuffer);
 
  581             if(numOfReadAccessChannels == 0)
 
  584                     << 
"There are no slow controls channels with read access!" << __E__;
 
  589                             << 
" slow controls channels total. " 
  590                             << numOfReadAccessChannels << 
" with read access enabled." 
  599     __FE_COUT__ << 
"Slow controls workloop done." << __E__;
 
  608     bool isPauseException = 
false;
 
  609     bool isStopException  = 
false;
 
  617         ss << 
"PAUSE Exception was caught during slow controls running thread: " 
  618            << e.what() << std::endl;
 
  619         isPauseException = 
true;
 
  623         ss << 
"STOP Exception was caught during slow controls running thread: " 
  624            << e.what() << std::endl;
 
  625         isStopException = 
true;
 
  627     catch(
const std::runtime_error& e)
 
  629         ss << 
"Caught an error during slow controls running thread of FE Interface '" 
  630            << Configurable::theConfigurationRecordName_ << 
"': " << e.what() << __E__;
 
  634         ss << 
"Caught an unknown error during slow controls running thread." << __E__;
 
  639         catch(
const std::exception& e)
 
  641             ss << 
"Exception message: " << e.what();
 
  653     __FE_COUT_ERR__ << ss.str();
 
  657            const std::string errorMessage,
 
  658            bool              isPauseException,
 
  659            bool              isStopException) {
 
  661                 fe, errorMessage, isPauseException, isStopException);
 
  682                                                const std::string& errorMessage,
 
  683                                                bool               isPauseException,
 
  684                                                bool               isStopException)
 
  687     std::stringstream feHeader;
 
  688     feHeader << 
":FE:" << fe->getInterfaceType() << 
":" << fe->getInterfaceUID() << 
":" 
  689              << fe->theConfigurationRecordName_ << 
"\t";
 
  693         __COUT_ERR__ << feHeader.str() << 
"Sending FE Async STOP Running Exception... \n" 
  694                      << errorMessage << __E__;
 
  695         fe->VStateMachine::parentSupervisor_->setAsyncPauseExceptionMessage(errorMessage);
 
  697     else if(isPauseException)
 
  699         __COUT_ERR__ << feHeader.str() << 
"Sending FE Async PAUSE Running Exception... \n" 
  700                      << errorMessage << __E__;
 
  701         fe->VStateMachine::parentSupervisor_->setAsyncStopExceptionMessage(errorMessage);
 
  704         __COUT_ERR__ << feHeader.str() << 
"Sending FE Async Running Error... \n" 
  705                      << errorMessage << __E__;
 
  707     XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
 
  708         fe->VStateMachine::parentSupervisor_->allSupervisorInfo_.getGatewayInfo()
 
  712     parameters.addParameter(
"ErrorMessage", errorMessage);
 
  714     xoap::MessageReference replyMessage =
 
  715         fe->VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
 
  717             isPauseException ? 
"AsyncPauseException" : 
"AsyncError",
 
  720     std::stringstream replyMessageSStream;
 
  721     replyMessageSStream << SOAPUtilities::translate(replyMessage);
 
  722     __COUT__ << feHeader.str() << 
"Received... " << replyMessageSStream.str()
 
  725     if(replyMessageSStream.str().find(
"Fault") != std::string::npos)
 
  727         __COUT_ERR__ << feHeader.str() << 
"Failure to indicate fault to Gateway..." 
  732 catch(
const xdaq::exception::Exception& e)
 
  735         __COUT__ << 
"SOAP message failure indicating front-end asynchronous running SOFT " 
  736                     "error back to Gateway: " 
  737                  << e.what() << __E__;
 
  739         __COUT__ << 
"SOAP message failure indicating front-end asynchronous running " 
  740                     "error back to Gateway: " 
  741                  << e.what() << __E__;
 
  747         __COUT__ << 
"Unknown error encounter indicating front-end asynchronous running " 
  748                     "SOFT error back to Gateway." 
  751         __COUT__ << 
"Unknown error encounter indicating front-end asynchronous running " 
  752                     "error back to Gateway." 
  772         bool isPauseException = 
false;
 
  773         bool isStopException  = 
false;
 
  781             ss << 
"SOFT Exception was caught while running: " << e.what() << std::endl;
 
  782             isPauseException = 
true;
 
  786             ss << 
"STOP Exception was caught while running: " << e.what() << std::endl;
 
  787             isStopException = 
true;
 
  789         catch(
const std::runtime_error& e)
 
  791             ss << 
"Caught an error during running at FE Interface '" 
  792                << Configurable::theConfigurationRecordName_ << 
"': " << e.what() << __E__;
 
  796             ss << 
"Caught an unknown error during running." << __E__;
 
  801             catch(
const std::exception& e)
 
  803                 ss << 
"Exception message: " << e.what();
 
  815         __FE_COUT_ERR__ << ss.str();
 
  819                const std::string errorMessage,
 
  820                bool              isPauseException,
 
  821                bool              isStopException) {
 
  823                     fe, errorMessage, isPauseException, isStopException);
 
  835     return continueWorkLoop_;
 
  847     const std::string&              feMacroName,
 
  849     const std::vector<std::string>& namesOfInputArgs,
 
  850     const std::vector<std::string>& namesOfOutputArgs,
 
  851     uint8_t                         requiredUserPermissions,
 
  852     const std::string&              allowedCallingFEs,
 
  853     const std::string&              feMacroTooltip)
 
  859                             std::to_string(requiredUserPermissions),
 
  864     const std::string&              feMacroName,
 
  865     frontEndMacroFunction_t         feMacroFunction,
 
  866     const std::vector<std::string>& namesOfInputArgs,
 
  867     const std::vector<std::string>& namesOfOutputArgs,
 
  868     const std::string&              requiredUserPermissions,
 
  869     const std::string&              allowedCallingFEs,
 
  870     const std::string&              feMacroTooltip)
 
  874         __FE_SS__ << 
"feMacroName '" << feMacroName << 
"' already exists! Not allowed." 
  876         __FE_COUT_ERR__ << 
"\n" << ss.str();
 
  882         frontEndMacroStruct_t(feMacroName,
 
  886                               requiredUserPermissions,
 
  897                                                          const std::string& argName)
 
  901         if(pair.first == argName)
 
  903             __COUT__ << argName << 
": " << pair.second << __E__;
 
  907     __SS__ << 
"Requested input argument not found with name '" << argName << 
"'" << __E__;
 
  915 std::string ots::getFEMacroConstArgumentValue<std::string>(
 
  916     FEVInterface::frontEndMacroConstArgs_t& args,
 
  917     const std::string&                      argName,
 
  918     const std::string&                      defaultValue)
 
  923     if(data == 
"Default")
 
  932 std::string ots::getFEMacroArgumentValue<std::string>(
 
  933     FEVInterface::frontEndMacroArgs_t& args, 
const std::string& argName)
 
  944                                               const std::string&   argName)
 
  946     for(std::pair<
const std::string ,
 
  947                   std::string >& pair : args)
 
  949         if(pair.first == argName)
 
  952     __SS__ << 
"Requested argument not found with name '" << argName << 
"'" << __E__;
 
  963     std::map<uint64_t, uint64_t> writeHistory;
 
  964     uint64_t                     writeAddress, writeValue, bitMask;
 
  967     std::string writeBuffer;
 
  968     std::string readBuffer;
 
  970     bool        ignoreError = 
true;
 
  976             theXDAQContextConfigTree_.
getNode(theConfigurationPath_)
 
  983                 __FE_COUT__ << 
"Disconnected configure sequence" << __E__;
 
  986                 __FE_COUT__ << 
"Handling configure sequence." << __E__;
 
  988                 for(
const auto& child : childrenMap)
 
  993                         child.second.getNode(
"WriteAddress").getValue<uint64_t>();
 
  994                     writeValue = child.second.getNode(
"WriteValue").getValue<uint64_t>();
 
  996                         child.second.getNode(
"StartingBitPosition").getValue<uint8_t>();
 
  998                         (1 << child.second.getNode(
"BitFieldSize").getValue<uint8_t>()) -
 
 1001                     writeValue &= bitMask;
 
 1002                     writeValue <<= bitPosition;
 
 1003                     bitMask = ~(bitMask << bitPosition);
 
 1006                     if(writeHistory.find(writeAddress) == writeHistory.end())
 
 1007                         writeHistory[writeAddress] = 0;  
 
 1009                     writeHistory[writeAddress] &= bitMask;     
 
 1010                     writeHistory[writeAddress] |= writeValue;  
 
 1013                             "\t Writing %s: \t %ld(0x%lX) \t %ld(0x%lX)",
 
 1014                             child.first.c_str(),
 
 1017                             writeHistory[writeAddress],
 
 1018                             writeHistory[writeAddress]);
 
 1020                     __FE_COUT__ << msg << __E__;
 
 1022                     universalWrite((
char*)&writeAddress,
 
 1023                                    (
char*)&(writeHistory[writeAddress]));
 
 1029             ignoreError = 
false;
 
 1039             << 
"Unable to access sequence of commands through configuration tree. " 
 1040             << 
"Assuming no sequence. " << __E__;
 
 1053     const std::string& feMacroName,
 
 1056     const std::vector<FEVInterface::frontEndMacroArg_t>& argsIn,
 
 1057     std::vector<FEVInterface::frontEndMacroArg_t>&       argsOut)
 
 1060     auto FEMacroIt = this->getMapOfFEMacroFunctions().find(feMacroName);
 
 1061     if(FEMacroIt == this->getMapOfFEMacroFunctions().end())
 
 1063         __CFG_SS__ << 
"FE Macro '" << feMacroName << 
"' of interfaceID '" 
 1064                    << getInterfaceUID() << 
"' was not found!" << __E__;
 
 1065         __CFG_COUT_ERR__ << 
"\n" << ss.str();
 
 1071     for(
unsigned int i = 0;
 
 1072         i < argsIn.size() && i < feMacro.namesOfInputArguments_.size();
 
 1074         if(argsIn[i].first != feMacro.namesOfInputArguments_[i])
 
 1076             __CFG_SS__ << 
"FE Macro '" << feMacro.feMacroName_ << 
"' of interfaceID '" 
 1077                        << getInterfaceUID() << 
"' was attempted with a mismatch in" 
 1078                        << 
" a name of an input argument. " << argsIn[i].first
 
 1079                        << 
" was given. " << feMacro.namesOfInputArguments_[i]
 
 1080                        << 
" expected." << __E__;
 
 1081             __CFG_COUT_ERR__ << 
"\n" << ss.str();
 
 1086     if(feMacro.namesOfInputArguments_.size() != argsIn.size())
 
 1088         __CFG_SS__ << 
"FE Macro '" << feMacro.feMacroName_ << 
"' of interfaceID '" 
 1089                    << getInterfaceUID() << 
"' was attempted with a mismatch in" 
 1090                    << 
" number of input arguments. " << argsIn.size() << 
" were given. " 
 1091                    << feMacro.namesOfInputArguments_.size() << 
" expected." << __E__;
 
 1092         __CFG_COUT_ERR__ << 
"\n" << ss.str();
 
 1096     __CFG_COUT__ << 
"# of input args = " << argsIn.size() << __E__;
 
 1097     for(
auto& argIn : argsIn)
 
 1098         __CFG_COUT__ << argIn.first << 
": " << argIn.second << __E__;
 
 1100     __CFG_COUT__ << 
"Launching FE Macro '" << feMacro.feMacroName_ << 
"' ..." << __E__;
 
 1103     for(
unsigned int i = 0; i < feMacro.namesOfOutputArguments_.size(); ++i)
 
 1105             feMacro.namesOfOutputArguments_[i], 
"DEFAULT"));
 
 1110     __CFG_COUT__ << 
"FE Macro complete!" << __E__;
 
 1112     __CFG_COUT__ << 
"# of output args = " << argsOut.size() << __E__;
 
 1113     for(
const auto& arg : argsOut)
 
 1114         __CFG_COUT__ << arg.first << 
": " << arg.second << __E__;
 
 1123     const std::string&                                   targetInterfaceID,
 
 1124     const std::string&                                   feMacroName,
 
 1125     const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs,
 
 1126     std::vector<FEVInterface::frontEndMacroArg_t>&       outputArgs)
 const 
 1128     __FE_COUTV__(targetInterfaceID);
 
 1132         inputArgs, 
";" , 
"," );
 
 1134     __FE_COUTV__(inputArgsStr);
 
 1136     xoap::MessageReference message =
 
 1137         SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
 
 1140     parameters.addParameter(
"type", 
"feMacro");
 
 1141     parameters.addParameter(
"requester", FEVInterface::interfaceUID_);
 
 1142     parameters.addParameter(
"targetInterfaceID", targetInterfaceID);
 
 1143     parameters.addParameter(
"feMacroName", feMacroName);
 
 1144     parameters.addParameter(
"inputArgs", inputArgsStr);
 
 1145     SOAPUtilities::addParameters(message, parameters);
 
 1147     __FE_COUT__ << 
"Sending FE communication: " << SOAPUtilities::translate(message)
 
 1150     xoap::MessageReference replyMessage =
 
 1153                 .getAllMacroMakerTypeSupervisorInfo()
 
 1155                 ->second.getDescriptor(),
 
 1158     __FE_COUT__ << 
"Response received: " << SOAPUtilities::translate(replyMessage)
 
 1162     rxParameters.addParameter(
"Error");
 
 1163     SOAPUtilities::receive(replyMessage, rxParameters);
 
 1165     std::string error = rxParameters.getValue(
"Error");
 
 1170         __FE_SS__ << 
"Error transmitting request to target interface '" 
 1171                   << targetInterfaceID << 
"' from '" << FEVInterface::interfaceUID_
 
 1172                   << 
".' " << error << __E__;
 
 1178     argsOutParameter.addParameter(
"outputArgs");
 
 1179     SOAPUtilities::receive(replyMessage, argsOutParameter);
 
 1181     std::string    outputArgsStr = argsOutParameter.getValue(
"outputArgs");
 
 1182     std::set<char> pairDelimiter({
';'}), nameValueDelimiter({
','});
 
 1184     std::map<std::string, std::string> mapToReturn;
 
 1186         outputArgsStr, mapToReturn, pairDelimiter, nameValueDelimiter);
 
 1189     for(
auto& mapPair : mapToReturn)
 
 1190         outputArgs.push_back(mapPair);
 
 1200                                        std::string&       retValue,
 
 1201                                        unsigned int       timeoutInSeconds)
 const 
 1203     __FE_COUTV__(requester);
 
 1206     std::string data = 
"0";
 
 1212             std::lock_guard<std::mutex> lock(
 
 1215             auto receiveBuffersForTargetIt =
 
 1216                 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.find(
 
 1217                     FEVInterface::interfaceUID_);
 
 1218             if(receiveBuffersForTargetIt !=
 
 1219                parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.end())
 
 1221                 __FE_COUT__ << 
"Number of source buffers found for front-end '" 
 1222                             << FEVInterface::interfaceUID_
 
 1223                             << 
"': " << receiveBuffersForTargetIt->second.size() << __E__;
 
 1225                 for(
auto& buffPair : receiveBuffersForTargetIt->second)
 
 1226                     __FE_COUTV__(buffPair.first);
 
 1229                 std::string                        sourceBufferId = 
"";
 
 1230                 std::queue<std::string >& sourceBuffer =
 
 1232                         requester, receiveBuffersForTargetIt->second, &sourceBufferId);
 
 1234                 __FE_COUT__ << 
"Found source buffer '" << sourceBufferId << 
"' with size " 
 1235                             << sourceBuffer.size() << __E__;
 
 1237                 if(sourceBuffer.size())
 
 1239                     __FE_COUT__ << 
"Found a value in queue of size " 
 1240                                 << sourceBuffer.size() << __E__;
 
 1243                     retValue = sourceBuffer.front();
 
 1248                     __FE_COUT__ << 
"Source buffer empty for '" << requester << 
"'" 
 1255             if(!timeoutInSeconds)
 
 1257                 __FE_SS__ << 
"Timeout (" << timeoutInSeconds
 
 1258                           << 
" s) waiting for front-end communication from " << requester
 
 1267         __FE_COUT__ << 
"Waiting for front-end communication from " << requester << 
" for " 
 1268                     << timeoutInSeconds << 
" more seconds..." << __E__;
 
 1283                                               unsigned int       timeoutInSeconds)
 const 
 1285     std::string retValue;
 
 1294     __COUTVS__(20, macroString);
 
 1300     std::vector<std::string> extractVec;
 
 1307         MACRONAME_NAME_INDEX  = 1,
 
 1308         MACRONAME_VALUE_INDEX = 3,
 
 1309         SEQUENCE_NAME_INDEX   = 5,
 
 1310         SEQUENCE_VALUE_INDEX  = 7,
 
 1311         LSBF_NAME_INDEX       = 17,
 
 1312         LSFBF_VALUE_INDEX     = 19,
 
 1316     if(MACRONAME_NAME_INDEX >= extractVec.size() ||
 
 1317        extractVec[MACRONAME_NAME_INDEX] != 
"name")
 
 1319         __SS__ << 
"Invalid sequence, 'name' expected in position " << MACRONAME_NAME_INDEX
 
 1323     if(SEQUENCE_NAME_INDEX >= extractVec.size() ||
 
 1324        extractVec[SEQUENCE_NAME_INDEX] != 
"sequence")
 
 1326         __SS__ << 
"Invalid sequence, 'sequence' expected in position " 
 1327                << SEQUENCE_NAME_INDEX << __E__;
 
 1330     if(LSBF_NAME_INDEX >= extractVec.size() || extractVec[LSBF_NAME_INDEX] != 
"LSBF")
 
 1332         __SS__ << 
"Invalid sequence, 'LSBF' expected in position " << LSBF_NAME_INDEX
 
 1336     macroName_ = extractVec[MACRONAME_VALUE_INDEX];
 
 1337     __COUTVS__(20, macroName_);
 
 1338     lsbf_ = extractVec[LSFBF_VALUE_INDEX] == 
"false" ? false : 
true;
 
 1339     __COUTVS__(20, 
lsbf_);
 
 1340     std::string& sequence = extractVec[SEQUENCE_VALUE_INDEX];
 
 1341     __COUTVS__(20, sequence);
 
 1343     std::vector<std::string> sequenceCommands;
 
 1348     for(
auto& command : sequenceCommands)
 
 1350         __COUTVS__(20, command);
 
 1355         std::vector<std::string> commandPieces;
 
 1360         __COUTVS__(20, commandPieces.size());
 
 1371         if(commandPieces.size() < 3 || commandPieces.size() > 4 ||
 
 1372            commandPieces[1].size() != 1)
 
 1374             __SS__ << 
"Invalid command type specified in command string: " << command
 
 1381         std::function<bool(
const std::string& 
 
 1383             localIsVariable = [](
const std::string& fieldValue) {
 
 1386                 __GEN_COUTV__(fieldValue);
 
 1389                 for(
const auto& c : fieldValue)
 
 1390                     if(!((c >= 
'0' && c <= 
'9') || (c >= 
'a' && c <= 
'f') ||
 
 1391                          (c >= 
'A' && c <= 
'F')))
 
 1396         if(commandPieces[1][0] == 
'r' && commandPieces.size() == 4)  
 
 1398             TLOG_DEBUG(20) << __COUT_HDR__ << 
"Read type found." << __E__;
 
 1402             operations_.push_back(
 
 1403                 std::make_pair(macroStruct_t::OP_TYPE_READ, readOps_.size()));
 
 1406             readOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
 
 1407             readOps_.back().dataIsVar_    = localIsVariable(commandPieces[3]);
 
 1409             if(!readOps_.back().addressIsVar_)
 
 1413                     std::string lsbfData = 
"";
 
 1416                     commandPieces[2] = 
"0" + commandPieces[2];
 
 1417                     for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
 
 1419                         __COUTVS__(20, commandPieces[2].size() - 2 * (i + 1));
 
 1422                             commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
 
 1424                             commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
 
 1425                         __COUTV__(lsbfData);
 
 1427                     __COUTVS__(20, lsbfData);
 
 1432                                             readOps_.back().address_);
 
 1436                 readOps_.back().addressVarName_ = commandPieces[2];
 
 1437                 __COUTVS__(20, readOps_.back().addressVarName_);
 
 1439                 namesOfInputArguments_.emplace(readOps_.back().addressVarName_);
 
 1442             if(readOps_.back().dataIsVar_)
 
 1444                 readOps_.back().dataVarName_ = commandPieces[3];
 
 1445                 __COUTVS__(20, readOps_.back().dataVarName_);
 
 1447                 namesOfOutputArguments_.emplace(readOps_.back().dataVarName_);
 
 1450         else if(commandPieces[1][0] == 
'w' && commandPieces.size() == 4)  
 
 1452             TLOG_DEBUG(20) << __COUT_HDR__ << 
"Write type found." << __E__;
 
 1456             operations_.push_back(
 
 1457                 std::make_pair(macroStruct_t::OP_TYPE_WRITE, writeOps_.size()));
 
 1460             writeOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
 
 1461             writeOps_.back().dataIsVar_    = localIsVariable(commandPieces[3]);
 
 1463             if(!writeOps_.back().addressIsVar_)
 
 1467                     std::string lsbfData = 
"";
 
 1470                     commandPieces[2] = 
"0" + commandPieces[2];
 
 1471                     for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
 
 1473                         __COUTV__(commandPieces[2].size() - 2 * (i + 1));
 
 1476                             commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
 
 1478                             commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
 
 1479                         __COUTV__(lsbfData);
 
 1481                     __COUTVS__(20, lsbfData);
 
 1486                                             writeOps_.back().address_);
 
 1490                 writeOps_.back().addressVarName_ = commandPieces[2];
 
 1491                 __COUTVS__(20, writeOps_.back().addressVarName_);
 
 1493                 namesOfInputArguments_.emplace(writeOps_.back().addressVarName_);
 
 1496             if(!writeOps_.back().dataIsVar_)
 
 1500                     std::string lsbfData = 
"";
 
 1503                     commandPieces[2] = 
"0" + commandPieces[3];
 
 1504                     for(
unsigned int i = 0; i < commandPieces[3].size() / 2; ++i)
 
 1506                         __COUTVS__(20, commandPieces[3].size() - 2 * (i + 1));
 
 1509                             commandPieces[3][commandPieces[3].size() - 2 * (i + 1)];
 
 1511                             commandPieces[3][commandPieces[3].size() - 2 * (i + 1) + 1];
 
 1512                         __COUTVS__(20, lsbfData);
 
 1514                     __COUTV__(lsbfData);
 
 1519                                             writeOps_.back().data_);
 
 1523                 writeOps_.back().dataVarName_ = commandPieces[3];
 
 1524                 __COUTVS__(20, writeOps_.back().dataVarName_);
 
 1526                 namesOfInputArguments_.emplace(writeOps_.back().dataVarName_);
 
 1529         else if(commandPieces[1][0] == 
'd' && commandPieces.size() == 3)  
 
 1531             TLOG_DEBUG(20) << __COUT_HDR__ << 
"Delay type found." << __E__;
 
 1534             operations_.push_back(
 
 1535                 std::make_pair(macroStruct_t::OP_TYPE_DELAY, delayOps_.size()));
 
 1538             delayOps_.back().delayIsVar_ = localIsVariable(commandPieces[2]);
 
 1540             if(!delayOps_.back().delayIsVar_)
 
 1544                 delayOps_.back().delayVarName_ = commandPieces[2];
 
 1545                 __COUTVS__(20, delayOps_.back().delayVarName_);
 
 1547                 namesOfInputArguments_.emplace(delayOps_.back().delayVarName_);
 
 1552             __SS__ << 
"Invalid command type '" << commandPieces[1][0]
 
 1553                    << 
"' specified with " << commandPieces.size() << 
" components." 
 1560     __COUT__ << operations_.size() << 
" operations extracted: \n\t" << readOps_.size()
 
 1561              << 
" reads \n\t" << writeOps_.size() << 
" writes \n\t" << delayOps_.size()
 
 1562              << 
" delays" << __E__;
 
 1564     __COUT__ << 
"Input arguments: " << __E__;
 
 1565     for(
const auto& inputArg : namesOfInputArguments_)
 
 1566         __COUT__ << 
"\t" << inputArg << __E__;
 
 1568     __COUT__ << 
"Output arguments: " << __E__;
 
 1569     for(
const auto& outputArg : namesOfOutputArguments_)
 
 1570         __COUT__ << 
"\t" << outputArg << __E__;
 
 1578     std::map<std::string /*name*/, uint64_t /*value*/>& variableMap)
 
 1582     __FE_COUT__ << 
"Running Macro '" << macro.macroName_ << 
"' of " 
 1583                 << macro.operations_.size() << 
" operations." << __E__;
 
 1585     for(
auto& op : macro.operations_)
 
 1587         if(op.first == macroStruct_t::OP_TYPE_READ)
 
 1589             __FE_COUT__ << 
"Doing read op..." << __E__;
 
 1591             if(readOp.addressIsVar_)
 
 1593                 __FE_COUTV__(readOp.addressVarName_);
 
 1594                 readOp.address_ = variableMap.at(readOp.addressVarName_);
 
 1597             uint64_t dataValue = 0;
 
 1599             __FE_COUT__ << std::hex << 
"Read address: \t 0x" << readOp.address_ << __E__
 
 1604             __FE_COUT__ << std::hex << 
"Read data: \t 0x" << dataValue << __E__
 
 1607             if(readOp.dataIsVar_)
 
 1609                 __FE_COUTV__(readOp.dataVarName_);
 
 1610                 variableMap.at(readOp.dataVarName_) = dataValue;
 
 1614         else if(op.first == macroStruct_t::OP_TYPE_WRITE)
 
 1616             __FE_COUT__ << 
"Doing write op..." << __E__;
 
 1618             if(writeOp.addressIsVar_)
 
 1620                 __FE_COUTV__(writeOp.addressVarName_);
 
 1621                 writeOp.address_ = variableMap.at(writeOp.addressVarName_);
 
 1623             if(writeOp.dataIsVar_)
 
 1625                 __FE_COUTV__(writeOp.dataVarName_);
 
 1626                 writeOp.data_ = variableMap.at(writeOp.dataVarName_);
 
 1629             __FE_COUT__ << std::hex << 
"Write address: \t 0x" << writeOp.address_ << __E__
 
 1631             __FE_COUT__ << std::hex << 
"Write data: \t 0x" << writeOp.data_ << __E__
 
 1634             universalWrite((
char*)&writeOp.address_, (
char*)&writeOp.data_);
 
 1637         else if(op.first == macroStruct_t::OP_TYPE_DELAY)
 
 1639             __FE_COUT__ << 
"Doing delay op..." << __E__;
 
 1642             if(delayOp.delayIsVar_)
 
 1644                 __FE_COUTV__(delayOp.delayVarName_);
 
 1645                 delayOp.
delay_ = variableMap.at(delayOp.delayVarName_);
 
 1648             __FE_COUT__ << std::dec << 
"Delay ms: \t " << delayOp.
delay_ << __E__;
 
 1650             usleep(delayOp.
delay_  * 1000);
 
 1655             __FE_SS__ << 
"Invalid command type '" << op.first << 
"!'" << __E__;
 
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 external specialized template access
void addSlowControlsChannels(ConfigurationTree slowControlsGroupLink, std::map< std::string, FESlowControlsChannel > *mapOfSlowControlsChannels)
std::string mfSubject_
for GEN_COUT decorations which would be safe in destructors, e.g. mirror interfaceUID_
std::pair< const std::string, std::string > frontEndMacroArg_t
end Slow Controls
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)
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_
< 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)