otsdaq  v1_01_03
 All Classes Namespaces Functions
FEVInterface.cc
1 #include "otsdaq-core/FECore/FEVInterface.h"
2 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
3 
4 #include "otsdaq-core/NetworkUtilities/UDPDataStreamerBase.h"
5 
6 
7 #include <iostream>
8 #include <sstream>
9 
10 using namespace ots;
11 
12 //========================================================================================================================
13 void FEVInterface::configureSlowControls(void)
14 {
15  ConfigurationTree slowControlsGroupLink =
16  theXDAQContextConfigTree_.getBackNode(
17  theConfigurationPath_).getNode("LinkToSlowControlChannelsConfiguration");
18 
19  if(slowControlsGroupLink.isDisconnected())
20  {
21  __MOUT__ << "slowControlsGroupLink is disconnected, so done configuring slow controls." <<
22  std::endl;
23  return;
24  }
25  __MOUT__ << "slowControlsGroupLink is valid! Configuring slow controls..." <<
26  std::endl;
27 
28  mapOfSlowControlsChannels_.clear();
29  std::vector<std::pair<std::string,ConfigurationTree> > groupLinkChildren =
30  slowControlsGroupLink.getChildren();
31  for(auto &groupLinkChild: groupLinkChildren)
32  {
33  //skip channels that are off
34  if(!(groupLinkChild.second.getNode("Status").getValue<bool>())) continue;
35 
36  __MOUT__ << "Channel:" << getInterfaceUID() <<
37  "/" << groupLinkChild.first << "\t Type:" <<
38  groupLinkChild.second.getNode("ChannelDataType") <<
39  std::endl;
40 
41  mapOfSlowControlsChannels_.insert(
42  std::pair<std::string,FESlowControlsChannel>(
43  groupLinkChild.first,
45  getInterfaceUID(),
46  groupLinkChild.first,
47  groupLinkChild.second.getNode("ChannelDataType").getValue<std::string>(),
48  universalDataSize_,
49  universalAddressSize_,
50  groupLinkChild.second.getNode("UniversalInterfaceAddress").getValue <std::string>(),
51  groupLinkChild.second.getNode("UniversalDataBitOffset").getValue <unsigned int>(),
52  groupLinkChild.second.getNode("ReadAccess").getValue <bool>(),
53  groupLinkChild.second.getNode("WriteAccess").getValue <bool>(),
54  groupLinkChild.second.getNode("MonitoringEnabled").getValue <bool>(),
55  groupLinkChild.second.getNode("RecordChangesOnly").getValue <bool>(),
56  groupLinkChild.second.getNode("DelayBetweenSamplesInSeconds").getValue <time_t>(),
57  groupLinkChild.second.getNode("LocalSavingEnabled").getValue <bool>(),
58  groupLinkChild.second.getNode("LocalFilePath").getValue <std::string>(),
59  groupLinkChild.second.getNode("RadixFileName").getValue <std::string>(),
60  groupLinkChild.second.getNode("SaveBinaryFile").getValue <bool>(),
61  groupLinkChild.second.getNode("AlarmsEnabled").getValue <bool>(),
62  groupLinkChild.second.getNode("LatchAlarms").getValue <bool>(),
63  groupLinkChild.second.getNode("LowLowThreshold").getValue <std::string>(),
64  groupLinkChild.second.getNode("LowThreshold").getValue <std::string>(),
65  groupLinkChild.second.getNode("HighThreshold").getValue <std::string>(),
66  groupLinkChild.second.getNode("HighHighThreshold").getValue <std::string>()
67  )));
68  }
69 
70 }
71 
72 //========================================================================================================================
73 bool FEVInterface::slowControlsRunning(void)
74 {
75  __MOUT__ << "slowControlsRunning" << std::endl;
76  std::string readVal;
77  readVal.resize(universalDataSize_); //size to data in advance
78 
79  FESlowControlsChannel *channel;
80 
81  const unsigned int txBufferSz = 1500;
82  const unsigned int txBufferFullThreshold = 750;
83  std::string txBuffer;
84  txBuffer.reserve(txBufferSz);
85 
86  ConfigurationTree FEInterfaceNode = theXDAQContextConfigTree_.getBackNode(
87  theConfigurationPath_);
88 
89  ConfigurationTree slowControlsInterfaceLink =
90  FEInterfaceNode.getNode("LinkToSlowControlsMonitorConfiguration");
91 
92  std::unique_ptr<UDPDataStreamerBase> txSocket;
93 
94  if(slowControlsInterfaceLink.isDisconnected())
95  {
96  __MOUT__ << "slowControlsInterfaceLink is disconnected, so no socket made." <<
97  std::endl;
98  }
99  else
100  {
101  __MOUT__ << "slowControlsInterfaceLink is valid! Create tx socket..." <<
102  std::endl;
103  txSocket.reset(new UDPDataStreamerBase(
104  FEInterfaceNode.getNode("SlowControlsTxSocketIPAddress").getValue <std::string>(),
105  FEInterfaceNode.getNode("SlowControlsTxSocketPort").getValue <int>(),
106  slowControlsInterfaceLink.getNode("IPAddress").getValue <std::string>(),
107  slowControlsInterfaceLink.getNode("Port").getValue <int>()
108  ));
109  }
110 
111 
112  //check if aggregate saving
113 
114 
115  FILE *fp = 0;
116  bool aggregateFileIsBinaryFormat = false;
117  if(FEInterfaceNode.getNode("SlowControlsLocalAggregateSavingEnabled").getValue<bool>())
118  {
119  aggregateFileIsBinaryFormat =
120  FEInterfaceNode.getNode("SlowControlsSaveBinaryFile").getValue<bool>();
121 
122  __MOUT_INFO__ << "Slow Controls Aggregate Saving turned On BinaryFormat=" <<
123  aggregateFileIsBinaryFormat << std::endl;
124 
125  std::string saveFullFileName =
126  FEInterfaceNode.getNode("SlowControlsLocalFilePath").getValue<std::string>() +
127  "/" +
128  FEInterfaceNode.getNode("SlowControlsRadixFileName").getValue<std::string>() +
129  "-" +
130  FESlowControlsChannel::underscoreString(getInterfaceUID()) +
131  "-" + std::to_string(time(0)) +
132  (aggregateFileIsBinaryFormat?".dat":".txt");
133 
134 
135  fp = fopen(saveFullFileName.c_str(),
136  aggregateFileIsBinaryFormat?
137  "ab":"a");
138  if(!fp)
139  {
140  __MOUT_ERR__ << "Failed to open slow controls channel file: " <<
141  saveFullFileName << std::endl;
142  //continue on, just nothing will be saved
143  }
144  else
145  __MOUT_INFO__ << "Slow controls aggregate file opened: " <<
146  saveFullFileName << std::endl;
147  }
148  else
149  __MOUT_INFO__ << "Slow Controls Aggregate Saving turned off." << std::endl;
150 
151 
152  time_t timeCounter = 0;
153 
154  while(slowControlsWorkLoop_.getContinueWorkLoop())
155  {
156  sleep(1); //seconds
157  ++timeCounter;
158 
159  if(txBuffer.size())
160  __MOUT__ << "txBuffer sz=" << txBuffer.size() << std::endl;
161 
162  txBuffer.resize(0); //clear buffer a la txBuffer = "";
163 
164  //__MOUT__ << "timeCounter=" << timeCounter << std::endl;
165  //__MOUT__ << "txBuffer sz=" << txBuffer.size() << std::endl;
166 
167  for(auto &slowControlsChannelPair : mapOfSlowControlsChannels_)
168  {
169  channel = &slowControlsChannelPair.second;
170 
171  //skip if no read access
172  if(!channel->readAccess_) continue;
173 
174  //skip if not a sampling moment in time for channel
175  if(timeCounter % channel->delayBetweenSamples_) continue;
176 
177 
178  __MOUT__ << "Channel:" << getInterfaceUID() <<
179  "/" << slowControlsChannelPair.first << std::endl;
180  __MOUT__ << "Monitoring..." << std::endl;
181 
182  universalRead(channel->getUniversalAddress(),
183  &readVal[0]);
184 
185  // { //print
186  // __SS__ << "0x ";
187  // for(int i=(int)universalAddressSize_-1;i>=0;--i)
188  // ss << std::hex << (int)((readVal[i]>>4)&0xF) <<
189  // (int)((readVal[i])&0xF) << " " << std::dec;
190  // ss << std::endl;
191  // __MOUT__ << "Sampled.\n" << ss.str();
192  // }
193 
194  //have sample
195  channel->handleSample(readVal,txBuffer, fp, aggregateFileIsBinaryFormat);
196  if(txBuffer.size())
197  __MOUT__ << "txBuffer sz=" << txBuffer.size() << std::endl;
198 
199  //make sure buffer hasn't exploded somehow
200  if(txBuffer.size() > txBufferSz)
201  {
202  __SS__ << "This should never happen hopefully!" << std::endl;
203  __MOUT_ERR__ << "\n" << ss.str();
204  throw std::runtime_error(ss.str());
205  }
206 
207  //send early if threshold reached
208  if(txSocket &&
209  txBuffer.size() > txBufferFullThreshold)
210  {
211  __MOUT__ << "Sending now! txBufferFullThreshold=" << txBufferFullThreshold << std::endl;
212  txSocket->send(txBuffer);
213  txBuffer.resize(0); //clear buffer a la txBuffer = "";
214  }
215 
216 
217  }
218 
219  if(txBuffer.size())
220  __MOUT__ << "txBuffer sz=" << txBuffer.size() << std::endl;
221 
222  //send anything left
223  if(txSocket &&
224  txBuffer.size())
225  {
226  __MOUT__ << "Sending now!" << std::endl;
227  txSocket->send(txBuffer);
228  }
229 
230  if(fp) fflush(fp); //flush anything in aggregate file for reading ease
231  }
232  if(fp) fclose(fp);
233  return false;
234 }
235 
236 //========================================================================================================================
237 //registerFEMacroFunction
238 // used by user-defined front-end interface implementations of this
239 // virtual interface class to register their macro functions.
240 //
241 // Front-end Macro Functions are then made accessible through the ots Control System
242 // web interfaces. The menu consisting of all enabled FEs macros is assembled
243 // by the FE Supervisor (and its FE Interface Manager).
244 void FEVInterface::registerFEMacroFunction(
245  const std::string &feMacroName, frontEndMacroFunction_t feMacroFunction,
246  const std::vector<std::string> &namesOfInputArgs,
247  const std::vector<std::string> &namesOfOutputArgs,
248  uint8_t requiredUserPermissions)
249 {
250  if(mapOfFEMacroFunctions_.find(feMacroName) !=
251  mapOfFEMacroFunctions_.end())
252  {
253  __SS__ << "feMacroName '" << feMacroName << "' already exists! Not allowed." << std::endl;
254  __MOUT_ERR__ << "\n" << ss.str();
255  throw std::runtime_error(ss.str());
256  }
257 
258  mapOfFEMacroFunctions_.insert(
259  std::pair<std::string, frontEndMacroStruct_t> (
260  feMacroName,
261  frontEndMacroStruct_t(
262  feMacroFunction,
263  namesOfInputArgs,
264  namesOfOutputArgs,
265  requiredUserPermissions
266  )));
267 }
268 
269 
270 //========================================================================================================================
271 //getInputArgumentString
272 // helper function for getting the value of an argument
273 const std::string& FEVInterface::getFEMacroInputArgument(frontEndMacroInArgs_t& argsIn,
274  const std::string& argName)
275 {
276 
277  for(const std::pair<const std::string /* input arg name */ , const std::string /* arg input value */ >&
278  pair : argsIn)
279  {
280  if(pair.first == argName)
281  return pair.second;
282  }
283  __SS__ << "Requested input argument not found with name '" << argName << "'" << std::endl;
284  __MOUT_ERR__ << "\n" << ss.str();
285  throw std::runtime_error(ss.str());
286 }
287 
288 //========================================================================================================================
289 //getOutputArgumentString
290 // helper function for getting the value of an argument
291 std::string& FEVInterface::getFEMacroOutputArgument(frontEndMacroOutArgs_t& argsOut,
292  const std::string& argName)
293 {
294 
295  for(std::pair<const std::string /* output arg name */ , std::string /* arg output value */ >&
296  pair : argsOut)
297  {
298  if(pair.first == argName)
299  return pair.second;
300  }
301  __SS__ << "Requested output argument not found with name '" << argName << "'" << std::endl;
302  __MOUT_ERR__ << "\n" << ss.str();
303  throw std::runtime_error(ss.str());
304 }
305 
306 
307 
308 
309 
310 
311 
312 
313 
314 
315 
316 
317 
318 
319 
320 
321 
322 
323 
324 
325 
326 
327 
328 
329 
330 
331 
332