AirScout/LibADSB/AirspeedHeadingMsg.cs

259 wiersze
7.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace LibADSB
{
public class AirspeedHeadingMsg : ExtendedSquitter
{
[Browsable(false)]
[DescriptionAttribute("Heading is availble in Airspeed Heading Message")]
public bool HasValidHeading
{
get
{
return heading_available;
}
}
[Browsable(false)]
[DescriptionAttribute("Heading in Airspeed Heading Message [kts]")]
public int Heading
{
get
{
return heading;
}
}
[Browsable(false)]
[DescriptionAttribute("Airspeed is availble in Airspeed Heading Message")]
public bool HasValidAirspeed
{
get
{
return airspeed_available;
}
}
[Browsable(false)]
[DescriptionAttribute("Airspeed is true airspeed in Airspeed Heading Message")]
public bool IsTrueAirspeed
{
get
{
return true_airspeed;
}
}
[Browsable(false)]
[DescriptionAttribute("Airspeed in Airspeed Heading Message [kts]")]
public int Airspeed
{
get
{
return airspeed;
}
}
[Browsable(false)]
[DescriptionAttribute("Heading is availble in Airspeed Heading Message")]
public bool IsBarometricVerticalSpeed
{
get
{
return vertical_source;
}
}
[Browsable(false)]
[DescriptionAttribute("Vertical rate is availble in Airspeed Heading Message")]
public bool HasValidVerticalRate
{
get
{
return vertical_rate_info_available;
}
}
[Browsable(false)]
[DescriptionAttribute("Vertical rate in Airspeed Heading Message")]
public int VerticalRate
{
get
{
return vertical_rate;
}
}
[Browsable(false)]
[DescriptionAttribute("Vertical source in Airspeed Heading Message")]
public bool VerticalSource
{
get
{
return vertical_source;
}
}
[Browsable(false)]
[DescriptionAttribute("Vertical rate DOWN in Airspeed Heading Message")]
public bool VerticalRateDown
{
get
{
return vertical_rate_down;
}
}
[Browsable(false)]
[DescriptionAttribute("GeoMinusBaro is available in Airspeed Heading Message")]
public bool HasGeoMinusBaro
{
get
{
return geo_minus_baro_available;
}
}
[Browsable(false)]
[DescriptionAttribute("GeoMinusBaro in Airspeed Heading Message [ft]")]
public int GeoMinusBaro
{
get
{
return geo_minus_baro;
}
}
private byte subtype;
private bool intent_change;
private bool ifr_capability;
private byte navigation_accuracy_category;
private bool heading_available;
private int heading; // in degrees
private bool true_airspeed; // 0 = indicated AS, 1 = true AS
private int airspeed; // in knots
private bool airspeed_available;
private bool vertical_source; // 0 = geometric, 1 = barometric
private bool vertical_rate_down; // 0 = up, 1 = down
private int vertical_rate; // in ft/s
private bool vertical_rate_info_available;
private int geo_minus_baro; // in ft
private bool geo_minus_baro_available;
/**
* @param raw_message raw ADS-B airspeed and heading message as hex string
* @throws BadFormatException if message has wrong format
*/
public AirspeedHeadingMsg(string raw_message)
: base(raw_message)
{
if (this.FormatTypeCode != 19)
{
throw new BadFormatException("Airspeed and heading messages must have typecode 19: " + raw_message);
}
byte[] msg = this.Message;
subtype = (byte) (msg[0]&0x7);
if (subtype != 3 && subtype != 4)
{
throw new BadFormatException("Airspeed and heading messages have subtype 3 or 4: " + raw_message);
}
intent_change = (msg[1]&0x80)>0;
ifr_capability = (msg[1]&0x40)>0;
navigation_accuracy_category = (byte) ((msg[1]>>3)&0x7);
// check this later
vertical_rate_info_available = true;
geo_minus_baro_available = true;
heading_available = (msg[1]&0x4)>0;
heading = (int)(((msg[1]&0x3)<<8 | msg[2]&0xFF) * 360.0/1024.0);
true_airspeed = (msg[3]&0x80)>0;
airspeed = (short) (((msg[3]&0x7F)<<3 | msg[4]>>5&0x07)-1);
if (airspeed == -1) airspeed_available = false;
if (subtype == 2) airspeed<<=2;
vertical_source = (msg[4]&0x10)>0;
vertical_rate_down = (msg[4]&0x08)>0;
vertical_rate = (short) ((((msg[4]&0x07)<<6 | msg[5]>>2&0x3F)-1)<<6);
if (vertical_rate == -1) vertical_rate_info_available = false;
geo_minus_baro = (short) (((msg[6]&0x7F)-1)*25);
if (geo_minus_baro == -1) geo_minus_baro_available = false;
if ((msg[6]&0x80)>0) geo_minus_baro *= -1;
}
/**
* Must be checked before accessing geo minus baro!
*
* @return whether geo-baro difference info is available
*/
public bool hasGeoMinusBaroInfo() {
return geo_minus_baro_available;
}
/**
* @return If supersonic, velocity has only 4 kts accuracy, otherwise 1 kt
*/
public bool isSupersonic() {
return subtype == 4;
}
/**
* @return true, if aircraft wants to change altitude for instance
*/
public bool hasChangeIntent() {
return intent_change;
}
/**
* Note: only in ADS-B version 1 transponders!!
* @return true, iff aircraft has equipage class A1 or higher
*/
public bool hasIFRCapability() {
return ifr_capability;
}
/**
* @return NAC according to RTCA DO-260A
*/
public byte getNavigationAccuracyCategory() {
return navigation_accuracy_category;
}
/**
* @return difference between barometric and geometric altitude in m
* @throws MissingInformationException if no geo/baro difference info is available
*/
public double getGeoMinusBaro()
{
if (!geo_minus_baro_available) throw new MissingInformationException("No geo/baro difference info available!");
return geo_minus_baro * 0.3048;
}
public override string ToString() {
string ret = base.ToString()+"\n"+
"Airspeed and heading:\n";
try { ret += "\tAirspeed:\t"+Airspeed+" kts\n"; }
catch (Exception e) { ret += "\tAirspeed:\t\tnot available\n"; }
ret += "\tAirspeed Type:\t\t"+(IsTrueAirspeed ? "true" : "indicated")+"\n";
try { ret += "\tHeading\t\t\t\t"+Heading+"\n"; }
catch (Exception e) { ret += "\tHeading\t\t\t\tnot available\n"; }
try { ret += "\tVertical rate:\t\t\t"+VerticalRate; }
catch (Exception e) { ret += "\tVertical rate:\t\t\tnot available"; }
return ret;
}
}
}