Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/main/java/de/serosystems/example/ExampleDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,8 @@ public void decodeMsg(long timestamp, String raw, Position receiver) {
System.out.println(" Has IFR capability: " + veloc.hasIFRCapability());

break;
case ADSB_TARGET_STATE_AND_STATUS:
case ADSB_TARGET_STATE_AND_STATUS_V1:
case ADSB_TARGET_STATE_AND_STATUS_V2:
System.out.println("["+icao24+"]: Target State and Status reported");
if (msg instanceof TargetStateAndStatusV1Msg) {
TargetStateAndStatusV1Msg tStatus = (TargetStateAndStatusV1Msg) msg;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ public enum subtype {
ADSB_SURFACE_STATUS_V1,
ADSB_AIRBORN_STATUS_V2,
ADSB_SURFACE_STATUS_V2,
ADSB_TARGET_STATE_AND_STATUS,
ADSB_TARGET_STATE_AND_STATUS_V1,
ADSB_TARGET_STATE_AND_STATUS_V2,
SURFACE_SYSTEM_STATUS,

// TIS-B subtypes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
*
* @author Matthias Schäfer (schaefer@sero-systems.de)
*/
public class AirborneOperationalStatusV1Msg extends ExtendedSquitter implements Serializable {
public class AirborneOperationalStatusV1Msg extends ExtendedSquitter implements Serializable, OperationalStatusV1Msg {

private static final long serialVersionUID = -4371842571556132611L;
private static final byte SUBTYPE_CODE = 0;

private byte subtype_code;
protected int capability_class_code; // actually 16 bit unsigned
protected int operational_mode_code; // actually 16 bit unsigned
private byte version;
Expand Down Expand Up @@ -90,10 +90,10 @@ public AirborneOperationalStatusV1Msg(ExtendedSquitter squitter) throws BadForma

BitReader b = BitReader.forBigEndian(msg);

subtype_code = b.readByte(6, 8);
if (subtype_code > 1) { // currently only 0 and 1 specified, 2-7 are reserved
throw new UnspecifiedFormatError("Operational status message subtype " + subtype_code + " reserved.");
} else if (subtype_code != 0) {
byte subtypeCode = b.readByte(6, 8);
if (subtypeCode > 1) { // currently only 0 and 1 specified, 2-7 are reserved
throw new UnspecifiedFormatError("Operational status message subtype " + subtypeCode + " reserved.");
} else if (subtypeCode != SUBTYPE_CODE) {
throw new BadFormatException("Not an airborne operational status message");
}

Expand All @@ -115,6 +115,14 @@ public AirborneOperationalStatusV1Msg(ExtendedSquitter squitter) throws BadForma
hrd = b.readByte(54, 54) == 1;
}

/**
* @return the subtype code, 0 for airborne operational status messages
*/
@Override
public byte getSubtypeCode() {
return SUBTYPE_CODE;
}

/**
* @return true if TCAS is operational or unknown, false if TCAS is not operational.
*/
Expand Down Expand Up @@ -258,7 +266,6 @@ public boolean getHorizontalReferenceDirection() {
@Override
public String toString() {
return "AirborneOperationalStatusV1Msg{" +
"subtype_code=" + subtype_code +
", capability_class_code=" + capability_class_code +
", operational_mode_code=" + operational_mode_code +
", version=" + version +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
/**
* @author Markus Fuchs (fuchs@opensky-network.org)
*/
public class AirborneOperationalStatusV2Msg extends AirborneOperationalStatusV1Msg implements Serializable {
public class AirborneOperationalStatusV2Msg extends AirborneOperationalStatusV1Msg implements Serializable, OperationalStatusV2Msg {

private static final long serialVersionUID = -2032348919695227545L;

Expand Down Expand Up @@ -87,13 +87,15 @@ public boolean hasOperationalTCAS() {
/**
* @return whether aircraft has an UAT receiver
*/
@Override
public boolean hasUATIn() {
return (capability_class_code & 0x20) != 0;
}

/**
* @return whether aircraft uses a single antenna or two
*/
@Override
public boolean hasSingleAntenna() {
return (operational_mode_code & 0x400) != 0;
}
Expand Down Expand Up @@ -121,6 +123,7 @@ else if (geometric_vertical_accuracy == 2)
*
* @return system design assurance (see A.1.4.10.14 in RTCA DO-260B)
*/
@Override
public byte getSystemDesignAssurance() {
return (byte) ((operational_mode_code & 0x300) >>> 8);
}
Expand All @@ -131,6 +134,7 @@ public byte getSystemDesignAssurance() {
* @return true if SIL (Source Integrity Level) is based on "per sample" probability, otherwise
* it's based on "per hour".
*/
@Override
public boolean hasSILSupplement() {
return sil_supplement;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class AirspeedHeadingMsg extends ExtendedSquitter implements Serializable
private boolean ifr_capability;
private byte navigation_accuracy_category;
private boolean heading_status_bit;
private double heading; // in degrees
private short heading; // raw value
private boolean true_airspeed; // 0 = indicated AS, 1 = true AS
private short airspeed; // in knots
private boolean airspeed_available;
Expand Down Expand Up @@ -98,7 +98,7 @@ public AirspeedHeadingMsg(ExtendedSquitter squitter) throws BadFormatException {

// heading available
heading_status_bit = (msg[1]&0x4)>0;
heading = ((msg[1]&0x3)<<8 | msg[2]&0xFF) * 360./1024.;
heading = (short) (((msg[1]&0x3)<<8) | (msg[2]&0xFF));

true_airspeed = (msg[3]&0x80)>0;
airspeed = (short) (((msg[3]&0x7F)<<3 | msg[4]>>>5&0x07)-1);
Expand Down Expand Up @@ -205,13 +205,21 @@ public Integer getGeoMinusBaro() {
return geo_minus_baro;
}

/**
* @return raw heading field value (10 bit). Check {@link #hasHeadingStatusFlag()} to determine whether this value
* is valid.
*/
public int getHeadingRaw() {
return heading;
}

/**
* @return heading in decimal degrees ([0, 360]). 0° = geographic north or null if no information is available.
* The latter can also be checked using {@link #hasHeadingStatusFlag()}.
*/
public Double getHeading() {
if (!heading_status_bit) return null;
return heading;
return heading * 360. / 1024.;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* This file is part of lib1090.
* Copyright (C) 2026 SeRo Systems GmbH
*
* lib1090 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lib1090 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with de.serosystems.lib1090. If not, see <http://www.gnu.org/licenses/>.
*/

package de.serosystems.lib1090.msgs.adsb;

/**
* Common API for ADS-B operational status messages.
*/
public interface OperationalStatusMsg {

/**
* @return whether 1090ES IN is available
*/
boolean has1090ESIn();

/**
* @return the version number of the formats and protocols in use on the aircraft installation
*/
byte getVersion();
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*
* @author Markus Fuchs (fuchs@opensky-network.org)
*/
public class OperationalStatusV0Msg extends ExtendedSquitter implements Serializable {
public class OperationalStatusV0Msg extends ExtendedSquitter implements Serializable, OperationalStatusMsg {

private static final long serialVersionUID = -8925123066831152922L;

Expand Down Expand Up @@ -106,6 +106,15 @@ public boolean hasOperationalCDTI() {
return (enroute_capabilities & 0x10) != 0;
}

/**
* @return whether 1090ES IN is available
* @see #hasOperationalCDTI() alias: the field has been renamed in V1
*/
@Override
public boolean has1090ESIn() {
return hasOperationalCDTI();
}

/**
* the version number of the formats and protocols in use on the aircraft installation.<br>
* 0: Conformant to DO-260/ED-102 and DO-242<br>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* This file is part of lib1090.
* Copyright (C) 2026 SeRo Systems GmbH
*
* lib1090 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lib1090 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with de.serosystems.lib1090. If not, see <http://www.gnu.org/licenses/>.
*/

package de.serosystems.lib1090.msgs.adsb;

import de.serosystems.lib1090.decoding.OperationalStatus;

/**
* Common API for ADS-B operational status version 1 messages.
*/
public interface OperationalStatusV1Msg extends OperationalStatusMsg {

/**
* @return the subtype code, 0 for airborne operational status messages and 1 for surface operational status messages
*/
byte getSubtypeCode();

/**
* @return the NIC supplement A to the format type code of position messages
*/
boolean hasNICSupplementA();

/**
* @return the navigation accuracy for position messages; rather use getPositionUncertainty
*/
byte getNACp();

/**
* Get the 95% horizontal accuracy bounds (EPU) derived from NACp value.
*
* @return the estimated position uncertainty according to the position NAC in meters (-1 for unknown)
*/
default double getPositionUncertainty() {
return OperationalStatus.nacPtoEPU(getNACp());
}

/**
* @return the source integrity level (SIL)
*/
byte getSIL();

/**
* @return whether TCAS Resolution Advisory (RA) is active
*/
boolean hasTCASResolutionAdvisory();

/**
* @return whether the IDENT switch is active
*/
boolean hasActiveIDENTSwitch();

/**
* @return whether ADS-B Transmitting Subsystem is receiving ATC services.
*/
boolean hasReceivingATCServices();

/**
* @return 0 if horizontal reference direction is the true north, 1 if magnetic north
*/
boolean getHorizontalReferenceDirection();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* This file is part of lib1090.
* Copyright (C) 2026 SeRo Systems GmbH
*
* lib1090 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lib1090 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with de.serosystems.lib1090. If not, see <http://www.gnu.org/licenses/>.
*/

package de.serosystems.lib1090.msgs.adsb;

/**
* Common API for ADS-B operational status version 2 messages.
*/
public interface OperationalStatusV2Msg extends OperationalStatusV1Msg {

/**
* @return whether aircraft has an UAT receiver
*/
boolean hasUATIn();

/**
* @return whether aircraft uses a single antenna or two
*/
boolean hasSingleAntenna();

/**
* For interpretation see Table 2-65 in DO-260B
*
* @return system design assurance (see A.1.4.10.14 in RTCA DO-260B)
*/
byte getSystemDesignAssurance();

/**
* DO-260B 2.2.3.2.7.2.14
*
* @return true if SIL (Source Integrity Level) is based on "per sample" probability, otherwise
* it's based on "per hour".
*/
boolean hasSILSupplement();
}
Loading
Loading