artdaq_epics_plugin  v1_02_11
epics_metric.cc
1 // epics_metric.cc: Epics Metric Plugin
2 // Author: Eric Flumerfelt
3 // Last Modified: 09/25/2015
4 //
5 // An implementation of the MetricPlugin interface for Epics/ChannelAccess
6 
7 #ifndef __EPICS_METRIC__
8 #define __EPICS_METRIC__ 1
9 
10 #include <unordered_map>
11 #include "artdaq-utilities/Plugins/MetricMacros.hh"
12 #include "messagefacility/MessageLogger/MessageLogger.h"
13 #undef STATIC_ASSERT
14 
15 #ifdef __clang__
16 #pragma clang diagnostic push
17 #pragma clang diagnostic ignored "-Wunused-parameter"
18 #endif
19 #include <cadef.h>
20 #ifdef __clang__
21 #pragma clang diagnostic pop
22 #endif
23 
27 namespace artdaq {
31 class EpicsMetric : public MetricPlugin
32 {
33 private:
34  std::string prefix_;
35  std::unordered_map<std::string, chid> channels_;
36 
37  bool checkChannel_(std::string name)
38  {
39  if (!channels_.count(name))
40  {
41  chid channel;
42  ca_search(name.c_str(), &channel);
43  auto sts = ca_pend_io(5.0);
44  if (sts != ECA_NORMAL)
45  {
46  SEVCHK(ca_clear_channel(channel), NULL);
47  mf::LogWarning("EPICS Plugin") << "Channel " << name << " not found!";
48  channels_[name] = nullptr;
49  return false;
50  }
51  channels_[name] = channel;
52  return true;
53  }
54  return channels_[name] != nullptr;
55  }
56 
57  std::string parseChannelName_(std::string prefix_, std::string name)
58  {
59  std::string caName = name;
60  if (name.find(".")) caName = name.replace(name.find("."), 1, "_");
61  //if (!prefix_.compare("")) caName = prefix_ + "_" + caName;
62  caName = prefix_ + "_" + caName;
63  mf::LogDebug("EPICS Plugin") << "Channel name is: " << caName;
64  return caName;
65  }
66 
67 public:
73  explicit EpicsMetric(fhicl::ParameterSet const& pset, std::string const& app_name)
74  : MetricPlugin(pset, app_name), prefix_(pset.get<std::string>("channel_name_prefix", "artdaq")), channels_() {}
75 
76  virtual ~EpicsMetric() { MetricPlugin::stopMetrics(); }
77 
82  std::string getLibName() const override { return "epics"; }
83 
87  void stopMetrics_() override
88  {
89  for (auto channel : channels_)
90  {
91  SEVCHK(ca_clear_channel(channel.second), NULL);
92  }
93  channels_.clear();
94  }
95 
99  void startMetrics_() override {}
100 
111  void sendMetric_(const std::string& name, const std::string& value, const std::string& unit) override
112  {
113  //std::string caName = prefix_ + ":" + name;
114  std::string caName = parseChannelName_(prefix_, name);
115 
116  std::string tmpValue = value + " " + unit;
117 
118  if (checkChannel_(caName))
119  {
120  // DBR_STRING, 40 characters
121  if (tmpValue.size() > 40)
122  {
123  tmpValue = tmpValue.erase(40);
124  }
125  SEVCHK(ca_put(DBR_STRING, channels_[caName], tmpValue.c_str()), NULL);
126  SEVCHK(ca_flush_io(), NULL);
127  }
128  }
129 
140  void sendMetric_(const std::string& name, const int& value, const std::string& unit) override
141  {
142  // DBR_LONG
143  //std::string caName = prefix_ + ":" + name;
144  std::string caName = parseChannelName_(prefix_, name);
145 
146  if (unit.size() > 0)
147  {
148  mf::LogDebug("EPICS Plugin") << "Not sure if I can send ChannelAccess Units...configure in db instead.";
149  }
150 
151  if (checkChannel_(caName))
152  {
153  dbr_long_t val = static_cast<dbr_long_t>(value);
154  SEVCHK(ca_put(DBR_LONG, channels_[caName], &val), NULL);
155  SEVCHK(ca_flush_io(), NULL);
156  }
157  }
158 
169  void sendMetric_(const std::string& name, const double& value, const std::string& unit) override
170  {
171  // DBR_DOUBLE
172  //std::string caName = prefix_ + ":" + name;
173  std::string caName = parseChannelName_(prefix_, name);
174 
175  if (unit.size() > 0)
176  {
177  mf::LogDebug("EPICS Plugin") << "Not sure if I can send ChannelAccess Units...configure in db instead.";
178  }
179 
180  if (checkChannel_(caName))
181  {
182  dbr_double_t val = static_cast<dbr_double_t>(value);
183  SEVCHK(ca_put(DBR_DOUBLE, channels_[caName], &val), NULL);
184  SEVCHK(ca_flush_io(), NULL);
185  }
186  }
187 
198  void sendMetric_(const std::string& name, const float& value, const std::string& unit) override
199  {
200  // DBR_FLOAT
201  //std::string caName = prefix_ + ":" + name;
202  std::string caName = parseChannelName_(prefix_, name);
203 
204  if (unit.size() > 0)
205  {
206  mf::LogDebug("EPICS Plugin") << "Not sure if I can send ChannelAccess Units...configure in db instead.";
207  }
208 
209  if (checkChannel_(caName))
210  {
211  dbr_float_t val = static_cast<dbr_float_t>(value);
212  SEVCHK(ca_put(DBR_FLOAT, channels_[caName], &val), NULL);
213  SEVCHK(ca_flush_io(), NULL);
214  }
215  }
216 
227  void sendMetric_(const std::string& name, const unsigned long int& value, const std::string& unit) override
228  {
229  // DBR_LONG, only unsigned type is only 16 bits, use widest integral field
230  //std::string caName = prefix_ + ":" + name;
231  std::string caName = parseChannelName_(prefix_, name);
232 
233  if (unit.size() > 0)
234  {
235  mf::LogDebug("EPICS Plugin") << "Not sure if I can send ChannelAccess Units...configure in db instead.";
236  }
237 
238  if (checkChannel_(caName))
239  {
240  dbr_ulong_t val = static_cast<dbr_ulong_t>(value);
241  SEVCHK(ca_put(DBR_LONG, channels_[caName], &val), NULL);
242  SEVCHK(ca_flush_io(), NULL);
243  }
244  }
245 };
246 } // End namespace artdaq
247 
248 DEFINE_ARTDAQ_METRIC(artdaq::EpicsMetric)
249 
250 #endif // End ifndef __EPICS_METRIC__
void sendMetric_(const std::string &name, const float &value, const std::string &unit) override
Send a float metric data point to ChannelAccess.
void sendMetric_(const std::string &name, const unsigned long int &value, const std::string &unit) override
Send an unsigned integer metric data point to ChannelAccess.
An instance of the MetricPlugin class that sends metric data using the Channel Access protocol from E...
Definition: epics_metric.cc:31
void stopMetrics_() override
Clears the registered ChannelAccess channels.
Definition: epics_metric.cc:87
void startMetrics_() override
No initialization is needed to start sending metrics.
Definition: epics_metric.cc:99
std::string getLibName() const override
Gets the unique library name of this plugin.
Definition: epics_metric.cc:82
void sendMetric_(const std::string &name, const std::string &value, const std::string &unit) override
Send a string metric data point to ChannelAccess.
EpicsMetric(fhicl::ParameterSet const &pset, std::string const &app_name)
Construct an instance of the EpicsMetric plugin.
Definition: epics_metric.cc:73
void sendMetric_(const std::string &name, const double &value, const std::string &unit) override
Send a double metric data point to ChannelAccess.
void sendMetric_(const std::string &name, const int &value, const std::string &unit) override
Send an integer metric data point to ChannelAccess.