All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.serosystems.lib1090.msgs.adsb.AirborneOperationalStatusV1Msg Maven / Gradle / Ivy

package de.serosystems.lib1090.msgs.adsb;

import de.serosystems.lib1090.exceptions.BadFormatException;
import de.serosystems.lib1090.exceptions.UnspecifiedFormatError;
import de.serosystems.lib1090.msgs.modes.ExtendedSquitter;

import java.io.Serializable;

/*
 *  This file is part of de.serosystems.lib1090.
 *
 *  de.serosystems.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.
 *
 *  de.serosystems.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 .
 */

/**
 * Decoder for ADS-B operational status message as specified in DO-260A (ADS-B version 1) with
 * subtype 0 (airborne)
 * @author Matthias Schäfer ([email protected])
 */
public class AirborneOperationalStatusV1Msg extends ExtendedSquitter implements Serializable {

	private static final long serialVersionUID = -4371842571556132611L;

	private byte subtype_code;
	private int capability_class_code; // actually 16 bit unsigned
	private int operational_mode_code; // actually 16 bit unsigned
	private byte version;
	private boolean nic_suppl; // may be passed to position messages
	private byte nac_pos; // navigational accuracy category - position
	private byte geometric_vertical_accuracy; // bit 49 and 50
	private byte sil; // surveillance integrity level
	private boolean nic_trk_hdg; // NIC baro for airborne status, heading/ground track info else
	private boolean hrd; // heading info is based on true north (0) or magnetic north (1)

	/** protected no-arg constructor e.g. for serialization with Kryo **/
	protected AirborneOperationalStatusV1Msg() { }

	/**
	 * @param raw_message The full Mode S message in hex representation
	 * @throws BadFormatException if message has the wrong typecode or ADS-B version
	 * @throws UnspecifiedFormatError if message has the wrong subtype
	 */
	public AirborneOperationalStatusV1Msg(String raw_message) throws BadFormatException, UnspecifiedFormatError {
		this(new ExtendedSquitter(raw_message));
	}

	/**
	 * @param raw_message The full Mode S message as byte array
	 * @throws BadFormatException if message has the wrong typecode or ADS-B version
	 * @throws UnspecifiedFormatError if message has the wrong subtype
	 */
	public AirborneOperationalStatusV1Msg(byte[] raw_message) throws BadFormatException, UnspecifiedFormatError {
		this(new ExtendedSquitter(raw_message));
	}

	/**
	 * @param squitter extended squitter which contains this message
	 * @throws BadFormatException  if message has the wrong typecode or ADS-B version or is not an airborne
	 * 								operational status message or the capability code is invalid.
	 * @throws UnspecifiedFormatError if message has the wrong subtype
	 */
	public AirborneOperationalStatusV1Msg(ExtendedSquitter squitter) throws BadFormatException, UnspecifiedFormatError {
		super(squitter);
		setType(subtype.ADSB_AIRBORN_STATUS_V1);

		if (getFormatTypeCode() != 31) {
			throw new BadFormatException("Operational status messages must have typecode 31.");
		}

		byte[] msg = this.getMessage();

		subtype_code = (byte)(msg[0] & 0x7);
		if (subtype_code > 1) // currently only 0 and 1 specified, 2-7 are reserved
			throw new UnspecifiedFormatError("Operational status message subtype "+subtype_code+" reserved.");

		capability_class_code = (msg[1]<<8)|msg[2];
		if (subtype_code != 0) {
			throw new BadFormatException("Not an airborne operational status message");
		}
		operational_mode_code = (msg[3]<<8)|msg[4];
		version = (byte) ((msg[5]>>>5) & 0x07);

		if ((capability_class_code & 0xC000) != 0)
			throw new BadFormatException("Unknown capability class code!");

		nic_suppl = ((msg[5] & 0x10) != 0);
		nac_pos = (byte) (msg[5] & 0xF);
		geometric_vertical_accuracy = (byte) ((msg[6] >>> 6) & 0x3);
		sil = (byte) ((msg[6]>>>4)&0x3);
		nic_trk_hdg = ((msg[6] & 0x8) != 0);
		hrd = ((msg[6] & 0x4) != 0);
	}

