private Report parseMic (Report theReport, int infoIndex, String theString)
{
int i = infoIndex, j, k;
// theReport is a structure with fields
// for parts of a packet
theReport.reportType = "Mic";
// theReport.theData is the packet received
String toField = theReport.toField;
int lastdash = toField.lastIndexOf('-');
if (lastdash == 6)
toField = toField.substring(0, lastdash);
else if (lastdash >= 0)
return null;
if (toField.length() != 6) return null;
// Get message and validate to field
int micmsg = 0;
for (j = 0; j < 3; j++)
{
micmsg <<= 1;
micmsg |= getMessageBit(toField, j);
if (micmsg == -1) return null;
}
if (micmsg > 7)
{
// Custom message
micmsg &= 0x07;
micmsg |= 0x08;
}
for (; j < 6; j++)
{
if (!isValidDest(toField.charAt(j))) return null;
}
// Parse the "TO" field
int c = cnvtDest(toField.charAt(0));
int d = (c & 0xf) * 10;
// Degrees
c = cnvtDest(toField.charAt(1));
d += (c & 0xf);
c = cnvtDest(toField.charAt(2));
int m = (c & 0xf) * 10;
// Minutes
c = cnvtDest(toField.charAt(3));
boolean north = (c >= 0x20);
m += (c & 0xf);
c = cnvtDest(toField.charAt(4));
boolean hund = (c >= 0x20);
int s = (c & 0xf) * 10;
// Hundredths of minutes
c = cnvtDest(toField.charAt(5));
boolean west = (c >= 0x20);
s += (c & 0xf);
theReport.position.lat = d + m / 60.0 + s / 6000.0;
// javAPRS stores southern latitudes as negative
if (!north) theReport.position.lat *= -1.0;
// Parse the Icon
theReport.icon = theString.charAt(i + 7) - ' ';
char ch = theString.charAt(i + 8);
theReport.altIcons = (ch != '/');
if (isLetterOrDigit(ch)) theReport.overlay = ch - ' ';
// Parse the longitude
d = theString.charAt(i + 1) - 28;
m = theString.charAt(i + 2) - 28;
s = theString.charAt(i + 3) - 28;
if (d < 0 || d > 99 || m < 0 || m > 99 || s < 0 || s > 99) return null;
// Adjust the degrees value
if (hund) d += 100;
if (d >= 190)
d -= 190;
else if (d >= 180)
d -= 80;
// Adjust minutes 0-9 to proper spot
if (m >= 60) m -= 60;
theReport.position.lon = d + m / 60.0 + s / 6000.0;
if (west) theReport.position.lon *= -1.0;
// Parse the Speed/Course (s/d)
m = theString.charAt(i + 5) - 28;
// DC+28
if (m < 0 || m > 97) return null;
s = theString.charAt(i + 4) - 28;
if (s < 0 || s > 99) return null;
s = (s * 10) + (m / 10);
//Speed (Knots)
d = theString.charAt(i + 6) - 28;
if (d < 0 || d > 99) return null;
d = ((m % 10) * 100) + d;
// Course
// Specification decoding method
if (s >= 800) s -= 800;
if (d >= 400) d -= 400;
if (d > 0)
{
theReport.course = d;
theReport.speed = s;
}
theReport.MicEInfo = MicEMsgs[micmsg];
if (theString.length() > i + 9)
{
theReport.comments = i + 9;
// Look for altitude
j = theString.indexOf('}', theReport.comments);
if (j >= theReport.comments + 3)
theReport.altitude = (int) Math.round(((((((theString.charAt(j - 3) - 33) * 91) + (theString.charAt(j - 2) - 33)) * 91) + (theString.charAt(j - 1) - 33)) - 10000) * 3.28084);
switch (theReport.theData[i])
{
case (byte) '\'':
if (theString.charAt(i + 9) == ']')
{
theReport.MicEInfo += " D700";
break;
}
case (byte) '`':
if (theString.charAt(i + 9) == '>')
theReport.MicEInfo += " D7";
}
}
return theReport;
}
protected final static String MicEMsgs[] = {"EMERGENCY",
"Priority",
"Special",
"Committed",
"Returning",
"In Service",
"En Route",
"Off Duty",
"",
"Custom 6",
"Custom 5",
"Custom 4",
"Custom 3",
"Custom 2",
"Custom 1",
"Custom 0"};
protected final int getMessageBit(String toField, int index)
{
char testchar = toField.charAt(index);
if ((testchar >= '0' && testchar <= '9') || testchar == 'L') return 0;
if (testchar >= 'A' && testchar <= 'K') return 9;
if (testchar >= 'P' && testchar <= 'Z') return 1;
return -1;
}
protected final boolean isValidDest(char testchar)
{
return ((testchar >= '0' && testchar <= '9') || testchar == 'L' || (testchar >= 'P' && testchar <= 'Z'));
}