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);
}
// 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;
}
Example #3
0
// 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;
        }
    }

}
// 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;
}
// 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 - 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;
}
// 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;
}
Example #8
0
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;
}
// 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;
}
Example #10
0
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];
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #14
0
Ais21::Ais21(const char *nmea_payload, const int pad) {
    assert(nmea_payload);
    init();

    const size_t num_bits = strlen(nmea_payload) * 6 - pad;

    // 272-360 - FIX: make this more careful
    if (272 > num_bits || num_bits > 360) { status = AIS_ERR_BAD_BIT_COUNT; return; }

    std::bitset<360> bs; // 360 % 6 == 0 -> 60 NMEA characters exactly
    status = aivdm_to_bits(bs, nmea_payload);
    if (had_error()) return;
    
    message_id = ubits(bs, 0, 6);
    if (message_id != 21) {status = AIS_ERR_WRONG_MSG_TYPE; return;}
    repeat_indicator = ubits(bs,6,2);
    mmsi = ubits(bs,8,30);
    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 = bool(bs[259]);
    aton_status = ubits(bs, 260, 8);
    raim = bool(bs[268]);
    virtual_aton = bool(bs[269]);
    assigned_mode = bool(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;
    }
    
}
Example #15
0
// TODO: pad
Ais22::Ais22(const char *nmea_payload) {
    assert(nmea_payload);
    init();

    const int num_char = std::strlen(nmea_payload);
    if (28 != num_char) { status = AIS_ERR_BAD_BIT_COUNT; return; }

    std::bitset<168> bs;
    status = aivdm_to_bits(bs, nmea_payload);
    if (had_error()) return;

    message_id = ubits(bs, 0, 6);
    if (message_id != 22) { status = AIS_ERR_WRONG_MSG_TYPE; return; }
    repeat_indicator = ubits(bs,6,2);
    mmsi = ubits(bs,8,30);
    spare = ubits(bs,38,2);

    chan_a = ubits(bs,40,12);
    chan_b = ubits(bs,52,12);
    txrx_mode = ubits(bs, 64, 4);
    power_low = bs[68];

    // WARNING: OUT OF ORDER DECODE
    bool addressed = bs[139];

    if (not(addressed)) {
      // geographic position
      pos_valid = true;
      dest_valid = false;
      x1 = sbits(bs, 69, 28) / 600000.;
      y1 = sbits(bs, 87, 27) / 600000.;
      x2 = sbits(bs, 104, 28) / 600000.;
      y2 = sbits(bs, 122, 27) / 600000.;
    } else {
      pos_valid = false;
      dest_valid = true;
      dest_mmsi_1 = ubits(bs, 69, 30);
      // TODO: save the 5 spare bits
      dest_mmsi_2 = ubits(bs, 104, 30);
      // TODO: save the 5 spare bits
    }

    // OUT OF ORDER: addressed is before
    chan_a_bandwidth = bs[140];
    chan_b_bandwidth = bs[141];
    zone_size = ubits(bs, 142, 3);

    spare2 = ubits(bs, 145, 23);
}
// River Information Systems ECE-TRANS-SC3-2006-10r-RIS.pdf
Ais8_200_23::Ais8_200_23(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

  assert(dac == 200);
  assert(fi == 23);

  const size_t num_bits = strlen(nmea_payload) * 6 - pad;

  if (num_bits != 256) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  bitset<256> bs;
  const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  utc_year_start = ubits(bs, 56, 9);
  utc_month_start = ubits(bs, 65, 4);
  utc_day_start = ubits(bs, 69, 4);  // ERROR: not enough bits to cover 1-31
  utc_year_end = ubits(bs, 73, 9);
  utc_month_end = ubits(bs, 82, 4);
  utc_day_end = ubits(bs, 86, 4);  // ERROR: not enough bits to cover 1-31

  utc_hour_start = ubits(bs, 90, 5);
  utc_min_start = ubits(bs, 95, 6);
  utc_hour_end = ubits(bs, 101, 5);
  utc_min_end = ubits(bs, 106, 6);

  x1 = (float)(sbits(bs, 112, 28) / 600000.0);//Crouse:Added typecasting
  y1 = (float)(sbits(bs, 140, 27) / 600000.0);//Crouse:Added typecasting
  x2 = (float)(sbits(bs, 167, 28) / 600000.0);//Crouse:Added typecasting
  y2 = (float)(sbits(bs, 195, 27) / 600000.0);//Crouse:Added typecasting

  type = ubits(bs, 222, 4);
  min = ubits(bs, 226, 9);
  max = ubits(bs, 235, 9);
  classification = ubits(bs, 244, 2);
  wind_dir = ubits(bs, 246, 4);
  spare2 = ubits(bs, 250, 6);

  status = AIS_OK;
}
// IMO Circ 289 - Extended ship static and voyage-related
// See also Circ 236
Ais8_1_24::Ais8_1_24(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

  assert(dac == 1);
  assert(fi == 24);

  const size_t num_bits = strlen(nmea_payload) * 6 - pad;

  if (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);
  air_draught = (float)(ubits(bs, 66, 13) / 10.0);  // m //Crouse: Added typecasting
  last_port = ais_str(bs, 79, 30);
  next_ports[0] = ais_str(bs, 109, 30);
  next_ports[1] = ais_str(bs, 139, 30);

  // TODO(schwehr): enum list of param types
  // 0 NA, 1 operational, 2 SNAFU, 3 no data
  for (size_t equip_num = 0; equip_num < 26; equip_num++) {
    solas_status[equip_num] = ubits(bs, 169 + 2 * equip_num, 2);
  }
  ice_class = ubits(bs, 221, 4);
  shaft_power = ubits(bs, 225, 18);  // horses
  vhf = ubits(bs, 243, 12);
  lloyds_ship_type = ais_str(bs, 255, 42);
  gross_tonnage = ubits(bs, 297, 18);
  laden_ballast = ubits(bs, 315, 2);
  heavy_oil = ubits(bs, 317, 2);
  light_oil = ubits(bs, 319, 2);
  diesel = ubits(bs, 321, 2);
  bunker_oil = ubits(bs, 323, 14);  // tonnes
  persons = ubits(bs, 337, 13);
  spare2 = ubits(bs, 350, 10);
  status = AIS_OK;
}
Example #18
0
// TODO: pad
Ais15::Ais15(const char *nmea_payload) {
    assert(nmea_payload);
    init();

    const int num_char = std::strlen(nmea_payload);
    if (num_char != 15 && num_char!=18 and num_char!=27) {
        // 88-160 bits
        status = AIS_ERR_BAD_BIT_COUNT;
        return;
    }

    std::bitset<162> bs; // 160 / 6 = 26.66
    status = aivdm_to_bits(bs, nmea_payload);
    if (had_error()) return;

    message_id = ubits(bs, 0, 6);
    if (15 != 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);

    mmsi_1 = ubits(bs,40,30);  // Destination ID 1

    msg_1_1 = ubits(bs,70,6);
    slot_offset_1_1 = ubits(bs,76,12);

    // TODO: set remaining fields to -1
    if (num_char <= 15) return;

    spare2 = ubits(bs,88,2);
    dest_msg_1_2 = ubits(bs,90,6);
    slot_offset_1_2 = ubits(bs,96,12);

    // TODO: set remaining fields to -1
    if (num_char <= 18) return;

    spare3 = ubits(bs,108,2);
    mmsi_2 = ubits(bs,110,30);
    msg_2 = ubits(bs,140,6);
    slot_offset_2 = ubits(bs,146,12);
    spare4 = ubits(bs,158,2);
}
// IMO Circ 289 - Route information
// See also Circ 236
Ais8_1_27::Ais8_1_27(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

  assert(dac == 1);
  assert(fi == 27);

  const size_t num_bits = strlen(nmea_payload) * 6 - pad;
  const size_t num_waypoints = (num_bits - 117) / 55;
  const size_t extra_bits = (num_bits - 117) % 55;

  if (extra_bits || num_waypoints > 16) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  bitset<997> bs;
  const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  link_id = ubits(bs, 56, 10);
  sender_type = ubits(bs, 66, 3);
  route_type = ubits(bs, 69, 5);
  utc_month = ubits(bs, 74, 4);
  utc_day = ubits(bs, 78, 5);
  utc_hour = ubits(bs, 83, 5);
  utc_min = ubits(bs, 88, 6);
  duration = ubits(bs, 94, 18);
  // TODO(schwehr): manage the case where num_waypoints does not match
  // const size_t num_waypoints_stated = ubits(bs, 112, 5);
  for (size_t waypoint_num = 0; waypoint_num < num_waypoints; waypoint_num++) {
    AisPoint pt;
    const size_t start = 117 + 55*waypoint_num;
    pt.x =  (float)(sbits(bs, start, 28) / 600000.0);//Crouse: Added typecasting
    pt.y =  (float)(sbits(bs, start + 28, 27) / 600000.0);//Crouse: Added typecasting
    waypoints.push_back(pt);
  }

  status = AIS_OK;
}
// 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;
}
Ais5::Ais5(const char *nmea_payload, const size_t pad)
    : AisMsg(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

  assert(message_id == 5);

  if (pad != 2 || strlen(nmea_payload) != 71) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  bitset<426> bs;
  const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  ais_version = ubits(bs, 38, 2);
  imo_num = ubits(bs, 40, 30);
  callsign = ais_str(bs, 70, 42);

  name = ais_str(bs, 112, 120);

  type_and_cargo = ubits(bs, 232, 8);
  dim_a = ubits(bs, 240, 9);
  dim_b = ubits(bs, 249, 9);
  dim_c = ubits(bs, 258, 6);
  dim_d = ubits(bs, 264, 6);
  fix_type = ubits(bs, 270, 4);
  eta_month = ubits(bs, 274, 4);
  eta_day = ubits(bs, 278, 5);
  eta_hour = ubits(bs, 283, 5);
  eta_minute = ubits(bs, 288, 6);
  draught = (float)(ubits(bs, 294, 8) / 10.0);//Crouse: Added typecasting
  destination = ais_str(bs, 302, 120);
  dte = bs[422];
  spare = bs[423];

  status = AIS_OK;
}
Example #22
0
// TODO: pad
Ais19::Ais19(const char *nmea_payload) {
    assert(nmea_payload);

    init();
    if (strlen(nmea_payload) != 52) { status = AIS_ERR_BAD_BIT_COUNT; return; }

    std::bitset<312> bs;
    status = aivdm_to_bits(bs, nmea_payload);
    if (had_error()) return;

    message_id = ubits(bs, 0, 6);
    if (19 != message_id) { status = AIS_ERR_WRONG_MSG_TYPE; return; }
    repeat_indicator = ubits(bs,6,2);
    mmsi = ubits(bs,8,30);

    spare = ubits(bs,38,8);
    sog = ubits(bs,46,10) / 10.;

    position_accuracy = bs[56];
    x = sbits(bs, 57, 28) / 600000.;
    y = sbits(bs, 85, 27) / 600000.;

    cog = ubits(bs, 112, 12) / 10.;
    true_heading = ubits(bs, 124, 9);
    timestamp = ubits(bs, 133, 6);
    spare2 = ubits(bs, 139, 4);

    name = ais_str(bs, 143, 120);

    type_and_cargo = ubits(bs, 263, 8);
    dim_a = ubits(bs, 271, 9);
    dim_b = ubits(bs, 280, 9);
    dim_c = ubits(bs, 289, 6);
    dim_d = ubits(bs, 295, 6);

    fix_type = ubits(bs, 301, 4);
    raim = bs[305];
    dte = bs[306];
    assigned_mode = bs[307];
    spare3 = ubits(bs,308,4);
}
Example #23
0
Ais8_366_22::Ais8_366_22(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

  assert(dac == 366);
  assert(fi == 22);

  const int num_bits = (strlen(nmea_payload) * 6) - pad;
  if (num_bits <= 208 || num_bits >= 1020) {
    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;
  }

  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 = static_cast<int>(floor((num_bits - 111)/90.));
  for (int area_idx = 0; area_idx < num_sub_areas; area_idx++) {
    Ais8_366_22_SubArea *area =
        ais8_366_22_subarea_factory(bs, 111 + 90*area_idx);
    if (area)
      sub_areas.push_back(area);
    else
      status = AIS_ERR_BAD_SUB_SUB_MSG;
  }
}
// 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;
}
Ais8_1_26::Ais8_1_26(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

  assert(dac == 1);
  assert(fi == 26);

  const ptrdiff_t num_bits = strlen(nmea_payload) * 6 - pad;//Crouse: Changed int to ptrdiff_t
  if (168 > num_bits || num_bits > 1098) {
    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;
  }

  const size_t num_sensor_reports = (num_bits - 56) / AIS8_1_26_REPORT_SIZE;

  // TODO(schwehr): what to do about extra data in sensor report msg 8_1_26?
  // if ((num_bits - 56) % AIS8_1_26_REPORT_SIZE)

  for (size_t report_idx = 0; report_idx < num_sensor_reports; report_idx++) {
    const size_t start = 56 + report_idx * AIS8_1_26_REPORT_SIZE;
    Ais8_1_26_SensorReport *sensor = ais8_1_26_sensor_report_factory(bs, start);
    if (sensor) {
        reports.push_back(sensor);
    } else {
      status = AIS_ERR_BAD_SUB_SUB_MSG;
    }
  }
  if (AIS_UNINITIALIZED == status)
    status = AIS_OK;
}
// IMO Circ 289 - VTS Generated/Synthetic Targets
// See also Circ 236
Ais8_1_17::Ais8_1_17(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

  assert(dac == 1);
  assert(fi == 17);

  const size_t num_bits = strlen(nmea_payload) * 6 - pad;
  const size_t num_targets = (num_bits - 56) / 120;
  const size_t extra_bits = (num_bits - 56) % 120;

  if (extra_bits || num_targets > 4) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  bitset<536> bs;
  const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  for (size_t target_num = 0; target_num < num_targets; target_num++) {
    Ais8_1_17_Target target;
    const size_t start = 56 + (120 * target_num);
    target.type = ubits(bs, start, 2);
    target.id = ais_str(bs,  start + 2, 42);
    target.spare = ubits(bs, start + 44, 4);
    target.y = (float)(sbits(bs, start + 48, 24) / 60000.0);  // booo - lat, lon //Crouse: Added typecasting
    target.x = (float)(sbits(bs, start + 72, 25) / 60000.0);//Crouse: Added typecasting
    target.cog = ubits(bs, start + 97, 9);
    target.timestamp = ubits(bs, start + 106, 6);
    target.sog = ubits(bs, start + 112, 8);
  }
  status = AIS_OK;
}
// IMO Circ 289 - Fairway Closed
// See also Circ 236
Ais8_1_13::Ais8_1_13(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;
  assert(dac == 1);
  assert(fi == 13);

  const size_t num_bits = strlen(nmea_payload) * 6 - pad;

  if (num_bits != 472) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  bitset<472> bs;
  const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  reason = ais_str(bs, 56, 120);
  location_from = ais_str(bs, 176, 120);
  location_to = ais_str(bs, 296, 120);
  radius = ubits(bs, 416, 10);
  units = ubits(bs, 426, 2);
  day_from = ubits(bs, 428, 5);
  month_from = ubits(bs, 433, 4);
  hour_from = ubits(bs, 437, 5);
  minute_from = ubits(bs, 442, 6);
  day_to = ubits(bs, 448, 5);
  month_to = ubits(bs, 453, 4);
  hour_to = ubits(bs, 457, 5);
  minute_to = ubits(bs, 462, 6);
  spare2 = ubits(bs, 468, 4);
  status = AIS_OK;
}
Ais8_1_0::Ais8_1_0(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

  assert(dac == 1);
  assert(fi == 0);

  const size_t num_bits = strlen(nmea_payload) * 6 - pad;

  if (56 > num_bits || num_bits > 1024) {
    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;
  }

  ack_required = bs[56];
  msg_seq = ubits(bs, 57, 11);

  const size_t text_size = 6 * ((num_bits - 68)/6);
  // wrong?  needs to land on 8-bit boundary
  const size_t spare2_size = num_bits - 68 - text_size;
  text = ais_str(bs, 68, text_size);

  // TODO(schwehr): Is this correct?
  if (!spare2_size)
    spare2 = 0;
  else
    spare2 = ubits(bs, 68, spare2_size);
  status = AIS_OK;
}
Example #29
0
Ais18::Ais18(const char *nmea_payload) {
    assert(nmea_payload);

    init();

    if (strlen(nmea_payload) != 168/6) {
        status = AIS_ERR_BAD_BIT_COUNT;
        return;
    }

    std::bitset<168> bs; // 1 slot
    status = aivdm_to_bits(bs, nmea_payload);
    if (had_error()) return;

    message_id = ubits(bs, 0, 6);
    if (18 != message_id) { status = AIS_ERR_WRONG_MSG_TYPE; return; }
    repeat_indicator = ubits(bs,6,2);
    mmsi = ubits(bs,8,30);

    spare = ubits(bs,38,8);
    sog = ubits(bs,46,10) / 10.;

    position_accuracy = ubits(bs,56,1);
    x = sbits(bs, 57, 28) / 600000.;
    y = sbits(bs, 85, 27) / 600000.;

    cog = ubits(bs, 112, 12) / 10.;
    true_heading = ubits(bs, 124, 9);
    timestamp = ubits(bs, 133, 6);
    spare2 = ubits(bs, 139, 2);
    unit_flag = bs[141];
    display_flag = bs[142];
    dsc_flag = bs[143];
    band_flag = bs[144];
    m22_flag = bs[145];
    mode_flag = bs[146];
    raim = bool(bs[147]);
    commstate_flag = bs[148];  // 0 SOTDMA, 1 ITDMA

    // FIX: set all to -1 and set valids to NOT!

    if (1 == unit_flag) {
        // CS - carrier sense - fixed commstate payload of 1100000000000000110
        int commstate = ubits(bs,149, 19);
        //std::cout << "\tcs commstate: " << commstate << std::endl;
        if (393222 != commstate) {
            // FIX: is this the right value?
            // FIX: return an error?
        }
    } else {
        sync_state = ubits(bs, 149, 2);
        if (0 == commstate_flag) {
            // SOTDMA
            slot_timeout = ubits(bs,151,3);

            switch (slot_timeout) {
            case 0:
                slot_offset = ubits(bs, 154, 14);
                slot_offset_valid = true;
                break;
            case 1:
                utc_hour = ubits(bs, 154, 5); 
                utc_min = ubits(bs, 159, 7);
                utc_spare = ubits(bs, 166, 2);
                utc_valid = true;
                break;
            case 2: // FALLTHROUGH
            case 4: // FALLTHROUGH
            case 6:
                slot_number = ubits(bs, 154, 14);
                slot_number_valid = true;
                break;
            case 3: // FALLTHROUGH
            case 5: // FALLTHROUGH
            case 7:
                received_stations = ubits(bs, 154, 14);
                received_stations_valid = true;
                break;
            default:
                assert (false);
            }

        } else {
            // ITDMA
            slot_increment = ubits(bs, 151, 13);
            slot_increment_valid = true;

            slots_to_allocate = ubits(bs, 164, 3);
            slots_to_allocate_valid = true;

            keep_flag = bool(bs[167]);
            keep_flag_valid = true;
        }
    }
}
Ais9::Ais9(const char *nmea_payload, const size_t pad)
    : AisMsg(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

  assert(message_id == 9);

  if (pad != 0 || strlen(nmea_payload) != 28) {
    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;
  }

  alt = ubits(bs, 38, 12);
  sog = (float)(ubits(bs, 50, 10) / 10.0);//Crouse:Added typecasting

  position_accuracy = bs[60];
  x = (float)(sbits(bs, 61, 28) / 600000.0);//Crouse:Added typecasting
  y = (float)(sbits(bs, 89, 27) / 600000.0);//Crouse:Added typecasting

  cog = (float)(ubits(bs, 116, 12) / 10.0);//Crouse:Added typecasting
  timestamp = ubits(bs, 128, 6);
  alt_sensor = bs[134];
  spare = ubits(bs, 135, 7);
  dte = bs[142];
  spare2 = ubits(bs, 143, 3);
  assigned_mode = bs[146];
  raim = bs[147];
  commstate_flag = bs[148];  // 0 SOTDMA, 1 ITDMA

  sync_state = ubits(bs, 149, 2);

#ifndef NDEBUG
  slot_timeout = -1;
  received_stations = slot_number = utc_hour = utc_min = utc_spare -1;
  slot_offset = slot_increment = slots_to_allocate = -1;
  keep_flag = false;
#endif

  slot_timeout_valid = false;
  received_stations_valid = false;
  slot_number_valid = false;
  utc_valid = false;
  slot_offset_valid = false;
  slot_increment_valid = false;
  slots_to_allocate_valid = false;
  keep_flag_valid = false;

  if (0 == commstate_flag) {
    // SOTDMA
    slot_timeout = ubits(bs, 151, 3);
    slot_timeout_valid = true;

    switch (slot_timeout) {
    case 0:
      slot_offset = ubits(bs, 154, 14);
      slot_offset_valid = true;
      break;
    case 1:
      utc_hour = ubits(bs, 154, 5);
      utc_min = ubits(bs, 159, 7);
      utc_spare = ubits(bs, 166, 2);
      utc_valid = true;
      break;
    case 2:  // FALLTHROUGH
    case 4:  // FALLTHROUGH
    case 6:
      slot_number = ubits(bs, 154, 14);
      slot_number_valid = true;
      break;
    case 3:  // FALLTHROUGH
    case 5:  // FALLTHROUGH
    case 7:
      received_stations = ubits(bs, 154, 14);
      received_stations_valid = true;
      break;
    default:
      assert(false);
    }
  } else {
    // ITDMA
    slot_increment = ubits(bs, 151, 13);
    slot_increment_valid = true;

    slots_to_allocate = ubits(bs, 164, 3);
    slots_to_allocate_valid = true;

    keep_flag = bs[167];
    keep_flag_valid = true;
  }

  status = AIS_OK;
}