forked from schwehr/libais
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathais8.cpp
151 lines (131 loc) · 6.13 KB
/
ais8.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Since 2010-05-19
// Binary Broadcast Message (BBM) - 8
#include "ais.h"
#include <iomanip>
Ais8::Ais8(const char *nmea_payload) {
assert(nmea_payload);
assert(nmea_ord_initialized); // Make sure we have the lookup table built
init();
const int payload_len = strlen(nmea_payload)*6 - 46; // in bits w/o DAC/FI
//std::cout << "payload_len: " << strlen(nmea_payload) << " " << strlen(nmea_payload)*6 << " " << payload_len << " " << payload_len / 8 << "\n";
if (payload_len < 0 or payload_len > 952) {
status = AIS_ERR_BAD_BIT_COUNT;
return;
}
std::bitset<MAX_BITS> bs; // FIX: shouldn't this be a max of 1192?
status = aivdm_to_bits(bs, nmea_payload);
if (had_error()) return; // checks status
if (!decode_header8(bs)) return; // side effect - sets status
// Handle all the byte aligned payload
for (int i=0; i<payload_len/8; i++) {
const int start = 56+i*8;
//std::cout << "payload: " << i << " " << start <<"\n";
payload.push_back(ubits(bs,start,8));
}
const int remainder = payload_len % 8; // FIX: need to handle spare bits!!
//std::cout << "remainder: " << remainder << "\n";
if (remainder > 0) {
const int start = (payload_len/8) * 8;
//std::cout << "start: " << start <<"\n";
payload.push_back(ubits(bs, start, remainder));
}
}
bool Ais8::decode_header8(const std::bitset<MAX_BITS> &bs) {
message_id = ubits(bs, 0, 6);
if (8 != message_id) { status = AIS_ERR_WRONG_MSG_TYPE; return false; }
repeat_indicator = ubits(bs,6,2);
mmsi = ubits(bs,8,30);
spare = ubits(bs,38,2);
dac = ubits(bs,40,10);
fi = ubits(bs,50,6);
return true;
}
void Ais8::print() {
std::cout << "AIS_broadcast_binary_message: " << message_id
<< "\t\tdac: " << dac << "\tfi:" << fi << "\n";
std::cout << "\tpayload: "; // << std::hex << std::uppercase; // << std::setfill('0') << std::setw(2) << "\n";
for (std::vector<unsigned char>::iterator i = payload.begin(); i != payload.end(); i++) {
std::cout << std::hex <<std::setfill('0') << std::setw(2)<< int(*i);
}
std::cout << std::dec << std::nouppercase << std::endl;
//std::cout << "test: " << 1 << " " << 255 << " " << std::hex << 255 << std::endl;
}
//////////////////////////////////////////////////////////////////////
Ais8_1_11::Ais8_1_11(const char *nmea_payload) {
assert(nmea_payload);
init();
//CHECKPOINT;
if (strlen(nmea_payload) != 59) { status = AIS_ERR_BAD_BIT_COUNT; return; }
std::bitset<354> bs; // 352 + 2 spares to be 6 bit aligned
status = aivdm_to_bits(bs, nmea_payload);
if (had_error()) return; // checks status
// CHECKPOINT;
message_id = ubits(bs, 0, 6);
if (8 != message_id) { status = AIS_ERR_WRONG_MSG_TYPE; return; }
repeat_indicator = ubits(bs,6,2);
mmsi = ubits(bs,8,30);
spare = ubits(bs,38,2);
dac = ubits(bs,40,10);
fi = ubits(bs,50,6);
//CHECKPOINT;
// FIX: if dac is not 001, it could still possibly be correct
if ( 1 != dac || 11 != fi ) { status = AIS_ERR_WRONG_MSG_TYPE; return; }
y = sbits(bs,56,24) / 60000.; // YES, lat is first
x = sbits(bs,80,25) / 60000.;
day = ubits(bs,105,5);
hour = ubits(bs,110,5);
minute = ubits(bs,115,6);
wind_ave = ubits(bs,121,7);
wind_gust = ubits(bs,128,7);
wind_dir = ubits(bs,135,9);
wind_gust_dir = ubits(bs,144,9);
air_temp = ubits(bs,153,11) / 10. - 60;
rel_humid = ubits(bs,164,7);
dew_point = ubits(bs,171,10) / 10. - 20; // FIX: please be right
air_pres = ubits(bs,181,9) + 800;
air_pres_trend = ubits(bs,190,2);
horz_vis = ubits(bs,192,8) / 10.;
water_level = ubits(bs,200,9) / 10. - 10; // FIX: please be right for -10.0 to 30.0
water_level_trend = ubits(bs,209,2);
surf_cur_speed = ubits(bs,211,8) / 10.;
surf_cur_dir = ubits(bs,219,9);
cur_speed_2 = ubits(bs,228,8) / 10.;
cur_dir_2 = ubits(bs,236,9);
cur_depth_2 = ubits(bs,245,5);
cur_speed_3 = ubits(bs,250,8) / 10.;
cur_dir_3 = ubits(bs,258,9);
cur_depth_3 = ubits(bs,267,5);
wave_height = ubits(bs,272,8) / 10.;
wave_period = ubits(bs,280,6);
wave_dir = ubits(bs,286,9);
swell_height = ubits(bs,295,8) / 10.;
swell_period = ubits(bs,303,6);
swell_dir = ubits(bs,309,9);
sea_state = ubits(bs,318,4);
water_temp = ubits(bs,322,10) / 10. - 10; // FIX: please be right for -10.0 to +50.0
precip_type = ubits(bs,332,3);
salinity = ubits(bs,335,9);
ice = ubits(bs,344,2);
extended_water_level = ubits(bs,346,6); // FIX: how to treat this???
}
void Ais8_1_11::print() {
std::cout << "BBM_imo_1_11_met_hydro: " << message_id
<< "\t\tdac: " << dac << "\tfi:" << fi << "\n";
std::cout << "\tspare:" << spare << "\n"
<< "\tlocation:" << x << " " << y << "\t(lon, lat WGS84)" << "\n"
<< "\ttime:" << day << "T" << hour << ":" << minute << "Z\n"
<< "\twind:" << wind_ave << " " << wind_dir << "\n"
<< "\tgust:" << wind_gust << " " << wind_gust_dir << "\n"
<< "\tair_temp:" << air_temp << "\thumidity:" << rel_humid << "\t:" << horz_vis << "\n"
<< "\tdew_point:" << dew_point << "\tair_pres:" << air_pres << " trend: " << air_pres_trend << "\n"
<< "\twater_level:" << water_level << " trend: " << water_level_trend << "\n"
<< "\tcurrent:" << surf_cur_speed << " kts dir: " << surf_cur_dir << "\n"
<< "\tcurr2:" << cur_speed_2 << " kts dir: " << cur_dir_2 << "\t " << cur_depth_2 << " m deep\n"
<< "\tcurr3:" << cur_speed_3 << " kts dir: " << cur_dir_3 << "\t " << cur_depth_3 << " m deep\n"
<< "\twaves:" << wave_height << " " << wave_period << " " << wave_dir << "\n"
<< "\tswell:" << swell_height << " " << swell_period << " " << swell_dir << "\n"
<< "\tsea_state:" << sea_state << "\twater_temp:" << water_temp << "\n"
<< "\tprecip_type:" << precip_type << "\tsalinity:" << salinity << "\n"
<< "\tice:" << ice << "\n"
<< "\tspare_or_extended_wl:" << extended_water_level << std::endl;
}