DCCL v4
ccl_compatibility.cpp
1 // Copyright 2012-2020:
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 // File authors:
6 // Toby Schneider <toby@gobysoft.org>
7 // Chris Murphy <cmurphy@aphysci.com>
8 //
9 //
10 // This file is part of the Dynamic Compact Control Language Library
11 // ("DCCL").
12 //
13 // DCCL is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU Lesser General Public License as published by
15 // the Free Software Foundation, either version 2.1 of the License, or
16 // (at your option) any later version.
17 //
18 // DCCL is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU Lesser General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public License
24 // along with DCCL. If not, see <http://www.gnu.org/licenses/>.
25 
26 #include <chrono>
27 #include <ctime>
28 
29 #include "../codec.h"
30 #include "WhoiUtil.h"
31 #include "ccl_compatibility.h"
32 
33 extern "C"
34 {
35  void dccl3_load(dccl::Codec* dccl)
36  {
37  using namespace dccl;
38  using namespace dccl::legacyccl;
39 
40  dccl->manager().add<dccl::legacyccl::IdentifierCodec>("dccl.ccl.id");
41 
42  if (dccl->get_id_codec() != "dccl.ccl.id")
43  dccl->set_id_codec("dccl.ccl.id");
44 
45  dccl->manager().add<LatLonCompressedCodec>("_ccl_latloncompressed");
46  dccl->manager().add<FixAgeCodec>("_ccl_fix_age");
47  dccl->manager().add<TimeDateCodec>("_ccl_time_date");
48  dccl->manager().add<HeadingCodec>("_ccl_heading");
49  dccl->manager().add<DepthCodec>("_ccl_depth");
50  dccl->manager().add<VelocityCodec>("_ccl_velocity");
51  dccl->manager().add<WattsCodec>("_ccl_watts");
52  dccl->manager().add<GFIPitchOilCodec>("_ccl_gfi_pitch_oil");
53  dccl->manager().add<SpeedCodec>("_ccl_speed");
54  dccl->manager().add<HiResAltitudeCodec>("_ccl_hires_altitude");
55  dccl->manager().add<TemperatureCodec>("_ccl_temperature");
56  dccl->manager().add<SalinityCodec>("_ccl_salinity");
57  dccl->manager().add<SoundSpeedCodec>("_ccl_sound_speed");
58 
62  dccl->load<protobuf::CCLMDATCTD>();
66  }
67 
68  void dccl3_unload(dccl::Codec* dccl)
69  {
70  using namespace dccl;
71  using namespace dccl::legacyccl;
72 
73  dccl->unload<protobuf::CCLMDATEmpty>();
75  dccl->unload<protobuf::CCLMDATBathy>();
76  dccl->unload<protobuf::CCLMDATCTD>();
77  dccl->unload<protobuf::CCLMDATState>();
78  dccl->unload<protobuf::CCLMDATCommand>();
79  dccl->unload<protobuf::CCLMDATError>();
80 
81  dccl->manager().remove<dccl::legacyccl::IdentifierCodec>("dccl.ccl.id");
82  dccl->manager().remove<LatLonCompressedCodec>("_ccl_latloncompressed");
83  dccl->manager().remove<FixAgeCodec>("_ccl_fix_age");
84  dccl->manager().remove<TimeDateCodec>("_ccl_time_date");
85  dccl->manager().remove<HeadingCodec>("_ccl_heading");
86  dccl->manager().remove<DepthCodec>("_ccl_depth");
87  dccl->manager().remove<VelocityCodec>("_ccl_velocity");
88  dccl->manager().remove<WattsCodec>("_ccl_watts");
89  dccl->manager().remove<GFIPitchOilCodec>("_ccl_gfi_pitch_oil");
90  dccl->manager().remove<SpeedCodec>("_ccl_speed");
91  dccl->manager().remove<HiResAltitudeCodec>("_ccl_hires_altitude");
92  dccl->manager().remove<TemperatureCodec>("_ccl_temperature");
93  dccl->manager().remove<SalinityCodec>("_ccl_salinity");
94  dccl->manager().remove<SoundSpeedCodec>("_ccl_sound_speed");
95  }
96 }
97 
98 //
99 // LatLonCompressedCodec
100 //
101 
102 dccl::Bitset dccl::legacyccl::LatLonCompressedCodec::encode() { return encode(0); }
103 
104 dccl::Bitset dccl::legacyccl::LatLonCompressedCodec::encode(const double& wire_value)
105 {
106  LONG_AND_COMP encoded;
107  encoded.as_long = 0;
108  encoded.as_compressed = Encode_latlon(wire_value);
109  return dccl::Bitset(size(), static_cast<unsigned long>(encoded.as_long));
110 }
111 
112 double dccl::legacyccl::LatLonCompressedCodec::decode(Bitset* bits)
113 {
114  LONG_AND_COMP decoded;
115  decoded.as_long = static_cast<long>(bits->to_ulong());
116  return Decode_latlon(decoded.as_compressed);
117 }
118 
119 unsigned dccl::legacyccl::LatLonCompressedCodec::size()
120 {
121  return LATLON_COMPRESSED_BYTE_SIZE * BITS_IN_BYTE;
122 }
123 
124 //
125 // TimeDateCodec
126 //
127 
128 dccl::Bitset dccl::legacyccl::TimeDateCodec::encode() { return encode(0); }
129 
130 dccl::Bitset dccl::legacyccl::TimeDateCodec::encode(const dccl::uint64& wire_value)
131 {
132  TIME_DATE_LONG encoded;
133  encoded.as_long = 0;
134  encoded.as_time_date = Encode_time_date(wire_value / MICROSECONDS_IN_SECOND);
135  return dccl::Bitset(size(), static_cast<unsigned long>(encoded.as_long));
136 }
137 
138 dccl::uint64 dccl::legacyccl::TimeDateCodec::decode(Bitset* bits)
139 {
140  TIME_DATE_LONG decoded;
141  decoded.as_long = bits->to_ulong();
142  short mon, day, hour, min, sec;
143  Decode_time_date(decoded.as_time_date, &mon, &day, &hour, &min, &sec);
144 
145  // Get the current time
146  auto now = std::chrono::system_clock::now();
147  std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
148 
149  // Get the current year
150  std::tm current_year_tm = *std::gmtime(&now_time_t);
151  int current_year = current_year_tm.tm_year + 1900;
152 
153  // Construct a tm structure with the given date and time
154  std::tm input_tm;
155  input_tm.tm_year = current_year - 1900;
156  input_tm.tm_mon = mon - 1;
157  input_tm.tm_mday = day;
158  input_tm.tm_hour = hour;
159  input_tm.tm_min = min;
160  input_tm.tm_sec = sec;
161  input_tm.tm_isdst = -1; // Let the system determine the DST setting
162 
163  // Convert the input tm structure to a time_t
164  std::time_t input_time_t = timegm(&input_tm);
165 
166  return to_uint64_time(input_time_t);
167 }
168 
169 dccl::uint64 dccl::legacyccl::TimeDateCodec::to_uint64_time(const std::time_t& time_date)
170 {
171  std::chrono::system_clock::duration input_duration =
172  std::chrono::system_clock::from_time_t(time_date) -
173  std::chrono::system_clock::from_time_t(0); // UNIX Epoch
174  uint64_t microseconds_since_epoch =
175  std::chrono::duration_cast<std::chrono::microseconds>(input_duration).count();
176  return microseconds_since_epoch;
177 }
178 
179 unsigned dccl::legacyccl::TimeDateCodec::size()
180 {
181  return TIME_DATE_COMPRESSED_BYTE_SIZE * BITS_IN_BYTE;
182 }
183 
184 //
185 // HeadingCodec
186 //
187 dccl::Bitset dccl::legacyccl::HeadingCodec::encode(const float& wire_value)
188 {
189  return dccl::Bitset(size(), Encode_heading(wire_value));
190 }
191 
192 float dccl::legacyccl::HeadingCodec::decode(Bitset* bits)
193 {
194  return Decode_heading(bits->to_ulong());
195 }
196 
197 //
198 // DepthCodec
199 //
200 dccl::Bitset dccl::legacyccl::DepthCodec::encode(const float& wire_value)
201 {
202  return dccl::Bitset(size(), Encode_depth(wire_value));
203 }
204 
205 float dccl::legacyccl::DepthCodec::decode(Bitset* bits) { return Decode_depth(bits->to_ulong()); }
206 
207 //
208 // VelocityCodec
209 //
210 dccl::Bitset dccl::legacyccl::VelocityCodec::encode(const float& wire_value)
211 {
212  return dccl::Bitset(size(), Encode_est_velocity(wire_value));
213 }
214 
215 float dccl::legacyccl::VelocityCodec::decode(Bitset* bits)
216 {
217  return Decode_est_velocity(bits->to_ulong());
218 }
219 
220 //
221 // SpeedCodec
222 //
223 dccl::Bitset dccl::legacyccl::SpeedCodec::encode(const float& wire_value)
224 {
225  const google::protobuf::Message* root = FieldCodecBase::root_message();
226  const google::protobuf::FieldDescriptor* thrust_mode_field_desc =
227  root->GetDescriptor()->FindFieldByNumber(
228  FieldCodecBase::dccl_field_options().GetExtension(ccl).thrust_mode_tag());
229 
230  switch (root->GetReflection()->GetEnum(*root, thrust_mode_field_desc)->number())
231  {
232  default:
233  case protobuf::CCLMDATRedirect::RPM:
234  return dccl::Bitset(size(), Encode_speed(SPEED_MODE_RPM, wire_value));
235 
236  case protobuf::CCLMDATRedirect::METERS_PER_SECOND:
237  return dccl::Bitset(size(), Encode_speed(SPEED_MODE_MSEC, wire_value));
238  }
239 }
240 
241 float dccl::legacyccl::SpeedCodec::decode(Bitset* bits)
242 {
243  const google::protobuf::Message* root = FieldCodecBase::root_message();
244  const google::protobuf::FieldDescriptor* thrust_mode_field_desc =
245  root->GetDescriptor()->FindFieldByNumber(
246  FieldCodecBase::dccl_field_options().GetExtension(ccl).thrust_mode_tag());
247 
248  switch (root->GetReflection()->GetEnum(*root, thrust_mode_field_desc)->number())
249  {
250  default:
251  case protobuf::CCLMDATRedirect::RPM: return Decode_speed(SPEED_MODE_RPM, bits->to_ulong());
252 
253  case protobuf::CCLMDATRedirect::METERS_PER_SECOND:
254  return Decode_speed(SPEED_MODE_MSEC, bits->to_ulong());
255  }
256 }
257 
258 //
259 // WattsCodec
260 //
261 dccl::Bitset dccl::legacyccl::WattsCodec::encode(const float& wire_value)
262 {
263  return dccl::Bitset(size(), Encode_watts(wire_value, 1));
264 }
265 
266 float dccl::legacyccl::WattsCodec::decode(Bitset* bits) { return Decode_watts(bits->to_ulong()); }
267 
268 //
269 // GFIPitchOilCodec
270 //
272 dccl::legacyccl::GFIPitchOilCodec::encode(const protobuf::CCLMDATState::GFIPitchOil& wire_value)
273 {
274  return dccl::Bitset(
275  size(), Encode_gfi_pitch_oil(wire_value.gfi(), wire_value.pitch(), wire_value.oil()));
276 }
277 
279 dccl::legacyccl::GFIPitchOilCodec::decode(Bitset* bits)
280 {
281  float gfi, pitch, oil;
282  Decode_gfi_pitch_oil(bits->to_ulong(), &gfi, &pitch, &oil);
284  decoded.set_gfi(gfi);
285  decoded.set_pitch(pitch);
286  decoded.set_oil(oil);
287  return decoded;
288 }
289 
290 //
291 // HiResAltitudeCodec
292 //
293 dccl::Bitset dccl::legacyccl::HiResAltitudeCodec::encode(const float& wire_value)
294 {
295  return dccl::Bitset(size(), Encode_hires_altitude(wire_value));
296 }
297 
298 float dccl::legacyccl::HiResAltitudeCodec::decode(Bitset* bits)
299 {
300  return Decode_hires_altitude(bits->to_ulong());
301 }
302 
303 //
304 // SalinityCodec
305 //
306 dccl::Bitset dccl::legacyccl::SalinityCodec::encode(const float& wire_value)
307 {
308  return dccl::Bitset(size(), Encode_salinity(wire_value));
309 }
310 
311 float dccl::legacyccl::SalinityCodec::decode(Bitset* bits)
312 {
313  return Decode_salinity(bits->to_ulong());
314 }
315 
316 //
317 // TemperatureCodec
318 //
319 dccl::Bitset dccl::legacyccl::TemperatureCodec::encode(const float& wire_value)
320 {
321  return dccl::Bitset(size(), Encode_temperature(wire_value));
322 }
323 
324 float dccl::legacyccl::TemperatureCodec::decode(Bitset* bits)
325 {
326  return Decode_temperature(bits->to_ulong());
327 }
328 
329 //
330 // SoundSpeedCodec
331 //
332 dccl::Bitset dccl::legacyccl::SoundSpeedCodec::encode(const float& wire_value)
333 {
334  return dccl::Bitset(size(), Encode_sound_speed(wire_value));
335 }
336 
337 float dccl::legacyccl::SoundSpeedCodec::decode(Bitset* bits)
338 {
339  return Decode_sound_speed(bits->to_ulong());
340 }
dccl::legacyccl::IdentifierCodec
Definition: ccl_compatibility.h:44
dccl::legacyccl::HiResAltitudeCodec
Definition: ccl_compatibility.h:182
dccl::legacyccl::SpeedCodec
Definition: ccl_compatibility.h:223
dccl::legacyccl::VelocityCodec
Definition: ccl_compatibility.h:214
dccl::uint64
google::protobuf::uint64 uint64
an unsigned 64 bit integer
Definition: common.h:60
dccl::legacyccl::protobuf::CCLMDATRedirect
Definition: ccl.pb.h:344
dccl::Bitset::to_ulong
unsigned long to_ulong() const
Returns the value of the Bitset as an unsigned long integer. Equivalent to to<unsigned long>().
Definition: bitset.h:274
dccl
Dynamic Compact Control Language namespace.
Definition: any.h:49
dccl::legacyccl::TemperatureCodec
Definition: ccl_compatibility.h:270
dccl::legacyccl::DepthCodec
Definition: ccl_compatibility.h:195
dccl::legacyccl::TimeDateCodec
Definition: ccl_compatibility.h:152
dccl::Codec
The Dynamic CCL enCODer/DECoder. This is the main class you will use to load, encode and decode DCCL ...
Definition: codec.h:62
LONG_AND_COMP
Definition: WhoiUtil.h:34
dccl::legacyccl
DCCL Implementation of the REMUS CCL Language Library namespace.
Definition: ccl_compatibility.h:40
dccl::legacyccl::protobuf::CCLMDATEmpty
Definition: ccl.pb.h:221
TIME_DATE_LONG
Definition: WhoiUtil.h:46
dccl::legacyccl::LatLonCompressedCodec
Definition: ccl_compatibility.h:113
dccl::legacyccl::HeadingCodec
Definition: ccl_compatibility.h:173
dccl::legacyccl::protobuf::CCLMDATCommand
Definition: ccl.pb.h:1131
dccl::legacyccl::protobuf::CCLMDATBathy
Definition: ccl.pb.h:734
dccl::Bitset
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition: bitset.h:41
dccl::legacyccl::GFIPitchOilCodec
Definition: ccl_compatibility.h:248
dccl::legacyccl::protobuf::CCLMDATState
Definition: ccl.pb.h:1518
Message
dccl::legacyccl::FixAgeCodec
Definition: ccl_compatibility.h:126
dccl::legacyccl::WattsCodec
Definition: ccl_compatibility.h:239
dccl::legacyccl::protobuf::CCLMDATCTD
Definition: ccl.pb.h:909
dccl::legacyccl::SalinityCodec
Definition: ccl_compatibility.h:261
dccl::legacyccl::SoundSpeedCodec
Definition: ccl_compatibility.h:279
dccl::FieldCodecBase::dccl_field_options
dccl::DCCLFieldOptions dccl_field_options() const
Get the DCCL field option extension value for the current field.
Definition: field_codec.h:335
dccl::legacyccl::protobuf::CCLMDATError
Definition: ccl.pb.h:1865
dccl::legacyccl::protobuf::CCLMDATState_GFIPitchOil
Definition: ccl.pb.h:1381