Goby Underwater Autonomy Project
Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
|
00001 // copyright 2008, 2009 t. schneider tes@mit.edu 00002 // 00003 // this file is part of the Dynamic Compact Control Language (DCCL), 00004 // the goby-acomms codec. goby-acomms is a collection of libraries 00005 // for acoustic underwater networking 00006 // 00007 // This program is free software: you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation, either version 3 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // This software is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with this software. If not, see <http://www.gnu.org/licenses/>. 00019 00020 #ifndef MESSAGE20091211H 00021 #define MESSAGE20091211H 00022 00023 #include <iostream> 00024 #include <vector> 00025 #include <sstream> 00026 #include <bitset> 00027 #include <algorithm> 00028 #include <set> 00029 #include <map> 00030 00031 #include <boost/foreach.hpp> 00032 #include <boost/shared_ptr.hpp> 00033 00034 #include "message_var.h" 00035 #include "message_var_int.h" 00036 #include "message_var_float.h" 00037 #include "message_var_static.h" 00038 #include "message_var_hex.h" 00039 #include "message_var_bool.h" 00040 #include "message_var_string.h" 00041 #include "message_var_enum.h" 00042 #include "message_var_head.h" 00043 00044 #include "message_publish.h" 00045 #include "dccl_constants.h" 00046 00047 00048 namespace goby 00049 { 00050 namespace acomms 00051 { 00052 00053 // the DCCLMessage itself 00054 class DCCLMessage 00055 { 00056 public: 00057 DCCLMessage(); 00058 00059 // set 00060 void set_name(const std::string& name) {name_ = name;} 00061 00062 void set_id(unsigned id) 00063 { id_ = id; } 00064 template<typename T> void set_id(const T& t) 00065 { set_id(util::as<unsigned>(t)); } 00066 00067 void set_trigger(const std::string& trigger_type) 00068 { trigger_type_ = trigger_type; } 00069 00070 void set_trigger_var(const std::string& trigger_var) 00071 { trigger_var_ = trigger_var; } 00072 00073 void set_trigger_time(double trigger_time) 00074 { trigger_time_ = trigger_time; } 00075 template<typename T> void set_trigger_time(const T& t) 00076 { set_trigger_time(util::as<double>(t)); } 00077 00078 void set_trigger_mandatory(const std::string& trigger_mandatory) 00079 { trigger_mandatory_ = trigger_mandatory; } 00080 00081 void set_in_var(const std::string& in_var) 00082 { in_var_ = in_var; } 00083 00084 void set_out_var(const std::string& out_var) 00085 { out_var_ = out_var; } 00086 00087 void set_size(unsigned size) 00088 { size_ = size; } 00089 00090 template<typename T> void set_size(const T& t) 00091 { set_size(util::as<unsigned>(t)); } 00092 00093 void set_repeat_enabled(unsigned repeat_enabled) 00094 { repeat_enabled_ = repeat_enabled; } 00095 template<typename T> void set_repeat_enabled(const T& t) 00096 { set_repeat_enabled(util::as<unsigned>(t)); } 00097 00098 void add_message_var(const std::string& type); 00099 void add_publish(); 00100 00101 //get 00102 std::string name() const { return name_; } 00103 unsigned id() const { return id_; } 00104 unsigned size() const { return size_; } 00105 std::string trigger_var() const { return trigger_var_; } 00106 std::string trigger_mandatory() const { return trigger_mandatory_; } 00107 double trigger_time() const { return trigger_time_; } 00108 unsigned trigger_number() const { return trigger_number_; } 00109 std::string trigger_type() const { return trigger_type_; } 00110 std::string in_var() const { return in_var_; } 00111 std::string out_var() const { return out_var_; } 00112 bool repeat_enabled() const { return repeat_enabled_; } 00113 unsigned repeat() const { return repeat_; } 00114 00115 DCCLMessageVar& last_message_var() { return *layout_.back(); } 00116 DCCLMessageVar& header_var(acomms::DCCLHeaderPart p) { return *header_[p]; } 00117 DCCLPublish& last_publish() { return publishes_.back(); } 00118 00119 std::vector< boost::shared_ptr<DCCLMessageVar> >& layout() { return layout_; } 00120 std::vector< boost::shared_ptr<DCCLMessageVar> >& header() { return header_; } 00121 00122 const std::vector< boost::shared_ptr<DCCLMessageVar> >& layout_const() const { return layout_; } 00123 const std::vector< boost::shared_ptr<DCCLMessageVar> >& header_const() const { return header_; } 00124 00125 std::vector<DCCLPublish>& publishes() { return publishes_; } 00126 00127 std::set<std::string> get_pubsub_encode_vars(); 00128 std::set<std::string> get_pubsub_decode_vars(); 00129 std::set<std::string> get_pubsub_src_vars(); 00130 std::set<std::string> get_pubsub_all_vars(); 00131 00132 boost::shared_ptr<DCCLMessageVar> name2message_var(const std::string& name) const; 00133 00134 00135 //other 00136 std::string get_display() const; 00137 std::string get_short_display() const; 00138 std::map<std::string, std::string> message_var_names() const; 00139 void preprocess(); 00140 void set_repeat_array_length(); 00141 unsigned calc_total_size(); 00142 00143 void set_head_defaults(std::map<std::string, std::vector<DCCLMessageVal> >& in, unsigned modem_id); 00144 00145 00146 void head_encode(std::string& head, std::map<std::string, std::vector<DCCLMessageVal> >& in); 00147 void head_decode(const std::string& head, std::map<std::string, std::vector<DCCLMessageVal> >& out); 00148 00149 void body_encode(std::string& body, std::map<std::string, std::vector<DCCLMessageVal> >& in); 00150 void body_decode(std::string& body, std::map<std::string, std::vector<DCCLMessageVal> >& out); 00151 00152 // increment, means increase trigger number 00153 // prefix ++DCCLMessage 00154 DCCLMessage& operator++() 00155 { ++trigger_number_; return(*this); } 00156 // postfix DCCLMessage++ 00157 const DCCLMessage operator++(int) 00158 { DCCLMessage tmp(*this); ++(*this); return tmp;} 00159 00160 00161 private: 00162 unsigned bytes_head() const 00163 { return acomms::DCCL_NUM_HEADER_BYTES; } 00164 unsigned bits_head() const 00165 { return bytes2bits(acomms::DCCL_NUM_HEADER_BYTES); } 00166 00167 // more efficient way to do ceil(total_bits / 8) 00168 // to get the number of bytes rounded up. 00169 00170 enum { BYTE_MASK = 7 }; // 00000111 00171 unsigned used_bytes_body() const 00172 { 00173 return (body_bits_& BYTE_MASK) ? 00174 bits2bytes(body_bits_) + 1 : 00175 bits2bytes(body_bits_); 00176 } 00177 00178 unsigned used_bytes_total() const 00179 { return bytes_head() + used_bytes_body(); } 00180 00181 unsigned used_bits_body() const 00182 { return body_bits_; } 00183 00184 unsigned used_bits_total() const 00185 { return bits_head() + used_bits_body(); } 00186 00187 unsigned requested_bytes_body() const 00188 { return size_ - acomms::DCCL_NUM_HEADER_BYTES; } 00189 00190 unsigned requested_bytes_total() const 00191 { return size_; } 00192 00193 unsigned requested_bits_body() const 00194 { return bytes2bits(size_ - acomms::DCCL_NUM_HEADER_BYTES); } 00195 00196 unsigned requested_bits_total() const 00197 { return bytes2bits(size_); } 00198 00199 00200 private: 00201 // total request size of message, e.g. 32 bytes 00202 unsigned size_; 00203 00204 unsigned trigger_number_; 00205 // actual used bits in body part of message (not including header bits) 00206 unsigned body_bits_; 00207 00208 unsigned id_; 00209 unsigned modem_id_; 00210 double trigger_time_; 00211 00212 bool repeat_enabled_; 00213 unsigned repeat_; 00214 00215 std::string name_; 00216 std::string trigger_type_; 00217 std::string trigger_var_; 00218 std::string trigger_mandatory_; 00219 std::string in_var_; 00220 std::string out_var_; 00221 00222 std::vector< boost::shared_ptr<DCCLMessageVar> > layout_; 00223 std::vector< boost::shared_ptr<DCCLMessageVar> > header_; 00224 00225 00226 std::vector<DCCLPublish> publishes_; 00227 00228 }; 00229 00230 00231 inline void bitset2string(const boost::dynamic_bitset<unsigned char>& body_bits, 00232 std::string& body) 00233 { 00234 body.resize(body_bits.num_blocks()); // resize the string to fit the bitset 00235 to_block_range(body_bits, body.rbegin()); 00236 } 00237 00238 inline void string2bitset(boost::dynamic_bitset<unsigned char>& body_bits, 00239 const std::string& body) 00240 { 00241 from_block_range(body.rbegin(), body.rend(), body_bits); 00242 } 00243 00244 00245 std::ostream& operator<< (std::ostream& out, const DCCLMessage& message); 00246 } 00247 } 00248 #endif