From a67664919b2ed4bdd8eac7a0731a90f64279332a Mon Sep 17 00:00:00 2001 From: Markus Fuchs Date: Sun, 1 Oct 2023 09:51:32 +0200 Subject: [PATCH 1/6] refactoring: move altitude code decoding to dedicated class --- .../lib1090/decoding/Altitude.java | 67 +++++++++++++++++++ .../lib1090/decoding/package-info.java | 4 ++ .../lib1090/msgs/bds/ThreatIdentityData.java | 4 +- .../lib1090/msgs/modes/AltitudeReply.java | 60 +---------------- .../msgs/modes/CommBAltitudeReply.java | 3 +- .../lib1090/msgs/modes/LongACAS.java | 3 +- .../lib1090/msgs/modes/ShortACAS.java | 3 +- 7 files changed, 81 insertions(+), 63 deletions(-) create mode 100644 src/main/java/de/serosystems/lib1090/decoding/Altitude.java create mode 100644 src/main/java/de/serosystems/lib1090/decoding/package-info.java diff --git a/src/main/java/de/serosystems/lib1090/decoding/Altitude.java b/src/main/java/de/serosystems/lib1090/decoding/Altitude.java new file mode 100644 index 0000000..b4ea4dd --- /dev/null +++ b/src/main/java/de/serosystems/lib1090/decoding/Altitude.java @@ -0,0 +1,67 @@ +package de.serosystems.lib1090.decoding; + +/** + * @author Markus Fuchs (fuchs@sero-systems.de) + */ +public final class Altitude { + + private Altitude() {} + + /** + * This method converts a gray code encoded int to a standard decimal int + * @param gray gray code encoded int of length bitlength + * bitlength bitlength of gray code + * @return radix 2 encoded integer + */ + public static int grayToBin(int gray, int bitlength) { + int result = 0; + for (int i = bitlength-1; i >= 0; --i) + result = result|((((0x1<<(i+1))&result)>>>1)^((1<>>1) | ((altitude_code&0x1F80)>>>2); + return 25*N-1000; + } + else { // altitude is above 50175ft, so we use 100ft increments + + // it's decoded using the Gillham code + int C1 = (0x1000&altitude_code)>>>12; + int A1 = (0x0800&altitude_code)>>>11; + int C2 = (0x0400&altitude_code)>>>10; + int A2 = (0x0200&altitude_code)>>>9; + int C4 = (0x0100&altitude_code)>>>8; + int A4 = (0x0080&altitude_code)>>>7; + int B1 = (0x0020&altitude_code)>>>5; + int B2 = (0x0008&altitude_code)>>>3; + int D2 = (0x0004&altitude_code)>>>2; + int B4 = (0x0002&altitude_code)>>>1; + int D4 = (0x0001&altitude_code); + + // this is standard gray code + int N500 = grayToBin(D2<<7|D4<<6|A1<<5|A2<<4|A4<<3|B1<<2|B2<<1|B4, 8); + + // 100-ft steps must be converted + int N100 = grayToBin(C1<<2|C2<<1|C4, 3)-1; + if (N100 == 6) N100=4; + if (N500%2 != 0) N100=4-N100; // invert it + + return -1200+N500*500+N100*100; + } + } + else return null; // unspecified metric encoding + } +} diff --git a/src/main/java/de/serosystems/lib1090/decoding/package-info.java b/src/main/java/de/serosystems/lib1090/decoding/package-info.java new file mode 100644 index 0000000..08869e1 --- /dev/null +++ b/src/main/java/de/serosystems/lib1090/decoding/package-info.java @@ -0,0 +1,4 @@ +/** + * The decoding package contains common decoding functions, which are used in different messages and protocols. + */ +package de.serosystems.lib1090.decoding; \ No newline at end of file diff --git a/src/main/java/de/serosystems/lib1090/msgs/bds/ThreatIdentityData.java b/src/main/java/de/serosystems/lib1090/msgs/bds/ThreatIdentityData.java index 14dc13a..2f8c879 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/bds/ThreatIdentityData.java +++ b/src/main/java/de/serosystems/lib1090/msgs/bds/ThreatIdentityData.java @@ -1,7 +1,7 @@ package de.serosystems.lib1090.msgs.bds; +import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; -import de.serosystems.lib1090.msgs.modes.AltitudeReply; import java.io.Serializable; @@ -128,7 +128,7 @@ public Short getEncodedBearing() { * @return the decoded barometric altitude in feet if applicable */ public Integer getAltitude() { - return AltitudeReply.decodeAltitude(altitudeCode); + return Altitude.decode13BitAltitude(altitudeCode); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/modes/AltitudeReply.java b/src/main/java/de/serosystems/lib1090/msgs/modes/AltitudeReply.java index 3c651d7..5f2ba4c 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/modes/AltitudeReply.java +++ b/src/main/java/de/serosystems/lib1090/msgs/modes/AltitudeReply.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.modes; +import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.ModeSDownlinkMsg; @@ -188,68 +189,11 @@ public short getAltitudeCode() { return altitude_code; } - /** - * This method converts a gray code encoded int to a standard decimal int - * @param gray gray code encoded int of length bitlength - * bitlength bitlength of gray code - * @return radix 2 encoded integer - */ - private static int grayToBin(int gray, int bitlength) { - int result = 0; - for (int i = bitlength-1; i >= 0; --i) - result = result|((((0x1<<(i+1))&result)>>>1)^((1<>>1) | ((altitude_code&0x1F80)>>>2); - return 25*N-1000; - } - else { // altitude is above 50175ft, so we use 100ft increments - - // it's decoded using the Gillham code - int C1 = (0x1000&altitude_code)>>>12; - int A1 = (0x0800&altitude_code)>>>11; - int C2 = (0x0400&altitude_code)>>>10; - int A2 = (0x0200&altitude_code)>>>9; - int C4 = (0x0100&altitude_code)>>>8; - int A4 = (0x0080&altitude_code)>>>7; - int B1 = (0x0020&altitude_code)>>>5; - int B2 = (0x0008&altitude_code)>>>3; - int D2 = (0x0004&altitude_code)>>>2; - int B4 = (0x0002&altitude_code)>>>1; - int D4 = (0x0001&altitude_code); - - // this is standard gray code - int N500 = grayToBin(D2<<7|D4<<6|A1<<5|A2<<4|A4<<3|B1<<2|B2<<1|B4, 8); - - // 100-ft steps must be converted - int N100 = grayToBin(C1<<2|C2<<1|C4, 3)-1; - if (N100 == 6) N100=4; - if (N500%2 != 0) N100=4-N100; // invert it - - return -1200+N500*500+N100*100; - } - } - else return null; // unspecified metric encoding + return Altitude.decode13BitAltitude(altitude_code); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/modes/CommBAltitudeReply.java b/src/main/java/de/serosystems/lib1090/msgs/modes/CommBAltitudeReply.java index 0d6521a..33d5d62 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/modes/CommBAltitudeReply.java +++ b/src/main/java/de/serosystems/lib1090/msgs/modes/CommBAltitudeReply.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.modes; +import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.ModeSDownlinkMsg; @@ -198,7 +199,7 @@ public short getAltitudeCode() { * @return the decoded altitude in feet */ public Integer getAltitude() { - return AltitudeReply.decodeAltitude(altitude_code); + return Altitude.decode13BitAltitude(altitude_code); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/modes/LongACAS.java b/src/main/java/de/serosystems/lib1090/msgs/modes/LongACAS.java index b3ddbf9..c99c04f 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/modes/LongACAS.java +++ b/src/main/java/de/serosystems/lib1090/msgs/modes/LongACAS.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.modes; +import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.ModeSDownlinkMsg; @@ -217,7 +218,7 @@ public short getAltitudeCode() { * @return the decoded altitude in feet */ public Integer getAltitude() { - return AltitudeReply.decodeAltitude(altitude_code); + return Altitude.decode13BitAltitude(altitude_code); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/modes/ShortACAS.java b/src/main/java/de/serosystems/lib1090/msgs/modes/ShortACAS.java index d675c7e..c74682e 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/modes/ShortACAS.java +++ b/src/main/java/de/serosystems/lib1090/msgs/modes/ShortACAS.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.modes; +import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.ModeSDownlinkMsg; @@ -202,7 +203,7 @@ public short getAltitudeCode() { * @return the decoded altitude in feet */ public Integer getAltitude() { - return AltitudeReply.decodeAltitude(altitude_code); + return Altitude.decode13BitAltitude(altitude_code); } @Override From 6bd6a23599f6b28785970624d2f166d02722c7d6 Mon Sep 17 00:00:00 2001 From: Markus Fuchs Date: Sun, 1 Oct 2023 10:07:50 +0200 Subject: [PATCH 2/6] refactoring: moved altitude and identity decoding to dedicated class --- .../lib1090/decoding/Altitude.java | 41 +++++++ .../lib1090/decoding/Identification.java | 104 ++++++++++++++++++ .../lib1090/decoding/Identity.java | 43 ++++++++ .../msgs/adsb/AirbornePositionV0Msg.java | 50 +-------- .../adsb/EmergencyOrPriorityStatusMsg.java | 4 +- .../lib1090/msgs/adsb/IdentificationMsg.java | 102 +---------------- .../msgs/adsr/AirbornePositionV0Msg.java | 3 +- .../msgs/bds/AircraftIdentification.java | 6 +- .../msgs/modes/CommBIdentifyReply.java | 3 +- .../lib1090/msgs/modes/IdentifyReply.java | 26 +---- .../lib1090/msgs/tisb/CoarsePositionMsg.java | 4 +- .../msgs/tisb/FineAirbornePositionMsg.java | 3 +- .../lib1090/msgs/tisb/IdentificationMsg.java | 4 +- .../msgs/bds/AircraftIdentificationTest.java | 6 +- 14 files changed, 214 insertions(+), 185 deletions(-) create mode 100644 src/main/java/de/serosystems/lib1090/decoding/Identification.java create mode 100644 src/main/java/de/serosystems/lib1090/decoding/Identity.java diff --git a/src/main/java/de/serosystems/lib1090/decoding/Altitude.java b/src/main/java/de/serosystems/lib1090/decoding/Altitude.java index b4ea4dd..c4c43ee 100644 --- a/src/main/java/de/serosystems/lib1090/decoding/Altitude.java +++ b/src/main/java/de/serosystems/lib1090/decoding/Altitude.java @@ -64,4 +64,45 @@ public static Integer decode13BitAltitude(short altitude_code) { } else return null; // unspecified metric encoding } + + /** + * Decode altitude according to DO-260B 2.2.3.2.3.4.3
+ * @param altitude_encoded 12 bit encoded altitude + * @return + */ + public static Integer decode12BitAltitude(short altitude_encoded) { + // In contrast to the decodeAltitude method in {@link de.serosystems.lib1090.msgs.modes.AltitudeReply}, input + // does not contain the MBit + boolean Qbit = (altitude_encoded&0x10)!=0; + int N; + if (Qbit) { // altitude reported in 25ft increments + N = (altitude_encoded&0xF) | ((altitude_encoded&0xFE0)>>>1); + return 25*N-1000; + } + else { // altitude is above 50175ft, so we use 100ft increments + + // it's decoded using the Gillham code + int C1 = (0x800&altitude_encoded)>>>11; + int A1 = (0x400&altitude_encoded)>>>10; + int C2 = (0x200&altitude_encoded)>>>9; + int A2 = (0x100&altitude_encoded)>>>8; + int C4 = (0x080&altitude_encoded)>>>7; + int A4 = (0x040&altitude_encoded)>>>6; + int B1 = (0x020&altitude_encoded)>>>5; + int B2 = (0x008&altitude_encoded)>>>3; + int D2 = (0x004&altitude_encoded)>>>2; + int B4 = (0x002&altitude_encoded)>>>1; + int D4 = (0x001&altitude_encoded); + + // this is standard gray code + int N500 = grayToBin(D2<<7|D4<<6|A1<<5|A2<<4|A4<<3|B1<<2|B2<<1|B4, 8); + + // 100-ft steps must be converted + int N100 = grayToBin(C1<<2|C2<<1|C4, 3)-1; + if (N100 == 6) N100=4; + if (N500%2 != 0) N100=4-N100; // invert it + + return -1200+N500*500+N100*100; + } + } } diff --git a/src/main/java/de/serosystems/lib1090/decoding/Identification.java b/src/main/java/de/serosystems/lib1090/decoding/Identification.java new file mode 100644 index 0000000..3847049 --- /dev/null +++ b/src/main/java/de/serosystems/lib1090/decoding/Identification.java @@ -0,0 +1,104 @@ +package de.serosystems.lib1090.decoding; + +/** + * @author Markus Fuchs (fuchs@sero-systems.de) + */ +public final class Identification { + + private Identification() {} + + /** + * Maps ADS-B encoded to readable characters + * @param digit encoded digit + * @return readable character + */ + public static char mapChar(byte digit) { + if (digit>0 && digit<27) return (char) ('A'+digit-1); + else if (digit>47 && digit<58) return (char) ('0'+digit-48); + else return ' '; + } + + /** + * Maps ADS-B encoded to readable characters + * @param digits array of encoded digits + * @return array of decoded characters + */ + public static char[] mapChar(byte[] digits) { + char[] result = new char[digits.length]; + + for (int i=0; i=1; i--) { + // calculate offsets + byte_off = (i*6)/8; bit_off = (i*6)%8; + + // char aligned with byte? + if (bit_off == 0) identity[i-1] = (byte) (msg[byte_off]&0x3F); + else { + ++byte_off; + identity[i-1] = (byte) (msg[byte_off]>>>(8-bit_off)&(0x3F>>>(6-bit_off))); + // should we add bits from the next byte? + if (bit_off < 6) identity[i-1] |= msg[byte_off-1]< 300000 lbs)", + "High Performance (> 5g acceleration and 400 kts)", + "Rotorcraft" + },{ + "No ADS-B Emitter Category Information", + "Glider / sailplane", + "Lighter-than-air", + "Parachutist / Skydiver", + "Ultralight / hang-glider / paraglider", + "Reserved", + "Unmanned Aerial Vehicle", + "Space / Trans-atmospheric vehicle", + },{ + "No ADS-B Emitter Category Information", + "Surface Vehicle – Emergency Vehicle", + "Surface Vehicle – Service Vehicle", + "Point Obstacle (includes tethered balloons)", + "Cluster Obstacle", + "Line Obstacle", + "Reserved", + "Reserved" + },{ + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved" + }}; + + return categories[4-type_code][emitter_category]; + } +} diff --git a/src/main/java/de/serosystems/lib1090/decoding/Identity.java b/src/main/java/de/serosystems/lib1090/decoding/Identity.java new file mode 100644 index 0000000..3aca148 --- /dev/null +++ b/src/main/java/de/serosystems/lib1090/decoding/Identity.java @@ -0,0 +1,43 @@ +package de.serosystems.lib1090.decoding; + +/** + * @author Markus Fuchs (fuchs@sero-systems.de) + */ +public final class Identity { + + + private Identity() {} + + /** + * @return The identity/Mode A code (see ICAO Annex 10 V4). + * Special codes are
+ *
    + *
  • 7700 indicates emergency
    + *
  • 7600 indicates radiocommunication failure
  • + *
  • 7500 indicates unlawful interference
  • + *
  • 2000 indicates that transponder is not yet operated
  • + *
+ */ + public static String decodeIdentity(short identity) { + int C1 = (0x1000&identity)>>>12; + int A1 = (0x800&identity)>>>11; + int C2 = (0x400&identity)>>>10; + int A2 = (0x200&identity)>>>9; + int C4 = (0x100&identity)>>>8; + int A4 = (0x080&identity)>>>7; + // ZERO + int B1 = (0x020&identity)>>>5; + int D1 = (0x010&identity)>>>4; + int B2 = (0x008&identity)>>>3; + int D2 = (0x004&identity)>>>2; + int B4 = (0x002&identity)>>>1; + int D4 = (0x001&identity); + + String A = Integer.toString((A4<<2)+(A2<<1)+A1); + String B = Integer.toString((B4<<2)+(B2<<1)+B1); + String C = Integer.toString((C4<<2)+(C2<<1)+C1); + String D = Integer.toString((D4<<2)+(D2<<1)+D1); + + return A+B+C+D; + } +} diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java index 1cf6f34..46777ce 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java @@ -2,6 +2,7 @@ import de.serosystems.lib1090.Position; import de.serosystems.lib1090.cpr.CPREncodedPosition; +import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.PositionMsg; @@ -336,57 +337,10 @@ public boolean hasValidAltitude() { return altitude_available; } - /** - * This method converts a gray code encoded int to a standard decimal int - * @param gray gray code encoded int of length bitlength - * bitlength bitlength of gray code - * @return radix 2 encoded integer - */ - private static int grayToBin(int gray, int bitlength) { - int result = 0; - for (int i = bitlength-1; i >= 0; --i) - result = result|((((0x1<<(i+1))&result)>>>1)^((1<>>1); - return 25*N-1000; - } - else { // altitude is above 50175ft, so we use 100ft increments - - // it's decoded using the Gillham code - int C1 = (0x800&altitude_encoded)>>>11; - int A1 = (0x400&altitude_encoded)>>>10; - int C2 = (0x200&altitude_encoded)>>>9; - int A2 = (0x100&altitude_encoded)>>>8; - int C4 = (0x080&altitude_encoded)>>>7; - int A4 = (0x040&altitude_encoded)>>>6; - int B1 = (0x020&altitude_encoded)>>>5; - int B2 = (0x008&altitude_encoded)>>>3; - int D2 = (0x004&altitude_encoded)>>>2; - int B4 = (0x002&altitude_encoded)>>>1; - int D4 = (0x001&altitude_encoded); - - // this is standard gray code - int N500 = grayToBin(D2<<7|D4<<6|A1<<5|A2<<4|A4<<3|B1<<2|B2<<1|B4, 8); - - // 100-ft steps must be converted - int N100 = grayToBin(C1<<2|C2<<1|C4, 3)-1; - if (N100 == 6) N100=4; - if (N500%2 != 0) N100=4-N100; // invert it - - return -1200+N500*500+N100*100; - } - } - @Override public Integer getAltitude() { if (!altitude_available) return null; - return decodeAltitude(altitude_encoded); + return Altitude.decode12BitAltitude(altitude_encoded); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/EmergencyOrPriorityStatusMsg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/EmergencyOrPriorityStatusMsg.java index d6454f6..7f00baa 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/EmergencyOrPriorityStatusMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/EmergencyOrPriorityStatusMsg.java @@ -1,9 +1,9 @@ package de.serosystems.lib1090.msgs.adsb; +import de.serosystems.lib1090.decoding.Identity; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.modes.ExtendedSquitter; -import de.serosystems.lib1090.msgs.modes.IdentifyReply; import java.io.Serializable; @@ -118,7 +118,7 @@ public short getModeACode() { } public String getIdentity() { - return IdentifyReply.decodeIdentity(mode_a_code); + return Identity.decodeIdentity(mode_a_code); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/IdentificationMsg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/IdentificationMsg.java index 0f5a539..9e0cf04 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/IdentificationMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/IdentificationMsg.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.adsb; +import de.serosystems.lib1090.decoding.Identification; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.modes.ExtendedSquitter; @@ -35,31 +36,6 @@ public class IdentificationMsg extends ExtendedSquitter implements Serializable private byte emitter_category; private byte[] identity; - /** - * Maps ADS-B encoded to readable characters - * @param digit encoded digit - * @return readable character - */ - private static char mapChar (byte digit) { - if (digit>0 && digit<27) return (char) ('A'+digit-1); - else if (digit>47 && digit<58) return (char) ('0'+digit-48); - else return ' '; - } - - /** - * Maps ADS-B encoded to readable characters - * @param digits array of encoded digits - * @return array of decoded characters - */ - public static char[] mapChar (byte[] digits) { - char[] result = new char[digits.length]; - - for (int i=0; i=1; i--) { - // calculate offsets - byte_off = (i*6)/8; bit_off = (i*6)%8; - - // char aligned with byte? - if (bit_off == 0) identity[i-1] = (byte) (msg[byte_off]&0x3F); - else { - ++byte_off; - identity[i-1] = (byte) (msg[byte_off]>>>(8-bit_off)&(0x3F>>>(6-bit_off))); - // should we add bits from the next byte? - if (bit_off < 6) identity[i-1] |= msg[byte_off-1]< 300000 lbs)", - "High Performance (> 5g acceleration and 400 kts)", - "Rotorcraft" - },{ - "No ADS-B Emitter Category Information", - "Glider / sailplane", - "Lighter-than-air", - "Parachutist / Skydiver", - "Ultralight / hang-glider / paraglider", - "Reserved", - "Unmanned Aerial Vehicle", - "Space / Trans-atmospheric vehicle", - },{ - "No ADS-B Emitter Category Information", - "Surface Vehicle – Emergency Vehicle", - "Surface Vehicle – Service Vehicle", - "Point Obstacle (includes tethered balloons)", - "Cluster Obstacle", - "Line Obstacle", - "Reserved", - "Reserved" - },{ - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved" - }}; - - return categories[4-type_code][emitter_category]; + return Identification.mapChar(identity); } /** @@ -189,7 +95,7 @@ public static String categoryDescription(byte type_code, byte emitter_category) * the ADS-B message format specification */ public String getCategoryDescription() { - return categoryDescription(getFormatTypeCode(), emitter_category); + return Identification.categoryDescription(getFormatTypeCode(), emitter_category); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV0Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV0Msg.java index f83b4d8..4659e15 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV0Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV0Msg.java @@ -2,6 +2,7 @@ import de.serosystems.lib1090.Position; import de.serosystems.lib1090.cpr.CPREncodedPosition; +import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.PositionMsg; @@ -225,7 +226,7 @@ public boolean getIMF () { @Override public Integer getAltitude() { if (!altitude_available) return null; - return decodeAltitude(altitude_encoded); + return Altitude.decode12BitAltitude(altitude_encoded); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/bds/AircraftIdentification.java b/src/main/java/de/serosystems/lib1090/msgs/bds/AircraftIdentification.java index 473988e..7a3e301 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/bds/AircraftIdentification.java +++ b/src/main/java/de/serosystems/lib1090/msgs/bds/AircraftIdentification.java @@ -1,6 +1,6 @@ package de.serosystems.lib1090.msgs.bds; -import de.serosystems.lib1090.msgs.adsb.IdentificationMsg; +import de.serosystems.lib1090.decoding.Identification; import java.io.Serializable; import java.util.Arrays; @@ -53,7 +53,7 @@ public AircraftIdentification(byte[] message) { setBds(BDSRegister.bdsCode.AIRCRAFT_IDENTIFICATION); this.bdsCode = extractBdsCode(message); - this.aircraftIdentification = IdentificationMsg.decodeAircraftIdentification(message); + this.aircraftIdentification = Identification.decodeAircraftIdentification(message); } @@ -64,7 +64,7 @@ public AircraftIdentification(byte[] message) { * @return The call sign as 8 characters array */ public char[] getAircraftIdentification() { - return IdentificationMsg.mapChar(aircraftIdentification); + return Identification.mapChar(aircraftIdentification); } // Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/modes/CommBIdentifyReply.java b/src/main/java/de/serosystems/lib1090/msgs/modes/CommBIdentifyReply.java index 9644852..707d3d2 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/modes/CommBIdentifyReply.java +++ b/src/main/java/de/serosystems/lib1090/msgs/modes/CommBIdentifyReply.java @@ -1,6 +1,7 @@ package de.serosystems.lib1090.msgs.modes; import de.serosystems.lib1090.Tools; +import de.serosystems.lib1090.decoding.Identity; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.ModeSDownlinkMsg; @@ -214,7 +215,7 @@ public byte[] getMessage() { * */ public String getIdentity() { - return IdentifyReply.decodeIdentity(identity); + return Identity.decodeIdentity(identity); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/modes/IdentifyReply.java b/src/main/java/de/serosystems/lib1090/msgs/modes/IdentifyReply.java index fa6e2da..0e4d8b2 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/modes/IdentifyReply.java +++ b/src/main/java/de/serosystems/lib1090/msgs/modes/IdentifyReply.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.modes; +import de.serosystems.lib1090.decoding.Identity; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.ModeSDownlinkMsg; @@ -201,30 +202,7 @@ public short getIdentityCode() { * */ public String getIdentity() { - return decodeIdentity(identity); - } - - public static String decodeIdentity(short identity) { - int C1 = (0x1000&identity)>>>12; - int A1 = (0x800&identity)>>>11; - int C2 = (0x400&identity)>>>10; - int A2 = (0x200&identity)>>>9; - int C4 = (0x100&identity)>>>8; - int A4 = (0x080&identity)>>>7; - // ZERO - int B1 = (0x020&identity)>>>5; - int D1 = (0x010&identity)>>>4; - int B2 = (0x008&identity)>>>3; - int D2 = (0x004&identity)>>>2; - int B4 = (0x002&identity)>>>1; - int D4 = (0x001&identity); - - String A = Integer.toString((A4<<2)+(A2<<1)+A1); - String B = Integer.toString((B4<<2)+(B2<<1)+B1); - String C = Integer.toString((C4<<2)+(C2<<1)+C1); - String D = Integer.toString((D4<<2)+(D2<<1)+D1); - - return A+B+C+D; + return Identity.decodeIdentity(identity); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/tisb/CoarsePositionMsg.java b/src/main/java/de/serosystems/lib1090/msgs/tisb/CoarsePositionMsg.java index 948ca91..022200c 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/tisb/CoarsePositionMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/tisb/CoarsePositionMsg.java @@ -9,7 +9,7 @@ import java.io.Serializable; -import static de.serosystems.lib1090.msgs.adsb.AirbornePositionV0Msg.decodeAltitude; +import static de.serosystems.lib1090.decoding.Altitude.decode12BitAltitude; /* * This file is part of de.serosystems.lib1090. @@ -183,7 +183,7 @@ public boolean hasValidAltitude() { @Override public Integer getAltitude() { if (!hasValidAltitude()) return null; - return decodeAltitude(encoded_altitude); + return decode12BitAltitude(encoded_altitude); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/tisb/FineAirbornePositionMsg.java b/src/main/java/de/serosystems/lib1090/msgs/tisb/FineAirbornePositionMsg.java index 275477c..31a45e1 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/tisb/FineAirbornePositionMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/tisb/FineAirbornePositionMsg.java @@ -2,6 +2,7 @@ import de.serosystems.lib1090.Position; import de.serosystems.lib1090.cpr.CPREncodedPosition; +import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.PositionMsg; @@ -223,7 +224,7 @@ public boolean hasValidAltitude() { @Override public Integer getAltitude() { if (!hasValidAltitude()) return null; - return decodeAltitude(encoded_altitude); + return Altitude.decode12BitAltitude(encoded_altitude); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/tisb/IdentificationMsg.java b/src/main/java/de/serosystems/lib1090/msgs/tisb/IdentificationMsg.java index de9a762..435fe78 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/tisb/IdentificationMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/tisb/IdentificationMsg.java @@ -7,8 +7,8 @@ import java.io.Serializable; import java.util.Arrays; -import static de.serosystems.lib1090.msgs.adsb.IdentificationMsg.categoryDescription; -import static de.serosystems.lib1090.msgs.adsb.IdentificationMsg.mapChar; +import static de.serosystems.lib1090.decoding.Identification.categoryDescription; +import static de.serosystems.lib1090.decoding.Identification.mapChar; /* * This file is part of de.serosystems.lib1090. diff --git a/src/test/java/de/serosystems/lib1090/msgs/bds/AircraftIdentificationTest.java b/src/test/java/de/serosystems/lib1090/msgs/bds/AircraftIdentificationTest.java index 2f87721..628ed19 100644 --- a/src/test/java/de/serosystems/lib1090/msgs/bds/AircraftIdentificationTest.java +++ b/src/test/java/de/serosystems/lib1090/msgs/bds/AircraftIdentificationTest.java @@ -1,6 +1,6 @@ package de.serosystems.lib1090.msgs.bds; -import de.serosystems.lib1090.msgs.adsb.IdentificationMsg; +import de.serosystems.lib1090.decoding.Identification; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -32,8 +32,8 @@ public void bdsCode() { @Test public void aircraftIdentification() { - byte[] identityByteArray = IdentificationMsg.decodeAircraftIdentification(msg); - char[] identityCharArray = IdentificationMsg.mapChar(identityByteArray); + byte[] identityByteArray = Identification.decodeAircraftIdentification(msg); + char[] identityCharArray = Identification.mapChar(identityByteArray); assertEquals("KLM1017 ", String.valueOf(identityCharArray)); From f745247ddaff6e98d438210e3861cab603c67b9a Mon Sep 17 00:00:00 2001 From: Markus Fuchs Date: Sun, 1 Oct 2023 10:16:55 +0200 Subject: [PATCH 3/6] refactoring: moved EPU decoding to dedicated class --- .../lib1090/decoding/OperationalStatus.java | 30 +++++++++++++++++++ .../adsb/AirborneOperationalStatusV1Msg.java | 16 ++-------- .../adsb/SurfaceOperationalStatusV1Msg.java | 17 ++--------- .../adsr/AirborneOperationalStatusV1Msg.java | 17 ++--------- .../adsr/SurfaceOperationalStatusV1Msg.java | 17 ++--------- 5 files changed, 41 insertions(+), 56 deletions(-) create mode 100644 src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java diff --git a/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java b/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java new file mode 100644 index 0000000..83e5ea9 --- /dev/null +++ b/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java @@ -0,0 +1,30 @@ +package de.serosystems.lib1090.decoding; + +/** + * @author Markus Fuchs (fuchs@sero-systems.de) + */ +public final class OperationalStatus { + + private OperationalStatus() {} + + /** + * Get the 95% horizontal accuracy bounds (EPU) derived from NACp value, see table A-13 in RCTA DO-260B + * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) + */ + public static double nacPtoEPU(byte nacPos) { + switch (nacPos) { + case 1: return 18520; + case 2: return 7408; + case 3: return 3704; + case 4: return 1852.0; + case 5: return 926.0; + case 6: return 555.6; + case 7: return 185.2; + case 8: return 92.6; + case 9: return 30.0; + case 10: return 10.0; + case 11: return 3.0; + default: return -1; + } + } +} diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirborneOperationalStatusV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirborneOperationalStatusV1Msg.java index 0db573b..1a3851d 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirborneOperationalStatusV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirborneOperationalStatusV1Msg.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.adsb; +import de.serosystems.lib1090.decoding.OperationalStatus; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.modes.ExtendedSquitter; @@ -206,20 +207,7 @@ public byte getNACp() { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - switch (nac_pos) { - case 1: return 18520; - case 2: return 7408; - case 3: return 3704; - case 4: return 1852.0; - case 5: return 926.0; - case 6: return 555.6; - case 7: return 185.2; - case 8: return 92.6; - case 9: return 30.0; - case 10: return 10.0; - case 11: return 3.0; - default: return -1; - } + return OperationalStatus.nacPtoEPU(nac_pos); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfaceOperationalStatusV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfaceOperationalStatusV1Msg.java index 9a1288a..b63c49b 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfaceOperationalStatusV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfaceOperationalStatusV1Msg.java @@ -6,6 +6,8 @@ import java.io.Serializable; +import static de.serosystems.lib1090.decoding.OperationalStatus.nacPtoEPU; + /* * This file is part of de.serosystems.lib1090. * @@ -273,20 +275,7 @@ public byte getNACp() { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - switch (nac_pos) { - case 1: return 18520; - case 2: return 7408; - case 3: return 3704; - case 4: return 1852.0; - case 5: return 926.0; - case 6: return 555.6; - case 7: return 185.2; - case 8: return 92.6; - case 9: return 30.0; - case 10: return 10.0; - case 11: return 3.0; - default: return -1; - } + return nacPtoEPU(nac_pos); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirborneOperationalStatusV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirborneOperationalStatusV1Msg.java index b715069..a439628 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirborneOperationalStatusV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirborneOperationalStatusV1Msg.java @@ -6,6 +6,8 @@ import java.io.Serializable; +import static de.serosystems.lib1090.decoding.OperationalStatus.nacPtoEPU; + /* * This file is part of de.serosystems.lib1090. * @@ -215,20 +217,7 @@ public byte getNACp() { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - switch (nac_pos) { - case 1: return 18520; - case 2: return 7408; - case 3: return 3704; - case 4: return 1852.0; - case 5: return 926.0; - case 6: return 555.6; - case 7: return 185.2; - case 8: return 92.6; - case 9: return 30.0; - case 10: return 10.0; - case 11: return 3.0; - default: return -1; - } + return nacPtoEPU(nac_pos); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfaceOperationalStatusV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfaceOperationalStatusV1Msg.java index 0fc80c2..b903ad8 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfaceOperationalStatusV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfaceOperationalStatusV1Msg.java @@ -6,6 +6,8 @@ import java.io.Serializable; +import static de.serosystems.lib1090.decoding.OperationalStatus.nacPtoEPU; + /* * This file is part of de.serosystems.lib1090. * @@ -282,20 +284,7 @@ public byte getNACp() { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - switch (nac_pos) { - case 1: return 18520; - case 2: return 7408; - case 3: return 3704; - case 4: return 1852.0; - case 5: return 926.0; - case 6: return 555.6; - case 7: return 185.2; - case 8: return 92.6; - case 9: return 30.0; - case 10: return 10.0; - case 11: return 3.0; - default: return -1; - } + return nacPtoEPU(nac_pos); } /** From 28b94c48f7c6add3e8b5fbb8176e38d7d4b6cdb2 Mon Sep 17 00:00:00 2001 From: Markus Fuchs Date: Sun, 1 Oct 2023 10:17:17 +0200 Subject: [PATCH 4/6] refactoring: removed duplicate switch-case branches --- .../lib1090/msgs/adsb/AirbornePositionV0Msg.java | 8 ++++---- .../lib1090/msgs/adsb/AirbornePositionV2Msg.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java index 46777ce..9a7e0b1 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java @@ -123,7 +123,6 @@ public double getHorizontalContainmentRadiusLimit() { */ public static double typeCodeToHCR(byte formatTypeCode) { switch (formatTypeCode) { - case 0: case 18: case 22: return -1; case 9: case 20: return 7.5; case 10: case 21: return 25; case 11: return 185.2; @@ -133,6 +132,7 @@ public static double typeCodeToHCR(byte formatTypeCode) { case 15: return 3704; case 16: return 18520; case 17: return 37040; + // case 0: case 18: case 22: return -1; default: return -1; } } @@ -158,7 +158,6 @@ public byte getNACp() { */ public static byte typeCodeToNACp(byte formatTypeCode) { switch (formatTypeCode) { - case 0: case 18: case 22: return 0; case 9: case 20: return 11; case 10: case 21: return 10; case 11: return 8; @@ -167,6 +166,7 @@ public static byte typeCodeToNACp(byte formatTypeCode) { case 14: return 5; case 15: return 4; case 16: case 17: return 1; + // case 0: case 18: case 22: return 0; default: return 0; } } @@ -194,7 +194,6 @@ public double getPositionUncertainty() { */ public static double typeCodeToPositionUncertainty(byte formatTypeCode) { switch (formatTypeCode) { - case 0: case 18: case 22: return -1; case 9: return 3; case 10: return 10; case 11: return 92.6; @@ -204,6 +203,7 @@ public static double typeCodeToPositionUncertainty(byte formatTypeCode) { case 15: return 1852; case 16: return 9260; case 17: return 18520; + // case 0: case 18: case 22: return -1; default: return -1; } } @@ -225,7 +225,6 @@ public byte getNIC() { */ public static byte typeCodeToNIC(byte formatTypeCode) { switch (formatTypeCode) { - case 0: case 18: case 22: return 0; case 9: case 20: return 11; case 6: case 10: case 21: return 10; case 7: case 11: return 8; @@ -234,6 +233,7 @@ public static byte typeCodeToNIC(byte formatTypeCode) { case 14: return 5; case 15: return 4; case 16: case 17: return 1; + // case 0: case 18: case 22: return 0; default: return 0; } } diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV2Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV2Msg.java index c83ba35..078e704 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV2Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV2Msg.java @@ -84,7 +84,6 @@ public boolean hasNICSupplementB() { */ public double getHorizontalContainmentRadiusLimit() { switch (getFormatTypeCode()) { - case 0: case 18: case 22: return -1; case 9: case 20: return 7.5; case 10: case 21: return 25; case 11: @@ -98,6 +97,7 @@ public double getHorizontalContainmentRadiusLimit() { case 16: return hasNICSupplementB() && hasNICSupplementA() ? 7408 : 14816; case 17: return 37040; + // case 0: case 18: case 22: return -1; default: return -1; } } @@ -108,7 +108,6 @@ public double getHorizontalContainmentRadiusLimit() { */ public byte getNIC() { switch (getFormatTypeCode()) { - case 0: case 18: case 22: return 0; case 9: case 20: return 11; case 10: case 21: return 10; case 11: @@ -120,6 +119,7 @@ public byte getNIC() { case 16: return (byte) (hasNICSupplementB() && hasNICSupplementA() ? 3 : 2); case 17: return 1; + // case 0: case 18: case 22: return 0; default: return 0; } } From 725f95387178323555ed0e354c9b3ab3001650a7 Mon Sep 17 00:00:00 2001 From: Markus Fuchs Date: Sun, 1 Oct 2023 10:57:57 +0200 Subject: [PATCH 5/6] refactoring: removed duplicate code --- .../lib1090/decoding/AirbornePosition.java | 155 +++++++++++++++++ .../lib1090/decoding/Airspeed.java | 30 ++++ .../lib1090/decoding/OperationalStatus.java | 59 +++++++ .../lib1090/decoding/SurfacePosition.java | 158 ++++++++++++++++++ .../lib1090/decoding/VelocityOverGround.java | 30 ++++ .../msgs/adsb/AirbornePositionV0Msg.java | 109 +----------- .../msgs/adsb/AirbornePositionV1Msg.java | 29 +--- .../lib1090/msgs/adsb/AirspeedHeadingMsg.java | 15 +- .../adsb/SurfaceOperationalStatusV1Msg.java | 48 +----- .../msgs/adsb/SurfacePositionV0Msg.java | 69 +------- .../msgs/adsb/SurfacePositionV1Msg.java | 21 +-- .../msgs/adsb/VelocityOverGroundMsg.java | 19 +-- .../msgs/adsr/AirbornePositionV0Msg.java | 13 +- .../msgs/adsr/AirbornePositionV1Msg.java | 31 +--- .../lib1090/msgs/adsr/AirspeedHeadingMsg.java | 15 +- .../adsr/SurfaceOperationalStatusV1Msg.java | 49 +----- .../msgs/adsr/SurfacePositionV0Msg.java | 75 ++------- .../msgs/adsr/SurfacePositionV1Msg.java | 23 +-- .../msgs/adsr/VelocityOverGroundMsg.java | 15 +- .../msgs/tisb/FineAirbornePositionMsg.java | 13 +- .../msgs/tisb/FineSurfacePositionMsg.java | 75 ++------- 21 files changed, 513 insertions(+), 538 deletions(-) create mode 100644 src/main/java/de/serosystems/lib1090/decoding/AirbornePosition.java create mode 100644 src/main/java/de/serosystems/lib1090/decoding/Airspeed.java create mode 100644 src/main/java/de/serosystems/lib1090/decoding/SurfacePosition.java create mode 100644 src/main/java/de/serosystems/lib1090/decoding/VelocityOverGround.java diff --git a/src/main/java/de/serosystems/lib1090/decoding/AirbornePosition.java b/src/main/java/de/serosystems/lib1090/decoding/AirbornePosition.java new file mode 100644 index 0000000..0e3b4d1 --- /dev/null +++ b/src/main/java/de/serosystems/lib1090/decoding/AirbornePosition.java @@ -0,0 +1,155 @@ +package de.serosystems.lib1090.decoding; + +import de.serosystems.lib1090.msgs.adsb.AirborneOperationalStatusV1Msg; + +/** + * @author Markus Fuchs (fuchs@sero-systems.de) + */ +public final class AirbornePosition { + + private AirbornePosition() {} + + /** + * Values according to DO-260B Table N-11 + * @return Navigation integrity category. A NIC of 0 means "unkown". + */ + public static byte decodeNIC(byte formatTypeCode, boolean nicSupplA) { + switch (formatTypeCode) { + case 9: case 20: return 11; + case 10: case 21: return 10; + case 11: return (byte) (nicSupplA ? 9 : 8); + case 12: return 7; + case 13: return 6; + case 14: return 5; + case 15: return 4; + case 16: return (byte) (nicSupplA ? 3 : 2); + case 17: return 1; + // case 0: case 18: case 22: return 0; + default: return 0; + } + } + + /** + * The position error, i.e., 95% accuracy for the horizontal position. For the navigation accuracy category + * (NACp) see {@link AirborneOperationalStatusV1Msg}. Values according to DO-260B Table N-11. + * + * The horizontal containment radius is also known as "horizontal protection level". + * + * @return horizontal containment radius limit in meters. A return value of -1 means "unknown". + * If aircraft uses ADS-B version 1+, set NIC supplement A from Operational Status Message + * for better precision. + */ + public static double decodeHCR(byte formatTypeCode, boolean nicSupplA) { + switch (formatTypeCode) { + case 9: case 20: return 7.5; + case 10: case 21: return 25; + case 11: return nicSupplA ? 75.0 : 185.2; + case 12: return 370.4; + case 13: return nicSupplA ? 1111.2 : 926; + case 14: return 1852; + case 15: return 3704; + case 16: return nicSupplA ? 7408 : 14816; + case 17: return 37040; + // case 0: case 18: case 22: return -1; + default: return -1; + } + } + + /** + * According to DO-260B Table N-4 + * + * @param formatTypeCode the messages' format type code + * @return the derived HCR + */ + public static double typeCodeToHCR(byte formatTypeCode) { + switch (formatTypeCode) { + case 9: case 20: return 7.5; + case 10: case 21: return 25; + case 11: return 185.2; + case 12: return 370.4; + case 13: return 926; + case 14: return 1852; + case 15: return 3704; + case 16: return 18520; + case 17: return 37040; + // case 0: case 18: case 22: return -1; + default: return -1; + } + } + + /** + * According to DO-260B Table N-7 + * + * @param formatTypeCode the messages' format type code + * @return the derived NACp + */ + public static byte typeCodeToNACp(byte formatTypeCode) { + switch (formatTypeCode) { + case 9: case 20: return 11; + case 10: case 21: return 10; + case 11: return 8; + case 12: return 7; + case 13: return 6; + case 14: return 5; + case 15: return 4; + case 16: case 17: return 1; + // case 0: case 18: case 22: return 0; + default: return 0; + } + } + + /** + * According to DO-260B Table N-7 + * + * @param formatTypeCode the messages' format type code + * @return the derived position uncertainty in meters + */ + public static double typeCodeToPositionUncertainty(byte formatTypeCode) { + switch (formatTypeCode) { + case 9: return 3; + case 10: return 10; + case 11: return 92.6; + case 12: return 185.2; + case 13: return 463; + case 14: return 926; + case 15: return 1852; + case 16: return 9260; + case 17: return 18520; + // case 0: case 18: case 22: return -1; + default: return -1; + } + } + + /** + * According to DO-260B Table 2-200. + * + * @param formatTypeCode the messages' format type code + * @return the derived NIC + */ + public static byte typeCodeToNIC(byte formatTypeCode) { + switch (formatTypeCode) { + case 9: case 20: return 11; + case 6: case 10: case 21: return 10; + case 7: case 11: return 8; + case 12: return 7; + case 13: return 6; + case 14: return 5; + case 15: return 4; + case 16: case 17: return 1; + // case 0: case 18: case 22: return 0; + default: return 0; + } + } + + /** + * According to DO-260B Table N-8. + * @param formatTypeCode the messages' format type code + * @return the derived SIL + */ + public static byte typeCodeToSIL(byte formatTypeCode) { + switch (formatTypeCode) { + case 0: case 18: case 22: return 0; + default: return 2; + } + } +} diff --git a/src/main/java/de/serosystems/lib1090/decoding/Airspeed.java b/src/main/java/de/serosystems/lib1090/decoding/Airspeed.java new file mode 100644 index 0000000..1348247 --- /dev/null +++ b/src/main/java/de/serosystems/lib1090/decoding/Airspeed.java @@ -0,0 +1,30 @@ +package de.serosystems.lib1090.decoding; + +/** + * @author Markus Fuchs (fuchs@sero-systems.de) + */ +public final class Airspeed { + + private Airspeed() {} + + /** + * The 95% accuracy for horizontal velocity. We interpret the coding according to + * DO-260B Table 2-22 for all ADS-B versions. + * @return Navigation Accuracy Category for velocity according to RTCA DO-260B 2.2.3.2.6.1.5 in m/s, -1 means + * "unknown" or >10m + */ + public static double decodeNACv(byte navigationAccuracyCategory) { + switch(navigationAccuracyCategory) { + case 1: + return 10; + case 2: + return 3; + case 3: + return 1; + case 4: + return 0.3F; + default: + return -1; + } + } +} diff --git a/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java b/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java index 83e5ea9..99a449f 100644 --- a/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java +++ b/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java @@ -27,4 +27,63 @@ public static double nacPtoEPU(byte nacPos) { default: return -1; } } + + /** + * According to DO-260B Table 2-74. Compatible with ADS-B version 1 and 2 + * @return the airplane's length in meters; -1 for unknown + */ + public static int decodeAirplaneLength(byte airplaneLenWidth) { + switch (airplaneLenWidth) { + case 1: + return 15; + case 2: + case 3: + return 25; + case 4: + case 5: + return 35; + case 6: + case 7: + return 45; + case 8: + case 9: + return 55; + case 10: + case 11: + return 65; + case 12: + case 13: + return 75; + case 14: + case 15: + return 85; + default: + return -1; + } + } + + /** + * According to DO-260B Table 2-74. Compatible with ADS-B version 1 and 2. + * @return the airplane's width in meters + */ + public static double decodeAirplaneWidth(byte airplaneLenWidth) { + switch (airplaneLenWidth) { + case 1: return 23; + case 2: return 28.5; + case 3: return 34; + case 4: return 33; + case 5: return 38; + case 6: return 39.5; + case 7: return 45; + case 8: return 45; + case 9: return 52; + case 10: return 59.5; + case 11: return 67; + case 12: return 72.5; + case 13: return 80; + case 14: return 80; + case 15: return 90; + default: return -1; + } + } } diff --git a/src/main/java/de/serosystems/lib1090/decoding/SurfacePosition.java b/src/main/java/de/serosystems/lib1090/decoding/SurfacePosition.java new file mode 100644 index 0000000..4ba546f --- /dev/null +++ b/src/main/java/de/serosystems/lib1090/decoding/SurfacePosition.java @@ -0,0 +1,158 @@ +package de.serosystems.lib1090.decoding; + +import de.serosystems.lib1090.msgs.adsb.AirborneOperationalStatusV1Msg; +import de.serosystems.lib1090.msgs.adsb.SurfaceOperationalStatusV1Msg; +import de.serosystems.lib1090.msgs.adsb.SurfaceOperationalStatusV2Msg; + +/** + * @author Markus Fuchs (fuchs@sero-systems.de) + */ +public final class SurfacePosition { + + + private SurfacePosition() {} + + /** + * @return speed resolution (accuracy) in knots or null if ground speed is not available. + */ + public static Double groundSpeedResolution(byte movement) { + double resolution; + + if (movement >= 1 && movement <= 8) + resolution = 0.125; + else if (movement >= 9 && movement <= 12) + resolution = 0.25; + else if (movement >= 13 && movement <= 38) + resolution = 0.5; + else if (movement >= 39 && movement <= 93) + resolution = 1; + else if (movement >= 94 && movement <= 108) + resolution = 2; + else if (movement >= 109 && movement <= 123) + resolution = 5; + else if (movement == 124) + resolution = 175; + else + return null; + + return resolution; + } + + /** + * @return speed in knots or null if ground speed is not available. + */ + public static Double groundSpeed(byte movement) { + double speed; + + if (movement == 1) + speed = 0; + else if (movement >= 2 && movement <= 8) + speed = 0.125+(movement -2)*0.125; + else if (movement >= 9 && movement <= 12) + speed = 1+(movement -9)*0.25; + else if (movement >= 13 && movement <= 38) + speed = 2+(movement -13)*0.5; + else if (movement >= 39 && movement <= 93) + speed = 15+(movement -39); + else if (movement >= 94 && movement <= 108) + speed = 70+(movement -94)*2; + else if (movement >= 109 && movement <= 123) + speed = 100+(movement -109)*5; + else if (movement == 124) + speed = 175; + else + return null; + + return speed; + } + + /** + * @return Navigation integrity category. A NIC of 0 means "unkown". Values according to DO-260B Table N-4. + */ + public static byte decodeNIC(byte formatTypeCode) { + switch (formatTypeCode) { + case 5: return 11; + case 6: return 10; + case 7: return 8; + // case 0: case 8: return 0; + default: return 0; + } + } + + /** + * Get the 95% horizontal accuracy bounds (EPU) derived from NACp value in meter, see table N-7 in RCTA DO-260B. + * + * The concept of NACp has been introduced in ADS-B version 1. For version 0 transmitters, a mapping exists which + * is reflected by this method. + * Values are comparable to those of {@link SurfaceOperationalStatusV1Msg}'s and + * {@link SurfaceOperationalStatusV2Msg}'s getPositionUncertainty method for aircraft supporting ADS-B + * version 1 and 2. + * + * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) + */ + public static double decodeEPU(byte formatTypeCode) { + switch (formatTypeCode) { + case 5: return 3; + case 6: return 10; + case 7: return 92.6; + // case 0: case 8: return -1; + default: return -1; + } + } + + /** + * The position error, i.e., 95% accuracy for the horizontal position. Values according to DO-260B Table N-4. + * + * The horizontal containment radius is also known as "horizontal protection level". + * + * @return horizontal containment radius limit in meters. A return value of -1 means "unkown". + */ + public static double decodeHCR(byte formatTypeCode) { + switch (formatTypeCode) { + case 5: return 7.5; + case 6: return 25; + case 7: return 185.2; + // case 0: case 8: return -1; + default: return -1; + } + } + + /** + * Values according to DO-260B Table N-11 + * @return Navigation integrity category. A NIC of 0 means "unkown". If aircraft uses ADS-B version 1+, + * set NIC supplement A from Operational Status Message for better precision. + */ + public static byte decodeNIC(byte formatTypeCode, boolean nicSupplA) { + switch (formatTypeCode) { + case 0: case 8: return 0; + case 5: return 11; + case 6: return 10; + case 7: + return (byte) (nicSupplA ? 9 : 8); + default: return 0; + } + } + + /** + * The position error, i.e., 95% accuracy for the horizontal position. For the navigation accuracy category + * (NACp) see {@link AirborneOperationalStatusV1Msg}. Values according to DO-260B Table N-11. + * + * The horizontal containment radius is also known as "horizontal protection level". + * + * @return horizontal containment radius limit in meters. A return value of -1 means "unknown". + * If aircraft uses ADS-B version 1+, set NIC supplement A from Operational Status Message + * for better precision. + */ + public static double decodeHCR(byte formatTypeCode, boolean nicSupplA) { + switch (formatTypeCode) { + case 5: return 7.5; + case 6: return 25; + case 7: + return nicSupplA ? 75 : 185.2; + case 8: + return 185.2; + // case 0: return -1; + default: return -1; + } + } +} diff --git a/src/main/java/de/serosystems/lib1090/decoding/VelocityOverGround.java b/src/main/java/de/serosystems/lib1090/decoding/VelocityOverGround.java new file mode 100644 index 0000000..d2f41bb --- /dev/null +++ b/src/main/java/de/serosystems/lib1090/decoding/VelocityOverGround.java @@ -0,0 +1,30 @@ +package de.serosystems.lib1090.decoding; + +/** + * @author Markus Fuchs (fuchs@sero-systems.de) + */ +public final class VelocityOverGround { + + private VelocityOverGround() {} + + /** + * The 95% accuracy for horizontal velocity. We interpret the coding according to + * DO-260B Table 2-22 for all ADS-B versions. + * @return Navigation Accuracy Category for velocity according to RTCA DO-260B 2.2.3.2.6.1.5 in m/s, -1 means + * "unknown" or >10m + */ + public static float decodeAccuracyBound(byte navigationAccuracyCategory) { + switch(navigationAccuracyCategory) { + case 1: + return 10; + case 2: + return 3; + case 3: + return 1; + case 4: + return 0.3f; + default: + return -1; + } + } +} diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java index 9a7e0b1..8b0f61f 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV0Msg.java @@ -2,6 +2,7 @@ import de.serosystems.lib1090.Position; import de.serosystems.lib1090.cpr.CPREncodedPosition; +import de.serosystems.lib1090.decoding.AirbornePosition; import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; @@ -112,29 +113,7 @@ public AirbornePositionV0Msg(ExtendedSquitter squitter, Long timestamp) throws B * @return horizontal containment radius limit in meters. A return value of -1 means "unkown". */ public double getHorizontalContainmentRadiusLimit() { - return typeCodeToHCR(getFormatTypeCode()); - } - - /** - * According to DO-260B Table N-4 - * - * @param formatTypeCode the messages' format type code - * @return the derived HCR - */ - public static double typeCodeToHCR(byte formatTypeCode) { - switch (formatTypeCode) { - case 9: case 20: return 7.5; - case 10: case 21: return 25; - case 11: return 185.2; - case 12: return 370.4; - case 13: return 926; - case 14: return 1852; - case 15: return 3704; - case 16: return 18520; - case 17: return 37040; - // case 0: case 18: case 22: return -1; - default: return -1; - } + return AirbornePosition.typeCodeToHCR(getFormatTypeCode()); } /** @@ -147,28 +126,7 @@ public static double typeCodeToHCR(byte formatTypeCode) { * {@link AirborneOperationalStatusV1Msg}. */ public byte getNACp() { - return typeCodeToNACp(getFormatTypeCode()); - } - - /** - * According to DO-260B Table N-7 - * - * @param formatTypeCode the messages' format type code - * @return the derived NACp - */ - public static byte typeCodeToNACp(byte formatTypeCode) { - switch (formatTypeCode) { - case 9: case 20: return 11; - case 10: case 21: return 10; - case 11: return 8; - case 12: return 7; - case 13: return 6; - case 14: return 5; - case 15: return 4; - case 16: case 17: return 1; - // case 0: case 18: case 22: return 0; - default: return 0; - } + return AirbornePosition.typeCodeToNACp(getFormatTypeCode()); } /** @@ -183,29 +141,7 @@ public static byte typeCodeToNACp(byte formatTypeCode) { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - return typeCodeToPositionUncertainty(getFormatTypeCode()); - } - - /** - * According to DO-260B Table N-7 - * - * @param formatTypeCode the messages' format type code - * @return the derived position uncertainty in meters - */ - public static double typeCodeToPositionUncertainty(byte formatTypeCode) { - switch (formatTypeCode) { - case 9: return 3; - case 10: return 10; - case 11: return 92.6; - case 12: return 185.2; - case 13: return 463; - case 14: return 926; - case 15: return 1852; - case 16: return 9260; - case 17: return 18520; - // case 0: case 18: case 22: return -1; - default: return -1; - } + return AirbornePosition.typeCodeToPositionUncertainty(getFormatTypeCode()); } /** @@ -214,28 +150,7 @@ public static double typeCodeToPositionUncertainty(byte formatTypeCode) { * @return Navigation integrity category. A NIC of 0 means "unkown". */ public byte getNIC() { - return typeCodeToNIC(getFormatTypeCode()); - } - - /** - * According to DO-260B Table 2-200. - * - * @param formatTypeCode the messages' format type code - * @return the derived NIC - */ - public static byte typeCodeToNIC(byte formatTypeCode) { - switch (formatTypeCode) { - case 9: case 20: return 11; - case 6: case 10: case 21: return 10; - case 7: case 11: return 8; - case 12: return 7; - case 13: return 6; - case 14: return 5; - case 15: return 4; - case 16: case 17: return 1; - // case 0: case 18: case 22: return 0; - default: return 0; - } + return AirbornePosition.typeCodeToNIC(getFormatTypeCode()); } /** @@ -251,19 +166,7 @@ public static byte typeCodeToNIC(byte formatTypeCode) { * the NIC containment radius. */ public byte getSIL() { - return typeCodeToSIL(getFormatTypeCode()); - } - - /** - * According to DO-260B Table N-8. - * @param formatTypeCode the messages' format type code - * @return the derived SIL - */ - public static byte typeCodeToSIL(byte formatTypeCode) { - switch (formatTypeCode) { - case 0: case 18: case 22: return 0; - default: return 2; - } + return AirbornePosition.typeCodeToSIL(getFormatTypeCode()); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV1Msg.java index 25f4864..6c9a138 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirbornePositionV1Msg.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.adsb; +import de.serosystems.lib1090.decoding.AirbornePosition; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.modes.ExtendedSquitter; @@ -92,19 +93,7 @@ public boolean hasNICSupplementA() { * for better precision. */ public double getHorizontalContainmentRadiusLimit() { - switch (getFormatTypeCode()) { - case 0: case 18: case 22: return -1; - case 9: case 20: return 7.5; - case 10: case 21: return 25; - case 11: return nic_suppl_a ? 75.0 : 185.2; - case 12: return 370.4; - case 13: return nic_suppl_a ? 1111.2 : 926; - case 14: return 1852; - case 15: return 3704; - case 16: return nic_suppl_a ? 7408 : 14816; - case 17: return 37040; - default: return -1; - } + return AirbornePosition.decodeHCR(getFormatTypeCode(), nic_suppl_a); } /** @@ -112,19 +101,7 @@ public double getHorizontalContainmentRadiusLimit() { * @return Navigation integrity category. A NIC of 0 means "unkown". */ public byte getNIC() { - switch (getFormatTypeCode()) { - case 0: case 18: case 22: return 0; - case 9: case 20: return 11; - case 10: case 21: return 10; - case 11: return (byte) (nic_suppl_a ? 9 : 8); - case 12: return 7; - case 13: return 6; - case 14: return 5; - case 15: return 4; - case 16: return (byte) (nic_suppl_a ? 3 : 2); - case 17: return 1; - default: return 0; - } + return AirbornePosition.decodeNIC(getFormatTypeCode(), nic_suppl_a); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirspeedHeadingMsg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirspeedHeadingMsg.java index 07a4ab3..19b6050 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/AirspeedHeadingMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/AirspeedHeadingMsg.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.adsb; +import de.serosystems.lib1090.decoding.Airspeed; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.modes.ExtendedSquitter; @@ -184,18 +185,7 @@ public boolean hasIFRCapability() { * "unknown" or >10m */ public double getNACv() { - switch(navigation_accuracy_category) { - case 1: - return 10; - case 2: - return 3; - case 3: - return 1; - case 4: - return 0.3F; - default: - return -1; - } + return Airspeed.decodeNACv(navigation_accuracy_category); } /** @@ -207,7 +197,6 @@ public Integer getAirspeed() { return (int) airspeed; } - /** * @return whether altitude is derived by barometric sensor or GNSS */ diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfaceOperationalStatusV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfaceOperationalStatusV1Msg.java index b63c49b..8d6c7af 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfaceOperationalStatusV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfaceOperationalStatusV1Msg.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.adsb; +import de.serosystems.lib1090.decoding.OperationalStatus; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.modes.ExtendedSquitter; @@ -191,33 +192,7 @@ public byte getGPSAntennaOffset() { * @return the airplane's length in meters; -1 for unknown */ public int getAirplaneLength() { - switch (airplane_len_width) { - case 1: - return 15; - case 2: - case 3: - return 25; - case 4: - case 5: - return 35; - case 6: - case 7: - return 45; - case 8: - case 9: - return 55; - case 10: - case 11: - return 65; - case 12: - case 13: - return 75; - case 14: - case 15: - return 85; - default: - return -1; - } + return OperationalStatus.decodeAirplaneLength(airplane_len_width); } /** @@ -225,24 +200,7 @@ public int getAirplaneLength() { * @return the airplane's width in meters */ public double getAirplaneWidth() { - switch (airplane_len_width) { - case 1: return 23; - case 2: return 28.5; - case 3: return 34; - case 4: return 33; - case 5: return 38; - case 6: return 39.5; - case 7: return 45; - case 8: return 45; - case 9: return 52; - case 10: return 59.5; - case 11: return 67; - case 12: return 72.5; - case 13: return 80; - case 14: return 80; - case 15: return 90; - default: return -1; - } + return OperationalStatus.decodeAirplaneWidth(airplane_len_width); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfacePositionV0Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfacePositionV0Msg.java index 9e52a46..58dd815 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfacePositionV0Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfacePositionV0Msg.java @@ -2,6 +2,7 @@ import de.serosystems.lib1090.Position; import de.serosystems.lib1090.cpr.CPREncodedPosition; +import de.serosystems.lib1090.decoding.SurfacePosition; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.PositionMsg; @@ -103,13 +104,7 @@ public SurfacePositionV0Msg(ExtendedSquitter squitter, Long timestamp) throws Ba * @return horizontal containment radius limit in meters. A return value of -1 means "unkown". */ public double getHorizontalContainmentRadiusLimit() { - switch (getFormatTypeCode()) { - case 0: case 8: return -1; - case 5: return 7.5; - case 6: return 25; - case 7: return 185.2; - default: return -1; - } + return SurfacePosition.decodeHCR(getFormatTypeCode()); } /** @@ -137,26 +132,14 @@ public byte getNACp() { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - switch (getFormatTypeCode()) { - case 0: case 8: return -1; - case 5: return 3; - case 6: return 10; - case 7: return 92.6; - default: return -1; - } + return SurfacePosition.decodeEPU(getFormatTypeCode()); } /** * @return Navigation integrity category. A NIC of 0 means "unkown". Values according to DO-260B Table N-4. */ public byte getNIC() { - switch (getFormatTypeCode()) { - case 0: case 8: return 0; - case 5: return 11; - case 6: return 10; - case 7: return 8; - default: return 0; - } + return SurfacePosition.decodeNIC(getFormatTypeCode()); } /** @@ -187,28 +170,7 @@ public boolean hasGroundSpeed() { * {@link #hasGroundSpeed()}. */ public Double getGroundSpeed() { - double speed; - - if (movement == 1) - speed = 0; - else if (movement >= 2 && movement <= 8) - speed = 0.125+(movement-2)*0.125; - else if (movement >= 9 && movement <= 12) - speed = 1+(movement-9)*0.25; - else if (movement >= 13 && movement <= 38) - speed = 2+(movement-13)*0.5; - else if (movement >= 39 && movement <= 93) - speed = 15+(movement-39); - else if (movement >= 94 && movement <= 108) - speed = 70+(movement-94)*2; - else if (movement >= 109 && movement <= 123) - speed = 100+(movement-109)*5; - else if (movement == 124) - speed = 175; - else - return null; - - return speed; + return SurfacePosition.groundSpeed(movement); } /** @@ -216,26 +178,7 @@ else if (movement == 124) * checked with {@link #hasGroundSpeed()}. */ public Double getGroundSpeedResolution() { - double resolution; - - if (movement >= 1 && movement <= 8) - resolution = 0.125; - else if (movement >= 9 && movement <= 12) - resolution = 0.25; - else if (movement >= 13 && movement <= 38) - resolution = 0.5; - else if (movement >= 39 && movement <= 93) - resolution = 1; - else if (movement >= 94 && movement <= 108) - resolution = 2; - else if (movement >= 109 && movement <= 123) - resolution = 5; - else if (movement == 124) - resolution = 175; - else - return null; - - return resolution; + return SurfacePosition.groundSpeedResolution(movement); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfacePositionV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfacePositionV1Msg.java index 8f1855c..0073bab 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfacePositionV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/SurfacePositionV1Msg.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.adsb; +import de.serosystems.lib1090.decoding.SurfacePosition; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.modes.ExtendedSquitter; @@ -75,16 +76,7 @@ public void setNICSupplementA(boolean nic_suppl) { */ @Override public double getHorizontalContainmentRadiusLimit() { - switch (getFormatTypeCode()) { - case 0: return -1; - case 5: return 7.5; - case 6: return 25; - case 7: - return hasNICSupplementA() ? 75 : 185.2; - case 8: - return 185.2; - default: return -1; - } + return SurfacePosition.decodeHCR(getFormatTypeCode(), hasNICSupplementA()); } /** @@ -94,14 +86,7 @@ public double getHorizontalContainmentRadiusLimit() { */ @Override public byte getNIC() { - switch (getFormatTypeCode()) { - case 0: case 8: return 0; - case 5: return 11; - case 6: return 10; - case 7: - return (byte) (hasNICSupplementA() ? 9 : 8); - default: return 0; - } + return SurfacePosition.decodeNIC(getFormatTypeCode(), hasNICSupplementA()); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsb/VelocityOverGroundMsg.java b/src/main/java/de/serosystems/lib1090/msgs/adsb/VelocityOverGroundMsg.java index c8b0a19..4e12019 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsb/VelocityOverGroundMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsb/VelocityOverGroundMsg.java @@ -1,5 +1,6 @@ package de.serosystems.lib1090.msgs.adsb; +import de.serosystems.lib1090.decoding.VelocityOverGround; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.modes.ExtendedSquitter; @@ -173,21 +174,9 @@ public byte getNACv() { * "unknown" or >10m */ public float getAccuracyBound() { - switch(navigation_accuracy_category) { - case 1: - return 10; - case 2: - return 3; - case 3: - return 1; - case 4: - return 0.3f; - default: - return -1; - } + return VelocityOverGround.decodeAccuracyBound(navigation_accuracy_category); } - /** * @return velocity from east to south in knots or null if information is not available */ @@ -196,7 +185,6 @@ public Integer getEastToWestVelocity() { return (direction_west ? east_west_velocity : -east_west_velocity); } - /** * @return velocity from north to south in knots or null if information is not available */ @@ -205,7 +193,6 @@ public Integer getNorthToSouthVelocity() { return (direction_south ? north_south_velocity : -north_south_velocity); } - /** * @return whether altitude is derived by barometric sensor or GNSS */ @@ -213,7 +200,6 @@ public boolean isBarometricVerticalSpeed() { return vertical_source; } - /** * @return vertical rate in feet/min (negative value means descending) or null if information is not available. The * latter can also be checked with {@link #hasVerticalRateInfo()} @@ -223,7 +209,6 @@ public Integer getVerticalRate() { return (vertical_rate_down ? -vertical_rate : vertical_rate); } - /** * @return difference between barometric and geometric altitude in feet or null if information is not available. The * latter can also be checked with {@link #hasGeoMinusBaroInfo()} diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV0Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV0Msg.java index 4659e15..4e9bb01 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV0Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV0Msg.java @@ -2,6 +2,7 @@ import de.serosystems.lib1090.Position; import de.serosystems.lib1090.cpr.CPREncodedPosition; +import de.serosystems.lib1090.decoding.AirbornePosition; import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; @@ -12,8 +13,6 @@ import java.io.Serializable; -import static de.serosystems.lib1090.msgs.adsb.AirbornePositionV0Msg.*; - /* * This file is part of de.serosystems.lib1090. * @@ -113,7 +112,7 @@ public AirbornePositionV0Msg(ExtendedSquitter squitter, Long timestamp) throws B * @return horizontal containment radius limit in meters. A return value of -1 means "unkown". */ public double getHorizontalContainmentRadiusLimit() { - return typeCodeToHCR(getFormatTypeCode()); + return AirbornePosition.typeCodeToHCR(getFormatTypeCode()); } /** @@ -126,7 +125,7 @@ public double getHorizontalContainmentRadiusLimit() { * {@link AirborneOperationalStatusV1Msg}. */ public byte getNACp() { - return typeCodeToNACp(getFormatTypeCode()); + return AirbornePosition.typeCodeToNACp(getFormatTypeCode()); } /** @@ -141,14 +140,14 @@ public byte getNACp() { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - return typeCodeToPositionUncertainty(getFormatTypeCode()); + return AirbornePosition.typeCodeToPositionUncertainty(getFormatTypeCode()); } /** * @return Navigation integrity category. A NIC of 0 means "unkown". */ public byte getNIC() { - return typeCodeToNIC(getFormatTypeCode()); + return AirbornePosition.typeCodeToNIC(getFormatTypeCode()); } /** @@ -164,7 +163,7 @@ public byte getNIC() { * the NIC containment radius. */ public byte getSIL() { - return typeCodeToSIL(getFormatTypeCode()); + return AirbornePosition.typeCodeToSIL(getFormatTypeCode()); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV1Msg.java index d77b2a2..fafd7a4 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirbornePositionV1Msg.java @@ -7,6 +7,9 @@ import java.io.Serializable; +import static de.serosystems.lib1090.decoding.AirbornePosition.decodeNIC; +import static de.serosystems.lib1090.decoding.AirbornePosition.decodeHCR; + /* * This file is part of de.serosystems.lib1090. * @@ -94,19 +97,7 @@ public boolean hasNICSupplementA() { * for better precision. */ public double getHorizontalContainmentRadiusLimit() { - switch (getFormatTypeCode()) { - case 0: case 18: case 22: return -1; - case 9: case 20: return 7.5; - case 10: case 21: return 25; - case 11: return nic_suppl_a ? 75.0 : 185.2; - case 12: return 370.4; - case 13: return nic_suppl_a ? 1111.2 : 926; - case 14: return 1852; - case 15: return 3704; - case 16: return nic_suppl_a ? 7408 : 14816; - case 17: return 37040; - default: return -1; - } + return decodeHCR(getFormatTypeCode(), nic_suppl_a); } /** @@ -114,19 +105,7 @@ public double getHorizontalContainmentRadiusLimit() { * @return Navigation integrity category. A NIC of 0 means "unkown". */ public byte getNIC() { - switch (getFormatTypeCode()) { - case 0: case 18: case 22: return 0; - case 9: case 20: return 11; - case 10: case 21: return 10; - case 11: return (byte) (nic_suppl_a ? 9 : 8); - case 12: return 7; - case 13: return 6; - case 14: return 5; - case 15: return 4; - case 16: return (byte) (nic_suppl_a ? 3 : 2); - case 17: return 1; - default: return 0; - } + return decodeNIC(getFormatTypeCode(), nic_suppl_a); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirspeedHeadingMsg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirspeedHeadingMsg.java index 997fc5b..a9f770c 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/AirspeedHeadingMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/AirspeedHeadingMsg.java @@ -6,6 +6,8 @@ import java.io.Serializable; +import static de.serosystems.lib1090.decoding.Airspeed.decodeNACv; + /* * This file is part of de.serosystems.lib1090. * @@ -184,18 +186,7 @@ public boolean hasIFRCapability() { * "unknown" or >10m */ public double getNACv() { - switch(navigation_accuracy_category) { - case 1: - return 10; - case 2: - return 3; - case 3: - return 1; - case 4: - return 0.3F; - default: - return -1; - } + return decodeNACv(navigation_accuracy_category); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfaceOperationalStatusV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfaceOperationalStatusV1Msg.java index b903ad8..249346c 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfaceOperationalStatusV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfaceOperationalStatusV1Msg.java @@ -7,6 +7,8 @@ import java.io.Serializable; import static de.serosystems.lib1090.decoding.OperationalStatus.nacPtoEPU; +import static de.serosystems.lib1090.decoding.OperationalStatus.decodeAirplaneLength; +import static de.serosystems.lib1090.decoding.OperationalStatus.decodeAirplaneWidth; /* * This file is part of de.serosystems.lib1090. @@ -200,33 +202,7 @@ public byte getGPSAntennaOffset() { * @return the airplane's length in meters; -1 for unknown */ public int getAirplaneLength() { - switch (airplane_len_width) { - case 1: - return 15; - case 2: - case 3: - return 25; - case 4: - case 5: - return 35; - case 6: - case 7: - return 45; - case 8: - case 9: - return 55; - case 10: - case 11: - return 65; - case 12: - case 13: - return 75; - case 14: - case 15: - return 85; - default: - return -1; - } + return decodeAirplaneLength(airplane_len_width); } /** @@ -234,24 +210,7 @@ public int getAirplaneLength() { * @return the airplane's width in meters */ public double getAirplaneWidth() { - switch (airplane_len_width) { - case 1: return 23; - case 2: return 28.5; - case 3: return 34; - case 4: return 33; - case 5: return 38; - case 6: return 39.5; - case 7: return 45; - case 8: return 45; - case 9: return 52; - case 10: return 59.5; - case 11: return 67; - case 12: return 72.5; - case 13: return 80; - case 14: return 80; - case 15: return 90; - default: return -1; - } + return decodeAirplaneWidth(airplane_len_width); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfacePositionV0Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfacePositionV0Msg.java index 7687319..458157b 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfacePositionV0Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfacePositionV0Msg.java @@ -2,6 +2,7 @@ import de.serosystems.lib1090.Position; import de.serosystems.lib1090.cpr.CPREncodedPosition; +import de.serosystems.lib1090.decoding.SurfacePosition; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.PositionMsg; @@ -13,6 +14,11 @@ import java.io.Serializable; +import static de.serosystems.lib1090.decoding.SurfacePosition.groundSpeed; +import static de.serosystems.lib1090.decoding.SurfacePosition.groundSpeedResolution; +import static de.serosystems.lib1090.decoding.SurfacePosition.decodeEPU; +import static de.serosystems.lib1090.decoding.SurfacePosition.decodeHCR; + /* * This file is part of de.serosystems.lib1090. * @@ -107,13 +113,8 @@ public SurfacePositionV0Msg(ExtendedSquitter squitter, Long timestamp) throws Ba * @return horizontal containment radius limit in meters. A return value of -1 means "unkown". */ public double getHorizontalContainmentRadiusLimit() { - switch (getFormatTypeCode()) { - case 0: case 8: return -1; - case 5: return 7.5; - case 6: return 25; - case 7: return 185.2; - default: return -1; - } + return decodeHCR(getFormatTypeCode()); + } /** @@ -141,26 +142,14 @@ public byte getNACp() { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - switch (getFormatTypeCode()) { - case 0: case 8: return -1; - case 5: return 3; - case 6: return 10; - case 7: return 92.6; - default: return -1; - } + return decodeEPU(getFormatTypeCode()); } /** * @return Navigation integrity category. A NIC of 0 means "unkown". Values according to DO-260B Table N-4. */ public byte getNIC() { - switch (getFormatTypeCode()) { - case 0: case 8: return 0; - case 5: return 11; - case 6: return 10; - case 7: return 8; - default: return 0; - } + return SurfacePosition.decodeNIC(getFormatTypeCode()); } /** @@ -191,28 +180,7 @@ public boolean hasGroundSpeed() { * {@link #hasGroundSpeed()}. */ public Double getGroundSpeed() { - double speed; - - if (movement == 1) - speed = 0; - else if (movement >= 2 && movement <= 8) - speed = 0.125+(movement-2)*0.125; - else if (movement >= 9 && movement <= 12) - speed = 1+(movement-9)*0.25; - else if (movement >= 13 && movement <= 38) - speed = 2+(movement-13)*0.5; - else if (movement >= 39 && movement <= 93) - speed = 15+(movement-39); - else if (movement >= 94 && movement <= 108) - speed = 70+(movement-94)*2; - else if (movement >= 109 && movement <= 123) - speed = 100+(movement-109)*5; - else if (movement == 124) - speed = 175; - else - return null; - - return speed; + return groundSpeed(movement); } /** @@ -220,26 +188,7 @@ else if (movement == 124) * checked with {@link #hasGroundSpeed()}. */ public Double getGroundSpeedResolution() { - double resolution; - - if (movement >= 1 && movement <= 8) - resolution = 0.125; - else if (movement >= 9 && movement <= 12) - resolution = 0.25; - else if (movement >= 13 && movement <= 38) - resolution = 0.5; - else if (movement >= 39 && movement <= 93) - resolution = 1; - else if (movement >= 94 && movement <= 108) - resolution = 2; - else if (movement >= 109 && movement <= 123) - resolution = 5; - else if (movement == 124) - resolution = 175; - else - return null; - - return resolution; + return groundSpeedResolution(movement); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfacePositionV1Msg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfacePositionV1Msg.java index 7d75b64..86a0936 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfacePositionV1Msg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/SurfacePositionV1Msg.java @@ -7,6 +7,9 @@ import java.io.Serializable; +import static de.serosystems.lib1090.decoding.SurfacePosition.decodeNIC; +import static de.serosystems.lib1090.decoding.SurfacePosition.decodeHCR; + /** * @author Markus Fuchs (fuchs@opensky-network.org) * @author Matthias Schäfer (schaefer@sero-systems.de) @@ -77,16 +80,7 @@ public void setNICSupplementA(boolean nic_suppl) { */ @Override public double getHorizontalContainmentRadiusLimit() { - switch (getFormatTypeCode()) { - case 0: return -1; - case 5: return 7.5; - case 6: return 25; - case 7: - return hasNICSupplementA() ? 75 : 185.2; - case 8: - return 185.2; - default: return -1; - } + return decodeHCR(getFormatTypeCode(), hasNICSupplementA()); } /** @@ -96,14 +90,7 @@ public double getHorizontalContainmentRadiusLimit() { */ @Override public byte getNIC() { - switch (getFormatTypeCode()) { - case 0: case 8: return 0; - case 5: return 11; - case 6: return 10; - case 7: - return (byte) (hasNICSupplementA() ? 9 : 8); - default: return 0; - } + return decodeNIC(getFormatTypeCode(), hasNICSupplementA()); } @Override diff --git a/src/main/java/de/serosystems/lib1090/msgs/adsr/VelocityOverGroundMsg.java b/src/main/java/de/serosystems/lib1090/msgs/adsr/VelocityOverGroundMsg.java index d0b0b2d..b7ecedd 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/adsr/VelocityOverGroundMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/adsr/VelocityOverGroundMsg.java @@ -6,6 +6,8 @@ import java.io.Serializable; +import static de.serosystems.lib1090.decoding.VelocityOverGround.decodeAccuracyBound; + /* * This file is part of de.serosystems.lib1090. * @@ -173,18 +175,7 @@ public byte getNACv() { * "unknown" or >10m */ public float getAccuracyBound() { - switch(navigation_accuracy_category) { - case 1: - return 10; - case 2: - return 3; - case 3: - return 1; - case 4: - return 0.3f; - default: - return -1; - } + return decodeAccuracyBound(navigation_accuracy_category); } diff --git a/src/main/java/de/serosystems/lib1090/msgs/tisb/FineAirbornePositionMsg.java b/src/main/java/de/serosystems/lib1090/msgs/tisb/FineAirbornePositionMsg.java index 31a45e1..dff1eca 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/tisb/FineAirbornePositionMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/tisb/FineAirbornePositionMsg.java @@ -2,6 +2,7 @@ import de.serosystems.lib1090.Position; import de.serosystems.lib1090.cpr.CPREncodedPosition; +import de.serosystems.lib1090.decoding.AirbornePosition; import de.serosystems.lib1090.decoding.Altitude; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; @@ -12,8 +13,6 @@ import java.io.Serializable; -import static de.serosystems.lib1090.msgs.adsb.AirbornePositionV0Msg.*; - /* * This file is part of de.serosystems.lib1090. * @@ -120,7 +119,7 @@ public FineAirbornePositionMsg(ExtendedSquitter squitter, Long timestamp) throws * @return horizontal containment radius limit in meters. A return value of -1 means "unkown". */ public double getHorizontalContainmentRadiusLimit() { - return typeCodeToHCR(getFormatTypeCode()); + return AirbornePosition.typeCodeToHCR(getFormatTypeCode()); } /** @@ -133,7 +132,7 @@ public double getHorizontalContainmentRadiusLimit() { * {@link AirborneOperationalStatusV1Msg}. */ public byte getNACp() { - return typeCodeToNACp(getFormatTypeCode()); + return AirbornePosition.typeCodeToNACp(getFormatTypeCode()); } /** @@ -148,14 +147,14 @@ public byte getNACp() { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - return typeCodeToPositionUncertainty(getFormatTypeCode()); + return AirbornePosition.typeCodeToPositionUncertainty(getFormatTypeCode()); } /** * @return Navigation integrity category. A NIC of 0 means "unkown". */ public byte getNIC() { - return typeCodeToNIC(getFormatTypeCode()); + return AirbornePosition.typeCodeToNIC(getFormatTypeCode()); } /** @@ -171,7 +170,7 @@ public byte getNIC() { * the NIC containment radius. */ public byte getSIL() { - return typeCodeToSIL(getFormatTypeCode()); + return AirbornePosition.typeCodeToSIL(getFormatTypeCode()); } /** diff --git a/src/main/java/de/serosystems/lib1090/msgs/tisb/FineSurfacePositionMsg.java b/src/main/java/de/serosystems/lib1090/msgs/tisb/FineSurfacePositionMsg.java index db3985e..3f81ca0 100644 --- a/src/main/java/de/serosystems/lib1090/msgs/tisb/FineSurfacePositionMsg.java +++ b/src/main/java/de/serosystems/lib1090/msgs/tisb/FineSurfacePositionMsg.java @@ -2,6 +2,7 @@ import de.serosystems.lib1090.Position; import de.serosystems.lib1090.cpr.CPREncodedPosition; +import de.serosystems.lib1090.decoding.SurfacePosition; import de.serosystems.lib1090.exceptions.BadFormatException; import de.serosystems.lib1090.exceptions.UnspecifiedFormatError; import de.serosystems.lib1090.msgs.PositionMsg; @@ -13,6 +14,11 @@ import java.io.Serializable; +import static de.serosystems.lib1090.decoding.SurfacePosition.groundSpeed; +import static de.serosystems.lib1090.decoding.SurfacePosition.groundSpeedResolution; +import static de.serosystems.lib1090.decoding.SurfacePosition.decodeEPU; +import static de.serosystems.lib1090.decoding.SurfacePosition.decodeHCR; + /* * This file is part of de.serosystems.lib1090. * @@ -111,13 +117,8 @@ public FineSurfacePositionMsg(ExtendedSquitter squitter, Long timestamp) throws * @return horizontal containment radius limit in meters. A return value of -1 means "unkown". */ public double getHorizontalContainmentRadiusLimit() { - switch (getFormatTypeCode()) { - case 0: case 8: return -1; - case 5: return 7.5; - case 6: return 25; - case 7: return 185.2; - default: return -1; - } + return decodeHCR(getFormatTypeCode()); + } /** @@ -145,26 +146,14 @@ public byte getNACp() { * @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown) */ public double getPositionUncertainty() { - switch (getFormatTypeCode()) { - case 0: case 8: return -1; - case 5: return 3; - case 6: return 10; - case 7: return 92.6; - default: return -1; - } + return decodeEPU(getFormatTypeCode()); } /** * @return Navigation integrity category. A NIC of 0 means "unkown". Values according to DO-260B Table N-4. */ public byte getNIC() { - switch (getFormatTypeCode()) { - case 0: case 8: return 0; - case 5: return 11; - case 6: return 10; - case 7: return 8; - default: return 0; - } + return SurfacePosition.decodeNIC(getFormatTypeCode()); } /** @@ -195,28 +184,7 @@ public boolean hasGroundSpeed() { * {@link #hasGroundSpeed()}. */ public Double getGroundSpeed() { - double speed; - - if (movement == 1) - speed = 0; - else if (movement >= 2 && movement <= 8) - speed = 0.125+(movement-2)*0.125; - else if (movement >= 9 && movement <= 12) - speed = 1+(movement-9)*0.25; - else if (movement >= 13 && movement <= 38) - speed = 2+(movement-13)*0.5; - else if (movement >= 39 && movement <= 93) - speed = 15+(movement-39); - else if (movement >= 94 && movement <= 108) - speed = 70+(movement-94)*2; - else if (movement >= 109 && movement <= 123) - speed = 100+(movement-109)*5; - else if (movement == 124) - speed = 175; - else - return null; - - return speed; + return groundSpeed(movement); } /** @@ -224,26 +192,7 @@ else if (movement == 124) * checked with {@link #hasGroundSpeed()}. */ public Double getGroundSpeedResolution() { - double resolution; - - if (movement >= 1 && movement <= 8) - resolution = 0.125; - else if (movement >= 9 && movement <= 12) - resolution = 0.25; - else if (movement >= 13 && movement <= 38) - resolution = 0.5; - else if (movement >= 39 && movement <= 93) - resolution = 1; - else if (movement >= 94 && movement <= 108) - resolution = 2; - else if (movement >= 109 && movement <= 123) - resolution = 5; - else if (movement == 124) - resolution = 175; - else - return null; - - return resolution; + return groundSpeedResolution(movement); } /** From a3f0d2b8dc2c5b495273c83a9a1da74641ad645f Mon Sep 17 00:00:00 2001 From: Markus Fuchs Date: Tue, 7 Nov 2023 11:01:51 +0100 Subject: [PATCH 6/6] refactoring: address line break consistency --- .../lib1090/decoding/Airspeed.java | 15 +++---- .../lib1090/decoding/Altitude.java | 2 +- .../lib1090/decoding/OperationalStatus.java | 40 +++++-------------- .../lib1090/decoding/SurfacePosition.java | 19 +++------ .../lib1090/decoding/VelocityOverGround.java | 15 +++---- 5 files changed, 27 insertions(+), 64 deletions(-) diff --git a/src/main/java/de/serosystems/lib1090/decoding/Airspeed.java b/src/main/java/de/serosystems/lib1090/decoding/Airspeed.java index 1348247..c9b7c00 100644 --- a/src/main/java/de/serosystems/lib1090/decoding/Airspeed.java +++ b/src/main/java/de/serosystems/lib1090/decoding/Airspeed.java @@ -15,16 +15,11 @@ private Airspeed() {} */ public static double decodeNACv(byte navigationAccuracyCategory) { switch(navigationAccuracyCategory) { - case 1: - return 10; - case 2: - return 3; - case 3: - return 1; - case 4: - return 0.3F; - default: - return -1; + case 1: return 10; + case 2: return 3; + case 3: return 1; + case 4: return 0.3F; + default: return -1; } } } diff --git a/src/main/java/de/serosystems/lib1090/decoding/Altitude.java b/src/main/java/de/serosystems/lib1090/decoding/Altitude.java index c4c43ee..bf6f74b 100644 --- a/src/main/java/de/serosystems/lib1090/decoding/Altitude.java +++ b/src/main/java/de/serosystems/lib1090/decoding/Altitude.java @@ -68,7 +68,7 @@ public static Integer decode13BitAltitude(short altitude_code) { /** * Decode altitude according to DO-260B 2.2.3.2.3.4.3
* @param altitude_encoded 12 bit encoded altitude - * @return + * @return altitude in feet */ public static Integer decode12BitAltitude(short altitude_encoded) { // In contrast to the decodeAltitude method in {@link de.serosystems.lib1090.msgs.modes.AltitudeReply}, input diff --git a/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java b/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java index 99a449f..cab6592 100644 --- a/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java +++ b/src/main/java/de/serosystems/lib1090/decoding/OperationalStatus.java @@ -34,31 +34,15 @@ public static double nacPtoEPU(byte nacPos) { */ public static int decodeAirplaneLength(byte airplaneLenWidth) { switch (airplaneLenWidth) { - case 1: - return 15; - case 2: - case 3: - return 25; - case 4: - case 5: - return 35; - case 6: - case 7: - return 45; - case 8: - case 9: - return 55; - case 10: - case 11: - return 65; - case 12: - case 13: - return 75; - case 14: - case 15: - return 85; - default: - return -1; + case 1: return 15; + case 2: case 3: return 25; + case 4: case 5: return 35; + case 6: case 7: return 45; + case 8: case 9: return 55; + case 10: case 11: return 65; + case 12: case 13: return 75; + case 14: case 15: return 85; + default: return -1; } } @@ -74,14 +58,12 @@ public static double decodeAirplaneWidth(byte airplaneLenWidth) { case 4: return 33; case 5: return 38; case 6: return 39.5; - case 7: return 45; - case 8: return 45; + case 7: case 8: return 45; case 9: return 52; case 10: return 59.5; case 11: return 67; case 12: return 72.5; - case 13: return 80; - case 14: return 80; + case 13: case 14: return 80; case 15: return 90; default: return -1; } diff --git a/src/main/java/de/serosystems/lib1090/decoding/SurfacePosition.java b/src/main/java/de/serosystems/lib1090/decoding/SurfacePosition.java index 4ba546f..0180a72 100644 --- a/src/main/java/de/serosystems/lib1090/decoding/SurfacePosition.java +++ b/src/main/java/de/serosystems/lib1090/decoding/SurfacePosition.java @@ -70,13 +70,7 @@ else if (movement == 124) * @return Navigation integrity category. A NIC of 0 means "unkown". Values according to DO-260B Table N-4. */ public static byte decodeNIC(byte formatTypeCode) { - switch (formatTypeCode) { - case 5: return 11; - case 6: return 10; - case 7: return 8; - // case 0: case 8: return 0; - default: return 0; - } + return decodeNIC(formatTypeCode, false); } /** @@ -124,11 +118,10 @@ public static double decodeHCR(byte formatTypeCode) { */ public static byte decodeNIC(byte formatTypeCode, boolean nicSupplA) { switch (formatTypeCode) { - case 0: case 8: return 0; case 5: return 11; case 6: return 10; - case 7: - return (byte) (nicSupplA ? 9 : 8); + case 7: return (byte) (nicSupplA ? 9 : 8); + // case 0: case 8: return 0; default: return 0; } } @@ -147,10 +140,8 @@ public static double decodeHCR(byte formatTypeCode, boolean nicSupplA) { switch (formatTypeCode) { case 5: return 7.5; case 6: return 25; - case 7: - return nicSupplA ? 75 : 185.2; - case 8: - return 185.2; + case 7: return nicSupplA ? 75 : 185.2; + case 8: return 185.2; // case 0: return -1; default: return -1; } diff --git a/src/main/java/de/serosystems/lib1090/decoding/VelocityOverGround.java b/src/main/java/de/serosystems/lib1090/decoding/VelocityOverGround.java index d2f41bb..6e91780 100644 --- a/src/main/java/de/serosystems/lib1090/decoding/VelocityOverGround.java +++ b/src/main/java/de/serosystems/lib1090/decoding/VelocityOverGround.java @@ -15,16 +15,11 @@ private VelocityOverGround() {} */ public static float decodeAccuracyBound(byte navigationAccuracyCategory) { switch(navigationAccuracyCategory) { - case 1: - return 10; - case 2: - return 3; - case 3: - return 1; - case 4: - return 0.3f; - default: - return -1; + case 1: return 10; + case 2: return 3; + case 3: return 1; + case 4: return 0.3f; + default: return -1; } } }