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