00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef DIVERMSG_HPP_
00038 #define DIVERMSG_HPP_
00039 #include <labust/tools/BitPacker.hpp>
00040 #include <labust/tritech/detail/message_preprocess.hpp>
00041
00042 #include <boost/preprocessor/tuple/rem.hpp>
00043 #include <boost/scoped_ptr.hpp>
00044
00045 #include <iostream>
00046 #include <bitset>
00047
00048 #include <string>
00049 #include <map>
00050 #include <stdexcept>
00051
00052 namespace labust
00053 {
00054 namespace tritech
00055 {
00062 class LatLon2Bits
00063 {
00064 public:
00065 void convert(double lat, double lon, int bits = 7);
00066
00067 int lat, lon;
00068
00069 protected:
00070 template <size_t precission>
00071 void latlonToBits(double lat, double lon);
00072 };
00073
00074 template <> void LatLon2Bits::latlonToBits<7>(double lat, double lon);
00075 template <> void LatLon2Bits::latlonToBits<10>(double lat, double lon);
00076 template <> void LatLon2Bits::latlonToBits<14>(double lat, double lon);
00077 template <> void LatLon2Bits::latlonToBits<18>(double lat, double lon);
00078 template <> void LatLon2Bits::latlonToBits<22>(double lat, double lon);
00079
00091 struct DiverMsg
00092 {
00096 enum {msgByteCount = 6};
00100 enum {nextKMLSet=6, endOfKML=7, initReq=8};
00104 enum {type=0,
00105 z,
00106 lat,
00107 lon,
00108 def,
00109 msg,
00110 kmlno,
00111 kmlx,
00112 kmly,
00113 img,
00114 empty,
00115 chksum,
00116 num_elements};
00117
00118 typedef std::vector<int> BitMap;
00119 typedef std::map<int, BitMap > BitsCollection;
00120 static BitsCollection topsideMap, diverMap;
00121
00122 DEFINE_MAPPED_MESSAGES(topsideMap,
00123
00124 (PositionInit, 0, (0, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0))
00125 (Position_18, 1, (7, 18, 18, 0, 0, 0, 0, 0, 0, 1, 0))
00126 (PositionMsg, 2, (7, 7, 7, 0, 18, 0, 0, 0, 0, 5, 0))
00127 (PositionImg, 3, (7, 7, 0, 0, 0, 0, 0, 0, 23, 0, 0))
00128 (Position_14Def, 4, (7, 14, 14, 5, 0, 0, 0, 0, 0, 4, 0))
00129 (PositionMsgDef, 5, (7, 7, 7, 5, 18, 0, 0, 0, 0, 0, 0))
00130 (PositionImgDef, 6, (7, 7, 7, 5, 0, 0, 0, 0, 18, 0, 0))
00131 (PositionKml, 7, (7, 7, 7, 0, 0, 3, 10, 10, 0, 0, 0))
00132 (PositionChk, 8, (7, 7, 7, 0, 0, 0, 0, 0, 0, 17, 6))
00133 (PositionMsgChk, 9, (7, 7, 7, 0, 12, 0, 0, 0, 0, 5, 6))
00134 (PositionImgChk, 10, (7, 7, 7, 0, 0, 0, 0, 0, 17, 0, 6))
00135 (PositionDefChk, 11, (7, 7, 7, 5, 0, 0, 0, 0, 0, 12, 6))
00136 (PositionMsgDefChk, 12, (7, 7, 7, 5, 12, 0, 0, 0, 0, 0, 6))
00137 (PositionImgDefChk, 13, (7, 7, 7, 5, 0, 0, 0, 0, 12, 0, 6)));
00138
00139 DEFINE_MAPPED_MESSAGES(diverMap,
00140
00141 (PositionInitAck, 0, (0, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0))
00142 (MsgReply, 1, (0, 0, 0, 0, 42, 0, 0, 0, 0, 2, 0))
00143 (ImgReply, 2, (0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0))
00144 (DefReply, 3, (0, 0, 0, 5, 0, 0, 0, 0, 0, 39, 0))
00145 (MsgDefReply, 4, (0, 0, 0, 5, 36, 0, 0, 0, 0, 3, 0))
00146 (ImgDefReply, 5, (0, 0, 0, 5, 39, 0, 0, 0, 0, 0, 0))
00147 (MsgChkReply, 6, (0, 0, 0, 0, 36, 0, 0, 0, 0, 2, 6))
00148 (ImgChkReply, 7, (0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 6))
00149 (KmlReply, 11, (0, 0, 0, 0, 0, 3, 10, 10, 0, 21, 0)));
00150
00151 DiverMsg(bool default_topside = true):
00152 latitude(0),
00153 longitude(0),
00154 depth(0),
00155 depthRes(0.5),
00156 data(num_elements,0),
00157 default_topside(true)
00158 {
00159 DiverMsg::register_topsideMap();
00160 DiverMsg::register_diverMap();
00161 };
00162
00163 struct AutoDiver
00164 {
00165 inline static const DiverMsg::BitsCollection& map(){return DiverMsg::diverMap;};
00166 };
00167
00168 struct AutoTopside
00169 {
00170 inline static const DiverMsg::BitsCollection& map() {return DiverMsg::topsideMap;};
00171 };
00172
00173 template <class MsgType>
00174 uint64_t encode(int msg_type = -1)
00175 {
00176 if (msg_type != -1) data[type] = msg_type;
00177
00178 if (MsgType::map().find(type) == MsgType::map().end())
00179 {
00180 throw std::invalid_argument("DiverMsg::encode : Unknown message type, skipping encoding.");
00181 }
00182
00183 const BitMap& map =MsgType::map().at(data[type]);
00184 llEncoder.convert(latitude,longitude, map[lat]);
00185 data[lat] = llEncoder.lat;
00186 data[lon] = llEncoder.lon;
00187 data[z] = int(depth/depthRes);
00188 return labust::tools::BitPacker::pack(map, data);
00189 }
00190
00191 inline uint64_t encode(int type = -1)
00192 {
00193 return (default_topside?encode<AutoTopside>(type):encode<AutoDiver>(type));
00194 }
00195
00196 template <class MsgType>
00197 std::string toString(int type = -1)
00198 {
00199 std::string retVal(msgByteCount+1,'\0');
00200 retVal[0] = msgByteCount*8;
00201 uint64_t data = encode<MsgType>(type);
00202 const char* p=reinterpret_cast<const char*>(&data);
00203
00204 for (int i=0; i<msgByteCount; ++i) retVal[i+1] = p[(msgByteCount-1)-i];
00205 return retVal;
00206 }
00207
00208 inline std::string toString(int type = -1)
00209 {
00210 return (default_topside?toString<AutoTopside>(type):toString<AutoDiver>(type));
00211 }
00212
00213 template <class MsgType>
00214 void decode(uint64_t data, int type = -1)
00215 {
00216 if (type == -1) type = testType(data);
00217
00218 if (MsgType::map().find(type) == MsgType::map().end())
00219 {
00220 throw std::invalid_argument("DiverMsg::decode : Unknown message type, skipping decoding.");
00221 }
00222 labust::tools::BitPacker::unpack(data,MsgType::map().at(type), this->data);
00223 }
00224
00225 inline void decode(uint64_t data, int type = -1)
00226 {
00227 default_topside?decode<AutoDiver>(data,type):decode<AutoTopside>(data,type);
00228 }
00229
00230 template <class MsgType>
00231 void fromString(const std::string& msg, int type = -1)
00232 {
00233 if (msg.size() <msgByteCount)
00234 {
00235 throw std::invalid_argument("DiverMsg::fromString : Wrong message size.");
00236 }
00237 uint64_t data;
00238 char* ret=reinterpret_cast<char*>(&data);
00239
00240 for (int i=0; i<msgByteCount; ++i)
00241 {
00242
00243 ret[i] = msg[1+(msgByteCount-1)-i];
00244
00245 }
00246
00247 decode<MsgType>(data, type);
00248 }
00249
00250 void fromString(const std::string& msg, int type = -1)
00251 {
00252 default_topside?fromString<AutoDiver>(msg,type):fromString<AutoTopside>(msg,type);
00253 }
00254
00255 static inline uint8_t testType(const std::string& data)
00256 {
00257 return (data[1] >> 4) & 0xF;
00258 }
00259
00260 static inline uint8_t testType(uint64_t data, size_t msgSize = 48)
00261 {
00262 return (data >> (msgSize - 4)) & 0xF;
00263 }
00264
00265 std::vector<int64_t> data;
00266 LatLon2Bits llEncoder;
00267 double latitude, longitude, depth, depthRes, kml_latitude, kml_longitude;
00268 bool default_topside;
00269 };
00270
00271 #include <labust/tritech/detail/message_preprocess_undef.hpp>
00272 }
00273 }
00274
00275 #endif
00276
00277
00278