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

de.serosystems.lib1090.msgs.modes.LongACAS Maven / Gradle / Ivy

package de.serosystems.lib1090.msgs.modes;

import de.serosystems.lib1090.exceptions.BadFormatException;
import de.serosystems.lib1090.exceptions.UnspecifiedFormatError;
import de.serosystems.lib1090.msgs.ModeSDownlinkMsg;

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 Mode S long air-air ACAS replies (DF 0)
 * @author Matthias Schäfer ([email protected])
 */
public class LongACAS extends ModeSDownlinkMsg implements Serializable {

	private static final long serialVersionUID = 1052613416840618986L;

	private boolean airborne;
	private byte sensitivity_level;
	private byte reply_information;
	private short altitude_code;
	private boolean valid_rac;
	private short active_resolution_advisories;
	private byte racs_record; // RAC = resolution advisory complement
	private boolean ra_terminated;
	private boolean multiple_threat_encounter;

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

	/**
	 * @param raw_message raw long air-to-air ACAS reply as hex string
	 * @throws BadFormatException if message is not long air-to-air ACAS reply or
	 * contains wrong values.
	 * @throws UnspecifiedFormatError if message has format that is not further specified in DO-260B
	 */
	public LongACAS(String raw_message) throws BadFormatException, UnspecifiedFormatError {
		this(new ModeSDownlinkMsg(raw_message));
	}

	/**
	 * @param raw_message raw long air-to-air ACAS reply as byte array
	 * @throws BadFormatException if message is not long air-to-air ACAS reply or
	 * contains wrong values.
	 * @throws UnspecifiedFormatError if message has format that is not further specified in DO-260B
	 */
	public LongACAS(byte[] raw_message) throws BadFormatException, UnspecifiedFormatError {
		this(new ModeSDownlinkMsg(raw_message));
	}

	/**
	 * @param reply Mode S reply containing this long air-to-air ACAS reply
	 * @throws BadFormatException if message is not long air-to-air ACAS reply or 
	 * contains wrong values.
	 */
	public LongACAS(ModeSDownlinkMsg reply) throws BadFormatException {
		super(reply);
		setType(subtype.LONG_ACAS);

		if (getDownlinkFormat() != 16) {
			throw new BadFormatException("Message is not a long ACAS (air-air) message!");
		}

		byte[] payload = getPayload();
		airborne = (getFirstField()&0x4)==0;
		sensitivity_level = (byte) ((payload[0]>>>5)&0x7);
		reply_information = (byte) ((payload[0]&0x7)<<1 | (payload[1]>>>7)&0x1);
		altitude_code = (short) ((payload[1]<<8 | payload[2]&0xFF)&0x1FFF);

		// extract MV/air-air coordination info; see Annex 10 Vol 4: 4.3.8.4.2.4
		valid_rac = payload[3] == 0x30;
		active_resolution_advisories = (short) ((payload[4]<<6 | (payload[5]>>>2)&0x3F)&0x3FFF);
		racs_record = (byte) ((payload[5]<<2 | (payload[6]>>>6)&0x3)&0xF);
		ra_terminated = (payload[6]>>>5&0x1) == 1;
		multiple_threat_encounter = (payload[6]>>>4&0x1) == 1;
	}

	/**
	 * Important note: check this before using any of
	 * {@link #getActiveResolutionAdvisories()},
	 * {@link #noPassBelow()}, {@link #noPassAbove()},
	 * {@link #noTurnLeft()}, {@link #noTurnRight()},
	 * {@link #hasTerminated()}, {@link #hasMultipleThreats()}
	 * @return true if resolution advisory complement is valid
	 */
	public boolean hasValidRAC() {
		return valid_rac;
	}

	/**
	 * @return the binary encoded information about active
	 * resolution advisories (see Annex 10V4; 4.3.8.4.2.2.1.1)
	 */
	public short getActiveResolutionAdvisories() {
		return active_resolution_advisories;
	}

	/**
	 * @return the binary encoded resolution advisory complement
	 * @see #noPassBelow()
	 * @see #noPassAbove()
	 * @see #noTurnLeft()
	 * @see #noTurnRight()
	 */
	public byte getResolutionAdvisoryComplement() {
		return racs_record;
	}

	/**
	 * @return true iff do not pass below advisory is active
	 */
	public boolean noPassBelow() {
		return (racs_record&8)==8;
	}

	/**
	 * @return true iff do not pass above advisory is active
	 */
	public boolean noPassAbove() {
		return (racs_record&4)==4;
	}

	/**
	 * @return true iff do not turn left advisory is active
	 */
	public boolean noTurnLeft() {
		return (racs_record&2)==2;
	}

	/**
	 * @return true iff do not turn right advisory is active
	 */
	public boolean noTurnRight() {
		return (racs_record&1)==1;
	}


	/**
	 * @return true if aircraft is airborne, false if it is on the ground
	 */
	public boolean isAirborne() {
		return airborne;
	}

	/**
	 * @return true iff the RA from {@link #getActiveResolutionAdvisories()} has been terminated
	 */
	public boolean hasTerminated() {
		return ra_terminated;
	}

	/**
	 * @return true iff two or more threats are being processed
	 */
	public boolean hasMultipleThreats() {
		return multiple_threat_encounter;
	}

	/**
	 * @return the sensitivity level at which ACAS is currently operating
	 */
	public byte getSensitivityLevel() {
		return sensitivity_level;
	}

	/**
	 * This field is used to report the aircraft's maximum cruising 
	 * true airspeed capability and type of reply to interrogating aircraft
	 * @return the air-to-air reply information according to 3.1.2.8.2.2
	 * @see #getMaximumAirspeed()
	 * @see #hasOperatingACAS()
	 */
	public byte getReplyInformation() {
		return reply_information;
	}

	/**
	 * @return whether a/c has operating ACARS (derived from reply information)
	 * @see #getReplyInformation()
	 */
	public boolean hasOperatingACAS() {
		return getReplyInformation() != 0;
	}

	/**
	 * @return the maximum airspeed in kt as specified in ICAO Annex 10V4 3.1.2.8.2.2
* null if unknown
Integer.MAX_VALUE if unbound */ public Integer getMaximumAirspeed() { return ShortACAS.decodeMaximumAirspeed(getReplyInformation()); } /** * @return The 13 bits altitude code (see ICAO Annex 10 V4) */ public short getAltitudeCode() { return altitude_code; } /** * @return the decoded altitude in feet */ public Integer getAltitude() { return AltitudeReply.decodeAltitude(altitude_code); } @Override public String toString() { return super.toString() + "\n\tLongACAS{" + "airborne=" + airborne + ", sensitivity_level=" + sensitivity_level + ", reply_information=" + reply_information + ", altitude_code=" + altitude_code + ", valid_rac=" + valid_rac + ", active_resolution_advisories=" + active_resolution_advisories + ", racs_record=" + racs_record + ", ra_terminated=" + ra_terminated + ", multiple_threat_encounter=" + multiple_threat_encounter + '}'; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy