otsdaq  v2_05_02_indev
FESupervisor.cc
1 #include "otsdaq/CoreSupervisors/FESupervisor.h"
2 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
3 #include "otsdaq/FECore/FEVInterfacesManager.h"
4 
5 #include "artdaq/DAQdata/Globals.hh" // instantiates artdaq::Globals::metricMan_
6 
7 #include "artdaq-core/Utilities/ExceptionHandler.hh" /*for artdaq::ExceptionHandler*/
8 
9 #include "fhiclcpp/make_ParameterSet.h"
10 
11 // https://cdcvs.fnal.gov/redmine/projects/artdaq/repository/revisions/develop/entry/artdaq/DAQdata/Globals.hh
12 // for metric manager include
13 // https://cdcvs.fnal.gov/redmine/projects/artdaq/repository/revisions/develop/entry/artdaq/Application/DataReceiverCore.cc
14 // for metric manager configuration example
15 
16 // get pset from Board Reader metric manager table
17 // try
18 // {
19 // metricMan->initialize(metric_pset, app_name);
20 // }
21 // catch (...)
22 // {
23 // ExceptionHandler(ExceptionHandlerRethrow::no,
24 // "Error loading metrics in
25 // DataReceiverCore::initialize()");
26 // }
27 //..
28 //
29 // metricMan->do_start();
30 // ..
31 // metricMan->shutdown();
32 
33 using namespace ots;
34 
35 XDAQ_INSTANTIATOR_IMPL(FESupervisor)
36 
37 //==============================================================================
38 FESupervisor::FESupervisor(xdaq::ApplicationStub* stub) : CoreSupervisorBase(stub)
39 {
40  __SUP_COUT__ << "Constructing..." << __E__;
41 
42  xoap::bind(this, &FESupervisor::macroMakerSupervisorRequest, "MacroMakerSupervisorRequest", XDAQ_NS_URI);
43 
44  xoap::bind(this, &FESupervisor::workLoopStatusRequest, "WorkLoopStatusRequest", XDAQ_NS_URI);
45 
46  xoap::bind(this, &FESupervisor::frontEndCommunicationRequest, "FECommunication", XDAQ_NS_URI);
47 
48  try
49  {
50  CoreSupervisorBase::theStateMachineImplementation_.push_back(
51  new FEVInterfacesManager(CorePropertySupervisorBase::getContextTreeNode(), CorePropertySupervisorBase::getSupervisorConfigurationPath()));
52  }
53  catch(...)
54  {
55  if(CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
56  {
57  __SUP_COUT_WARN__ << "Error caught constructing FE Interface Manager. In "
58  "Macro Maker mode, the input fhicl defines the "
59  "configuration tree, make sure you specified a valid "
60  "fcl file path."
61  << __E__;
62  }
63  throw;
64  }
65 
66  extractFEInterfacesManager();
67 
68  __SUP_COUT__ << "Constructed." << __E__;
69 
70  if(CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
71  {
72  __SUP_COUT_INFO__ << "Macro Maker mode, so configuring at startup!" << __E__;
73  if(!theFEInterfacesManager_)
74  {
75  __SUP_SS__ << "Missing FE Interface manager!" << __E__;
76  __SUP_SS_THROW__;
77  }
78 
79  // copied from CoreSupervisorBase::transitionConfiguring()
80 
81  // Now that the configuration manager has all the necessary configurations,
82  // create all objects that depend on the configuration (the first iteration)
83 
84  try
85  {
86  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
87  preStateMachineExecutionLoop();
88  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
89  {
90  // if one state machine is doing a sub-iteration, then target that one
91  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 && i != subIterationWorkStateMachineIndex_)
92  continue; // skip those not in the sub-iteration
93 
94  if(stateMachinesIterationDone_[i])
95  continue; // skip state machines already done
96 
97  preStateMachineExecution(i);
98  theStateMachineImplementation_[i]->parentSupervisor_ = this; // for backwards compatibility, kept out of configure
99  // parameters
100  theStateMachineImplementation_[i]->configure(); // e.g. for FESupervisor,
101  // this is configure of
102  // FEVInterfacesManager
103  postStateMachineExecution(i);
104  }
105  postStateMachineExecutionLoop();
106  }
107  catch(const std::runtime_error& e)
108  {
109  __SUP_SS__ << "Error was caught while configuring: " << e.what() << __E__;
110  __SUP_COUT_ERR__ << "\n" << ss.str();
111  theStateMachine_.setErrorMessage(ss.str());
112  }
113  catch(...)
114  {
115  __SUP_SS__ << "Unknown error was caught while configuring. Please checked the logs." << __E__;
116  __SUP_COUT_ERR__ << "\n" << ss.str();
117  theStateMachine_.setErrorMessage(ss.str());
118  }
119  } // end Macro Maker mode initial configure
120 } // end constructor
121 
122 //==============================================================================
123 FESupervisor::~FESupervisor(void)
124 {
125  __SUP_COUT__ << "Destroying..." << __E__;
126  // theStateMachineImplementation_ is reset and the object it points to deleted in
127  // ~CoreSupervisorBase()
128 
129  artdaq::Globals::CleanUpGlobals(); // destruct metricManager (among other things)
130 
131  __SUP_COUT__ << "Destructed." << __E__;
132 } // end destructor
133 
134 //==============================================================================
135 xoap::MessageReference FESupervisor::frontEndCommunicationRequest(xoap::MessageReference message) try
136 {
137  __SUP_COUT__ << "FE Request received: " << SOAPUtilities::translate(message) << __E__;
138 
139  if(!theFEInterfacesManager_)
140  {
141  __SUP_SS__ << "No FE Interface Manager!" << __E__;
142  __SUP_SS_THROW__;
143  }
144  SOAPParameters typeParameter, rxParameters; // params for xoap to recv
145  typeParameter.addParameter("type");
146  SOAPUtilities::receive(message, typeParameter);
147 
148  std::string type = typeParameter.getValue("type");
149 
150  // types
151  // feSend
152  // feMacro
153  // feMacroMultiDimensionalStart
154  // macroMultiDimensionalStart
155  // feMacroMultiDimensionalCheck
156  // macroMultiDimensionalCheck
157 
158  rxParameters.addParameter("requester");
159  rxParameters.addParameter("targetInterfaceID");
160 
161  if(type == "feSend")
162  {
163  __SUP_COUTV__(type);
164 
165  rxParameters.addParameter("value");
166  SOAPUtilities::receive(message, rxParameters);
167 
168  std::string requester = rxParameters.getValue("requester");
169  std::string targetInterfaceID = rxParameters.getValue("targetInterfaceID");
170  std::string value = rxParameters.getValue("value");
171 
172  __SUP_COUTV__(requester);
173  __SUP_COUTV__(targetInterfaceID);
174  __SUP_COUTV__(value);
175 
176  // test that the interface exists
177  theFEInterfacesManager_->getFEInterface(targetInterfaceID);
178 
179  // mutex scope
180  {
181  std::lock_guard<std::mutex> lock(theFEInterfacesManager_->frontEndCommunicationReceiveMutex_);
182 
183  theFEInterfacesManager_->frontEndCommunicationReceiveBuffer_[targetInterfaceID][requester].emplace(value);
184 
185  __SUP_COUT__ << "Number of target interface ID '" << targetInterfaceID
186  << "' buffers: " << theFEInterfacesManager_->frontEndCommunicationReceiveBuffer_[targetInterfaceID].size() << __E__;
187  __SUP_COUT__ << "Number of source interface ID '" << requester
188  << "' values received: " << theFEInterfacesManager_->frontEndCommunicationReceiveBuffer_[targetInterfaceID][requester].size() << __E__;
189  }
190  return SOAPUtilities::makeSOAPMessageReference("Received");
191  } // end type feSend
192  else if(type == "feMacro")
193  {
194  __SUP_COUTV__(type);
195 
196  rxParameters.addParameter("feMacroName");
197  rxParameters.addParameter("inputArgs");
198 
199  SOAPUtilities::receive(message, rxParameters);
200 
201  std::string requester = rxParameters.getValue("requester");
202  std::string targetInterfaceID = rxParameters.getValue("targetInterfaceID");
203  std::string feMacroName = rxParameters.getValue("feMacroName");
204  std::string inputArgs = rxParameters.getValue("inputArgs");
205 
206  __SUP_COUTV__(requester);
207  __SUP_COUTV__(targetInterfaceID);
208  __SUP_COUTV__(feMacroName);
209  __SUP_COUTV__(inputArgs);
210 
211  std::string outputArgs;
212  try
213  {
214  theFEInterfacesManager_->runFEMacroByFE(requester, targetInterfaceID, feMacroName, inputArgs, outputArgs);
215  }
216  catch(std::runtime_error& e)
217  {
218  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the FE Macro named '" << feMacroName
219  << "' with target FE '" << targetInterfaceID << "' failed. Here is the error:\n\n"
220  << e.what() << __E__;
221  __SUP_SS_THROW__;
222  }
223  catch(...)
224  {
225  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the FE Macro named '" << feMacroName
226  << "' with target FE '" << targetInterfaceID << "' failed due to an unknown error." << __E__;
227  __SUP_SS_THROW__;
228  }
229 
230  __SUP_COUTV__(outputArgs);
231 
232  xoap::MessageReference replyMessage = SOAPUtilities::makeSOAPMessageReference("feMacrosResponse");
233  SOAPParameters txParameters;
234  txParameters.addParameter("requester", requester);
235  txParameters.addParameter("targetInterfaceID", targetInterfaceID);
236  txParameters.addParameter("feMacroName", feMacroName);
237  txParameters.addParameter("outputArgs", outputArgs);
238  SOAPUtilities::addParameters(replyMessage, txParameters);
239 
240  __SUP_COUT__ << "Sending FE macro result: " << SOAPUtilities::translate(replyMessage) << __E__;
241 
242  return replyMessage;
243  } // end type feMacro
244  else if(type == "feMacroMultiDimensionalStart" || // from iterator
245  type == "macroMultiDimensionalStart") // from iterator
246  {
247  __SUP_COUTV__(type);
248 
249  if(type[0] == 'm')
250  {
251  rxParameters.addParameter("macroString");
252  rxParameters.addParameter("macroName");
253  }
254  else
255  rxParameters.addParameter("feMacroName");
256 
257  rxParameters.addParameter("enableSavingOutput");
258  rxParameters.addParameter("outputFilePath");
259  rxParameters.addParameter("outputFileRadix");
260  rxParameters.addParameter("inputArgs");
261 
262  SOAPUtilities::receive(message, rxParameters);
263 
264  std::string requester = rxParameters.getValue("requester");
265  std::string targetInterfaceID = rxParameters.getValue("targetInterfaceID");
266  std::string macroName, macroString;
267  if(type[0] == 'm')
268  {
269  macroName = rxParameters.getValue("macroName");
270  macroString = rxParameters.getValue("macroString");
271  __SUP_COUTV__(macroString);
272  }
273  else
274  macroName = rxParameters.getValue("feMacroName");
275  bool enableSavingOutput = rxParameters.getValue("enableSavingOutput") == "1";
276  std::string outputFilePath = rxParameters.getValue("outputFilePath");
277  std::string outputFileRadix = rxParameters.getValue("outputFileRadix");
278  std::string inputArgs = rxParameters.getValue("inputArgs");
279 
280  __SUP_COUTV__(requester);
281  __SUP_COUTV__(targetInterfaceID);
282  __SUP_COUTV__(macroName);
283  __SUP_COUTV__(enableSavingOutput);
284  __SUP_COUTV__(outputFilePath);
285  __SUP_COUTV__(outputFileRadix);
286  __SUP_COUTV__(inputArgs);
287 
288  if(type[0] == 'm') // start Macro
289  {
290  try
291  {
292  theFEInterfacesManager_->startMacroMultiDimensional(
293  requester, targetInterfaceID, macroName, macroString, enableSavingOutput, outputFilePath, outputFileRadix, inputArgs);
294  }
295  catch(std::runtime_error& e)
296  {
297  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the Macro named '" << macroName << "' with target FE '"
298  << targetInterfaceID << "' failed to start multi-dimensional launch. "
299  << "Here is the error:\n\n"
300  << e.what() << __E__;
301  __SUP_SS_THROW__;
302  }
303  catch(...)
304  {
305  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the Macro named '" << macroName << "' with target FE '"
306  << targetInterfaceID << "' failed to start multi-dimensional launch "
307  << "due to an unknown error." << __E__;
308  __SUP_SS_THROW__;
309  }
310  }
311  else // start FE Macro
312  {
313  try
314  {
315  theFEInterfacesManager_->startFEMacroMultiDimensional(
316  requester, targetInterfaceID, macroName, enableSavingOutput, outputFilePath, outputFileRadix, inputArgs);
317  }
318  catch(std::runtime_error& e)
319  {
320  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the FE Macro named '" << macroName
321  << "' with target FE '" << targetInterfaceID << "' failed to start multi-dimensional launch. "
322  << "Here is the error:\n\n"
323  << e.what() << __E__;
324  __SUP_SS_THROW__;
325  }
326  catch(...)
327  {
328  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the FE Macro named '" << macroName
329  << "' with target FE '" << targetInterfaceID << "' failed to start multi-dimensional launch "
330  << "due to an unknown error." << __E__;
331  __SUP_SS_THROW__;
332  }
333  }
334 
335  xoap::MessageReference replyMessage = SOAPUtilities::makeSOAPMessageReference(type + "Done");
336  SOAPParameters txParameters;
337  // txParameters.addParameter("started", "1");
338  SOAPUtilities::addParameters(replyMessage, txParameters);
339 
340  __SUP_COUT__ << "Sending FE macro result: " << SOAPUtilities::translate(replyMessage) << __E__;
341 
342  return replyMessage;
343  } // end type (fe)MacroMultiDimensionalStart
344  else if(type == "feMacroMultiDimensionalCheck" || // from iterator
345  type == "macroMultiDimensionalCheck")
346  {
347  __SUP_COUTV__(type);
348  if(type[0] == 'm')
349  rxParameters.addParameter("macroName");
350  else
351  rxParameters.addParameter("feMacroName");
352  rxParameters.addParameter("targetInterfaceID");
353 
354  SOAPUtilities::receive(message, rxParameters);
355 
356  std::string targetInterfaceID = rxParameters.getValue("targetInterfaceID");
357  std::string macroName;
358  if(type[0] == 'm')
359  macroName = rxParameters.getValue("macroName");
360  else
361  macroName = rxParameters.getValue("feMacroName");
362 
363  __SUP_COUTV__(targetInterfaceID);
364  __SUP_COUTV__(macroName);
365 
366  bool done = false;
367  try
368  {
369  done = theFEInterfacesManager_->checkMacroMultiDimensional(targetInterfaceID, macroName);
370  }
371  catch(std::runtime_error& e)
372  {
373  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the FE Macro named '" << macroName << "' with target FE '"
374  << targetInterfaceID << "' failed to check multi-dimensional launch. "
375  << "Here is the error:\n\n"
376  << e.what() << __E__;
377  __SUP_SS_THROW__;
378  }
379  catch(...)
380  {
381  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the FE Macro named '" << macroName << "' with target FE '"
382  << targetInterfaceID << "' failed to check multi-dimensional launch "
383  << "due to an unknown error." << __E__;
384  __SUP_SS_THROW__;
385  }
386 
387  xoap::MessageReference replyMessage = SOAPUtilities::makeSOAPMessageReference(type + "Done");
388  SOAPParameters txParameters;
389  txParameters.addParameter("Done", done ? "1" : "0");
390  SOAPUtilities::addParameters(replyMessage, txParameters);
391 
392  __SUP_COUT__ << "Sending FE macro result: " << SOAPUtilities::translate(replyMessage) << __E__;
393 
394  return replyMessage;
395  } // end type (fe)MacroMultiDimensionalCheck
396  else
397  {
398  __SUP_SS__ << "Unrecognized FE Communication type: " << type << __E__;
399  __SUP_SS_THROW__;
400  }
401 }
402 catch(const std::runtime_error& e)
403 {
404  __SUP_SS__ << "Error encountered processing FE communication request: " << e.what() << __E__;
405  __SUP_COUT_ERR__ << ss.str();
406 
407  SOAPParameters parameters;
408  parameters.addParameter("Error", ss.str());
409  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "FailFECommunicationRequest", parameters);
410 }
411 catch(...)
412 {
413  __SUP_SS__ << "Unknown error encountered processing FE communication request." << __E__;
414  __SUP_COUT_ERR__ << ss.str();
415 
416  SOAPParameters parameters;
417  parameters.addParameter("Error", ss.str());
418  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "FailFECommunicationRequest", parameters);
419 } // end frontEndCommunicationRequest()
420 
421 //==============================================================================
422 // macroMakerSupervisorRequest
423 // Handles all MacroMaker Requests:
424 // - GetInterfaces (returns interface type and id)
425 //
426 // Note: this code assumes a CoreSupervisorBase has only one
427 // FEVInterfacesManager in its vector of state machines
428 xoap::MessageReference FESupervisor::macroMakerSupervisorRequest(xoap::MessageReference message)
429 {
430  __SUP_COUT__ << "$$$$$$$$$$$$$$$$$" << __E__;
431 
432  // receive request parameters
433  SOAPParameters parameters;
434  parameters.addParameter("Request");
435 
436  __SUP_COUT__ << "Received Macro Maker message: " << SOAPUtilities::translate(message) << __E__;
437 
438  SOAPUtilities::receive(message, parameters);
439  std::string request = parameters.getValue("Request");
440 
441  __SUP_COUT__ << "request: " << request << __E__;
442 
443  // request types:
444  // GetInterfaces
445  // UniversalWrite
446  // UniversalRead
447  // GetInterfaceMacros
448  // RunInterfaceMacro
449  // RunMacroMakerMacro
450 
451  SOAPParameters retParameters;
452 
453  try
454  {
455  if(request == "GetInterfaces")
456  {
457  if(theFEInterfacesManager_)
458  retParameters.addParameter("FEList", theFEInterfacesManager_->getFEListString(std::to_string(getApplicationDescriptor()->getLocalId())));
459  else // if no FE interfaces, return empty string
460  retParameters.addParameter("FEList", "");
461 
462  // if errors in state machine, send also
463  if(theStateMachine_.getErrorMessage() != "")
464  retParameters.addParameter("frontEndError", theStateMachine_.getErrorMessage());
465 
466  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "Response", retParameters);
467  }
468  else if(request == "UniversalWrite")
469  {
470  if(!theFEInterfacesManager_)
471  {
472  __SUP_SS__ << "No FE Interface Manager! Are you configured?" << __E__;
473  __SUP_SS_THROW__;
474  }
475  // params for running macros
476  SOAPParameters requestParameters;
477  requestParameters.addParameter("InterfaceID");
478  requestParameters.addParameter("Address");
479  requestParameters.addParameter("Data");
480  SOAPUtilities::receive(message, requestParameters);
481  std::string interfaceID = requestParameters.getValue("InterfaceID");
482  std::string addressStr = requestParameters.getValue("Address");
483  std::string dataStr = requestParameters.getValue("Data");
484 
485  __SUP_COUT__ << "Address: " << addressStr << " Data: " << dataStr << " InterfaceID: " << interfaceID << __E__;
486 
487  // parameters interface index!
488  // unsigned int index = stoi(indexStr); // As long as the supervisor has only
489  // one interface, this index will remain 0?
490 
491  __SUP_COUT__ << "theFEInterfacesManager_->getInterfaceUniversalAddressSize(index) "
492  << theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID) << __E__;
493  __SUP_COUT__ << "theFEInterfacesManager_->getInterfaceUniversalDataSize(index) "
494  << theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID) << __E__;
495 
496  // Converting std::string to char*
497  // char address
498 
499  char tmpHex[3]; // for use converting hex to binary
500  tmpHex[2] = '\0';
501 
502  __SUP_COUT__ << "Translating address: ";
503 
504  std::string addressTmp;
505  addressTmp.reserve(theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID));
506  char* address = &addressTmp[0];
507 
508  if(addressStr.size() % 2) // if odd, make even
509  addressStr = "0" + addressStr;
510  unsigned int i = 0;
511  for(; i < addressStr.size() && i / 2 < theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID); i += 2)
512  {
513  tmpHex[0] = addressStr[addressStr.size() - 1 - i - 1];
514  tmpHex[1] = addressStr[addressStr.size() - 1 - i];
515  sscanf(tmpHex, "%hhX", (unsigned char*)&address[i / 2]);
516  printf("%2.2X", (unsigned char)address[i / 2]);
517  }
518  // finish and fill with 0s
519  for(; i / 2 < theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID); i += 2)
520  {
521  address[i / 2] = 0;
522  printf("%2.2X", (unsigned char)address[i / 2]);
523  }
524 
525  std::cout << __E__;
526 
527  __SUP_COUT__ << "Translating data: ";
528 
529  std::string dataTmp;
530  dataTmp.reserve(theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID));
531  char* data = &dataTmp[0];
532 
533  if(dataStr.size() % 2) // if odd, make even
534  dataStr = "0" + dataStr;
535 
536  i = 0;
537  for(; i < dataStr.size() && i / 2 < theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID); i += 2)
538  {
539  tmpHex[0] = dataStr[dataStr.size() - 1 - i - 1];
540  tmpHex[1] = dataStr[dataStr.size() - 1 - i];
541  sscanf(tmpHex, "%hhX", (unsigned char*)&data[i / 2]);
542  printf("%2.2X", (unsigned char)data[i / 2]);
543  }
544  // finish and fill with 0s
545  for(; i / 2 < theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID); i += 2)
546  {
547  data[i / 2] = 0;
548  printf("%2.2X", (unsigned char)data[i / 2]);
549  }
550 
551  std::cout << __E__;
552 
553  // char* address = new char[addressStr.size() + 1];
554  // std::copy(addressStr.begin(), addressStr.end(), address);
555  // address[addressStr.size()] = '\0';
556  // char* data = new char[dataStr.size() + 1];
557  // std::copy(dataStr.begin(), dataStr.end(), data);
558  // data[dataStr.size()] = '\0';
559 
560  theFEInterfacesManager_->universalWrite(interfaceID, address, data);
561 
562  // delete[] address;
563  // delete[] data;
564 
565  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "DataWritten", retParameters);
566  }
567  else if(request == "UniversalRead")
568  {
569  if(!theFEInterfacesManager_)
570  {
571  __SUP_SS__ << "No FE Interface Manager! Are you configured?" << __E__;
572  __SUP_SS_THROW__;
573  }
574 
575  // params for running macros
576  SOAPParameters requestParameters;
577  requestParameters.addParameter("InterfaceID");
578  requestParameters.addParameter("Address");
579  SOAPUtilities::receive(message, requestParameters);
580  std::string interfaceID = requestParameters.getValue("InterfaceID");
581  std::string addressStr = requestParameters.getValue("Address");
582 
583  __SUP_COUT__ << "Address: " << addressStr << " InterfaceID: " << interfaceID << __E__;
584 
585  // parameters interface index!
586  // parameter address and data
587  // unsigned int index = stoi(indexStr); // As long as the supervisor has only
588  // one interface, this index will remain 0?
589 
590  __SUP_COUT__ << "theFEInterfacesManager_->getInterfaceUniversalAddressSize(index) "
591  << theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID) << __E__;
592  __SUP_COUT__ << "theFEInterfacesManager_->getInterfaceUniversalDataSize(index) "
593  << theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID) << __E__;
594 
595  char tmpHex[3]; // for use converting hex to binary
596  tmpHex[2] = '\0';
597 
598  __SUP_COUT__ << "Translating address: ";
599 
600  std::string addressTmp;
601  addressTmp.reserve(theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID));
602  char* address = &addressTmp[0];
603 
604  if(addressStr.size() % 2) // if odd, make even
605  addressStr = "0" + addressStr;
606 
607  unsigned int i = 0;
608  for(; i < addressStr.size() && i / 2 < theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID); i += 2)
609  {
610  tmpHex[0] = addressStr[addressStr.size() - 1 - i - 1];
611  tmpHex[1] = addressStr[addressStr.size() - 1 - i];
612  sscanf(tmpHex, "%hhX", (unsigned char*)&address[i / 2]);
613  printf("%2.2X", (unsigned char)address[i / 2]);
614  }
615  // finish and fill with 0s
616  for(; i / 2 < theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID); i += 2)
617  {
618  address[i / 2] = 0;
619  printf("%2.2X", (unsigned char)address[i / 2]);
620  }
621 
622  std::cout << __E__;
623 
624  unsigned int dataSz = theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID);
625  std::string dataStr;
626  dataStr.resize(dataSz);
627  char* data = &dataStr[0];
628 
629  // std::string result =
630  // theFEInterfacesManager_->universalRead(index,address,data);
631  // __SUP_COUT__<< result << __E__ << __E__;
632 
633  try
634  {
635  theFEInterfacesManager_->universalRead(interfaceID, address, data);
636  }
637  catch(const std::runtime_error& e)
638  {
639  // do not allow read exception to crash everything when a macromaker
640  // command
641  __MOUT_ERR__ << "Exception caught during read: " << e.what() << __E__;
642  __SUP_COUT_ERR__ << "Exception caught during read: " << e.what() << __E__;
643  retParameters.addParameter("dataResult", "Time Out Error");
644  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "aa", retParameters);
645  }
646  catch(...)
647  {
648  // do not allow read exception to crash everything when a macromaker
649  // command
650  __MOUT_ERR__ << "Exception caught during read." << __E__;
651  __SUP_COUT_ERR__ << "Exception caught during read." << __E__;
652  retParameters.addParameter("dataResult", "Time Out Error");
653  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "aa", retParameters);
654  }
655 
656  // if dataSz is less than 8 show what the unsigned number would be
657  if(dataSz <= 8)
658  {
659  std::string str8(data);
660  str8.resize(8);
661  __SUP_COUT__ << "decResult[" << dataSz << " bytes]: " << *((unsigned long long*)(&str8[0])) << __E__;
662  }
663 
664  std::string hexResultStr;
665  hexResultStr.reserve(dataSz * 2 + 1);
666  char* hexResult = &hexResultStr[0];
667  // go through each byte and convert it to hex value (i.e. 2 0-F chars)
668  // go backwards through source data since should be provided in host order
669  // (i.e. a cast to unsigned long long should acquire expected value)
670  for(unsigned int i = 0; i < dataSz; ++i)
671  {
672  sprintf(&hexResult[i * 2], "%2.2X", (unsigned char)data[dataSz - 1 - i]);
673  }
674 
675  __SUP_COUT__ << "hexResult[" << strlen(hexResult) << " nibbles]: " << std::string(hexResult) << __E__;
676 
677  retParameters.addParameter("dataResult", hexResult);
678  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "aa", retParameters);
679  }
680  else if(request == "GetInterfaceMacros")
681  {
682  if(theFEInterfacesManager_)
683  retParameters.addParameter("FEMacros",
684  theFEInterfacesManager_->getFEMacrosString(CorePropertySupervisorBase::getSupervisorUID(),
685  std::to_string(CoreSupervisorBase::getSupervisorLID())));
686  else
687  retParameters.addParameter("FEMacros", "");
688 
689  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "Response", retParameters);
690  }
691  else if(request == "RunInterfaceMacro")
692  {
693  if(!theFEInterfacesManager_)
694  {
695  __SUP_SS__ << "Missing FE Interface Manager! Are you configured?" << __E__;
696  __SUP_SS_THROW__;
697  }
698 
699  // params for running macros
700  SOAPParameters requestParameters;
701  requestParameters.addParameter("feMacroName");
702  requestParameters.addParameter("inputArgs");
703  requestParameters.addParameter("outputArgs");
704  requestParameters.addParameter("InterfaceID");
705  SOAPUtilities::receive(message, requestParameters);
706  std::string interfaceID = requestParameters.getValue("InterfaceID");
707  std::string feMacroName = requestParameters.getValue("feMacroName");
708  std::string inputArgs = requestParameters.getValue("inputArgs");
709  std::string outputArgs = requestParameters.getValue("outputArgs");
710 
711  // outputArgs must be filled with the proper argument names
712  // and then the response output values will be returned in the string.
713  try
714  {
715  theFEInterfacesManager_->runFEMacro(interfaceID, feMacroName, inputArgs, outputArgs);
716  }
717  catch(std::runtime_error& e)
718  {
719  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the FE Macro named '" << feMacroName
720  << "' with target FE '" << interfaceID << "' failed. Here is the error:\n\n"
721  << e.what() << __E__;
722  __SUP_SS_THROW__;
723  }
724  catch(...)
725  {
726  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the FE Macro named '" << feMacroName
727  << "' with target FE '" << interfaceID << "' failed due to an unknown error." << __E__;
728  __SUP_SS_THROW__;
729  }
730 
731  // retParameters.addParameter("success", success ? "1" : "0");
732  retParameters.addParameter("outputArgs", outputArgs);
733 
734  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "Response", retParameters);
735  }
736  else if(request == "RunMacroMakerMacro")
737  {
738  if(!theFEInterfacesManager_)
739  {
740  __SUP_SS__ << "Missing FE Interface Manager! Are you configured?" << __E__;
741  __SUP_SS_THROW__;
742  }
743 
744  // params for running macros
745  SOAPParameters requestParameters;
746  requestParameters.addParameter("macroName");
747  requestParameters.addParameter("macroString");
748  requestParameters.addParameter("inputArgs");
749  requestParameters.addParameter("outputArgs");
750  requestParameters.addParameter("InterfaceID");
751  SOAPUtilities::receive(message, requestParameters);
752  std::string interfaceID = requestParameters.getValue("InterfaceID");
753  std::string macroName = requestParameters.getValue("macroName");
754  std::string macroString = requestParameters.getValue("macroString");
755  std::string inputArgs = requestParameters.getValue("inputArgs");
756  std::string outputArgs = requestParameters.getValue("outputArgs");
757 
758  // outputArgs must be filled with the proper argument names
759  // and then the response output values will be returned in the string.
760  try
761  {
762  theFEInterfacesManager_->runMacro(interfaceID, macroString, inputArgs, outputArgs);
763  }
764  catch(std::runtime_error& e)
765  {
766  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the MacroMaker Macro named '" << macroName
767  << "' with target FE '" << interfaceID << "' failed. Here is the error:\n\n"
768  << e.what() << __E__;
769  __SUP_SS_THROW__;
770  }
771  catch(...)
772  {
773  __SUP_SS__ << "In Supervisor with LID=" << getApplicationDescriptor()->getLocalId() << " the MacroMaker Macro named '" << macroName
774  << "' with target FE '" << interfaceID << "' failed due to an unknown error." << __E__;
775  __SUP_SS_THROW__;
776  }
777 
778  retParameters.addParameter("outputArgs", outputArgs);
779 
780  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "Response", retParameters);
781  }
782  else
783  {
784  __SUP_SS__ << "Unrecognized request received! '" << request << "'" << __E__;
785  __SUP_SS_THROW__;
786  }
787  }
788  catch(const std::runtime_error& e)
789  {
790  __SUP_SS__ << "Error occurred handling request: " << e.what() << __E__;
791  __SUP_COUT_ERR__ << ss.str();
792  retParameters.addParameter("Error", ss.str());
793  }
794  catch(...)
795  {
796  __SUP_SS__ << "Error occurred handling request." << __E__;
797  __SUP_COUT_ERR__ << ss.str();
798  retParameters.addParameter("Error", ss.str());
799  }
800 
801  return SOAPUtilities::makeSOAPMessageReference(supervisorClassNoNamespace_ + "FailRequest", retParameters);
802 
803 } // end macroMakerSupervisorRequest()
804 
805 //==============================================================================
806 xoap::MessageReference FESupervisor::workLoopStatusRequest(xoap::MessageReference /*message*/)
807 {
808  if(!theFEInterfacesManager_)
809  {
810  __SUP_SS__ << "Invalid request for front-end workloop status from Supervisor "
811  "without a FEVInterfacesManager."
812  << __E__;
813  __SUP_SS_THROW__;
814  }
815 
816  return SOAPUtilities::makeSOAPMessageReference(
817  (theFEInterfacesManager_->allFEWorkloopsAreDone() ? CoreSupervisorBase::WORK_LOOP_DONE : CoreSupervisorBase::WORK_LOOP_WORKING));
818 } // end workLoopStatusRequest()
819 
820 //==============================================================================
821 // extractFEInterfaceManager
822 //
823 // locates theFEInterfacesManager in state machines vector and
824 // returns 0 if not found.
825 //
826 // Note: this code assumes a CoreSupervisorBase has only one
827 // FEVInterfacesManager in its vector of state machines
828 FEVInterfacesManager* FESupervisor::extractFEInterfacesManager()
829 {
830  theFEInterfacesManager_ = 0;
831 
832  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
833  {
834  try
835  {
836  theFEInterfacesManager_ = dynamic_cast<FEVInterfacesManager*>(theStateMachineImplementation_[i]);
837  if(!theFEInterfacesManager_)
838  {
839  // dynamic_cast returns null pointer on failure
840  __SUP_SS__ << "Dynamic cast failure!" << __E__;
841  __SUP_SS_THROW__;
842  }
843  __SUP_COUT__ << "State Machine " << i << " WAS of type FEVInterfacesManager" << __E__;
844 
845  break;
846  }
847  catch(...)
848  {
849  __SUP_COUT__ << "State Machine " << i << " was NOT of type FEVInterfacesManager" << __E__;
850  }
851  }
852 
853  __SUP_COUT__ << "theFEInterfacesManager pointer = " << theFEInterfacesManager_ << __E__;
854 
855  return theFEInterfacesManager_;
856 } // end extractFEInterfaceManager()
857 
858 //==============================================================================
859 void FESupervisor::transitionConfiguring(toolbox::Event::Reference /*event*/)
860 {
861  __SUP_COUT__ << "transitionConfiguring" << __E__;
862 
863  { //do like start of CoreSupervisorBase::transitionConfiguring
864  // activate the configuration tree (the first iteration)
865  if(RunControlStateMachine::getIterationIndex() == 0 && RunControlStateMachine::getSubIterationIndex() == 0)
866  {
867  std::pair<std::string /*group name*/, TableGroupKey> theGroup(
868  SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).getParameters().getValue("ConfigurationTableGroupName"),
869  TableGroupKey(SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).getParameters().getValue("ConfigurationTableGroupKey")));
870 
871  __SUP_COUT__ << "Configuration table group name: " << theGroup.first << " key: " << theGroup.second << __E__;
872 
873  theConfigurationManager_->loadTableGroup(theGroup.first, theGroup.second, true /*doActivate*/);
874  }
875  } //end start like CoreSupervisorBase::transitionConfiguring
876 
877  // get pset from Board Reader metric manager table
878  try
879  {
880  // FIXME -- this should be enabled and named by configuration!
881 
882  __COUTV__(CorePropertySupervisorBase::getSupervisorConfigurationPath());
883 
884  ConfigurationTree feSupervisorNode = CorePropertySupervisorBase::getSupervisorTableNode();
885 
886  bool enableMetricManager = false;
887  try
888  {
889  enableMetricManager = feSupervisorNode.getNode(
890  "/EnableSlowControlsMetricManager").getValue<bool>();
891  }
892  catch(...) { }//ignore error
893 
894 
895  if(enableMetricManager)
896  {
897  if(!metricMan)
898  {
899  __SUP_COUT__ << "Metric manager is not instantiated! Attempting to fix." << __E__;
900  metricMan = std::make_unique<artdaq::MetricManager>();
901  }
902  std::string metricNamePreamble = feSupervisorNode.getNode(
903  "/SlowControlsMetricManagerChannelNamePreamble").getValue<std::string>();
904  __COUTV__(metricNamePreamble);
905 
906  std::string metric_string = "epics: {metricPluginType:epics level:3 channel_name_prefix:Mu2e}";
907  fhicl::ParameterSet metric_pset;
908  fhicl::make_ParameterSet(metric_string, metric_pset);
909 
910  metricMan->initialize(metric_pset,metricNamePreamble);
911 
912  __SUP_COUT__ << "transitionConfiguring metric manager(" << metricMan <<
913  ") initialized = " << metricMan->Initialized() << __E__;
914  }
915  else
916  __SUP_COUT__ << "Metric Manager disabled." << __E__;
917  }
918  catch(const std::runtime_error& e)
919  {
920  __SS__ << "Error loading metrics in FESupervisor::transitionConfiguring(): " << e.what() << __E__;
921  __COUT_ERR__ << ss.str();
922  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
923 
924  //__SS_THROW_ONLY__;
925  theStateMachine_.setErrorMessage(ss.str());
926  throw toolbox::fsm::exception::Exception("Transition Error" /*name*/,
927  ss.str() /* message*/,
928  "FESupervisor::transitionConfiguring" /*module*/,
929  __LINE__ /*line*/,
930  __FUNCTION__ /*function*/
931  );
932  }
933  catch(...)
934  {
935  __SS__ << "Error loading metrics in FESupervisor::transitionConfiguring()" << __E__;
936  __COUT_ERR__ << ss.str();
937  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
938 
939  //__SS_THROW_ONLY__;
940  theStateMachine_.setErrorMessage(ss.str());
941  throw toolbox::fsm::exception::Exception("Transition Error" /*name*/,
942  ss.str() /* message*/,
943  "FESupervisor::transitionConfiguring" /*module*/,
944  __LINE__ /*line*/,
945  __FUNCTION__ /*function*/
946  );
947  }
948 
949  CoreSupervisorBase::transitionConfiguringFSMs();
950 
951  __SUP_COUT__ << "transitionConfiguring done." << __E__;
952 } // end transitionConfiguring()
953 
954 //==============================================================================
955 void FESupervisor::transitionHalting(toolbox::Event::Reference event)
956 {
957  __SUP_COUT__ << "transitionHalting" << __E__;
958 
959  try
960  {
961 
962  if(metricMan && metricMan->Initialized()) {
963  metricMan->shutdown(); //will set initilized_ to false with mutex, which should prevent races
964  metricMan.reset(nullptr);
965  }
966  else
967  __SUP_COUT__ << "Metric manager(" << metricMan << ") already shutdown." << __E__;
968  }
969  catch(...)
970  {
971  __SS__ << "Error shutting down metrics in FESupervisor::transitionHalting()" << __E__;
972  __COUT_ERR__ << ss.str();
973  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
974 
975  //__SS_THROW_ONLY__;
976  theStateMachine_.setErrorMessage(ss.str());
977  throw toolbox::fsm::exception::Exception("Transition Error" /*name*/,
978  ss.str() /* message*/,
979  "FESupervisor::transitionHalting" /*module*/,
980  __LINE__ /*line*/,
981  __FUNCTION__ /*function*/
982  );
983  }
984 
985  CoreSupervisorBase::transitionHalting(event);
986  __SUP_COUT__ << "transitionHalting done." << __E__;
987 } // end transitionHalting()
void startMacroMultiDimensional(const std::string &requester, const std::string &interfaceID, const std::string &macroName, const std::string &macroString, const bool enableSavingOutput, const std::string &outputFilePath, const std::string &outputFileRadix, const std::string &inputArgs)