otsdaq  v2_04_02
FEVInterface.h
1 #ifndef _ots_FEVInterface_h_
2 #define _ots_FEVInterface_h_
3 
4 #define TRACE_NAME "FEVInterface"
5 #include "artdaq/DAQdata/Globals.hh"
6 
7 #include "otsdaq/Configurable/Configurable.h"
8 #include "otsdaq/FECore/FESlowControlsWorkLoop.h"
9 #include "otsdaq/FiniteStateMachine/VStateMachine.h"
10 #include "otsdaq/WorkLoopManager/WorkLoop.h"
11 
12 #include "otsdaq/CoreSupervisors/CoreSupervisorBase.h"
13 
14 #include "otsdaq/SupervisorInfo/AllSupervisorInfo.h" //to send errors to Gateway, e.g.
15 
16 #include "otsdaq/CoreSupervisors/FESupervisor.h"
17 
18 #include "otsdaq/FECore/FESlowControlsChannel.h"
19 #include "otsdaq/SOAPUtilities/SOAPMessenger.h" //for xdaq::ApplicationDescriptor communication
20 
21 #include <array>
22 #include <iostream>
23 #include <string>
24 #include <vector>
25 
26 #include "otsdaq/Macros/CoutMacros.h"
27 
28 #define __ARGS__ \
29  const frontEndMacroStruct_t & feMacroStruct, \
30  FEVInterface::frontEndMacroConstArgs_t argsIn, \
31  FEVInterface::frontEndMacroArgs_t argsOut
32 
33 #define __GET_ARG_IN__(X, Y) getFEMacroConstArgumentValue<Y>(argsIn, X)
34 #define __GET_ARG_OUT__(X, Y) getFEMacroArgumentValue<Y>(argsOut, X)
35 
36 #define __SET_ARG_IN__(X, Y) FEVInterface::emplaceFEMacroArgumentValue(argsIn, X, Y)
37 #define __SET_ARG_OUT__(X, Y) FEVInterface::setFEMacroArgumentValue(argsOut, X, Y)
38 
39 namespace ots
40 {
41 class FEVInterfacesManager;
42 
43 // FEVInterface
44 // This class is a virtual class defining the features of front-end interface plugin
45 // class. The features include configuration hooks, finite state machine handlers,
46 // Front-end Macros for web accessible C++ handlers, slow controls hooks, as well as
47 // universal write and read for Macro Maker compatibility.
48 //
49 // It inherits workloop as 'public virtual' for the case that other classes like
50 // DataProducer will also be inherited by child class and only one workloop is
51 // desired.
52 class FEVInterface : public VStateMachine, public WorkLoop, public Configurable
53 {
54  // clang-format off
55 
56  friend class FEVInterfacesManager;
57 
58  public:
60  const std::string& interfaceUID,
61  const ConfigurationTree& theXDAQContextConfigTree,
62  const std::string& configurationPath);
63 
64  virtual ~FEVInterface(void);
65 
66 
67  FEVInterfacesManager* parentInterfaceManager_;
68 
69  const std::string& getInterfaceUID (void) const { return interfaceUID_; }
70  virtual std::string getInterfaceType (void) const
71  {
72  return theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
73  .getNode("FEInterfacePluginName")
74  .getValue<std::string>();
75  } // end getInterfaceType()
76 
77  virtual void universalRead (char* address, char* returnValue) = 0; // throw std::runtime_error exception on error/timeout
78  virtual void universalWrite (char* address, char* writeValue) = 0;
79  const unsigned int& getUniversalAddressSize (void) { return universalAddressSize_; }
80  const unsigned int& getUniversalDataSize (void) { return universalDataSize_; }
81 
82  void runSequenceOfCommands (const std::string& treeLinkName);
83 
84  static void sendAsyncErrorToGateway (FEVInterface* fe, const std::string& errMsg, bool isSoftError);
85 
87  // start State Machine handlers
88  void configure (void)
89  {
90  __COUT__ << "\t Configure" << std::endl;
91  runSequenceOfCommands(
92  "LinkToConfigureSequence"); /*Run Configure Sequence Commands*/
93  }
94  void start (std::string runNumber)
95  {
96  __COUT__ << "\t Start" << std::endl;
97  runSequenceOfCommands("LinkToStartSequence"); /*Run Start Sequence Commands*/
98  }
99  void stop (void)
100  {
101  __COUT__ << "\t Stop" << std::endl;
102  runSequenceOfCommands("LinkToStopSequence"); /*Run Stop Sequence Commands*/
103  }
104  void halt (void) { stop(); }
105  void pause (void) { stop(); }
106  void resume (void) { start(""); }
107  bool running (void) { /*while(WorkLoop::continueWorkLoop_){;}*/ return false; }
108  // end State Machine handlers
110 
112  // start Slow Controls
113  virtual void configureSlowControls (void);
114  void addSlowControlsChannels (ConfigurationTree slowControlsGroupLink, const std::string& subInterfaceID, std::map<std::string /* ROC UID*/, FESlowControlsChannel>* mapOfSlowControlsChannels);
115 
116  virtual void resetSlowControlsChannelIterator (void);
117  virtual FESlowControlsChannel* getNextSlowControlsChannel (void);
118  virtual unsigned int getSlowControlsChannelCount (void);
119  virtual void getSlowControlsValue (FESlowControlsChannel& channel, std::string& readValue);
120  bool slowControlsRunning (void); // slow controls workloop calls this
121  void startSlowControlsWorkLoop (void) { slowControlsWorkLoop_.startWorkLoop(); }
122  void stopSlowControlsWorkLoop (void) { slowControlsWorkLoop_.stopWorkLoop(); }
123 
124  protected:
125  // Slow Controls members
126  std::map<std::string, FESlowControlsChannel> mapOfSlowControlsChannels_;
127  std::map<std::string,
128  FESlowControlsChannel>::iterator slowControlsChannelsIterator_;
129  FESlowControlsWorkLoop slowControlsWorkLoop_;
130  // end Slow Controls
132 
134  // start FE Macros
135  public:
136  // public types and functions for map of FE macros
137  using frontEndMacroArg_t = std::pair<const std::string /* arg name */, std::string /* arg return value */>;
138  using frontEndMacroArgs_t = std::vector<frontEndMacroArg_t>&;
139  using frontEndMacroConstArgs_t = const std::vector<frontEndMacroArg_t>&;
140  struct frontEndMacroStruct_t; // declare name for __ARGS__
141  using frontEndMacroFunction_t = void (ots::FEVInterface::*)(__ARGS__); // void function (vector-of-inputs, vector-of-outputs)
142  struct frontEndMacroStruct_t // members fully define a front-end macro function
143  {
145  const std::string& feMacroName,
146  const frontEndMacroFunction_t& feMacroFunction,
147  const std::vector<std::string>& namesOfInputArgs,
148  const std::vector<std::string>& namesOfOutputArgs,
149  const uint8_t requiredUserPermissions = 1 /*1:=user,255:=admin*/,
150  const std::string& allowedCallingFrontEnds = "*" /*StringMacros:: wild card set match string (i.e. string-to-set, then wild-card-set match)*/)
151  : feMacroName_ (feMacroName)
152  , macroFunction_ (feMacroFunction)
153  , namesOfInputArguments_ (namesOfInputArgs)
154  , namesOfOutputArguments_ (namesOfOutputArgs)
155  , requiredUserPermissions_ (requiredUserPermissions)
156  , allowedCallingFrontEnds_ (allowedCallingFrontEnds)
157  {
158  }
159 
160  const std::string feMacroName_;
161  const frontEndMacroFunction_t macroFunction_; // Note: must be called using this instance
162  const std::vector<std::string> namesOfInputArguments_, namesOfOutputArguments_;
163  const uint8_t requiredUserPermissions_;
164  const std::string allowedCallingFrontEnds_;
165  }; //end frontEndMacroStruct_t
166  const std::map<std::string, frontEndMacroStruct_t>& getMapOfFEMacroFunctions(void)
167  {
168  return mapOfFEMacroFunctions_;
169  }
170  void runSelfFrontEndMacro (
171  const std::string& feMacroName,
172  const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs,
173  std::vector<FEVInterface::frontEndMacroArg_t>& outputArgs);
174  // end FE Macros
176 
178  // start Macros
180  {
181  macroStruct_t(const std::string& macroString);
182 
183  enum
184  {
185  OP_TYPE_READ,
186  OP_TYPE_WRITE,
187  OP_TYPE_DELAY,
188  };
189 
190  struct readOp_t
191  {
192  uint64_t address_;
193  bool addressIsVar_;
194  std::string addressVarName_;
195  bool dataIsVar_;
196  std::string dataVarName_;
197  }; // end macroStruct_t::writeOp_t declaration
198 
199  struct writeOp_t
200  {
201  uint64_t address_;
202  bool addressIsVar_;
203  std::string addressVarName_;
204  uint64_t data_;
205  bool dataIsVar_;
206  std::string dataVarName_;
207  }; // end macroStruct_t::writeOp_t declaration
208 
209  struct delayOp_t
210  {
211  uint64_t delay_; // milliseconds
212  bool delayIsVar_;
213  std::string delayVarName_;
214  }; // end macroStruct_t::writeOp_t declaration
215 
216  std::string macroName_;
217  std::vector<std::pair<unsigned int /*op type*/,
218  unsigned int /*index in specific type vector*/> >
219  operations_;
220  std::vector<macroStruct_t::readOp_t> readOps_;
221  std::vector<macroStruct_t::writeOp_t> writeOps_;
222  std::vector<macroStruct_t::delayOp_t> delayOps_;
223  std::set<std::string> namesOfInputArguments_, namesOfOutputArguments_;
224  bool lsbf_; // least significant byte first
225  }; // end macroStruct_t declaration
226  protected:
227  void runMacro(FEVInterface::macroStruct_t& macro,
228  std::map<std::string /*name*/, uint64_t /*value*/>& variableMap);
229 
230  public:
231  // end FE Macros
233 
235  // start FE communication helpers
236 
237  template<class T>
238  void sendToFrontEnd (const std::string& targetInterfaceID, const T& value) const;
239  void runFrontEndMacro (const std::string& targetInterfaceID,const std::string& feMacroName, const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs, std::vector<FEVInterface::frontEndMacroArg_t>& outputArgs) const;
240 
242  // receiveFromFrontEnd
243  // * can be used for source interface ID to accept a message from any front-end
244  // NOTE: can not overload functions based on return type, so T& passed as value
245  template<class T>
246  void receiveFromFrontEnd (const std::string& requester, T& retValue, unsigned int timeoutInSeconds = 1) const;
247  // specialized template function for T=std::string
248  void receiveFromFrontEnd (const std::string& requester, std::string& retValue, unsigned int timeoutInSeconds = 1) const;
249  // NOTE: can not overload functions based on return type, so calls function with T&
250  // passed as value
251  template<class T>
252  T receiveFromFrontEnd (const std::string& requester = "*", unsigned int timeoutInSeconds = 1) const;
253  // specialized template function for T=std::string
254  std::string receiveFromFrontEnd (const std::string& requester = "*", unsigned int timeoutInSeconds = 1) const;
255 
256  // end FE Communication helpers
258 
259  protected:
260  bool workLoopThread (toolbox::task::WorkLoop* workLoop);
261 
262  std::string interfaceUID_;
263 
264  unsigned int universalAddressSize_ = 0;
265  unsigned int universalDataSize_ = 0;
266 
267 
268  // FE Macro Function members and helper functions:
269 
270  std::map<std::string, frontEndMacroStruct_t> mapOfFEMacroFunctions_; // Map of FE Macro functions members
271  void registerFEMacroFunction (
272  const std::string& feMacroName,
273  frontEndMacroFunction_t feMacroFunction,
274  const std::vector<std::string>& namesOfInputArgs,
275  const std::vector<std::string>& namesOfOutputArgs,
276  uint8_t requiredUserPermissions = 1 /*1:=user,255:=admin*/,
277  const std::string& allowedCallingFEs = "*" /*StringMacros:: wild card set match string (i.e. string-to-set, then wild-card-set match)*/);
278 
279  public: // for external specialized template access
280  static const std::string& getFEMacroConstArgument (frontEndMacroConstArgs_t args, const std::string& argName);
281  static std::string& getFEMacroArgument (frontEndMacroArgs_t args, const std::string& argName);
282 
283  protected:
284  template<class T>
285  std::string& setFEMacroArgumentValue (frontEndMacroArgs_t args, const std::string& argName, const T& value) const;
286 
287  template<class T>
288  std::string& emplaceFEMacroArgumentValue (frontEndMacroArgs_t args, const std::string& argName, const T& value) const;
289 
290 
291 }; // end FEVInterface class
292 
293 template<class T>
294 T getFEMacroConstArgumentValue (FEVInterface::frontEndMacroConstArgs_t args, const std::string& argName);
295 
296 // specialized template version of getFEMacroConstArgumentValue for string
297 template<>
298 std::string getFEMacroConstArgumentValue<std::string> (FEVInterface::frontEndMacroConstArgs_t args, const std::string& argName);
299 
300 template<class T>
301 T getFEMacroArgumentValue (FEVInterface::frontEndMacroArgs_t args, const std::string& argName);
302 
303 // specialized template version of getFEMacroArgumentValue for string
304 template<>
305 std::string getFEMacroArgumentValue<std::string> (FEVInterface::frontEndMacroArgs_t argsIn, const std::string& argName);
306 
307 // include template definitions required at include level for compiler
308 #include "otsdaq/FECore/FEVInterface.icc"
309 
310 // clang-format on
311 
312 } // namespace ots
313 
314 #endif