DCCL v4
ccl_compatibility.cpp
1 // Copyright 2012-2023:
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 #include <chrono>
26 #include <ctime>
27 
28 #include "../codec.h"
29 #include "WhoiUtil.h"
30 #include "ccl_compatibility.h"
31 
32 extern "C"
33 {
34  void dccl3_load(dccl::Codec* dccl)
35  {
36  using namespace dccl;
37  using namespace dccl::legacyccl;
38 
39  dccl->manager().add<dccl::legacyccl::IdentifierCodec>("dccl.ccl.id");
40 
41  if (dccl->get_id_codec() != "dccl.ccl.id")
42  dccl->set_id_codec("dccl.ccl.id");
43 
44  dccl->manager().add<LatLonCompressedCodec>("_ccl_latloncompressed");
45  dccl->manager().add<FixAgeCodec>("_ccl_fix_age");
46  dccl->manager().add<TimeDateCodec>("_ccl_time_date");
47  dccl->manager().add<HeadingCodec>("_ccl_heading");
48  dccl->manager().add<DepthCodec>("_ccl_depth");
49  dccl->manager().add<VelocityCodec>("_ccl_velocity");
50  dccl->manager().add<WattsCodec>("_ccl_watts");
51  dccl->manager().add<GFIPitchOilCodec>("_ccl_gfi_pitch_oil");
52  dccl->manager().add<SpeedCodec>("_ccl_speed");
53  dccl->manager().add<HiResAltitudeCodec>("_ccl_hires_altitude");
54  dccl->manager().add<TemperatureCodec>("_ccl_temperature");
55  dccl->manager().add<SalinityCodec>("_ccl_salinity");
56  dccl->manager().add<SoundSpeedCodec>("_ccl_sound_speed");
57 
61  dccl->load<protobuf::CCLMDATCTD>();
65  }
66 
67  void dccl3_unload(dccl::Codec* dccl)
68  {
69  using namespace dccl;
70  using namespace dccl::legacyccl;
71 
72  dccl->unload<protobuf::CCLMDATEmpty>();
74  dccl->unload<protobuf::CCLMDATBathy>();
75  dccl->unload<protobuf::CCLMDATCTD>();
76  dccl->unload<protobuf::CCLMDATState>();
77  dccl->unload<protobuf::CCLMDATCommand>();
78  dccl->unload<protobuf::CCLMDATError>();
79 
80  dccl->manager().remove<dccl::legacyccl::IdentifierCodec>("dccl.ccl.id");
81  dccl->manager().remove<LatLonCompressedCodec>("_ccl_latloncompressed");
82  dccl->manager().remove<FixAgeCodec>("_ccl_fix_age");
83  dccl->manager().remove<TimeDateCodec>("_ccl_time_date");
84  dccl->manager().remove<HeadingCodec>("_ccl_heading");
85  dccl->manager().remove<DepthCodec>("_ccl_depth");
86  dccl->manager().remove<VelocityCodec>("_ccl_velocity");
87  dccl->manager().remove<WattsCodec>("_ccl_watts");
88  dccl->manager().remove<GFIPitchOilCodec>("_ccl_gfi_pitch_oil");
89  dccl->manager().remove<SpeedCodec>("_ccl_speed");
90  dccl->manager().remove<HiResAltitudeCodec>("_ccl_hires_altitude");
91  dccl->manager().remove<TemperatureCodec>("_ccl_temperature");
92  dccl->manager().remove<SalinityCodec>("_ccl_salinity");
93  dccl->manager().remove<SoundSpeedCodec>("_ccl_sound_speed");
94  }
95 }
96 
97 //
98 // LatLonCompressedCodec
99 //
100 
101 dccl::Bitset dccl::legacyccl::LatLonCompressedCodec::encode() { return encode(0); }
102 
103 dccl::Bitset dccl::legacyccl::LatLonCompressedCodec::encode(const double& wire_value)
104 {
105  LONG_AND_COMP encoded;
106  encoded.as_long = 0;
107  encoded.as_compressed = Encode_latlon(wire_value);
108  return dccl::Bitset(size(), static_cast<unsigned long>(encoded.as_long));
109 }
110 
111 double dccl::legacyccl::LatLonCompressedCodec::decode(Bitset* bits)
112 {
113  LONG_AND_COMP decoded;
114  decoded.as_long = static_cast<long>(bits->to_ulong());
115  return Decode_latlon(decoded.as_compressed);
116 }
117 
118 unsigned dccl::legacyccl::LatLonCompressedCodec::size()
119 {
120  return LATLON_COMPRESSED_BYTE_SIZE * BITS_IN_BYTE;
121 }
122 
123 //
124 // TimeDateCodec
125 //
126 
127 dccl::Bitset dccl::legacyccl::TimeDateCodec::encode() { return encode(0); }
128 
129 dccl::Bitset dccl::legacyccl::TimeDateCodec::encode(const dccl::uint64& wire_value)
130 {
131  TIME_DATE_LONG encoded;
132  encoded.as_long = 0;
133  encoded.as_time_date = Encode_time_date(wire_value / MICROSECONDS_IN_SECOND);
134  return dccl::Bitset(size(), static_cast<unsigned long>(encoded.as_long));
135 }
136 
137 dccl::uint64 dccl::legacyccl::TimeDateCodec::decode(Bitset* bits)
138 {
139  TIME_DATE_LONG decoded;
140  decoded.as_long = bits->to_ulong();
141  short mon, day, hour, min, sec;
142  Decode_time_date(decoded.as_time_date, &mon, &day, &hour, &min, &sec);
143 
144  // Get the current time
145  auto now = std::chrono::system_clock::now();
146  std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
147 
148  // Get the current year
149  std::tm current_year_tm = *std::gmtime(&now_time_t);
150  int current_year = current_year_tm.tm_year + 1900;
151 
152  // Construct a tm structure with the given date and time
153  std::tm input_tm;
154  input_tm.tm_year = current_year - 1900;
155  input_tm.tm_mon = mon - 1;
156  input_tm.tm_mday = day;
157  input_tm.tm_hour = hour;
158  input_tm.tm_min = min;
159  input_tm.tm_sec = sec;
160  input_tm.tm_isdst = -1; // Let the system determine the DST setting
161 
162  // Convert the input tm structure to a time_t
163  std::time_t input_time_t = timegm(&input_tm);
164 
165  return to_uint64_time(input_time_t);
166 }
167 
168 dccl::uint64 dccl::legacyccl::TimeDateCodec::to_uint64_time(const std::time_t& time_date)
169 {
170  std::chrono::system_clock::duration input_duration =
171  std::chrono::system_clock::from_time_t(time_date) -
172  std::chrono::system_clock::from_time_t(0); // UNIX Epoch
173  uint64_t microseconds_since_epoch =
174  std::chrono::duration_cast<std::chrono::microseconds>(input_duration).count();
175  return microseconds_since_epoch;
176 }
177 
178 unsigned dccl::legacyccl::TimeDateCodec::size()
179 {
180  return TIME_DATE_COMPRESSED_BYTE_SIZE * BITS_IN_BYTE;
181 }
182 
183 //
184 // HeadingCodec
185 //
186 dccl::Bitset dccl::legacyccl::HeadingCodec::encode(const float& wire_value)
187 {
188  return dccl::Bitset(size(), Encode_heading(wire_value));
189 }
190 
191 float dccl::legacyccl::HeadingCodec::decode(Bitset* bits)
192 {
193  return Decode_heading(bits->to_ulong());
194 }
195 
196 //
197 // DepthCodec
198 //
199 dccl::Bitset dccl::legacyccl::DepthCodec::encode(const float& wire_value)
200 {
201  return dccl::Bitset(size(), Encode_depth(wire_value));
202 }
203 
204 float dccl::legacyccl::DepthCodec::decode(Bitset* bits) { return Decode_depth(bits->to_ulong()); }
205 
206 //
207 // VelocityCodec
208 //
209 dccl::Bitset dccl::legacyccl::VelocityCodec::encode(const float& wire_value)
210 {
211  return dccl::Bitset(size(), Encode_est_velocity(wire_value));
212 }
213 
214 float dccl::legacyccl::VelocityCodec::decode(Bitset* bits)
215 {
216  return Decode_est_velocity(bits->to_ulong());
217 }
218 
219 //
220 // SpeedCodec
221 //
222 dccl::Bitset dccl::legacyccl::SpeedCodec::encode(const float& wire_value)
223 {
224  const google::protobuf::Message* root = FieldCodecBase::root_message();
225  const google::protobuf::FieldDescriptor* thrust_mode_field_desc =
226  root->GetDescriptor()->FindFieldByNumber(
227  FieldCodecBase::dccl_field_options().GetExtension(ccl).thrust_mode_tag());
228 
229  switch (root->GetReflection()->GetEnum(*root, thrust_mode_field_desc)->number())
230  {
231  default:
232  case protobuf::CCLMDATRedirect::RPM:
233  return dccl::Bitset(size(), Encode_speed(SPEED_MODE_RPM, wire_value));
234 
235  case protobuf::CCLMDATRedirect::METERS_PER_SECOND:
236  return dccl::Bitset(size(), Encode_speed(SPEED_MODE_MSEC, wire_value));
237  }
238 }
239 
240 float dccl::legacyccl::SpeedCodec::decode(Bitset* bits)
241 {
242  const google::protobuf::Message* root = FieldCodecBase::root_message();
243  const google::protobuf::FieldDescriptor* thrust_mode_field_desc =
244  root->GetDescriptor()->FindFieldByNumber(
245  FieldCodecBase::dccl_field_options().GetExtension(ccl).thrust_mode_tag());
246 
247  switch (root->GetReflection()->GetEnum(*root, thrust_mode_field_desc)->number())
248  {
249  default:
250  case protobuf::CCLMDATRedirect::RPM: return Decode_speed(SPEED_MODE_RPM, bits->to_ulong());
251 
252  case protobuf::CCLMDATRedirect::METERS_PER_SECOND:
253  return Decode_speed(SPEED_MODE_MSEC, bits->to_ulong());
254  }
255 }
256 
257 //
258 // WattsCodec
259 //
260 dccl::Bitset dccl::legacyccl::WattsCodec::encode(const float& wire_value)
261 {
262  return dccl::Bitset(size(), Encode_watts(wire_value, 1));
263 }
264 
265 float dccl::legacyccl::WattsCodec::decode(Bitset* bits) { return Decode_watts(bits->to_ulong()); }
266 
267 //
268 // GFIPitchOilCodec
269 //
271 dccl::legacyccl::GFIPitchOilCodec::encode(const protobuf::CCLMDATState::GFIPitchOil& wire_value)
272 {
273  return dccl::Bitset(
274  size(), Encode_gfi_pitch_oil(wire_value.gfi(), wire_value.pitch(), wire_value.oil()));
275 }
276 
278 dccl::legacyccl::GFIPitchOilCodec::decode(Bitset* bits)
279 {
280  float gfi, pitch, oil;
281  Decode_gfi_pitch_oil(bits->to_ulong(), &gfi, &pitch, &oil);
283  decoded.set_gfi(gfi);
284  decoded.set_pitch(pitch);
285  decoded.set_oil(oil);
286  return decoded;
287 }
288 
289 //
290 // HiResAltitudeCodec
291 //
292 dccl::Bitset dccl::legacyccl::HiResAltitudeCodec::encode(const float& wire_value)
293 {
294  return dccl::Bitset(size(), Encode_hires_altitude(wire_value));
295 }
296 
297 float dccl::legacyccl::HiResAltitudeCodec::decode(Bitset* bits)
298 {
299  return Decode_hires_altitude(bits->to_ulong());
300 }
301 
302 //
303 // SalinityCodec
304 //
305 dccl::Bitset dccl::legacyccl::SalinityCodec::encode(const float& wire_value)
306 {
307  return dccl::Bitset(size(), Encode_salinity(wire_value));
308 }
309 
310 float dccl::legacyccl::SalinityCodec::decode(Bitset* bits)
311 {
312  return Decode_salinity(bits->to_ulong());
313 }
314 
315 //
316 // TemperatureCodec
317 //
318 dccl::Bitset dccl::legacyccl::TemperatureCodec::encode(const float& wire_value)
319 {
320  return dccl::Bitset(size(), Encode_temperature(wire_value));
321 }
322 
323 float dccl::legacyccl::TemperatureCodec::decode(Bitset* bits)
324 {
325  return Decode_temperature(bits->to_ulong());
326 }
327 
328 //
329 // SoundSpeedCodec
330 //
331 dccl::Bitset dccl::legacyccl::SoundSpeedCodec::encode(const float& wire_value)
332 {
333  return dccl::Bitset(size(), Encode_sound_speed(wire_value));
334 }
335 
336 float dccl::legacyccl::SoundSpeedCodec::decode(Bitset* bits)
337 {
338  return Decode_sound_speed(bits->to_ulong());
339 }
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:275
dccl
Dynamic Compact Control Language namespace.
Definition: any.h:46
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:42
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:334
dccl::legacyccl::protobuf::CCLMDATError
Definition: ccl.pb.h:1865
dccl::legacyccl::protobuf::CCLMDATState_GFIPitchOil
Definition: ccl.pb.h:1381