private string DecodeVelocityOverGroundMsg(ModeSReply msg, DateTime timestamp) { VelocityOverGroundMsg velocity = (VelocityOverGroundMsg)msg; if (msg.ICAO24 == null) { return("VelocityOverGroundMsg: No ICAO24 found."); } string icao24 = BitConverter.ToString(msg.ICAO24).Replace("-", String.Empty); // check if ICAO is already stored in lookup table ADSBInfo info = null; if (!adsbinfos.TryGetValue(icao24, out info)) { // no --> add new entry info = new ADSBInfo(); info.ICAO24 = icao24; adsbinfos.Add(icao24, info); } // add information if (velocity.HasValidVelocity) { info.Speed = velocity.Velocity; } if (velocity.HasValidHeading) { info.Heading = velocity.Heading; } return("[" + info.ICAO24 + "] VelocityOverGroundMsg: Speed=" + info.Speed.ToString() + ", Heading= " + info.Heading.ToString()); }
public string DecodeMessage(string raw_msg, DateTime timestamp) { // decode an ADS-B message and add information to list // cut off first and last character raw_msg = raw_msg.Substring(1, raw_msg.Length - 2); // do generic decoding first ModeSReply msg = LibADSB.Decoder.GenericDecoder(raw_msg); if (!msg.CheckParity) { return("Parity error, no decode."); } // parity is OK, let's start to sort the messages and calculate // Console.WriteLine(msg.ToString()); // lock adsbinfolist lock (adsbinfos) { try { if (msg.GetType() == typeof(IdentificationMsg)) { // Identification message; return(DecodeIdentificationMsg(msg, timestamp)); } else if (msg.GetType() == typeof(AirbornePositionMsg)) { // Airborne position message return(DecodeAirbornePositionMsg(msg, timestamp)); } else if (msg.GetType() == typeof(VelocityOverGroundMsg)) { // Velocity over ground message return(DecodeVelocityOverGroundMsg(msg, timestamp)); } else if (msg.GetType() == typeof(AirspeedHeadingMsg)) { // Airspeed heading message return(DecodeAirspeedHeadingMsg(msg, timestamp)); } } catch (Exception ex) { string s = msg.GetType().ToString(); return("Error while decoding " + s + ": " + ex.Message); } } return("Unknown message."); }
private string DecodeIdentificationMsg(ModeSReply msg, DateTime timestamp) { IdentificationMsg ident = (IdentificationMsg)msg; if (msg.ICAO24 == null) { return("IdentifyMsg: No ICAO24 found."); } string icao24 = BitConverter.ToString(msg.ICAO24).Replace("-", String.Empty); // check if ICAO is already stored in lookup table ADSBInfo info = null; if (!adsbinfos.TryGetValue(icao24, out info)) { // no --> add new entry info = new ADSBInfo(); info.ICAO24 = icao24; adsbinfos.Add(icao24, info); } // add call sign info.Call = ident.getIdentity(); return("[" + info.ICAO24 + "] IdentificationMsg: Call=" + info.Call); }
private string DecodeAirbornePositionMsg(ModeSReply msg, DateTime timestamp) { // Airborne position message --> we need subsequent messages to decode AirbornePositionMsg pos = (AirbornePositionMsg)msg; if (msg.ICAO24 == null) { return("AirbornePositionMsg: No ICAO24 found."); } string icao24 = BitConverter.ToString(msg.ICAO24).Replace("-", String.Empty); // check if ICAO is already stored in lookup table ADSBInfo info = null; if (!adsbinfos.TryGetValue(icao24, out info)) { // no --> add new entry info = new ADSBInfo(); info.ICAO24 = icao24; adsbinfos.Add(icao24, info); } // adsbinfo found --> update information and calculate position // contains valid position? if (!pos.HasValidPosition) { // no --> return error meesage return("[" + info.ICAO24 + "] AirbornePositionMsg: No valid position found."); } info.ICAO24 = icao24; info.NICSupplementA = pos.NICSupplementA; // position calculated before if (!double.IsNaN(info.Lat) & !double.IsNaN(info.Lon)) { try { // use local CPR double[] localpos = pos.getLocalPosition(info.Lat, info.Lon); // we have a pos --> store in info and update timestamp info.Lat = localpos[0]; info.Lon = localpos[1]; if (pos.HasValidAltitude) { info.Alt = pos.Altitude; } info.Timestamp = timestamp; return("[" + info.ICAO24 + "] AirbornePositionMsg: Lat= " + info.Lat.ToString("F8") + ", Lon=" + info.Lon.ToString("F8") + ", Alt= " + info.Alt.ToString() + ", Time= " + info.Timestamp.ToString("HH:mm:ss.fff")); } catch (Exception ex) { } } // no position calculated before if (pos.IsOddFormat) { try { // odd message info.LastOddAirborne = pos; info.LastOddTimestamp = DateTime.UtcNow; // check if even message was received before and not older than 10secs--> calculate global CPR if ((info.LastEvenAirborne != null) && ((info.LastOddTimestamp - info.LastOddTimestamp).TotalSeconds <= 10)) { try { double[] globalpos = pos.getGlobalPosition(info.LastEvenAirborne); // we have a position --> store in info and update timestamp info.Lat = globalpos[0]; info.Lon = globalpos[1]; if (pos.HasValidAltitude) { info.Alt = pos.Altitude; } // info.Timestamp = timestamp; return("[" + info.ICAO24 + "] AirbornePositionMsg: Lat= " + info.Lat.ToString("F8") + ", Lon=" + info.Lon.ToString("F8") + ", Alt= " + info.Alt.ToString() + ", Time= " + info.Timestamp.ToString("HH:mm:ss.fff")); } catch { return("[" + info.ICAO24 + "] AirbornePositionMsg: Error while decoding position"); } } return("[" + info.ICAO24 + "] AirbornePositionMsg: No decoding possible yet"); } catch (Exception ex) { } } // even message info.LastEvenAirborne = pos; info.LastEvenTimestamp = DateTime.UtcNow; // check if odd message was received before and not older than 10secs --> calculate global CPR if ((info.LastOddAirborne != null) && ((info.LastEvenTimestamp - info.LastOddTimestamp).TotalSeconds <= 10)) { try { double[] globalpos = pos.getGlobalPosition(info.LastOddAirborne); // we have a position --> store in info and update timestamp info.Lat = globalpos[0]; info.Lon = globalpos[1]; if (pos.HasValidAltitude) { info.Alt = pos.Altitude; } // info.Timestamp = timestamp; return("[" + info.ICAO24 + "] AirbornePositionMsg: Lat= " + info.Lat.ToString("F8") + ", Lon=" + info.Lon.ToString("F8") + ", Alt= " + info.Alt.ToString() + ", Time= " + info.Timestamp.ToString("HH:mm:ss.fff")); } catch { return("[" + info.ICAO24 + "] AirbornePositionMsg: Error while decoding position"); } } else { return("[" + info.ICAO24 + "] AirbornePositionMsg:No decoding possible yet"); } }
/** * A top-down ADS-B decoder. Use instanceof to check for the message type. * @param raw_message The Mode S message in hex representation */ public static ModeSReply GenericDecoder(String raw_message) { ModeSReply modes = new ModeSReply(raw_message); // check parity; Note: some receivers set parity to 0 if (modes.IsZeroParity() || modes.CheckParity) { // check if it is an ADS-B message if (modes.DownlinkFormat == 17 || modes.DownlinkFormat == 18) { ExtendedSquitter es1090 = new ExtendedSquitter(raw_message); // what kind of extended squitter? byte ftc = es1090.FormatTypeCode; if (ftc >= 1 && ftc <= 4) // identification message { return(new IdentificationMsg(raw_message)); } if (ftc >= 5 && ftc <= 8) // surface position message { return(new SurfacePositionMsg(raw_message)); } if ((ftc >= 9 && ftc <= 18) || (ftc >= 20 && ftc <= 22)) // airborne position message { return(new AirbornePositionMsg(raw_message)); } if (ftc == 19) // possible velocity message, check subtype { int subtype = es1090.Message[0] & 0x7; if (subtype == 1 || subtype == 2) // velocity over ground { return(new VelocityOverGroundMsg(raw_message)); } else if (subtype == 3 || subtype == 4) // airspeed & heading { return(new AirspeedHeadingMsg(raw_message)); } } /* * if (ftc == 28) { // aircraft status message, check subtype * int subtype = es1090.getMessage()[0]&0x7; * * if (subtype == 1) // emergency/priority status * return new EmergencyOrPriorityStatusMsg(raw_message); * if (subtype == 2) // TCAS resolution advisory report * return new TCASResolutionAdvisoryMsg(raw_message); * } * * if (ftc == 31) { // operational status message * int subtype = es1090.getMessage()[0]&0x7; * * if (subtype == 0 || subtype == 1) // airborne or surface? * return new OperationalStatusMsg(raw_message); * } */ return(es1090); // unknown extended squitter } } return(modes); // unknown mode s reply }