Esempio n. 1
0
        private static bool BruteForceAP(ref ModeSMessage message)
        {
            var aux         = new byte[ModesLongMessageBytes];
            int messageType = message.MessageType;
            int messageBits = message.RawMessage.Length * 8;

            if (messageType != 0 && messageType != 4 && messageType != 5 && messageType != 16 && messageType != 20 &&
                messageType != 21 && messageType != 24)
            {
                return(false);
            }

            int lastByte = (messageBits / 8) - 1;

            Array.Copy(message.RawMessage, aux, messageBits / 8);

            // -- Compute the CRC of the message and XOR it with the AP field to recover the address.
            // -- (ADDR xor CRC) xor CRC = ADDR

            uint crc = Checksum(aux, messageBits);

            aux[lastByte]     ^= (byte)(crc & 0xff);
            aux[lastByte - 1] ^= (byte)((crc >> 8) & 0xff);
            aux[lastByte - 2] ^= (byte)((crc >> 16) & 0xff);

            var address = (uint)(aux[lastByte] | (aux[lastByte - 1] << 8) | (aux[lastByte - 2] << 16));

            if (!WasICAORecentlySeen(address))
            {
                return(false);
            }

            message.Aa1 = aux[lastByte - 2];
            message.Aa2 = aux[lastByte - 1];
            message.Aa3 = aux[lastByte];

            return(true);
        }
Esempio n. 2
0
        public static ModeSMessage DecodeMessage(byte[] message)
        {
            var result = new ModeSMessage();

            // -- Get the message type first.
            result.MessageType = message[0] >> 3; /* Downlink Format */
            result.RawMessage  = new byte[GetMessageLength(result.MessageType)];
            result.Crc         = Checksum1(message, result.RawMessage.Length * 8);
            uint crc2 = Checksum(message, result.RawMessage.Length * 8);

            Array.Copy(message, result.RawMessage, result.RawMessage.Length);

            result.ErrorBit = -1;
            result.IsCrcOk  = (result.Crc == crc2);

            // -- Error correction
            if (!result.IsCrcOk && FixErrors && (result.MessageType == 11 || result.MessageType == 17))
            {
                result.ErrorBit = FixSingleBitErrors(ref result.RawMessage, result.RawMessage.Length * 8);
                if (result.ErrorBit != -1)
                {
                    result.Crc     = Checksum(result.RawMessage, result.RawMessage.Length * 8);
                    result.IsCrcOk = true;
                }
            }

            result.Ca   = message[0] & 7; // -- Capabilities
            result.Aa1  = message[1];     // -- ICAO address
            result.Aa2  = message[2];
            result.Aa3  = message[3];
            result.ICAO = (uint)((result.Aa1 << 16) | (result.Aa2 << 8) | (result.Aa3));

            // -- DF-17 Type
            result.MessageTypeExtended = message[4] >> 3;
            result.MessageSubType      = message[4] & 7;

            // -- Fields for DF4,5,20,21.
            result.FlightStatus    = message[0] & 7;
            result.DownlinkRequest = message[1] >> 3 & 31;
            result.UtilityMessage  = ((message[1] & 7) << 3) | message[2] >> 5;

            { // -- squawk  decoding.
                int a, b, c, d;

                a = ((message[3] & 0x80) >> 5) |
                    ((message[2] & 0x02) >> 0) |
                    ((message[2] & 0x08) >> 3);
                b = ((message[3] & 0x02) << 1) |
                    ((message[3] & 0x08) >> 2) |
                    ((message[3] & 0x20) >> 5);
                c = ((message[2] & 0x01) << 2) |
                    ((message[2] & 0x04) >> 1) |
                    ((message[2] & 0x10) >> 4);
                d = ((message[3] & 0x01) << 2) |
                    ((message[3] & 0x04) >> 1) |
                    ((message[3] & 0x10) >> 4);

                result.Identity = a * 1000 + b * 100 + c * 10 + d;
            }

            // -- DF 11 & 17; Populate ICAO Whitelist. For DFs with an AP field, try to decode it.
            if (result.MessageType != 11 && result.MessageType != 17)
            {
                result.IsCrcOk = BruteForceAP(ref result);
            }
            else
            {
                // -- If this is DF11 or 17 and checksum is ok, we can add this to list of recently seen.
                if (result.IsCrcOk && result.ErrorBit == -1)
                {
                    var address = (uint)result.ICAO;
                    AddRecentlySeenICAOAddress(address);
                }
            }

            // -- Decode 13 bit altitude for DF0,16,20
            if (result.MessageType == 0 || result.MessageType == 4 || result.MessageType == 16 ||
                result.MessageType == 20)
            {
                var altitudeUnit = 0;
                result.Altitude = DecodeAC13Field(result.RawMessage, ref altitudeUnit);
                result.Unit     = altitudeUnit;
            }

            // -- Extended squitter specific stuff
            if (result.MessageType == 17)
            {
                if (result.MessageTypeExtended >= 1 && result.MessageTypeExtended <= 4)
                {
                    // -- Aircraft Flight Information
                    result.AircraftType = result.MessageTypeExtended - 1;
                    result.Flight       = GetAircraftIdentifier(message);
                }
                else if (result.MessageTypeExtended >= 9 && result.MessageTypeExtended <= 18)
                {
                    // -- Position message
                    var positionUnit = 0;
                    result.Fflag       = message[6] & (1 << 2);
                    result.Tflag       = message[6] & (1 << 3);
                    result.Altitude    = DecodeAC12Field(message, ref positionUnit);
                    result.RawLatitude = ((message[6] & 3) << 15) |
                                         (message[7] << 7) |
                                         (message[8] >> 1);
                    result.RawLongitude = ((message[8] & 1) << 16) |
                                          (message[9] << 8) |
                                          message[10];
                }
                else if (result.MessageTypeExtended == 19 && result.MessageSubType >= 1 &&
                         result.MessageSubType <= 4)
                {
                    // -- Velocity Message
                }
                else if (result.MessageSubType == 3 || result.MessageSubType == 4)
                {
                    // -- Heading message.
                    result.HeadingIsValid = (message[5] & (1 << 2)) > 0;
                    result.Heading        = (int)((360.0 / 128) * (((message[5] & 3) << 5) | (message[6] >> 3)));
                }
            }

            result.IsPhaseCorrected = false;
            return(result);
        }