Goby v2
message.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 // Community contributors (see AUTHORS file)
5 //
6 //
7 // This file is part of the Goby Underwater Autonomy Project Libraries
8 // ("The Goby Libraries").
9 //
10 // The Goby Libraries are free software: you can redistribute them and/or modify
11 // them under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // The Goby Libraries are distributed in the hope that they will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
22 
23 #include <boost/foreach.hpp>
24 
25 #include "goby/acomms/dccl/dccl.h"
26 #include "goby/common/logger.h"
27 #include "goby/util/as.h"
28 #include "message.h"
29 
30 using goby::glog;
31 using goby::util::as;
32 
33 goby::transitional::DCCLMessage::DCCLMessage()
34  : size_(0), trigger_number_(1), id_(0), trigger_time_(0.0), repeat_enabled_(false), repeat_(1)
35 {
36  header_.resize(DCCL_NUM_HEADER_PARTS);
37  header_[HEAD_CCL_ID] = boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarCCLID());
38  header_[HEAD_DCCL_ID] = boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarDCCLID());
39  header_[HEAD_TIME] = boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarTime());
40  header_[HEAD_SRC_ID] = boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarSrc());
41  header_[HEAD_DEST_ID] = boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarDest());
42  header_[HEAD_MULTIMESSAGE_FLAG] =
43  boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarMultiMessageFlag());
44  header_[HEAD_BROADCAST_FLAG] =
45  boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarBroadcastFlag());
46  header_[HEAD_UNUSED] = boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarUnused());
47 }
48 
49 // add a new message_var to the current messages vector
50 void goby::transitional::DCCLMessage::add_message_var(const std::string& type)
51 {
52  if (type == "static")
53  layout_.push_back(boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarStatic()));
54  else if (type == "int")
55  layout_.push_back(boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarInt()));
56  else if (type == "string")
57  layout_.push_back(boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarString()));
58  else if (type == "float")
59  layout_.push_back(boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarFloat()));
60  else if (type == "enum")
61  layout_.push_back(boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarEnum()));
62  else if (type == "bool")
63  layout_.push_back(boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarBool()));
64  else if (type == "hex")
65  layout_.push_back(boost::shared_ptr<DCCLMessageVar>(new DCCLMessageVarHex()));
66 }
67 
68 // add a new publish, i.e. a set of parameters to publish
69 // upon receipt of an incoming (hex) message
70 void goby::transitional::DCCLMessage::add_publish()
71 {
72  DCCLPublish p;
73  publishes_.push_back(p);
74 }
75 
76 // a number of tasks to perform after reading in an entire <message> from
77 // the xml file
78 void goby::transitional::DCCLMessage::preprocess()
79 {
80  // calculate number of repeated messages that will fit and put this in `repeat_`.
81  if (repeat_enabled_)
82  {
83  glog.is(goby::common::logger::WARN) &&
84  glog << "<repeat> is deprecated and ignored in this version of Goby. Simply post a "
85  "message several times."
86  << std::endl;
87  }
88 
89  // body_bits_ = calc_total_size();
90 
91  // initialize header vars
92  BOOST_FOREACH (boost::shared_ptr<DCCLMessageVar> mv, header_)
93  mv->initialize(*this);
94  BOOST_FOREACH (boost::shared_ptr<DCCLMessageVar> mv, layout_)
95  mv->initialize(*this);
96 
97  // iterate over publishes_
98  BOOST_FOREACH (DCCLPublish& p, publishes_)
99  p.initialize(*this);
100 
101  // set incoming_var / outgoing_var if not set
102  if (in_var_ == "")
103  in_var_ = "IN_" + boost::to_upper_copy(name_) + "_HEX_" + as<std::string>(size_) + "B";
104  if (out_var_ == "")
105  out_var_ = "OUT_" + boost::to_upper_copy(name_) + "_HEX_" + as<std::string>(size_) + "B";
106 }
107 
108 void goby::transitional::DCCLMessage::set_repeat_array_length()
109 {
110  // set array_length_ for repeated messages for all DCCLMessageVars
111  BOOST_FOREACH (boost::shared_ptr<DCCLMessageVar> mv, layout_)
112  mv->set_array_length(repeat_);
113 }
114 
115 unsigned goby::transitional::DCCLMessage::calc_total_size()
116 {
117  boost::shared_ptr<acomms::DCCLFieldCodecBase> codec = acomms::DCCLFieldCodecManager::find(
118  descriptor_, descriptor_->options().GetExtension(dccl::msg).codec());
119  unsigned u = 0;
120  codec->base_max_size(&u, descriptor_, acomms::MessageHandler::BODY);
121  return u;
122 }
123 
124 std::map<std::string, std::string> goby::transitional::DCCLMessage::message_var_names() const
125 {
126  std::map<std::string, std::string> s;
127  BOOST_FOREACH (const boost::shared_ptr<DCCLMessageVar> mv, layout_)
128  s.insert(std::pair<std::string, std::string>(mv->name(), type_to_string(mv->type())));
129  return s;
130 }
131 
132 void goby::transitional::DCCLMessage::set_head_defaults(
133  std::map<std::string, std::vector<DCCLMessageVal> >& in, unsigned modem_id)
134 {
135  for (std::vector<boost::shared_ptr<DCCLMessageVar> >::iterator it = header_.begin(),
136  n = header_.end();
137  it != n; ++it)
138  { (*it)->set_defaults(in, modem_id, id_); } }
139 
140 boost::shared_ptr<goby::transitional::DCCLMessageVar>
141 goby::transitional::DCCLMessage::name2message_var(const std::string& name) const
142 {
143  BOOST_FOREACH (boost::shared_ptr<DCCLMessageVar> mv, layout_)
144  {
145  if (mv->name() == name)
146  return mv;
147  }
148  BOOST_FOREACH (boost::shared_ptr<DCCLMessageVar> mv, header_)
149  {
150  if (mv->name() == name)
151  return mv;
152  }
153 
154  throw goby::acomms::DCCLException(
155  std::string("DCCL: no such name \"" + name + "\" found in <layout> or <header>"));
156 
157  return boost::shared_ptr<DCCLMessageVar>();
158 }
159 
160 // Added in Goby2 for transition to Protobuf structure
161 void goby::transitional::DCCLMessage::write_schema_to_dccl2(std::ofstream* proto_file)
162 {
163  *proto_file << "message " << name_ << " { " << std::endl;
164  *proto_file << "\t"
165  << "option (dccl.msg).id = " << id_ << ";" << std::endl;
166  *proto_file << "\t"
167  << "option (dccl.msg).max_bytes = " << size_ << ";" << std::endl;
168 
169  int sequence_number = 0;
170 
171  header_[HEAD_TIME]->write_schema_to_dccl2(proto_file, ++sequence_number);
172  header_[HEAD_SRC_ID]->write_schema_to_dccl2(proto_file, ++sequence_number);
173  header_[HEAD_DEST_ID]->write_schema_to_dccl2(proto_file, ++sequence_number);
174 
175  BOOST_FOREACH (boost::shared_ptr<DCCLMessageVar> mv, layout_)
176  mv->write_schema_to_dccl2(proto_file, ++sequence_number);
177 
178  *proto_file << "} " << std::endl;
179 }
Definition: test2.pb.h:139
Definition: time.h:241
STL namespace.
common::FlexOstream glog
Access the Goby logger through this object.
The global namespace for the Goby project.