/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jaid.ais.message;
import nav.util.string.StringUtil;
/**
* AIS Messages 1,2 and 3 are dynamic position report messages that are
* transmitted periodically by mobile stations (i.e. vessels).
* For details see ITU-R M.1371-3.
*
* @author Benjamin Jakobus
* @version 1.0
* @since 1.0
*/
public class AISMsg1_2_3 extends AISMsg {
/* Underway, at anchor etc. */
private String navStatus;
/* 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. */
private int sotdmaSyncState;
private int sotdmaSlotTO;
private int sotdamSlotOffset;
/**
* Constructor.
* @param data Binary AIS Message data.
* @since 1.0
*/
public AISMsg1_2_3(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));
}
/**
* 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;
}
/**
* 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) {
int navCode = Integer.parseInt(input, 2);
switch (navCode) {
case 0:
navStatus = "under way";
break;
case 1:
navStatus = "at anchor";
break;
case 2:
navStatus = "under way";
break;
case 3:
navStatus = "under way";
break;
case 4:
navStatus = "under way";
break;
case 5:
navStatus = "moored";
break;
case 6:
navStatus = "under way";
break;
case 7:
navStatus = "under way";
break;
case 8:
navStatus = "under way";
break;
case 9:
navStatus = "under way";
break;
case 10:
navStatus = "under way";
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: (" + navCode + ")";
}
}
/**
* 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);
}
}