DCCL v4
Loading...
Searching...
No Matches
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
32extern "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
58 dccl->load<protobuf::CCLMDATEmpty>();
59 dccl->load<protobuf::CCLMDATRedirect>();
60 dccl->load<protobuf::CCLMDATBathy>();
61 dccl->load<protobuf::CCLMDATCTD>();
62 dccl->load<protobuf::CCLMDATState>();
63 dccl->load<protobuf::CCLMDATCommand>();
64 dccl->load<protobuf::CCLMDATError>();
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>();
73 dccl->unload<protobuf::CCLMDATRedirect>();
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
101dccl::Bitset dccl::legacyccl::LatLonCompressedCodec::encode() { return encode(0); }
102
103dccl::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
111double 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
118unsigned dccl::legacyccl::LatLonCompressedCodec::size()
119{
120 return LATLON_COMPRESSED_BYTE_SIZE * BITS_IN_BYTE;
121}
122
123//
124// TimeDateCodec
125//
126
127dccl::Bitset dccl::legacyccl::TimeDateCodec::encode() { return encode(0); }
128
129dccl::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
137dccl::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
168dccl::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
178unsigned dccl::legacyccl::TimeDateCodec::size()
179{
180 return TIME_DATE_COMPRESSED_BYTE_SIZE * BITS_IN_BYTE;
181}
182
183//
184// HeadingCodec
185//
186dccl::Bitset dccl::legacyccl::HeadingCodec::encode(const float& wire_value)
187{
188 return dccl::Bitset(size(), Encode_heading(wire_value));
189}
190
191float dccl::legacyccl::HeadingCodec::decode(Bitset* bits)
192{
193 return Decode_heading(bits->to_ulong());
194}
195
196//
197// DepthCodec
198//
199dccl::Bitset dccl::legacyccl::DepthCodec::encode(const float& wire_value)
200{
201 return dccl::Bitset(size(), Encode_depth(wire_value));
202}
203
204float dccl::legacyccl::DepthCodec::decode(Bitset* bits) { return Decode_depth(bits->to_ulong()); }
205
206//
207// VelocityCodec
208//
209dccl::Bitset dccl::legacyccl::VelocityCodec::encode(const float& wire_value)
210{
211 return dccl::Bitset(size(), Encode_est_velocity(wire_value));
212}
213
214float dccl::legacyccl::VelocityCodec::decode(Bitset* bits)
215{
216 return Decode_est_velocity(bits->to_ulong());
217}
218
219//
220// SpeedCodec
221//
222dccl::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
240float 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//
260dccl::Bitset dccl::legacyccl::WattsCodec::encode(const float& wire_value)
261{
262 return dccl::Bitset(size(), Encode_watts(wire_value, 1));
263}
264
265float dccl::legacyccl::WattsCodec::decode(Bitset* bits) { return Decode_watts(bits->to_ulong()); }
266
267//
268// GFIPitchOilCodec
269//
271dccl::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
277dccl::legacyccl::protobuf::CCLMDATState::GFIPitchOil
278dccl::legacyccl::GFIPitchOilCodec::decode(Bitset* bits)
279{
280 float gfi, pitch, oil;
281 Decode_gfi_pitch_oil(bits->to_ulong(), &gfi, &pitch, &oil);
282 protobuf::CCLMDATState::GFIPitchOil decoded;
283 decoded.set_gfi(gfi);
284 decoded.set_pitch(pitch);
285 decoded.set_oil(oil);
286 return decoded;
287}
288
289//
290// HiResAltitudeCodec
291//
292dccl::Bitset dccl::legacyccl::HiResAltitudeCodec::encode(const float& wire_value)
293{
294 return dccl::Bitset(size(), Encode_hires_altitude(wire_value));
295}
296
297float dccl::legacyccl::HiResAltitudeCodec::decode(Bitset* bits)
298{
299 return Decode_hires_altitude(bits->to_ulong());
300}
301
302//
303// SalinityCodec
304//
305dccl::Bitset dccl::legacyccl::SalinityCodec::encode(const float& wire_value)
306{
307 return dccl::Bitset(size(), Encode_salinity(wire_value));
308}
309
310float dccl::legacyccl::SalinityCodec::decode(Bitset* bits)
311{
312 return Decode_salinity(bits->to_ulong());
313}
314
315//
316// TemperatureCodec
317//
318dccl::Bitset dccl::legacyccl::TemperatureCodec::encode(const float& wire_value)
319{
320 return dccl::Bitset(size(), Encode_temperature(wire_value));
321}
322
323float dccl::legacyccl::TemperatureCodec::decode(Bitset* bits)
324{
325 return Decode_temperature(bits->to_ulong());
326}
327
328//
329// SoundSpeedCodec
330//
331dccl::Bitset dccl::legacyccl::SoundSpeedCodec::encode(const float& wire_value)
332{
333 return dccl::Bitset(size(), Encode_sound_speed(wire_value));
334}
335
336float dccl::legacyccl::SoundSpeedCodec::decode(Bitset* bits)
337{
338 return Decode_sound_speed(bits->to_ulong());
339}
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition bitset.h:43
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
The Dynamic CCL enCODer/DECoder. This is the main class you will use to load, encode and decode DCCL ...
Definition codec.h:63
dccl::DCCLFieldOptions dccl_field_options() const
Get the DCCL field option extension value for the current field.
DCCL Implementation of the REMUS CCL Language Library namespace.
Dynamic Compact Control Language namespace.
Definition any.h:47
google::protobuf::uint64 uint64
an unsigned 64 bit integer
Definition common.h:60