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