예제 #1
0
// IMO 1371-5 Ack
Ais6_1_5::Ais6_1_5(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), ack_dac(0), ack_fi(0), seq_num(0),
      ai_available(false), ai_response(0), spare(0) {
  assert(dac == 1);
  assert(fi == 5);

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

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  ack_dac = bs.ToUnsignedInt(88, 10);
  ack_fi = bs.ToUnsignedInt(98, 6);
  seq_num = bs.ToUnsignedInt(104, 11);
  ai_available = static_cast<bool>(bs[115]);
  ai_response = bs.ToUnsignedInt(116, 3);
  spare = bs.ToUnsignedInt(119, 49);

  assert(bs.GetRemaining() == 0);

  status = AIS_OK;
}
예제 #2
0
Ais6_1_0::Ais6_1_0(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), ack_required(false), msg_seq(0),
      spare2(0) {

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

  if (num_bits < 88 || num_bits > 936) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  AisBitset bs;  // TODO(schwehr): what is the real max size?
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  ack_required = bs[88];
  msg_seq = bs.ToUnsignedInt(89, 11);

  const size_t text_size = 6 * ((num_bits - 100) / 6);
  const size_t spare2_size = num_bits - 100 - text_size;
  text = bs.ToString(100, text_size);

  if (!spare2_size)
    spare2 = 0;
  else
    spare2 = bs.ToUnsignedInt(100 + text_size, spare2_size);

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #3
0
Ais6_1_1::Ais6_1_1(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), ack_dac(0), msg_seq(0), spare2(0) {
  assert(dac == 1);
  assert(fi == 1);

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

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  ack_dac = bs.ToUnsignedInt(88, 10);
  msg_seq = bs.ToUnsignedInt(98, 11);
  spare2 = bs.ToUnsignedInt(109, 3);

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #4
0
Ais6::Ais6(const char *nmea_payload, const size_t pad)
    : AisMsg(nmea_payload, pad),
      seq(0),
      mmsi_dest(0),
      retransmit(false),
      spare(0),
      dac(0),
      fi(0) {
  assert(message_id == 6);

  // TODO(olafsinram): 46 or rather 56?
  const int payload_len = num_bits - 46;  // in bits w/o DAC/FI
  if (num_bits < 88 || payload_len < 0 || payload_len > 952) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(38);
  seq = bs.ToUnsignedInt(38, 2);
  mmsi_dest = bs.ToUnsignedInt(40, 30);
  retransmit = !bs[70];
  spare = bs[71];
  dac = bs.ToUnsignedInt(72, 10);
  fi = bs.ToUnsignedInt(82, 6);
}
예제 #5
0
파일: ais8_1_26.cpp 프로젝트: rolker/libais
Ais8_1_26_Location::Ais8_1_26_Location(const AisBitset &bits,
                                       const size_t offset) {
  position = bits.ToAisPoint(offset, 55);
  z = bits.ToUnsignedInt(offset + 55, 11) / 10.;
  owner = bits.ToUnsignedInt(offset + 66, 4);
  timeout = bits.ToUnsignedInt(offset + 70, 3);
  spare = bits.ToUnsignedInt(offset + 73, 12);
}
예제 #6
0
Ais8_366_22_Rect::Ais8_366_22_Rect(const AisBitset &bs,
                                   const size_t offset) {
  const int scale_factor = bs.ToUnsignedInt(offset + 3, 2);
  position = bs.ToAisPoint(offset + 5, 55);
  e_dim_m = bs.ToUnsignedInt(offset + 60, 8) * scale_multipliers[scale_factor];
  n_dim_m = bs.ToUnsignedInt(offset + 68, 8) * scale_multipliers[scale_factor];
  orient_deg = bs.ToUnsignedInt(offset + 76, 9);
  spare = bs.ToUnsignedInt(offset + 85, 5);
}
예제 #7
0
Ais8_366_22_Sector::Ais8_366_22_Sector(const AisBitset &bits,
                                       const size_t offset) {
  const int scale_factor = bits.ToUnsignedInt(offset + 3, 2);
  position = bits.ToAisPoint(offset + 5, 55);
  radius_m =
      bits.ToUnsignedInt(offset + 60, 12) * scale_multipliers[scale_factor];
  left_bound_deg = bits.ToUnsignedInt(offset + 72, 9);
  right_bound_deg = bits.ToUnsignedInt(offset + 81, 9);
}
예제 #8
0
Ais8_366_22_Circle::Ais8_366_22_Circle(const AisBitset &bits,
                                       const size_t offset) {
  const int scale_factor = bits.ToUnsignedInt(offset + 3, 2);
  position = bits.ToAisPoint(offset + 5, 55);
  // TODO(schwehr): precision? And bit counts for radius  and spare?
  // TODO(schwehr): collapse these numbers
  radius_m =
      bits.ToUnsignedInt(offset + 60, 12) * scale_multipliers[scale_factor];
  spare = bits.ToUnsignedInt(offset + 72, 16);
}
예제 #9
0
파일: ais8_1_26.cpp 프로젝트: rolker/libais
Ais8_1_26_Curr2D::Ais8_1_26_Curr2D(const AisBitset &bits,
                                   const size_t offset) {
  for (size_t idx = 0; idx < 3; idx++) {
    size_t start = offset + idx * 26;
    currents[idx].speed = bits.ToUnsignedInt(start, 8) / 10.;
    currents[idx].dir = bits.ToUnsignedInt(start + 8, 9);
    currents[idx].depth = bits.ToUnsignedInt(start + 17, 9);
  }
  type = bits.ToUnsignedInt(offset + 78, 3);
  spare = bits.ToUnsignedInt(offset + 81, 4);
}
예제 #10
0
파일: ais8_1_26.cpp 프로젝트: rolker/libais
Ais8_1_26_HorzFlow::Ais8_1_26_HorzFlow(const AisBitset &bits,
                                       const size_t offset) {
  for (size_t idx = 0; idx < 2; idx++) {
    size_t start = offset + idx * 42;
    currents[idx].bearing = bits.ToUnsignedInt(start, 9);
    currents[idx].dist = bits.ToUnsignedInt(start + 9, 7);
    currents[idx].speed = bits.ToUnsignedInt(start + 16, 8) / 10.;
    currents[idx].dir = bits.ToUnsignedInt(start + 24, 9);
    currents[idx].level = bits.ToUnsignedInt(start + 33, 9);
  }
  spare = bits[offset + 84];
}
예제 #11
0
// TODO(schwehr): Merge with Polyline.
Ais8_366_22_Polygon::Ais8_366_22_Polygon(const AisBitset &bits,
                                         const size_t offset) {
  const int scale_factor = bits.ToUnsignedInt(offset + 3, 2);
  for (size_t i = 0; i < 4; i++) {
    const int angle = bits.ToUnsignedInt(offset + 5 + (i*21), 10);
    const int dist = bits.ToUnsignedInt(offset + 15 + (i*21), 11) *
                     scale_multipliers[scale_factor];
    if (dist == 0) {
      break;
    }
    angles.push_back(angle);
    dists_m.push_back(dist);
  }
  spare = bits[offset + 89];
}
예제 #12
0
파일: ais8_1_26.cpp 프로젝트: rolker/libais
Ais8_1_26_SeaState::Ais8_1_26_SeaState(const AisBitset &bits,
                                       const size_t offset) {
  swell_height = bits.ToUnsignedInt(offset, 8) / 10.;
  swell_period = bits.ToUnsignedInt(offset + 8, 6);
  swell_dir = bits.ToUnsignedInt(offset + 14, 9);
  sea_state = bits.ToUnsignedInt(offset + 23, 4);
  swell_sensor_type = bits.ToUnsignedInt(offset + 27, 3);
  water_temp = bits.ToInt(offset + 30, 10) / 10.;
  water_temp_depth = bits.ToUnsignedInt(offset + 40, 7) / 10.;
  water_sensor_type = bits.ToUnsignedInt(offset + 47, 3);
  wave_height = bits.ToUnsignedInt(offset + 50, 8) / 10.;
  wave_period = bits.ToUnsignedInt(offset + 58, 6);
  wave_dir = bits.ToUnsignedInt(offset + 64, 9);
  wave_sensor_type = bits.ToUnsignedInt(offset + 73, 3);
  salinity = bits.ToUnsignedInt(offset + 76, 9) / 10.;
}
예제 #13
0
// IFM 4: Capability reply - OLD ITU 1371-4
// TODO(schwehr): WTF?  10 + 128 + 6 == 80  Is this 168 or 232 bits?
Ais6_1_4::Ais6_1_4(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), ack_dac(0), capabilities(),
      cap_reserved(), spare2(0) {
  assert(dac == 1);
  assert(fi == 4);

  // TODO(schwehr): num_bits for 6_1_4.  226 bits?
  if (num_bits != 232) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  ack_dac = bs.ToUnsignedInt(88, 10);
  for (size_t cap_num = 0; cap_num < 128/2; cap_num++) {
    size_t start = 98 + cap_num * 2;
    capabilities[cap_num] = bs[start];
    cap_reserved[cap_num] = bs[start + 1];
  }
  // spare2 = bs.ToUnsignedInt(226, 6);  // OR NOT
  // TODO(schwehr): add in the offset of the dest mmsi

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #14
0
파일: ais8_1_26.cpp 프로젝트: rolker/libais
Ais8_1_26_Wx::Ais8_1_26_Wx(const AisBitset &bits,
                           const size_t offset) {
  air_temp = bits.ToInt(offset, 11) / 10.;
  air_temp_sensor_type = bits.ToUnsignedInt(offset + 11, 3);
  precip = bits.ToUnsignedInt(offset + 14, 2);
  horz_vis = bits.ToUnsignedInt(offset + 16, 8) / 10.;
  dew_point = bits.ToInt(offset + 24, 10) / 10.;
  dew_point_type = bits.ToUnsignedInt(offset + 34, 3);
  air_pressure = (bits.ToUnsignedInt(offset + 37, 9) + 800) / 100.0;  // Pa.
  air_pressure_trend = bits.ToUnsignedInt(offset + 46, 2);
  air_pressor_type = bits.ToUnsignedInt(offset + 48, 3);
  salinity = bits.ToUnsignedInt(offset + 51, 9) / 10.;
  spare = bits.ToUnsignedInt(offset + 60, 25);
}
예제 #15
0
파일: ais8_1_26.cpp 프로젝트: rolker/libais
Ais8_1_26_Salinity::Ais8_1_26_Salinity(const AisBitset &bits,
                                       const size_t offset) {
  water_temp = bits.ToUnsignedInt(offset, 10) / 10. - 10;
  conductivity = bits.ToUnsignedInt(offset + 10, 10) / 100.;
  pressure = bits.ToUnsignedInt(offset + 20, 16) / 10.;
  salinity = bits.ToUnsignedInt(offset + 36, 9) / 10.;
  salinity_type = bits.ToUnsignedInt(offset + 45, 2);
  sensor_type = bits.ToUnsignedInt(offset + 47, 3);
  spare[0] = bits.ToUnsignedInt(offset + 50, 32);
  spare[1] = bits.ToUnsignedInt(offset + 82, 3);
}
예제 #16
0
파일: ais8_1_26.cpp 프로젝트: rolker/libais
Ais8_1_26_AirDraught::Ais8_1_26_AirDraught(const AisBitset &bits,
                                           const size_t offset) {
  draught = bits.ToUnsignedInt(offset, 13) / 100.;
  gap = bits.ToUnsignedInt(offset + 13, 13) / 10.;
  trend = bits.ToUnsignedInt(offset + 26, 2);
  forecast_gap = bits.ToUnsignedInt(offset + 28, 13) / 10.;
  utc_day_forecast = bits.ToUnsignedInt(offset + 41, 5);
  utc_hour_forecast = bits.ToUnsignedInt(offset + 46, 5);
  utc_min_forecast = bits.ToUnsignedInt(offset + 51, 6);
  spare = bits.ToUnsignedInt(offset + 57, 28);
}
예제 #17
0
// IMO Circ 289 - Clearance time to enter port
Ais6_1_18::Ais6_1_18(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), link_id(0), utc_month(0), utc_day(0),
      utc_hour(0), utc_min(0), spare2() {
  assert(dac == 1);
  assert(fi == 18);

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

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  link_id = bs.ToUnsignedInt(88, 10);
  utc_month = bs.ToUnsignedInt(98, 4);
  utc_day = bs.ToUnsignedInt(102, 5);
  utc_hour = bs.ToUnsignedInt(107, 5);
  utc_min = bs.ToUnsignedInt(112, 6);
  port_berth = bs.ToString(118, 120);
  dest = bs.ToString(238, 30);
  position = bs.ToAisPoint(268, 49);
  spare2[0] = bs.ToUnsignedInt(317, 32);
  spare2[1] = bs.ToUnsignedInt(349, 11);

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #18
0
// http://www.e-navigation.nl/content/monitoring-aids-navigation
Ais6_0_0::Ais6_0_0(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad),
      sub_id(1),
      voltage(0.0),
      current(0.0),
      dc_power_supply(true),
      light_on(true),
      battery_low(false),
      off_position(false),
      spare2(0) {
  assert(dac == 0);
  assert(fi == 0);

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

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  sub_id = bs.ToUnsignedInt(88, 16);
  voltage = bs.ToUnsignedInt(104, 12) / 10.0;
  current = bs.ToUnsignedInt(116, 10) / 10.0;
  dc_power_supply = bs[126];
  light_on = bs[127];
  battery_low = bs[128];
  off_position = bs[129];

  spare2 = bs.ToUnsignedInt(130, 6);

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #19
0
파일: ais8_1_26.cpp 프로젝트: rolker/libais
Ais8_1_26_WaterLevel::Ais8_1_26_WaterLevel(const AisBitset &bits,
                                           const size_t offset) {
  type = bits[offset];
  level = bits.ToInt(offset + 1, 16) / 100.;
  trend = bits.ToUnsignedInt(offset + 17, 2);
  vdatum = bits.ToUnsignedInt(offset + 19, 5);
  sensor_type = bits.ToUnsignedInt(offset + 24, 3);
  forecast_type = bits[offset + 27];
  level_forecast = bits.ToInt(offset + 28, 16) / 100.;
  utc_day_forecast = bits.ToUnsignedInt(offset + 44, 5);
  utc_hour_forecast = bits.ToUnsignedInt(offset + 49, 5);
  utc_min_forecast = bits.ToUnsignedInt(offset + 54, 6);
  duration = bits.ToUnsignedInt(offset + 60, 8);
  spare = bits.ToUnsignedInt(offset + 68, 17);
}
예제 #20
0
Ais6_1_2::Ais6_1_2(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), req_dac(0), req_fi(0) {
  assert(dac == 1);
  assert(fi == 2);

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

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  req_dac = bs.ToUnsignedInt(88, 10);
  req_fi = bs.ToUnsignedInt(98, 6);

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #21
0
// IFM 40: people on board - OLD ITU 1371-4
Ais6_1_40::Ais6_1_40(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), persons(0), spare2(0) {
  assert(dac == 1);
  assert(fi == 40);

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

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  persons = bs.ToUnsignedInt(88, 13);
  spare2 = bs.ToUnsignedInt(101, 3);

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #22
0
// IMO Circ 289 - Berthing data
Ais6_1_20::Ais6_1_20(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), link_id(0), length(0), depth(0.0),
      mooring_position(0), utc_month(0), utc_day(0), utc_hour(0), utc_min(0),
      services_known(false), services() {
  assert(dac == 1);
  assert(fi == 20);

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

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  link_id = bs.ToUnsignedInt(88, 10);
  length = bs.ToUnsignedInt(98, 9);
  depth = bs.ToUnsignedInt(107, 8);
  mooring_position = bs.ToUnsignedInt(115, 3);
  utc_month = bs.ToUnsignedInt(118, 4);
  utc_day = bs.ToUnsignedInt(122, 5);
  utc_hour = bs.ToUnsignedInt(127, 5);
  utc_min = bs.ToUnsignedInt(132, 6);
  services_known = bs[138];
  for (size_t serv_num = 0; serv_num < 26; serv_num++) {
    // TODO(schwehr): const int val = bs.ToUnsignedInt(139 + 2*serv_num, 2);
    services[serv_num]
        = static_cast<int>(bs.ToUnsignedInt(139 + 2*serv_num, 2));
  }
  name = bs.ToString(191, 120);
  position = bs.ToAisPoint(311, 49);

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #23
0
파일: ais8_1_26.cpp 프로젝트: rolker/libais
Ais8_1_26_Curr3D::Ais8_1_26_Curr3D(const AisBitset &bits,
                                   const size_t offset) {
  for (size_t idx = 0; idx < 2; idx++) {
    size_t start = offset + idx * 33;
    currents[idx].north = bits.ToUnsignedInt(start, 8) / 10.;
    currents[idx].east = bits.ToUnsignedInt(start + 8, 8) / 10.;
    currents[idx].up = bits.ToUnsignedInt(start + 16, 8) / 10.;
    currents[idx].depth = bits.ToUnsignedInt(start + 24, 9);
  }
  type = bits.ToUnsignedInt(offset + 66, 3);
  spare = bits.ToUnsignedInt(offset + 69, 16);
}
예제 #24
0
// IMO Circ 289 - Tidal Window
// See also Circ 236
Ais6_1_14::Ais6_1_14(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), utc_month(0), utc_day(0) {
  // TODO(schwehr): untested - no sample of the correct length yet
  assert(dac == 1);
  assert(fi == 14);

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

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  utc_month = bs.ToUnsignedInt(88, 4);
  utc_day = bs.ToUnsignedInt(92, 5);

  for (size_t window_num = 0; window_num < 3; window_num++) {
    Ais6_1_14_Window w;
    const size_t start = 97 + window_num * 93;
    // Reversed order for lng/lat.
    float y = bs.ToInt(start, 27) / 600000.;
    float x = bs.ToInt(start + 27, 28) / 600000.;
    w.position = AisPoint(x, y);
    w.utc_hour_from = bs.ToUnsignedInt(start + 55, 5);
    w.utc_min_from = bs.ToUnsignedInt(start + 60, 6);
    w.utc_hour_to = bs.ToUnsignedInt(start + 66, 5);
    w.utc_min_to = bs.ToUnsignedInt(start + 71, 6);
    w.cur_dir = bs.ToUnsignedInt(start + 77, 9);
    w.cur_speed  = bs.ToUnsignedInt(start + 86, 7) / 10.;

    windows.push_back(w);
  }

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #25
0
// IMO Circ 289 - Tidal window
// See also Circ 236
Ais6_1_32::Ais6_1_32(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), utc_month(0), utc_day(0) {
  assert(dac == 1);
  assert(fi == 32);

  // TODO(schwehr): might get messages with not all windows
  if (num_bits != 350) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  utc_month = bs.ToUnsignedInt(88, 4);
  utc_day = bs.ToUnsignedInt(92, 5);

  for (size_t window_num = 0; window_num < 3; window_num++) {
    Ais6_1_32_Window w;
    const size_t start = 97 + 88*window_num;
    w.position = bs.ToAisPoint(start, 49);
    w.from_utc_hour = bs.ToUnsignedInt(start + 49, 5);
    w.from_utc_min = bs.ToUnsignedInt(start + 54, 6);
    w.to_utc_hour = bs.ToUnsignedInt(start + 60, 5);
    w.to_utc_min = bs.ToUnsignedInt(start + 65, 6);
    w.cur_dir = bs.ToUnsignedInt(start + 71, 9);
    w.cur_speed = bs.ToUnsignedInt(start + 80, 8) / 10.;
    windows.push_back(w);
  }

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #26
0
Ais8_366_22::Ais8_366_22(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad), link_id(0), notice_type(0), month(0), day(0),
      utc_hour(0), utc_minute(0), duration_minutes(0) {
  assert(dac == 366);
  assert(fi == 22);

  if (num_bits <= 208 || num_bits >= 1020) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  link_id = bs.ToUnsignedInt(56, 10);
  notice_type = bs.ToUnsignedInt(66, 7);
  month = bs.ToUnsignedInt(73, 4);
  day = bs.ToUnsignedInt(77, 5);
  utc_hour = bs.ToUnsignedInt(82, 5);
  utc_minute = bs.ToUnsignedInt(87, 6);

  duration_minutes = bs.ToUnsignedInt(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;
      return;
    }
  }

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #27
0
Ais23::Ais23(const char *nmea_payload, const size_t pad)
    : AisMsg(nmea_payload, pad), spare(0), station_type(0), type_and_cargo(0),
      spare2(3), txrx_mode(0), interval_raw(0), quiet(0), spare3(0) {

  assert(message_id == 23);

  if (pad != 2 || num_chars != 27) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(38);
  spare = bs.ToUnsignedInt(38, 2);

  position1 = bs.ToAisPoint(40, 35);
  position2 = bs.ToAisPoint(75, 35);

  station_type = bs.ToUnsignedInt(110, 4);
  type_and_cargo = bs.ToUnsignedInt(114, 8);
  spare2 = bs.ToUnsignedInt(122, 22);

  txrx_mode = bs.ToUnsignedInt(144, 2);
  interval_raw = bs.ToUnsignedInt(146, 4);
  quiet = bs.ToUnsignedInt(150, 4);
  spare3 = bs.ToUnsignedInt(154, 6);

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #28
0
// IMO Circ 289 - Dangerous cargo
// See also Circ 236
Ais6_1_12::Ais6_1_12(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), 
      un(0), value(0), value_unit(0), spare2(0) {
  assert(dac == 1);
  assert(fi == 12);

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

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  // TODO(schwehr): add in the offset of the dest mmsi

#if 0
  bs.SeekTo(56);
  last_port = bs.ToString(56, 30);
  utc_month_dep = bs.ToUnsignedInt(86, 4);
  utc_day_dep = bs.ToUnsignedInt(90, 5);
  utc_hour_dep = bs.ToUnsignedInt(95, 5);
  utc_min_dep = bs.ToUnsignedInt(100, 6);
  next_port = bs.ToString(106, 30);
  utc_month_next = bs.ToUnsignedInt(136, 4);  // estimated arrival
  utc_day_next = bs.ToUnsignedInt(140, 5);
  utc_hour_next = bs.ToUnsignedInt(145, 5);
  utc_min_next = bs.ToUnsignedInt(150, 6);
  main_danger = bs.ToString(156, 120);
  imo_cat = bs.ToString(276, 24);
  un = bs.ToUnsignedInt(300, 13);
  value = bs.ToUnsignedInt(313, 10);  // TODO(schwehr): units
  value_unit = bs.ToUnsignedInt(323, 2);
  spare = bs.ToUnsignedInt(325, 3);
  // 360
#endif

  // TODO(schwehr): Add assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}
예제 #29
0
Ais8_366_22_Text::Ais8_366_22_Text(const AisBitset &bits,
                                   const size_t offset) {
  text = string(bits.ToString(offset + 3, 84));
  spare = bits.ToUnsignedInt(offset + 87, 3);
}
예제 #30
0
// IMO Circ 289 - Dangerous cargo indication 2
// See also Circ 236
Ais6_1_25::Ais6_1_25(const char *nmea_payload, const size_t pad)
    : Ais6(nmea_payload, pad), amount_unit(0), amount(0) {
  assert(dac == 1);
  assert(fi == 25);

  // TODO(schwehr): verify multiple of the size of cargos + header
  //   or padded to a slot boundary
  // Allowing a message with no payloads
  // TODO(schwehr): (num_bits - 100) % 17 != 0) is okay
  if (num_bits < 100 || num_bits > 576) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }
  if ((num_bits - 100) % 17 != 0) {
    status = AIS_ERR_BAD_BIT_COUNT;
    return;
  }

  AisBitset bs;
  const AIS_STATUS r = bs.ParseNmeaPayload(nmea_payload, pad);
  if (r != AIS_OK) {
    status = r;
    return;
  }

  bs.SeekTo(88);
  amount_unit = bs.ToUnsignedInt(88, 2);
  amount = bs.ToUnsignedInt(90, 10);
  const size_t total_cargos = static_cast<int>(floor((num_bits - 100) / 17.));
  for (size_t cargo_num = 0; cargo_num < total_cargos; cargo_num++) {
    Ais6_1_25_Cargo cargo;
    const size_t start = 100 + 17*cargo_num;
    cargo.code_type = bs.ToUnsignedInt(start, 4);

    // TODO(schwehr): Is this the correct behavior?
    switch (cargo.code_type) {
      // No 0
      case 1:  // IMDG Code in packed form
        cargo.imdg = bs.ToUnsignedInt(start + 4, 7);
        cargo.imdg_valid = true;
        cargo.spare = bs.ToUnsignedInt(start + 11, 6);
        cargo.spare_valid = true;
        break;
      case 2:  // IGC Code
        cargo.un = bs.ToUnsignedInt(start + 4, 13);
        cargo.un_valid = true;
        break;
      case 3:  // BC Code
        cargo.bc = bs.ToUnsignedInt(start + 4, 3);
        cargo.bc_valid = true;
        cargo.imdg = bs.ToUnsignedInt(start + 7, 7);
        cargo.imdg_valid = true;
        cargo.spare = bs.ToUnsignedInt(start + 14, 3);
        cargo.spare_valid = true;
        break;
      case 4:  // MARPOL Annex I
        cargo.marpol_oil = bs.ToUnsignedInt(start + 4, 4);
        cargo.marpol_oil_valid = true;
        cargo.spare = bs.ToUnsignedInt(start + 8, 9);
        cargo.spare_valid = true;
        break;
      case 5:  // MARPOL Annex II IBC
        cargo.marpol_cat = bs.ToUnsignedInt(start + 4, 3);
        cargo.marpol_cat_valid = true;
        cargo.spare = bs.ToUnsignedInt(start + 7, 10);
        cargo.spare_valid = true;
        break;
      // 6: Regional use
      // 7: 7-15 reserved for future
      default:
        break;  // Just push in an all blank record?
    }
    cargos.push_back(cargo);
  }

  assert(bs.GetRemaining() == 0);
  status = AIS_OK;
}