Ais12::Ais12(const char *nmea_payload, const size_t pad) : AisMsg(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(message_id == 12); // WARNING: The ITU 1371 specifications says the maximum number of bits is // 1008, but it appears that the maximum should be 1192. const size_t num_bits = strlen(nmea_payload) * 6 - pad; if (num_bits < 72 || num_bits > 1192) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<MAX_BITS> bs; // Spec says 1008 const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } seq_num = ubits(bs, 38, 2); dest_mmsi = ubits(bs, 40, 30); retransmitted = bs[70]; spare = bs[71]; const int num_txt = (num_bits - 72) / 6; const int num_txt_bits = num_txt * 6; text = ais_str(bs, 72, num_txt_bits); // TODO(schwehr): watch for trailing spares status = AIS_OK; }
// IMO Circ 289 - Number of persons on board // See also Circ 236 // TODO(schwehr): there might also be an addressed version? Ais8_1_16::Ais8_1_16(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 1); assert(fi == 16); const size_t num_bits = strlen(nmea_payload) * 6 - pad; if (num_bits != 72) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<72> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } persons = ubits(bs, 56, 13); spare2 = ubits(bs, 69, 3); status = AIS_OK; }
// IMO Circ 289 - Extended Shipdata - Air gap // See also Circ 236 Ais8_1_15::Ais8_1_15(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 1); assert(fi == 15); const size_t num_bits = strlen(nmea_payload) * 6 - pad; if (num_bits != 72) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<72> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } air_draught = (float)(ubits(bs, 56, 11) / 10.0);//Crouse: Added typecasting spare2 = ubits(bs, 67, 5); status = AIS_OK; }
// River Information Systems ECE-TRANS-SC3-2006-10r-RIS.pdf Ais8_200_24::Ais8_200_24(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 200); assert(fi == 24); const size_t num_bits = strlen(nmea_payload) * 6 - pad; if (num_bits != 168) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<168> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } ais_str(bs, 56, 12); for (size_t i = 0; i < 4; i++) { size_t start = 68 + 25*i; gauge_ids[i] = ubits(bs, start, 11); const int sign = bs[start + 11] ? 1 : -1; // 0 negative, 1 pos // ERROR: the spec has a bit listing mistake levels[i] = (float)(sign * ubits(bs, start + 12, 13)); } status = AIS_OK; }
// IMO Circ 289 - Text description // See also Circ 236 Ais8_1_29::Ais8_1_29(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 1); assert(fi == 29); const size_t num_bits = strlen(nmea_payload) * 6 - pad; if (72 > num_bits || num_bits > 1032) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<1032> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } link_id = ubits(bs, 56, 10); size_t text_bits = ((num_bits - 66) / 6) * 6; text = ais_str(bs, 66, text_bits); const size_t spare2_bits = num_bits - 66 - text_bits; if (spare2_bits) { const size_t start = 66 + text_bits; spare2 = ubits(bs, start, spare2_bits); } else { spare2 = 0; } status = AIS_OK; }
Ais8::Ais8(const char *nmea_payload, const size_t pad) : AisMsg(nmea_payload, pad) { // Ais8 is used in some apps as a standalone, so be extra // careful to make sure we have the lookup table built assert(nmea_ord_initialized); if (status != AIS_UNINITIALIZED) return; assert(message_id == 8); // in bits w/o DAC/FI const ptrdiff_t payload_len = strlen(nmea_payload) * 6 - 46 - pad;//Crouse: Changed from int to ptrdiff_t if (payload_len < 0 || payload_len > 952) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<MAX_BITS> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } spare = ubits(bs, 38, 2); dac = ubits(bs, 40, 10); fi = ubits(bs, 50, 6); }
// River Information Systems ECE-TRANS-SC3-2006-10r-RIS.pdf Ais8_200_40::Ais8_200_40(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 200); assert(fi == 40); const size_t num_bits = strlen(nmea_payload) * 6 - pad; if (num_bits != 168) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<168> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } x = (float)(sbits(bs, 56, 28) / 600000.0);//Crouse:Added typecasting y = (float)(sbits(bs, 84, 27) / 600000.0);//Crouse:Added typecasting form = ubits(bs, 111, 4); dir = ubits(bs, 115, 9); // degrees stream_dir = ubits(bs, 124, 3); status_raw = ubits(bs, 127, 30); // TODO(schwehr): status[ ] = bite me; spare2 = ubits(bs, 157, 11); status = AIS_OK; }
Ais10::Ais10(const char *nmea_payload, const size_t pad) : AisMsg(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(message_id == 10); if (pad != 0 || strlen(nmea_payload) != 12) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<72> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } spare = ubits(bs, 38, 2); dest_mmsi = ubits(bs, 40, 30); spare2 = ubits(bs, 70, 2); status = AIS_OK; }
Ais8_366_22_Sector::Ais8_366_22_Sector(const std::bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs,offset+3,2); x = sbits(bs, offset+5, 28) / 600000.; y = sbits(bs, offset+5+28, 27) / 600000.; radius_m = ubits(bs,offset+5+28+27,12) * scale_multipliers[scale_factor]; left_bound_deg = ubits(bs, offset+5+28+27+12, 9); right_bound_deg = ubits(bs, offset+5+28+27+12+9, 9); }
Ais8_366_22_Circle::Ais8_366_22_Circle(const std::bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs,offset+3,2); x = sbits(bs, offset+5, 28) / 600000.; y = sbits(bs, offset+5+28, 27) / 600000.; // TODO: precision? And bit counts for radius and spare? radius_m = ubits(bs,offset+5+28+27,12) * scale_multipliers[scale_factor]; spare = ubits(bs,offset+5+28+27+12,16); }
Ais8_366_22_Sector::Ais8_366_22_Sector(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs, offset + 3, 2); x = (float)(sbits(bs, offset + 5, 28) / 600000.0);//Crouse:Added typecasting y = (float)(sbits(bs, offset + 33, 27) / 600000.0);//Crouse:Added typecasting radius_m = ubits(bs, offset + 60, 12) * scale_multipliers[scale_factor]; left_bound_deg = ubits(bs, offset + 72, 9); right_bound_deg = ubits(bs, offset + 81, 9); }
Ais8_1_26_Location::Ais8_1_26_Location(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { x = (float)(sbits(bs, offset, 28) / 600000.0);//Crouse:Added typecasting y = (float)(sbits(bs, offset + 28, 27) / 600000.0);//Crouse:Added typecasting z = (float)(ubits(bs, offset + 55, 11) / 10.0);//Crouse:Added typecasting owner = ubits(bs, offset + 66, 4); timeout = ubits(bs, offset + 70, 3); spare = ubits(bs, offset + 73, 12); }
Ais8_366_22_Rect::Ais8_366_22_Rect(const std::bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs,offset+3,2); x = sbits(bs, offset+5, 28) / 600000.; y = sbits(bs, offset+5+28, 27) / 600000.; e_dim_m = ubits(bs, offset+5+28+27, 8) * scale_multipliers[scale_factor]; n_dim_m = ubits(bs, offset+5+28+27+8, 8) * scale_multipliers[scale_factor]; orient_deg = ubits(bs, offset+5+28+27+8+8, 9); spare = ubits(bs, offset+5+28+27+8+8+9, 5); }
Ais8_366_22_Rect::Ais8_366_22_Rect(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs, offset + 3, 2); x = (float)(sbits(bs, offset + 5, 28) / 600000.0);//Crouse:Added typecasting y = (float)(sbits(bs, offset + 33, 27) / 600000.0);//Crouse:Added typecasting e_dim_m = ubits(bs, offset + 60, 8) * scale_multipliers[scale_factor]; n_dim_m = ubits(bs, offset + 68, 8) * scale_multipliers[scale_factor]; orient_deg = ubits(bs, offset + 76, 9); spare = ubits(bs, offset + 85, 5); }
Ais8_366_22_Circle::Ais8_366_22_Circle(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs, offset + 3, 2); x = sbits(bs, offset + 5, 28) / 600000.; y = sbits(bs, offset + 33, 27) / 600000.; // TODO(schwehr): precision? And bit counts for radius and spare? // TODO(schwehr): collapse these numbers radius_m = ubits(bs, offset + 60, 12) * scale_multipliers[scale_factor]; spare = ubits(bs, offset + 72, 16); }
Ais8_1_26_Curr2D::Ais8_1_26_Curr2D(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { for (size_t idx = 0; idx < 3; idx++) { size_t start = offset + idx * 26; currents[idx].speed = (float)(ubits(bs, start, 8) / 10.0);//Crouse:Added typecasting currents[idx].dir = ubits(bs, start + 8, 9); currents[idx].depth = ubits(bs, start + 17, 9); } type = ubits(bs, offset + 78, 3); spare = ubits(bs, offset + 81, 4); }
Ais8_366_22_Polygon::Ais8_366_22_Polygon(const std::bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs,offset+3,2); for (size_t i=0; i<4; i++) { const int angle = ubits(bs, offset+5+ (i*21), 10); const int dist = ubits(bs, offset+5+10+ (i*21), 11) * scale_multipliers[scale_factor]; if (0==dist) break; angles.push_back(angle); dists_m.push_back(dist); } spare = bs[offset+89]; }
Ais8_1_26_HorzFlow::Ais8_1_26_HorzFlow(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { for (size_t idx = 0; idx < 2; idx++) { size_t start = offset + idx * 42; currents[idx].bearing = ubits(bs, start, 9); currents[idx].dist = ubits(bs, start + 9, 7); currents[idx].speed = (float)(ubits(bs, start + 16, 8) / 10.0);//Crouse:Added typecasting currents[idx].dir = ubits(bs, start + 24, 9); currents[idx].level = ubits(bs, start + 33, 9); } spare = bs[offset + 84]; }
Ais21::Ais21(const char *nmea_payload, const size_t pad) : AisMsg(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(message_id == 21); const size_t num_bits = strlen(nmea_payload) * 6 - pad; // TODO(schwehr): make this more careful than 272-360 if (num_bits < 272 || num_bits > 360) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<360> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } aton_type = ubits(bs, 38, 5); name = ais_str(bs, 43, 120); position_accuracy = bs[163]; x = sbits(bs, 164, 28) / 600000.; y = sbits(bs, 192, 27) / 600000.; dim_a = ubits(bs, 219, 9); dim_b = ubits(bs, 228, 9); dim_c = ubits(bs, 237, 6); dim_d = ubits(bs, 243, 6); fix_type = ubits(bs, 249, 4); timestamp = ubits(bs, 253, 6); off_pos = bs[259]; aton_status = ubits(bs, 260, 8); raim = bs[268]; virtual_aton = bs[269]; assigned_mode = bs[270]; spare = bs[271]; const size_t extra_total_bits = num_bits - 272; const size_t extra_chars = extra_total_bits / 6; const size_t extra_char_bits = extra_chars * 6; const size_t extra_bits = extra_total_bits % 6; if (extra_chars > 0) { name += ais_str(bs, 272, extra_char_bits); } if (extra_bits > 0) { spare2 = ubits(bs, 272 + extra_char_bits, extra_bits); } else { spare2 = 0; } status = AIS_OK; }
// TODO(schwehr): merge with Polyline Ais8_366_22_Polygon::Ais8_366_22_Polygon(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs, offset + 3, 2); for (size_t i = 0; i < 4; i++) { const int angle = ubits(bs, offset + 5 + (i*21), 10); const int dist = ubits(bs, offset + 15 + (i*21), 11) * scale_multipliers[scale_factor]; if (0 == dist) break; angles.push_back((const float)angle);//Crouse:Added typecasting dists_m.push_back((const float)dist);//Crouse:Added typecasting } spare = bs[offset + 89]; }
static void from_sixbit(unsigned char *bitvec, uint start, int count, char *to) /* beginning at bitvec bit start, unpack count sixbit characters */ { /*@ +type @*/ #ifdef S_SPLINT_S /* the real string causes a splint internal error */ const char sixchr[] = "abcd"; #else const char sixchr[64] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?"; #endif /* S_SPLINT_S */ int i; /* six-bit to ASCII */ for (i = 0; i < count; i++) { char newchar; newchar = sixchr[ubits(bitvec, start + 6 * i, 6U, false)]; if (newchar == '@') break; else to[i] = newchar; } to[i] = '\0'; /* trim spaces on right end */ for (i = count - 2; i >= 0; i--) if (to[i] == ' ' || to[i] == '@') to[i] = '\0'; else break; /*@ -type @*/ }
// River Information Systems ECE-TRANS-SC3-2006-10r-RIS.pdf // Inland ship static and voyage related data Ais8_200_10::Ais8_200_10(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 200); assert(fi == 10); const size_t num_bits = strlen(nmea_payload) * 6 - pad; if (num_bits != 168) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<168> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } eu_id = ais_str(bs, 56, 48); length = (float)(ubits(bs, 104, 13) / 10.0); // m //Crouse:Added typecasting beam = (float)(ubits(bs, 117, 10) / 10.0); // m //Crouse:Added typecasting ship_type = ubits(bs, 127, 14); haz_cargo = ubits(bs, 141, 3); draught = (float)(ubits(bs, 144, 11) / 10.0); // m //Crouse:Added typecasting loaded = ubits(bs, 155, 2); speed_qual = bs[157]; course_qual = bs[158]; heading_qual = bs[159]; spare2 = ubits(bs, 160, 8); status = AIS_OK; }
Ais8_1_26_Wx::Ais8_1_26_Wx(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { air_temp = (float)(sbits(bs, offset, 11) / 10.0);//Crouse:Added typecasting air_temp_sensor_type = ubits(bs, offset + 11, 3); precip = ubits(bs, offset + 14, 2); horz_vis = (float)(ubits(bs, offset + 16, 8) / 10.0);//Crouse:Added typecasting dew_point = (float)(sbits(bs, offset + 24, 10) / 10.0);//Crouse:Added typecasting dew_point_type = ubits(bs, offset + 34, 3); air_pressure = ubits(bs, offset + 37, 9)+799;//Crouse: added the +800 to put it into hectoPascals air_pressure_trend = ubits(bs, offset + 46, 2); air_pressor_type = ubits(bs, offset + 48, 3); salinity = (float)(ubits(bs, offset + 51, 9) / 10.0);//Crouse:Added typecasting spare = ubits(bs, offset + 60, 25); }
// TODO: pad Ais8_366_22::Ais8_366_22(const char *nmea_payload) { assert(nmea_payload); assert(strlen(nmea_payload) >= 28); init(); const int num_bits = (strlen(nmea_payload) * 6); if (208 <= num_bits && num_bits >= 1020) { status = AIS_ERR_BAD_BIT_COUNT; return; } std::bitset<MAX_BITS> bs; status = aivdm_to_bits(bs, nmea_payload); if (had_error()) return; if (!decode_header8(bs)) return; link_id = ubits(bs,56,10); notice_type = ubits(bs,66,7); month = ubits(bs,73,4); day = ubits(bs,77,5); utc_hour = ubits(bs,82,5); utc_minute = ubits(bs,87,6); duration_minutes = ubits(bs,93,18); const int num_sub_areas = int( floor( (num_bits - 111)/90.) ); for (int sub_area_idx=0; sub_area_idx < num_sub_areas; sub_area_idx++) { Ais8_366_22_SubArea *sub_area = ais8_366_22_subarea_factory(bs, 111+90*sub_area_idx); if (sub_area) { sub_areas.push_back(sub_area); } else { std::cout << "ERROR: bad sub area " << sub_area_idx << std::endl; } } }
Ais8_1_26_Salinity::Ais8_1_26_Salinity(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { water_temp = (float)(ubits(bs, offset, 10) / 10. - 10);//Crouse:Added typecasting conductivity = (float)(ubits(bs, offset + 10, 10) / 100.0);//Crouse:Added typecasting pressure = (float)(ubits(bs, offset + 20, 16) / 10.0);//Crouse:Added typecasting salinity = (float)(ubits(bs, offset + 36, 9) / 10.0);//Crouse:Added typecasting salinity_type = ubits(bs, offset + 45, 2); sensor_type = ubits(bs, offset + 47, 3); spare[0] = ubits(bs, offset + 50, 32); spare[1] = ubits(bs, offset + 82, 3); }
Ais8_1_26_AirDraught::Ais8_1_26_AirDraught(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { draught = (float)(ubits(bs, offset, 13) / 100.0);//Crouse:Added typecasting gap = (float)(ubits(bs, offset + 13, 13) / 10.0);//Crouse:Added typecasting trend = ubits(bs, offset + 26, 2); forcast_gap = (float)(ubits(bs, offset + 28, 13) / 10.0);//Crouse:Added typecasting utc_day_forcast = ubits(bs, offset + 41, 5); utc_hour_forcast = ubits(bs, offset + 46, 5); utc_min_forcast = ubits(bs, offset + 51, 6); spare = ubits(bs, offset + 57, 28); }
Ais24::Ais24(const char *nmea_payload, const size_t pad) : AisMsg(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(message_id == 24); const int num_bits = std::strlen(nmea_payload) * 6 - pad; if (num_bits != 160 && num_bits != 168) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<168> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } part_num = ubits(bs, 38, 2); switch (part_num) { case 0: // Part A if (num_bits != 160) { status = AIS_ERR_BAD_BIT_COUNT; return; } name = ais_str(bs, 40, 120); type_and_cargo = -1; dim_a = dim_b = dim_c = dim_d = spare = -1; break; case 1: // Part B if (num_bits != 168) { status = AIS_ERR_BAD_BIT_COUNT; return; } type_and_cargo = ubits(bs, 40, 8); vendor_id = ais_str(bs, 48, 42); callsign = ais_str(bs, 90, 42); dim_a = ubits(bs, 132, 9); dim_b = ubits(bs, 141, 9); dim_c = ubits(bs, 150, 6); dim_d = ubits(bs, 156, 6); spare = ubits(bs, 162, 6); break; case 2: // FALLTHROUGH - not yet defined by ITU case 3: // FALLTHROUGH - not yet defined by ITU default: status = AIS_ERR_BAD_MSG_CONTENT; return; } status = AIS_OK; }
// IMO Circ 289 - Marine traffic signal Ais8_1_19::Ais8_1_19(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 1); assert(fi == 19); const size_t num_bits = strlen(nmea_payload) * 6 - pad; // Some people transmit without the idiodic spare padding if (num_bits != 258 && num_bits != 360) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<360> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } link_id = ubits(bs, 56, 10); name = ais_str(bs, 66, 120); x = (float)(sbits(bs, 186, 25) / 60000.0);//Crouse: Added typecasting y = (float)(sbits(bs, 211, 24) / 60000.0);//Crouse: Added typecasting status = ubits(bs, 235, 2); signal = ubits(bs, 237, 5); utc_hour_next = ubits(bs, 242, 5); utc_min_next = ubits(bs, 247, 6); next_signal = ubits(bs, 253, 5); if (num_bits != 360) return; spare2[0] = ubits(bs, 258, 32); spare2[1] = ubits(bs, 290, 32); spare2[2] = ubits(bs, 322, 32); spare2[3] = ubits(bs, 354, 6); status = AIS_OK; }
Ais27::Ais27(const char *nmea_payload, const size_t pad) { assert(nmea_payload); assert(0==pad); init(); const size_t num_bits = strlen(nmea_payload) * 6 - pad; assert(96==num_bits); if (96 != num_bits) { status = AIS_ERR_BAD_BIT_COUNT; return; } std::bitset<96> bs; status = aivdm_to_bits(bs, nmea_payload); if (had_error()) return; message_id = ubits(bs, 0, 6); if (27 != message_id) {status = AIS_ERR_WRONG_MSG_TYPE; return;} repeat_indicator = ubits(bs,6,2); mmsi = ubits(bs,8,30); position_accuracy = bs[38]; raim = bs[39]; nav_status = ubits(bs, 40, 4); x = sbits(bs, 44, 18) / 600.; y = sbits(bs, 62, 17) / 600.; sog = ubits(bs,79,6); cog = ubits(bs,85,9); gnss = !bs[94]; spare = bs[95]; }
// River Information Systems ECE-TRANS-SC3-2006-10r-RIS.pdf Ais8_200_55::Ais8_200_55(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 200); assert(fi == 55); const size_t num_bits = strlen(nmea_payload) * 6 - pad; // People might get smart and leave out the 51 spare bits // TODO(schwehr): do we have any cases of that? if (num_bits != 88 && num_bits != 136 && num_bits != 168) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<168> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } crew = ubits(bs, 56, 8); passengers = ubits(bs, 64, 13); yet_more_personnel = ubits(bs, 77, 8); if (88 == num_bits) { spare2[0] = ubits(bs, 85, 3); spare2[1] = 0; spare2[2] = 0; } else if (136 == num_bits) { // as in the spec - maybe? spare2[0] = ubits(bs, 85, 32); spare2[1] = ubits(bs, 117, 32); spare2[2] = ubits(bs, 149, 19); } else { spare2[0] = ubits(bs, 85, 32); spare2[1] = ubits(bs, 117, 19); spare2[2] = 0; } status = AIS_OK; }