package jaid.ais.message;
import nav.util.string.StringUtil;
/**
* Represents AIS Message Type 18: Standard Class B equipment position report
* Message type 18 is output periodically and autonomously by Class B shipborn
* mobile equipment. They are a replacement for Messages 1, 2 or 3 (which are
* broadcasted by Class A vessels)
* See ITU-R M1.0371-3 for further information.
*
* @author Benjamin Jakobus
* @since 1.0
* @version 1.0
*/
public class AISMsg18 extends AISMsg {
/* Underway, at anchor etc. */
private String navStatus;
/* Navigation Status Code. */
private int navStatusCode;
/* Rate of Turn. */
private String rot;
/* Speed over Ground (in nautical miles per hour). */
private float sog;
/* Course over Ground (in degrees from 0 to 359). */
private float cog;
/* True Heading (in degrees from 0 to 359). */
private int hdg;
/* Regional Reserved. */
private int regReserved;
/* Spare. */
private int spare;
/* Receiver Autonomous Integrity Monitoring - RAIM. */
private int raim;
/* Link information. */
protected int sotdmaSyncState;
protected int sotdmaSlotTO;
protected int sotdamSlotOffset;
/*
* Navigation status constants (TODO: Refactor to use 'enum' instead).
*/
public static final int NAVSTATUS_UNDERWAY = 0;
public static final int NAVSTATUS_ATANCHOR = 1;
public static final int NAVSTATUS_UNDERWAY_NUC = 2;
public static final int NAVSTATUS_UNDERWAY_RESTRICTMAN = 3;
public static final int NAVSTATUS_UNDERWAY_CONSTRAINDRAFT = 4;
public static final int NAVSTATUS_MOORED = 5;
public static final int NAVSTATUS_UNDERWAY_AGROUND = 6;
public static final int NAVSTATUS_UNDERWAY_FISHING = 7;
public static final int NAVSTATUS_UNDERWAY_SAIL = 8;
public static final int NAVSTATUS_UNDERWAY_HSC = 9;
public static final int NAVSTATUS_UNDERWAY_WIG = 10;
public static final int NAVSTATUS_NOTDEF = 11;
/**
* Constructs a new AIS message type 18.
*
* @param data The AIS feed to parse.
* @since 1.0
*/
public AISMsg18(String data) {
// Message type (bits 0-5)
super.setMessageType(Integer.parseInt(data.substring(0, 6), 2));
// Repeat Indicator (7-8)
super.setRepeatIndicator(Integer.parseInt(data.substring(6, 8), 2));
// MMSI (9-38)
super.setMmsi(String.valueOf(Integer.parseInt(data.substring(8, 38), 2)));
// Navigation Status (39-42)
decodeNavStatus(data.substring(38, 42));
// Rate of Turn (43-50)
rot = decodeROT(Integer.parseInt(data.substring(42, 50), 2));
// Speed Over Ground (51-60)
sog = ((float) Integer.parseInt(data.substring(50, 60), 2)) / 10;
// Position Accuracy (61-61)
super.decodePosAccuracy(data.substring(60, 61));
// Position (61-116: 28 for long, 27 for lat)
super.decodePosition(data.substring(61, 116));
// Course Over Ground (116-128)
cog = ((float) Integer.parseInt(data.substring(116, 128), 2)) / 10;
// True Heading (129-137)
hdg = Integer.parseInt(data.substring(128, 137), 2);
// Time Stamp (137-143)
super.decodeTimeStamp(data.substring(137, 143));
}
@Override
public String print() {
String outStr = "";
outStr += "TYPE: " + super.getMsgType() + "\n";
outStr += " UTC: " + super.getUtcTimeStampStr() + "\n";
outStr += " RI: " + super.getRepeatIndicator() + "\n";
outStr += "MMSI: " + super.getMMSI() + "\n";
outStr += "NAME: " + super.getName() + "\n";
outStr += " LAT: " + super.getPosition().toStringDegMinLat() + "\n";
outStr += " LNG: " + super.getPosition().toStringDegMinLng() + "\n";
outStr += "PACC: " + super.getPosAccuracy() + "\n";
outStr += "DIMS: " + super.getA() + "m x " + super.getC() + "m\n";
outStr += "EPFS: " + super.getEpfs() + "\n";
return outStr;
}
/**
* Returns the target's navigational status.
*
* @return The target's navigational status (anchored, moored,
* under way e.t.c.).
* @since 1.0
*/
@Override
public String getNavStatus() {
return navStatus;
}
/**
* Returns the vessel's speed over ground (SOG).
*
* @return The target's SOG in nautical miles per hour.
* @since 1.0
*/
@Override
public float getSpeed() {
return sog;
}
/**
* Returns the vessel's heading.
*
* @return heading The vessel's heading in degrees (0 - 359).
* @since 1.0
*/
@Override
public int getHeading() {
return hdg;
}
/**
* Returns the vessel's course.
*
* @return course The vessel's course in degrees (0 - 359).
* @since 1.0
*/
@Override
public int getCourse() {
return Math.round(cog);
}
/**
* Decodes the Rate of Turn (ROT) information.
*
* @param aisROT ROT as transmitted by the AIS message.
* @return Decoded ROT.
* @since 1.0
*/
private String decodeROT(int aisROT) {
StringUtil u = new StringUtil();
if (aisROT == 0) {
return " ";
}
if (aisROT == 127) {
return ">>S >5�/30s";
}
if (aisROT == -127) {
return "<<P >5�/30s";
}
if (aisROT == 128) {
return " no data ";
}
if (aisROT > 0 && aisROT < 127) {
long tiROT = Math.round((aisROT / 4.733) * (aisROT / 4.733));
return (">>S " + u.padNum(tiROT, 3) + "�/60s");
}
if (aisROT < 0 && aisROT > -127) {
aisROT = -aisROT;
long tiROT = Math.round((aisROT / 4.733) * (aisROT / 4.733));
return ("<<P " + u.padNum(tiROT, 3) + "�/60s");
}
return aisROT + " ?? ";
}
/**
* Decodes the target's navidational status.
*
* @param input Navigational status code as contained within
* the binary AIS message.
* @since 1.0
*/
private void decodeNavStatus(String input) {
navStatusCode = Integer.parseInt(input, 2);
switch (navStatusCode) {
case 0:
navStatus = "underway";
break;
case 1:
navStatus = "at anchor";
break;
case 2:
navStatus = "underway-Not Under Command";
break;
case 3:
navStatus = "underway-Restricted Manoeuvrability";
break;
case 4:
navStatus = "underway-Constrained by Draft";
break;
case 5:
navStatus = "moored";
break;
case 6:
navStatus = "underway-Aground";
break;
case 7:
navStatus = "underway-Fishing";
break;
case 8:
navStatus = "underway-Sail";
break;
case 9:
navStatus = "underway-HSC";
break;
case 10:
navStatus = "underway-WIG";
break;
case 11:
navStatus = "not in use";
break;
case 12:
navStatus = "not in use";
break;
case 13:
navStatus = "not in use";
break;
case 14:
navStatus = "not in use";
break;
case 15:
navStatus = "not defined";
break;
default:
navStatus = "error: (" + navStatusCode + ")";
}
}
}