artdaq_demo  v3_09_01
AsciiSimulator_generator.cc
1 #include "artdaq-demo/Generators/AsciiSimulator.hh"
2 
3 #include "canvas/Utilities/Exception.h"
4 
5 #include "artdaq-core-demo/Overlays/AsciiFragment.hh"
6 #include "artdaq-core-demo/Overlays/AsciiFragmentWriter.hh"
7 #include "artdaq-core-demo/Overlays/FragmentType.hh"
8 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
9 #include "artdaq/Generators/GeneratorMacros.hh"
10 #include "cetlib_except/exception.h"
11 #include "fhiclcpp/ParameterSet.h"
12 
13 #include <fstream>
14 #include <iomanip>
15 #include <iostream>
16 #include <iterator>
17 
18 #include <unistd.h>
19 
20 namespace {
27 template<typename T>
28 T convertToASCII(std::string input)
29 {
30  if (input.size() < sizeof(T) / sizeof(char))
31  {
32  input.insert(0, sizeof(T) / sizeof(char) - input.size(), ' ');
33  }
34  else if (input.size() > sizeof(T) / sizeof(char))
35  {
36  input.erase(0, input.size() - sizeof(T) / sizeof(char));
37  }
38 
39  uint64_t bigOutput = 0ull;
40  // std::ofstream outputStr ("/tmp/ASCIIConverter.bin", std::ios::out | std::ios::app | std::ios::binary );
41  for (uint i = 0; i < input.length(); ++i)
42  {
43  // outputStr.write((char*)&input[i],sizeof(char));
44  bigOutput *= 0x100;
45  bigOutput += input[input.length() - i - 1];
46  }
47 
48  // outputStr.close();
49  return static_cast<T>(bigOutput);
50 }
51 } // namespace
52 
53 demo::AsciiSimulator::AsciiSimulator(fhicl::ParameterSet const& ps)
54  : CommandableFragmentGenerator(ps)
55  , throttle_usecs_(ps.get<size_t>("throttle_usecs", 100000))
56  , string1_(ps.get<std::string>("string1", "All work and no play makes ARTDAQ a dull library"))
57  , string2_(ps.get<std::string>("string2", "Hey, look at what ARTDAQ can do!"))
58  , timestamp_(0)
59  , timestampScale_(ps.get<int>("timestamp_scale_factor", 1))
60 {}
61 
62 bool demo::AsciiSimulator::getNext_(artdaq::FragmentPtrs& frags)
63 {
64  // JCF, 9/23/14
65 
66  // If throttle_usecs_ is greater than zero (i.e., user requests a
67  // sleep interval before generating the pseudodata) then during that
68  // interval perform a periodic check to see whether a stop request
69  // has been received
70 
71  // Values for throttle_usecs_ and throttle_usecs_check_ will have
72  // been tested for validity in constructor
73 
74  if (throttle_usecs_ > 0)
75  {
76  size_t nchecks = throttle_usecs_ / 10000;
77 
78  for (size_t i_c = 0; i_c < nchecks; ++i_c)
79  {
80  usleep(throttle_usecs_ / 10000);
81 
82  if (should_stop())
83  {
84  return false;
85  }
86  }
87  }
88  else
89  {
90  if (should_stop())
91  {
92  return false;
93  }
94  }
95 
96  // Set fragment's metadata
97  size_t data_size = (ev_counter() % 2) != 0u ? string1_.length() + 2 : string2_.length() + 2;
98  AsciiFragment::Metadata metadata;
99  std::string size_string = "S:" + std::to_string(data_size) + ",";
100  metadata.charsInLine = convertToASCII<AsciiFragment::Metadata::chars_in_line_t>(size_string);
101 
102  // And use it, along with the artdaq::Fragment header information
103  // (fragment id, sequence id, and user type) to create a fragment
104 
105  // We'll use the static factory function
106 
107  // artdaq::Fragment::FragmentBytes(std::size_t payload_size_in_bytes, sequence_id_t sequence_id,
108  // fragment_id_t fragment_id, type_t type, const T & metadata)
109 
110  // which will then return a unique_ptr to an artdaq::Fragment
111  // object. The advantage of this approach over using the
112  // artdaq::Fragment constructor is that, if we were to want to
113  // initialize the artdaq::Fragment with a nonzero-size payload (data
114  // after the artdaq::Fragment header and metadata), we could provide
115  // the size of the payload in bytes, rather than in units of the
116  // artdaq::Fragment's RawDataType (8 bytes, as of 3/26/14). The
117  // artdaq::Fragment constructor itself was not altered so as to
118  // maintain backward compatibility.
119 
120  std::size_t initial_payload_size = 0;
121 
122  std::unique_ptr<artdaq::Fragment> fragptr(artdaq::Fragment::FragmentBytes(
123  initial_payload_size, ev_counter(), fragment_id(), FragmentType::ASCII, metadata, timestamp_));
124  frags.emplace_back(std::move(fragptr));
125 
126  // Then any overlay-specific quantities next; will need the
127  // AsciiFragmentWriter class's setter-functions for this
128 
129  AsciiFragmentWriter newfrag(*frags.back());
130 
131  newfrag.set_hdr_line_number(
132  convertToASCII<AsciiFragment::Header::line_number_t>("LN:" + std::to_string(ev_counter()) + ","));
133 
134  newfrag.resize(data_size);
135 
136  // Now, generate the payload, based on the string to use
137  std::string string_to_use = (ev_counter() % 2) != 0u ? string1_ : string2_;
138  string_to_use += "\r\n";
139 
140  // std::ofstream output ("/tmp/ASCIIGenerator.bin", std::ios::out | std::ios::app | std::ios::binary );
141  for (uint i = 0; i < string_to_use.length(); ++i)
142  {
143  // output.write((char*)&string_to_use[i],sizeof(char));
144  *(newfrag.dataBegin() + i) = string_to_use[i]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
145  }
146  // output.close();
147 
148  ev_counter_inc();
149  timestamp_ += timestampScale_;
150 
151  return true;
152 }
153 
154 // The following macro is defined in artdaq's GeneratorMacros.hh header
155 DEFINE_ARTDAQ_COMMANDABLE_GENERATOR(demo::AsciiSimulator)
Generates ASCIIFragments filled with user-specified ASCII strings.
AsciiSimulator(fhicl::ParameterSet const &ps)
AsciiSimulator Constructor.
T convertToASCII(std::string input)
Convert sizeof(T) characters of a string to a number containing the ASCII representation of that stri...