Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
    }
    
}
// 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;
}
// 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;
}
Beispiel #6
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;
}
// 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;
}
// 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;
}
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;
}
// 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;
}
Beispiel #11
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);
}
// 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;
}
// 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;
}
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;
}
Beispiel #15
0
Ais8_366_22_Text::Ais8_366_22_Text(const bitset<AIS8_MAX_BITS> &bs,
                                   const size_t offset) {
  text = string(ais_str(bs, offset + 3, 84));
  spare = ubits(bs, offset + 87, 3);
}
Ais8_1_26_Station::Ais8_1_26_Station(const bitset<AIS8_MAX_BITS> &bs,
                                     const size_t offset) {
  name = ais_str(bs, offset, 84);
  spare = ubits(bs, offset + 84, 1);
}
// IMO Circ 289 - Weather observation report from ship
// See also Circ 236
Ais8_1_21::Ais8_1_21(const char *nmea_payload, const size_t pad)
    : Ais8(nmea_payload, pad) {
  if (status != AIS_UNINITIALIZED)
    return;

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

  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;
  }

  type_wx_report = bs[56];
  if (!type_wx_report) {
    // WX obs from ship
    location = ais_str(bs, 57, 120);
    x = (float)(sbits(bs, 177, 25) / 60000.0);//Crouse: Added typecasting
    y = (float)(sbits(bs, 202, 24) / 60000.0);//Crouse: Added typecasting
    utc_day = ubits(bs, 226, 5);
    utc_hour = ubits(bs, 231, 5);
    utc_min = ubits(bs, 236, 6);
    wx[0] = ubits(bs, 242, 4);  // TODO(schwehr): set wx[1] and wx[2]?
    horz_viz = (float)(ubits(bs, 246, 8) / 10.0);  // nautical miles //Crouse: Added typecasting
    humidity = ubits(bs, 254, 7);  // %
    wind_speed = ubits(bs, 261, 7);  // ave knots
    wind_dir = ubits(bs, 268, 9);
    pressure = (float)ubits(bs, 277, 9);  // hPa
    pressure_tendency = ubits(bs, 286, 4);
    // TODO(schwehr): is air_temp correct?
    air_temp = (float)(sbits(bs, 290, 11) / 10.0);  // C //Crouse: Added typecasting
    water_temp = (float)(ubits(bs, 301, 10) / 10.0 - 10);  // C //Crouse: Added typecasting
    wave_period = ubits(bs, 311, 6);  // s
    wave_height = (float)(ubits(bs, 317, 8) / 10.0);//Crouse: Added typecasting
    wave_dir = ubits(bs, 325, 9);
    swell_height = (float)(ubits(bs, 334, 8) / 10.0);  // m //Crouse: Added typecasting
    swell_dir = ubits(bs, 342, 9);
    swell_period = ubits(bs, 351, 6);  // s
    spare2 = ubits(bs, 357, 3);
  } else {
    // type == 1
    // PAIN IN THE ASS WMO OBS from ship
    // TODO(schwehr): double check the insanity
    x = (float)((ubits(bs, 57, 16) / 100.0) - 180);//Crouse: Added typecasting
    y = (float)((ubits(bs, 73, 15) / 100.0) - 180);//Crouse: Added typecasting

    utc_month = ubits(bs, 88, 4);
    utc_day = ubits(bs, 92, 6);
    utc_hour = ubits(bs, 98, 5);
    utc_min = ubits(bs, 102, 3) * 10;
    cog = ubits(bs, 106, 7) * 5;
    sog = (float)(ubits(bs, 113, 5) * 0.5);//Crouse: Added typecasting
    heading = ubits(bs, 118, 7) *5;  // Assume this is true degrees????
    pressure = (float)(ubits(bs, 125, 11) / 10.0 + 900);//Crouse: Added typecasting
    rel_pressure = (float)(ubits(bs, 136, 10) / 10.0 -50);//Crouse: Added typecasting
    pressure_tendency = ubits(bs, 146, 4);
    wind_dir = ubits(bs, 150, 7) * 5;
    wind_speed_ms = (float)(ubits(bs, 157, 8) * 0.5);  // m/s //Crouse: Added typecasting
    wind_dir_rel = ubits(bs, 165, 7) * 5;
    wind_speed_rel= (float)(ubits(bs, 172, 8) * 0.5);  // m/s //Crouse: Added typecasting
    wind_gust_speed = (float)(ubits(bs, 180, 8) * 0.5);  // m/s //Crouse: Added typecasting
    wind_gust_dir = ubits(bs, 188, 7) * 5;
    // 0C = 273.15 Kelvin
    // TODO(schwehr): change this to celcius
    air_temp_raw = ubits(bs, 195, 10);
    humidity =ubits(bs, 205, 7);
    water_temp_raw = ubits(bs, 212, 9);  // TODO(schwehr): change this to C
    horz_viz = (float)(pow((double)ubits(bs, 221, 6), 2) * 13.073);  // m //Crouse: added typecasting to get rid of an error compiling under Windows 
    wx[0] = ubits(bs, 227, 9);  // current
    wx[1] = ubits(bs, 236, 5);  // past 1
    wx[2] = ubits(bs, 241, 5);  // past 2
    cloud_total = ubits(bs, 246, 4) * 10;
    cloud_low = ubits(bs, 250, 4);
    cloud_low_type = ubits(bs, 254, 6);
    cloud_middle_type = ubits(bs, 260, 6);
    cloud_high_type = ubits(bs, 266, 6);
    alt_lowest_cloud_base = (float)(pow((double)ubits(bs, 272, 7), 2) * 0.16); //Crouse: Added typecasting to get rid of an error compiling under Windows
    wave_period = ubits(bs, 279, 5);  // s
    wave_height = (float)(ubits(bs, 284, 6) * 0.5);  // m //Crouse: Added typecasting
    swell_dir = ubits(bs, 290, 6) * 10;
    swell_period = ubits(bs, 296, 5);  // s
    swell_height = (float)(ubits(bs, 301, 6) * 0.5);  // m //Crouse: Added typecasting
    swell_dir_2 = ubits(bs, 307, 6) * 10;
    swell_period_2 = ubits(bs, 313, 5);  // s
    swell_height_2 = (float)(ubits(bs, 318, 6) * 0.5);  // m //Crouse: Added typecasting
    ice_thickness = (float)(ubits(bs, 324, 7) / 100.0);  // network is cm, storing m //Crouse: Added typecasting
    ice_accretion = ubits(bs, 331, 3);
    ice_accretion_cause = ubits(bs, 334, 3);
    sea_ice_concentration = ubits(bs, 337, 5);
    amt_type_ice = ubits(bs, 342, 4);
    ice_situation = ubits(bs, 346, 5);
    ice_devel = ubits(bs, 351, 5);
    bearing_ice_edge = ubits(bs, 356, 4) * 45;
  }
  status = AIS_OK;
}