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 #include "goby/acomms/acomms_constants.h"
23 #include "goby/acomms/connect.h"
24 #include "goby/acomms/dccl.h"
25 #include "goby/acomms/queue.h"
26 #include "goby/common/logger.h"
27 #include "goby/util/binary.h"
28 #include "test.pb.h"
29 // tests basic DCCL queuing with non-BROADCAST destination
30 
31 using goby::acomms::operator<<;
32 
33 int receive_count = 0;
34 GobyMessage msg_in_macrura, msg_in_broadcast, msg_in_unicorn;
36 const int MY_MODEM_ID = 1;
37 const int UNICORN_MODEM_ID = 3;
38 const int MACRURA_MODEM_ID = 4;
39 boost::posix_time::ptime current_time = boost::posix_time::second_clock::universal_time();
40 
41 int goby_message_qsize = 0;
42 
43 int handle_ack_count = 0;
44 
45 void handle_receive(const google::protobuf::Message& msg);
46 
47 void qsize(goby::acomms::protobuf::QueueSize size);
48 void handle_ack(const goby::acomms::protobuf::ModemTransmission& ack_msg,
49  const google::protobuf::Message& orig_msg);
50 
51 int main(int argc, char* argv[])
52 {
53  goby::glog.add_stream(goby::common::logger::DEBUG3, &std::cout);
54  goby::glog.set_name(argv[0]);
55 
57 
59  dccl_cfg.set_crypto_passphrase("my_passphrase!");
60  codec->set_cfg(dccl_cfg);
61 
63  cfg.set_modem_id(MY_MODEM_ID);
64 
65  goby::acomms::protobuf::QueuedMessageEntry* q_entry = cfg.add_message_entry();
66  q_entry->set_protobuf_name("GobyMessage");
67  q_entry->set_newest_first(true);
68 
69  goby::acomms::protobuf::QueuedMessageEntry::Role* src_role = q_entry->add_role();
70  src_role->set_type(goby::acomms::protobuf::QueuedMessageEntry::SOURCE_ID);
71  src_role->set_field("header.source_platform");
72 
73  goby::acomms::protobuf::QueuedMessageEntry::Role* dest_role = q_entry->add_role();
74  dest_role->set_type(goby::acomms::protobuf::QueuedMessageEntry::DESTINATION_ID);
75  dest_role->set_field("header.dest_platform");
76 
77  goby::acomms::protobuf::QueuedMessageEntry::Role* time_role = q_entry->add_role();
78  time_role->set_type(goby::acomms::protobuf::QueuedMessageEntry::TIMESTAMP);
79  time_role->set_field("header.time");
80 
81  q_manager.set_cfg(cfg);
82 
83  goby::acomms::connect(&q_manager.signal_receive, &handle_receive);
85  goby::acomms::connect(&q_manager.signal_ack, &handle_ack);
86 
87  msg_in_macrura.set_telegram("hello mac!");
88  msg_in_macrura.mutable_header()->set_time(goby::util::as<goby::uint64>(current_time));
89  msg_in_macrura.mutable_header()->set_source_platform(MY_MODEM_ID);
90  msg_in_macrura.mutable_header()->set_dest_platform(MACRURA_MODEM_ID);
91  msg_in_macrura.mutable_header()->set_dest_type(Header::PUBLISH_OTHER);
92 
93  msg_in_broadcast.set_telegram("hello all!");
94  msg_in_broadcast.mutable_header()->set_time(goby::util::as<goby::uint64>(current_time));
95 
96  msg_in_broadcast.mutable_header()->set_source_platform(MY_MODEM_ID);
97  msg_in_broadcast.mutable_header()->set_dest_type(Header::PUBLISH_ALL);
98 
99  msg_in_unicorn.set_telegram("hello uni!");
100  msg_in_unicorn.mutable_header()->set_time(goby::util::as<goby::uint64>(current_time));
101  msg_in_unicorn.mutable_header()->set_source_platform(MY_MODEM_ID);
102  msg_in_unicorn.mutable_header()->set_dest_platform(UNICORN_MODEM_ID);
103  msg_in_unicorn.mutable_header()->set_dest_type(Header::PUBLISH_OTHER);
104 
105  std::cout << "Pushed: " << msg_in_broadcast << std::endl;
106  q_manager.push_message(msg_in_broadcast);
107  assert(goby_message_qsize == 1);
108 
109  std::cout << "Pushed: " << msg_in_macrura << std::endl;
110  q_manager.push_message(msg_in_macrura);
111  assert(goby_message_qsize == 2);
112 
114 
115  // first send to Macrura, who is AWOL
116  transmit_msg.set_max_frame_bytes(256);
117  transmit_msg.set_dest(goby::acomms::QUERY_DESTINATION_ID);
118 
119  q_manager.handle_modem_data_request(&transmit_msg);
120 
121  // message without ack is sent and popped
122  assert(goby_message_qsize == 1);
123 
124  // repush the broadcast message
125  std::cout << "Pushed: " << msg_in_broadcast << std::endl;
126  q_manager.push_message(msg_in_broadcast);
127  assert(goby_message_qsize == 2);
128 
129  // push one for unicorn
130  std::cout << "Pushed: " << msg_in_unicorn << std::endl;
131  q_manager.push_message(msg_in_unicorn);
132  assert(goby_message_qsize == 3);
133 
134  transmit_msg.Clear();
135  transmit_msg.set_max_frame_bytes(256);
136  transmit_msg.set_dest(goby::acomms::QUERY_DESTINATION_ID);
137 
138  q_manager.handle_modem_data_request(&transmit_msg);
139 
140  // two ack, one not
141  assert(goby_message_qsize == 2);
142 
143  std::cout << "requesting data, got: " << transmit_msg << std::endl;
144  std::cout << "\tdata as hex: " << goby::util::hex_encode(transmit_msg.frame(0)) << std::endl;
145 
146  std::list<const google::protobuf::Message*> msgs;
147  msgs.push_back(&msg_in_unicorn);
148  msgs.push_back(&msg_in_broadcast);
149 
150  assert(transmit_msg.frame(0) == goby::acomms::DCCLCodec::get()->encode_repeated(msgs));
151  assert(transmit_msg.src() == MY_MODEM_ID);
152  assert(transmit_msg.dest() == UNICORN_MODEM_ID);
153  assert(transmit_msg.ack_requested() == true);
154 
155  // feed back the modem layer - both messages will be rejected
156  q_manager.handle_modem_receive(transmit_msg);
157  assert(receive_count == 0);
158 
159  // fake an ack from unicorn
161  ack.set_src(UNICORN_MODEM_ID);
162  ack.set_dest(MY_MODEM_ID);
163  ack.add_acked_frame(0);
164  ack.set_type(goby::acomms::protobuf::ModemTransmission::ACK);
165  q_manager.handle_modem_receive(ack);
166 
167  assert(goby_message_qsize == 1);
168  assert(handle_ack_count == 1);
169 
170  // pretend we're now Unicorn
171  cfg.set_modem_id(UNICORN_MODEM_ID);
172  q_manager.set_cfg(cfg);
173 
174  // feed back the modem layer
175  q_manager.handle_modem_receive(transmit_msg);
176 
177  assert(receive_count == 2);
178 
179  std::cout << "all tests passed" << std::endl;
180 }
181 
182 void handle_receive(const google::protobuf::Message& msg)
183 {
184  std::cout << "Received: " << msg << std::endl;
185 
186  GobyMessage typed_msg;
187  typed_msg.CopyFrom(msg);
188 
189  assert(typed_msg.header().time() == goby::util::as<goby::uint64>(current_time));
190 
191  if (!typed_msg.header().has_dest_platform())
192  assert(typed_msg.SerializeAsString() == msg_in_broadcast.SerializeAsString());
193  else if (typed_msg.header().dest_platform() == 3)
194  assert(typed_msg.SerializeAsString() == msg_in_unicorn.SerializeAsString());
195 
196  ++receive_count;
197 }
198 
199 void qsize(goby::acomms::protobuf::QueueSize size) { goby_message_qsize = size.size(); }
200 
201 void handle_ack(const goby::acomms::protobuf::ModemTransmission& ack_msg,
202  const google::protobuf::Message& orig_msg)
203 {
204  std::cout << "got an ack: " << ack_msg << "\n"
205  << "of original: " << orig_msg << std::endl;
206  assert(orig_msg.SerializeAsString() == msg_in_unicorn.SerializeAsString());
207  ++handle_ack_count;
208 }
provides an API to the goby-acomms Queuing Library.
Definition: queue_manager.h:49
boost::signals2::signal< void(const protobuf::ModemTransmission &ack_msg, const google::protobuf::Message &orig_msg)> signal_ack
Signals when acknowledgment of proper message receipt has been received. This is only sent for queues...
void set_name(const std::string &s)
Set the name of the application that the logger is serving.
Definition: flex_ostream.h:67
static DCCLCodec * get()
DCCLCodec is a singleton class; use this to get a pointer to the class.
Definition: dccl.h:124
boost::signals2::signal< void(const google::protobuf::Message &msg)> signal_receive
Signals when a DCCL message is received.
void handle_modem_data_request(protobuf::ModemTransmission *msg)
Finds data to send to the modem.
void handle_modem_receive(const protobuf::ModemTransmission &message)
Receive incoming data from the modem.
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.
void set_cfg(const protobuf::QueueManagerConfig &cfg)
Set (and overwrite completely if present) the current configuration. (protobuf::QueueManagerConfig de...
boost::signals2::signal< void(protobuf::QueueSize size)> signal_queue_size_change
Signals when any queue changes size (message is popped or pushed)
void add_stream(logger::Verbosity verbosity=logger::VERBOSE, std::ostream *os=0)
Attach a stream object (e.g. std::cout, std::ofstream, ...) to the logger with desired verbosity...
Definition: flex_ostream.h:96
void push_message(const google::protobuf::Message &new_message)
Push a message (and add the queue if it does not exist)
const int QUERY_DESTINATION_ID
special modem id used internally to goby-acomms for indicating that the MAC layer (amac) is agnostic ...