Goby v2
test.cpp
1 // Copyright 2009-2018 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 //
5 //
6 // This file is part of the Goby Underwater Autonomy Project Binaries
7 // ("The Goby Binaries").
8 //
9 // The Goby Binaries are free software: you can redistribute them and/or modify
10 // them under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // The Goby Binaries are distributed in the hope that they will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
21 
22 // tests functionality of the MMDriver WHOI Micro-Modem driver
23 
24 #include "goby/acomms/connect.h"
25 #include "goby/acomms/modemdriver/mm_driver.h"
26 #include "goby/common/application_base.h"
27 #include "goby/common/logger.h"
28 #include "goby/util/binary.h"
29 #include "test_config.pb.h"
30 using namespace goby::acomms;
31 using namespace goby::common::logger;
32 using namespace goby::common::logger_lock;
34 using goby::util::as;
35 using namespace boost::posix_time;
36 
37 boost::mutex driver_mutex;
38 int last_transmission_index = 0;
39 
41 {
42  public:
44 
45  private:
46  void iterate();
47 
49 
50  void handle_transmit_result1(const protobuf::ModemTransmission& msg);
51  void handle_data_receive1(const protobuf::ModemTransmission& msg);
52 
53  void handle_transmit_result2(const protobuf::ModemTransmission& msg);
54  void handle_data_receive2(const protobuf::ModemTransmission& msg);
55 
56  void
57  summary(const std::map<int, std::vector<micromodem::protobuf::ReceiveStatistics> >& receive,
59 
60  private:
62 
63  goby::acomms::MMDriver driver1, driver2;
64  // maps transmit index to receive statistics
65  std::map<int, std::vector<micromodem::protobuf::ReceiveStatistics> > driver1_receive,
66  driver2_receive;
67 
68  bool modems_running_;
69 };
70 
71 MMDriverTest2::MMDriverTest2(goby::test::protobuf::MMDriverTest2Config* cfg)
72  : ApplicationBase(cfg), cfg_(*cfg), modems_running_(true)
73 {
74  goby::glog.set_lock_action(lock);
75 
76  goby::glog.is(VERBOSE) && goby::glog << "Running test: " << cfg_ << std::endl;
77 }
78 
79 void MMDriverTest2::iterate()
80 {
81  goby::acomms::connect(&driver1.signal_receive, this, &MMDriverTest2::handle_data_receive1);
82  goby::acomms::connect(&driver1.signal_transmit_result, this,
83  &MMDriverTest2::handle_transmit_result1);
84  goby::acomms::connect(&driver2.signal_receive, this, &MMDriverTest2::handle_data_receive2);
85  goby::acomms::connect(&driver2.signal_transmit_result, this,
86  &MMDriverTest2::handle_transmit_result2);
87 
88  boost::thread modem_thread_A(
89  boost::bind(&MMDriverTest2::run, this, boost::ref(driver1), cfg_.mm1_cfg()));
90  boost::thread modem_thread_B(
91  boost::bind(&MMDriverTest2::run, this, boost::ref(driver2), cfg_.mm2_cfg()));
92 
93  while (!driver1.is_started() || !driver2.is_started()) usleep(10000);
94 
95  for (int i = 0, n = cfg_.repeat(); i < n; ++i)
96  {
97  goby::glog.is(VERBOSE) && goby::glog << "Beginning test sequence repetition " << i + 1
98  << " of " << n << std::endl;
99 
100  int o = cfg_.transmission_size();
101  for (last_transmission_index = 0; last_transmission_index < o; ++last_transmission_index)
102  {
103  if (cfg_.transmission(last_transmission_index).src() == 1)
104  {
105  boost::mutex::scoped_lock lock(driver_mutex);
106  driver1.handle_initiate_transmission(cfg_.transmission(last_transmission_index));
107  }
108  else if (cfg_.transmission(last_transmission_index).src() == 2)
109  {
110  boost::mutex::scoped_lock lock(driver_mutex);
111  driver2.handle_initiate_transmission(cfg_.transmission(last_transmission_index));
112  }
113  sleep(cfg_.transmission(last_transmission_index).slot_seconds());
114  }
115  }
116 
117  modems_running_ = false;
118  modem_thread_A.join();
119  modem_thread_B.join();
120 
121  summary(driver1_receive, cfg_.mm1_cfg());
122  summary(driver2_receive, cfg_.mm2_cfg());
123 
124  goby::glog.is(VERBOSE) && goby::glog << "Completed test" << std::endl;
125  quit();
126 }
127 
128 void MMDriverTest2::run(goby::acomms::MMDriver& modem, goby::acomms::protobuf::DriverConfig& cfg)
129 {
130  goby::glog.is(VERBOSE) && goby::glog << "Initializing modem" << std::endl;
131  modem.startup(cfg);
132 
133  while (modems_running_)
134  {
135  {
136  boost::mutex::scoped_lock lock(driver_mutex);
137  modem.do_work();
138  }
139  usleep(100000); // 0.1 seconds
140  }
141 
142  modem.shutdown();
143 }
144 
145 void MMDriverTest2::handle_data_receive1(const protobuf::ModemTransmission& msg)
146 {
147  goby::glog.is(VERBOSE) && goby::glog << "modem 1 Received: " << msg << std::endl;
148 
149  for (int i = 0, n = msg.ExtensionSize(micromodem::protobuf::receive_stat); i < n; ++i)
150  driver1_receive[last_transmission_index].push_back(
151  msg.GetExtension(micromodem::protobuf::receive_stat, i));
152 }
153 
154 void MMDriverTest2::handle_data_receive2(const protobuf::ModemTransmission& msg)
155 {
156  goby::glog.is(VERBOSE) && goby::glog << "modem 2 Received: " << msg << std::endl;
157 
158  for (int i = 0, n = msg.ExtensionSize(micromodem::protobuf::receive_stat); i < n; ++i)
159  driver2_receive[last_transmission_index].push_back(
160  msg.GetExtension(micromodem::protobuf::receive_stat, i));
161 }
162 
163 void MMDriverTest2::handle_transmit_result1(const protobuf::ModemTransmission& msg)
164 {
165  goby::glog.is(VERBOSE) && goby::glog << "modem 1 Transmitted: " << msg << std::endl;
166 }
167 
168 void MMDriverTest2::handle_transmit_result2(const protobuf::ModemTransmission& msg)
169 {
170  goby::glog.is(VERBOSE) && goby::glog << "modem 2 Transmitted: " << msg << std::endl;
171 }
172 
173 void MMDriverTest2::summary(
174  const std::map<int, std::vector<micromodem::protobuf::ReceiveStatistics> >& receive,
176 {
177  goby::glog.is(VERBOSE) && goby::glog << "*** Begin modem " << cfg.modem_id()
178  << " receive summary" << std::endl;
179 
180  for (std::map<int, std::vector<micromodem::protobuf::ReceiveStatistics> >::const_iterator
181  it = receive.begin(),
182  end = receive.end();
183  it != end; ++it)
184  {
185  goby::glog.is(VERBOSE) && goby::glog << "** Showing stats for this transmission (last "
186  "transmission before this reception occured): "
187  << cfg_.transmission(it->first).DebugString()
188  << std::flush;
189 
190  const std::vector<micromodem::protobuf::ReceiveStatistics>& current_receive_vector =
191  it->second;
192 
193  std::multiset<micromodem::protobuf::PacketType> type;
194  std::multiset<micromodem::protobuf::ReceiveMode> mode;
195  std::multiset<micromodem::protobuf::PSKErrorCode> code;
196 
197  for (int i = 0, n = current_receive_vector.size(); i < n; ++i)
198  {
199  goby::glog.is(VERBOSE) && goby::glog << "CACST #" << i << ": "
200  << current_receive_vector[i].ShortDebugString()
201  << std::endl;
202 
203  type.insert(current_receive_vector[i].packet_type());
204  mode.insert(current_receive_vector[i].mode());
205  code.insert(current_receive_vector[i].psk_error_code());
206  }
207 
208  goby::glog.is(VERBOSE) && goby::glog << "PacketType: " << std::endl;
209  for (int j = micromodem::protobuf::PacketType_MIN;
210  j <= micromodem::protobuf::PacketType_MAX; ++j)
211  {
212  if (micromodem::protobuf::PacketType_IsValid(j))
213  {
214  micromodem::protobuf::PacketType jt =
215  static_cast<micromodem::protobuf::PacketType>(j);
216  goby::glog.is(VERBOSE) && goby::glog << "\t"
217  << micromodem::protobuf::PacketType_Name(jt)
218  << ": " << type.count(jt) << std::endl;
219  }
220  }
221 
222  goby::glog.is(VERBOSE) && goby::glog << "ReceiveMode: " << std::endl;
223  for (int j = micromodem::protobuf::ReceiveMode_MIN;
224  j <= micromodem::protobuf::ReceiveMode_MAX; ++j)
225  {
226  if (micromodem::protobuf::ReceiveMode_IsValid(j))
227  {
228  micromodem::protobuf::ReceiveMode jt =
229  static_cast<micromodem::protobuf::ReceiveMode>(j);
230  goby::glog.is(VERBOSE) && goby::glog << "\t"
231  << micromodem::protobuf::ReceiveMode_Name(jt)
232  << ": " << mode.count(jt) << std::endl;
233  }
234  }
235 
236  goby::glog.is(VERBOSE) && goby::glog << "PSKErrorCode: " << std::endl;
237  for (int j = micromodem::protobuf::PSKErrorCode_MIN;
238  j <= micromodem::protobuf::PSKErrorCode_MAX; ++j)
239  {
240  if (micromodem::protobuf::PSKErrorCode_IsValid(j))
241  {
242  micromodem::protobuf::PSKErrorCode jt =
243  static_cast<micromodem::protobuf::PSKErrorCode>(j);
244  goby::glog.is(VERBOSE) && goby::glog << "\t"
245  << micromodem::protobuf::PSKErrorCode_Name(jt)
246  << ": " << code.count(jt) << std::endl;
247  }
248  }
249  }
250  goby::glog.is(VERBOSE) && goby::glog << "*** End modem " << cfg.modem_id() << " receive summary"
251  << std::endl;
252 }
253 
254 int main(int argc, char* argv[])
255 {
257  goby::run<MMDriverTest2>(argc, argv, &cfg);
258 }
void shutdown()
Stops the driver.
Definition: mm_driver.cpp:450
provides an API to the WHOI Micro-Modem driver
Definition: mm_driver.h:41
int run(int argc, char *argv[], Config *cfg)
Run a Goby application derived from MinimalApplicationBase. blocks caller until MinimalApplicationBas...
ReturnType goby_time()
Returns current UTC time as a boost::posix_time::ptime.
Definition: time.h:104
void do_work()
See ModemDriverBase::do_work()
Definition: mm_driver.cpp:463
void connect(Signal *signal, Slot slot)
connect a signal to a slot (e.g. function pointer)
Definition: connect.h:36
common::FlexOstream glog
Access the Goby logger through this object.
Objects pertaining to acoustic communications (acomms)
void startup(const protobuf::DriverConfig &cfg)
Starts the driver.
Definition: mm_driver.cpp:76