	/**
	 * @return whether operational TCAS is available
	 */
	public boolean hasOperationalTCAS() {
		return (capability_class_code & 0x2000) != 0;
	}

	/**
	 * @return whether 1090ES IN is available
	 */
	public boolean has1090ESIn() {
		return (capability_class_code & 0x1000) != 0;
	}

	/**
	 * @return whether aircraft has capability of sending messages to support Air-Referenced
	 *         Velocity Reports
	 */
	public boolean hasAirReferencedVelocity() {
		return (capability_class_code & 0x200) != 0;
	}

	/**
	 * @return whether aircraft has capability of sending messages to support Target
	 *         State Reports
	 */
	public boolean hasTargetStateReport() {
		return (capability_class_code & 0x100) != 0;
	}

	/**
	 * @return whether target change reports are supported
	 */
	public boolean supportsTargetChangeReport() {
		byte target_change_report_capability = (byte) ((capability_class_code & 0xC0)>>>6);
		return target_change_report_capability == 1 || target_change_report_capability == 2;
	}

	/**
	 * @return whether aircraft has an UAT receiver
	 */
	public boolean hasUATIn() {
		return (capability_class_code & 0x20) != 0;
	}

	/**
	 * @return whether TCAS Resolution Advisory (RA) is active
	 */
	public boolean hasTCASResolutionAdvisory() {
		return (operational_mode_code&0x2000) != 0;
	}

	/**
	 * @return whether the IDENT switch is active
	 */
	public boolean hasActiveIDENTSwitch() {
		return (operational_mode_code&0x1000) != 0;
	}

	/**
	 * @return whether aircraft uses a single antenna or two
	 */
	public boolean hasSingleAntenna() {
		return (operational_mode_code&0x400) != 0;
	}

	/**
	 * For interpretation see Table 2-65 in DO-260B
	 * @return system design assurance (see A.1.4.10.14 in RTCA DO-260B)
	 */
	public byte getSystemDesignAssurance() {
		return (byte) ((operational_mode_code&0x300)>>>8);
	}

	/**
	 * @return the version number of the formats and protocols in use on the aircraft installation.
* 0: Conformant to DO-260/ED-102 and DO-242
* 1: Conformant to DO-260A and DO-242A
* 2: Conformant to DO-260B/ED-102A and DO-242B
* 3-7: reserved */ public byte getVersion() { return version; } /** * @return the NIC supplement A to the format type code of position messages */ public boolean hasNICSupplementA() { return nic_suppl; } /** * @return the navigation accuracy for position messages; rather use getPositionUncertainty */ public byte getNACp() { return nac_pos; } /** * 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 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 the geometric vertical accuracy in meters or -1 for unknown */ public int getGeometricVerticalAccuracy() { if (geometric_vertical_accuracy == 1) return 150; else if (geometric_vertical_accuracy == 2) return 45; else return -1; } /** * @return the encoded geometric vertical accuracy (see DO-260B 2.2.3.2.7.2.8) */ public byte getGVA() { return geometric_vertical_accuracy; } /** * @return the source integrity level (SIL) which indicates the propability of exceeding * the NIC containment radius (see table A-15 in RCTA DO-260B) */ public byte getSIL() { return sil; } /** * @return the barometric altitude integrity code which indicates whether * barometric pressure altitude has been cross-checked against other * sources of pressure altitude. If false, altitude data has not been * cross-checked. */ public boolean getBarometricAltitudeIntegrityCode() { return nic_trk_hdg; } /** * @return 0 if horizontal reference direction is the true north, 1 if magnetic north */ public boolean getHorizontalReferenceDirection() { return hrd; } @Override public String toString() { return super.toString() + "\n\tAirborneOperationalStatusV1Msg{" + "subtype_code=" + subtype_code + ", capability_class_code=" + capability_class_code + ", operational_mode_code=" + operational_mode_code + ", version=" + version + ", nic_suppl=" + nic_suppl + ", nac_pos=" + nac_pos + ", geometric_vertical_accuracy=" + geometric_vertical_accuracy + ", sil=" + sil + ", nic_trk_hdg=" + nic_trk_hdg + ", hrd=" + hrd + '}'; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy