00001 #include "otsdaq-core/FECore/FEVInterface.h"
00002 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
00003
00004 #include "otsdaq-core/NetworkUtilities/UDPDataStreamerBase.h"
00005
00006
00007 #include <iostream>
00008 #include <sstream>
00009
00010 using namespace ots;
00011
00012
00013 void FEVInterface::configureSlowControls(void)
00014 {
00015 ConfigurationTree slowControlsGroupLink =
00016 theXDAQContextConfigTree_.getBackNode(
00017 theConfigurationPath_).getNode("LinkToSlowControlChannelsConfiguration");
00018
00019 if(slowControlsGroupLink.isDisconnected())
00020 {
00021 __MOUT__ << "slowControlsGroupLink is disconnected, so done configuring slow controls." <<
00022 std::endl;
00023 return;
00024 }
00025 __MOUT__ << "slowControlsGroupLink is valid! Configuring slow controls..." <<
00026 std::endl;
00027
00028 mapOfSlowControlsChannels_.clear();
00029 std::vector<std::pair<std::string,ConfigurationTree> > groupLinkChildren =
00030 slowControlsGroupLink.getChildren();
00031 for(auto &groupLinkChild: groupLinkChildren)
00032 {
00033
00034 if(!(groupLinkChild.second.getNode("Status").getValue<bool>())) continue;
00035
00036 __MOUT__ << "Channel:" << getInterfaceUID() <<
00037 "/" << groupLinkChild.first << "\t Type:" <<
00038 groupLinkChild.second.getNode("ChannelDataType") <<
00039 std::endl;
00040
00041 mapOfSlowControlsChannels_.insert(
00042 std::pair<std::string,FESlowControlsChannel>(
00043 groupLinkChild.first,
00044 FESlowControlsChannel(
00045 getInterfaceUID(),
00046 groupLinkChild.first,
00047 groupLinkChild.second.getNode("ChannelDataType").getValue<std::string>(),
00048 universalDataSize_,
00049 universalAddressSize_,
00050 groupLinkChild.second.getNode("UniversalInterfaceAddress").getValue <std::string>(),
00051 groupLinkChild.second.getNode("UniversalDataBitOffset").getValue <unsigned int>(),
00052 groupLinkChild.second.getNode("ReadAccess").getValue <bool>(),
00053 groupLinkChild.second.getNode("WriteAccess").getValue <bool>(),
00054 groupLinkChild.second.getNode("MonitoringEnabled").getValue <bool>(),
00055 groupLinkChild.second.getNode("RecordChangesOnly").getValue <bool>(),
00056 groupLinkChild.second.getNode("DelayBetweenSamplesInSeconds").getValue <time_t>(),
00057 groupLinkChild.second.getNode("LocalSavingEnabled").getValue <bool>(),
00058 groupLinkChild.second.getNode("LocalFilePath").getValue <std::string>(),
00059 groupLinkChild.second.getNode("RadixFileName").getValue <std::string>(),
00060 groupLinkChild.second.getNode("SaveBinaryFile").getValue <bool>(),
00061 groupLinkChild.second.getNode("AlarmsEnabled").getValue <bool>(),
00062 groupLinkChild.second.getNode("LatchAlarms").getValue <bool>(),
00063 groupLinkChild.second.getNode("LowLowThreshold").getValue <std::string>(),
00064 groupLinkChild.second.getNode("LowThreshold").getValue <std::string>(),
00065 groupLinkChild.second.getNode("HighThreshold").getValue <std::string>(),
00066 groupLinkChild.second.getNode("HighHighThreshold").getValue <std::string>()
00067 )));
00068 }
00069
00070 }
00071
00072
00073 bool FEVInterface::slowControlsRunning(void)
00074 {
00075 __MOUT__ << "slowControlsRunning" << std::endl;
00076 std::string readVal;
00077 readVal.resize(universalDataSize_);
00078
00079 FESlowControlsChannel *channel;
00080
00081 const unsigned int txBufferSz = 1500;
00082 const unsigned int txBufferFullThreshold = 750;
00083 std::string txBuffer;
00084 txBuffer.reserve(txBufferSz);
00085
00086 ConfigurationTree FEInterfaceNode = theXDAQContextConfigTree_.getBackNode(
00087 theConfigurationPath_);
00088
00089 ConfigurationTree slowControlsInterfaceLink =
00090 FEInterfaceNode.getNode("LinkToSlowControlsMonitorConfiguration");
00091
00092 std::unique_ptr<UDPDataStreamerBase> txSocket;
00093
00094 if(slowControlsInterfaceLink.isDisconnected())
00095 {
00096 __MOUT__ << "slowControlsInterfaceLink is disconnected, so no socket made." <<
00097 std::endl;
00098 }
00099 else
00100 {
00101 __MOUT__ << "slowControlsInterfaceLink is valid! Create tx socket..." <<
00102 std::endl;
00103 txSocket.reset(new UDPDataStreamerBase(
00104 FEInterfaceNode.getNode("SlowControlsTxSocketIPAddress").getValue <std::string>(),
00105 FEInterfaceNode.getNode("SlowControlsTxSocketPort").getValue <int>(),
00106 slowControlsInterfaceLink.getNode("IPAddress").getValue <std::string>(),
00107 slowControlsInterfaceLink.getNode("Port").getValue <int>()
00108 ));
00109 }
00110
00111
00112
00113
00114
00115 FILE *fp = 0;
00116 bool aggregateFileIsBinaryFormat = false;
00117 if(FEInterfaceNode.getNode("SlowControlsLocalAggregateSavingEnabled").getValue<bool>())
00118 {
00119 aggregateFileIsBinaryFormat =
00120 FEInterfaceNode.getNode("SlowControlsSaveBinaryFile").getValue<bool>();
00121
00122 __MOUT_INFO__ << "Slow Controls Aggregate Saving turned On BinaryFormat=" <<
00123 aggregateFileIsBinaryFormat << std::endl;
00124
00125 std::string saveFullFileName =
00126 FEInterfaceNode.getNode("SlowControlsLocalFilePath").getValue<std::string>() +
00127 "/" +
00128 FEInterfaceNode.getNode("SlowControlsRadixFileName").getValue<std::string>() +
00129 "-" +
00130 FESlowControlsChannel::underscoreString(getInterfaceUID()) +
00131 "-" + std::to_string(time(0)) +
00132 (aggregateFileIsBinaryFormat?".dat":".txt");
00133
00134
00135 fp = fopen(saveFullFileName.c_str(),
00136 aggregateFileIsBinaryFormat?
00137 "ab":"a");
00138 if(!fp)
00139 {
00140 __MOUT_ERR__ << "Failed to open slow controls channel file: " <<
00141 saveFullFileName << std::endl;
00142
00143 }
00144 else
00145 __MOUT_INFO__ << "Slow controls aggregate file opened: " <<
00146 saveFullFileName << std::endl;
00147 }
00148 else
00149 __MOUT_INFO__ << "Slow Controls Aggregate Saving turned off." << std::endl;
00150
00151
00152 time_t timeCounter = 0;
00153
00154 while(slowControlsWorkLoop_.getContinueWorkLoop())
00155 {
00156 sleep(1);
00157 ++timeCounter;
00158
00159 if(txBuffer.size())
00160 __MOUT__ << "txBuffer sz=" << txBuffer.size() << std::endl;
00161
00162 txBuffer.resize(0);
00163
00164
00165
00166
00167 for(auto &slowControlsChannelPair : mapOfSlowControlsChannels_)
00168 {
00169 channel = &slowControlsChannelPair.second;
00170
00171
00172 if(!channel->readAccess_) continue;
00173
00174
00175 if(timeCounter % channel->delayBetweenSamples_) continue;
00176
00177
00178 __MOUT__ << "Channel:" << getInterfaceUID() <<
00179 "/" << slowControlsChannelPair.first << std::endl;
00180 __MOUT__ << "Monitoring..." << std::endl;
00181
00182 universalRead(channel->getUniversalAddress(),
00183 &readVal[0]);
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 channel->handleSample(readVal,txBuffer, fp, aggregateFileIsBinaryFormat);
00196 if(txBuffer.size())
00197 __MOUT__ << "txBuffer sz=" << txBuffer.size() << std::endl;
00198
00199
00200 if(txBuffer.size() > txBufferSz)
00201 {
00202 __SS__ << "This should never happen hopefully!" << std::endl;
00203 __MOUT_ERR__ << "\n" << ss.str();
00204 throw std::runtime_error(ss.str());
00205 }
00206
00207
00208 if(txSocket &&
00209 txBuffer.size() > txBufferFullThreshold)
00210 {
00211 __MOUT__ << "Sending now! txBufferFullThreshold=" << txBufferFullThreshold << std::endl;
00212 txSocket->send(txBuffer);
00213 txBuffer.resize(0);
00214 }
00215
00216
00217 }
00218
00219 if(txBuffer.size())
00220 __MOUT__ << "txBuffer sz=" << txBuffer.size() << std::endl;
00221
00222
00223 if(txSocket &&
00224 txBuffer.size())
00225 {
00226 __MOUT__ << "Sending now!" << std::endl;
00227 txSocket->send(txBuffer);
00228 }
00229
00230 if(fp) fflush(fp);
00231 }
00232 if(fp) fclose(fp);
00233 return false;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 void FEVInterface::registerFEMacroFunction(
00245 const std::string &feMacroName, frontEndMacroFunction_t feMacroFunction,
00246 const std::vector<std::string> &namesOfInputArgs,
00247 const std::vector<std::string> &namesOfOutputArgs,
00248 uint8_t requiredUserPermissions)
00249 {
00250 if(mapOfFEMacroFunctions_.find(feMacroName) !=
00251 mapOfFEMacroFunctions_.end())
00252 {
00253 __SS__ << "feMacroName '" << feMacroName << "' already exists! Not allowed." << std::endl;
00254 __MOUT_ERR__ << "\n" << ss.str();
00255 throw std::runtime_error(ss.str());
00256 }
00257
00258 mapOfFEMacroFunctions_.insert(
00259 std::pair<std::string, frontEndMacroStruct_t> (
00260 feMacroName,
00261 frontEndMacroStruct_t(
00262 feMacroFunction,
00263 namesOfInputArgs,
00264 namesOfOutputArgs,
00265 requiredUserPermissions
00266 )));
00267 }
00268
00269
00270
00271
00272
00273 const std::string& FEVInterface::getFEMacroInputArgument(frontEndMacroInArgs_t& argsIn,
00274 const std::string& argName)
00275 {
00276
00277 for(const std::pair<const std::string /* input arg name */ , const std::string /* arg input value */ >&
00278 pair : argsIn)
00279 {
00280 if(pair.first == argName)
00281 return pair.second;
00282 }
00283 __SS__ << "Requested input argument not found with name '" << argName << "'" << std::endl;
00284 __MOUT_ERR__ << "\n" << ss.str();
00285 throw std::runtime_error(ss.str());
00286 }
00287
00288
00289
00290
00291 std::string& FEVInterface::getFEMacroOutputArgument(frontEndMacroOutArgs_t& argsOut,
00292 const std::string& argName)
00293 {
00294
00295 for(std::pair<const std::string /* output arg name */ , std::string /* arg output value */ >&
00296 pair : argsOut)
00297 {
00298 if(pair.first == argName)
00299 return pair.second;
00300 }
00301 __SS__ << "Requested output argument not found with name '" << argName << "'" << std::endl;
00302 __MOUT_ERR__ << "\n" << ss.str();
00303 throw std::runtime_error(ss.str());
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332