/// <summary>
        /// Translates the bytes for a Mode-S message into a cooked message object and causes a message received event to be raised on the background thread.
        /// </summary>
        /// <param name="now"></param>
        /// <param name="extractedBytes"></param>
        private void ProcessModeSMessageBytes(DateTime now, ExtractedBytes extractedBytes)
        {
            if (extractedBytes.Length == 7 || extractedBytes.Length == 14)
            {
                if (extractedBytes.HasParity)
                {
                    _ModeSParity.StripParity(extractedBytes.Bytes, extractedBytes.Offset, extractedBytes.Length);
                }

                try {
                    var modeSMessage = _ModeSMessageTranslator.Translate(extractedBytes.Bytes, extractedBytes.Offset);
                    if (modeSMessage != null)
                    {
                        bool hasPIField        = modeSMessage.ParityInterrogatorIdentifier != null;
                        bool isPIWithBadParity = hasPIField && modeSMessage.ParityInterrogatorIdentifier != 0;
                        var  adsbMessage       = _AdsbMessageTranslator.Translate(modeSMessage);

                        if ((hasPIField || isPIWithBadParity || adsbMessage == null) && _Statistics.Lock != null)
                        {
                            lock (_Statistics.Lock) {
                                if (hasPIField)
                                {
                                    ++_Statistics.ModeSWithPIField;
                                }
                                if (isPIWithBadParity)
                                {
                                    ++_Statistics.ModeSWithBadParityPIField;
                                }
                                if (adsbMessage == null)
                                {
                                    ++_Statistics.ModeSNotAdsbCount;
                                }
                            }
                        }

                        ++TotalMessages;
                        _MessageProcessingAndDispatchQueue.Enqueue(new MessageDispatch()
                        {
                            ModeSMessageEventArgs = new ModeSMessageEventArgs(now, modeSMessage, adsbMessage)
                        });
                    }
                } catch (Exception) {
                    ++TotalBadMessages;
                    if (!IgnoreBadMessages)
                    {
                        throw;
                    }
                }
            }
        }
Example #2
0
 public void ModeSTranslator_Translate_Throws_If_Statistics_Is_Not_Initialised()
 {
     _Translator.Statistics = null;
     _Translator.Translate(new byte[0], 0, null, false);
 }
Example #3
0
        /// <summary>
        /// Translates the bytes for a Mode-S message into a cooked message object and causes a message received event to be raised on the background thread.
        /// </summary>
        /// <param name="now"></param>
        /// <param name="extractedBytes"></param>
        private void ProcessModeSMessageBytes(DateTime now, ExtractedBytes extractedBytes)
        {
            if (extractedBytes.Length == 7 || extractedBytes.Length == 14)
            {
                if (extractedBytes.HasParity)
                {
                    _ModeSParity.StripParity(extractedBytes.Bytes, extractedBytes.Offset, extractedBytes.Length);
                }

                try {
                    var modeSMessage = _ModeSMessageTranslator.Translate(extractedBytes.Bytes, extractedBytes.Offset, extractedBytes.SignalLevel, extractedBytes.IsMlat);
                    if (modeSMessage != null)
                    {
                        bool hasPIField        = modeSMessage.ParityInterrogatorIdentifier != null;
                        bool isPIWithBadParity = hasPIField && modeSMessage.ParityInterrogatorIdentifier != 0;
                        var  adsbMessage       = _AdsbMessageTranslator.Translate(modeSMessage);

                        if ((hasPIField || isPIWithBadParity || adsbMessage == null) && Statistics != null)
                        {
                            Statistics.Lock(r => {
                                if (hasPIField)
                                {
                                    ++r.ModeSWithPIField;
                                }
                                if (isPIWithBadParity)
                                {
                                    ++r.ModeSWithBadParityPIField;
                                    ++r.ModeSDFStatistics[(int)modeSMessage.DownlinkFormat].BadParityPI;
                                }
                                if (adsbMessage == null)
                                {
                                    ++r.ModeSNotAdsbCount;
                                }
                            });
                        }

                        if (adsbMessage != null && modeSMessage.DownlinkFormat == DownlinkFormat.ExtendedSquitterNonTransponder)
                        {
                            if (adsbMessage.TisbIcaoModeAFlag == 0)
                            {
                                switch (modeSMessage.ControlField)
                                {
                                case ControlField.CoarseFormatTisb:
                                case ControlField.FineFormatTisb:
                                    modeSMessage.Icao24           = modeSMessage.NonIcao24Address.GetValueOrDefault();
                                    modeSMessage.NonIcao24Address = null;
                                    break;
                                }
                            }
                        }

                        ++TotalMessages;
                        _MessageProcessingAndDispatchQueue.Enqueue(new MessageDispatch()
                        {
                            ModeSMessageEventArgs = new ModeSMessageEventArgs(now, modeSMessage, adsbMessage)
                        });
                    }
                } catch (Exception) {
                    ++TotalBadMessages;
                    if (!IgnoreBadMessages)
                    {
                        throw;
                    }
                }
            }
        }
Example #4
0
        public void ModeSTranslator_Translate_Decodes_Packets_Correctly()
        {
            for (var conversionMethod = 0; conversionMethod < 2; ++conversionMethod)
            {
                var worksheet     = new ExcelWorksheetData(TestContext);
                var expectedValue = new SpreadsheetFieldValue(worksheet, 7);

                var bits  = worksheet.String("Packet");
                var bytes = TestUtilities.ConvertBitStringToBytes(bits);

                var reply = conversionMethod == 0 ? _Translator.Translate(bytes.ToArray()) : _Translator.Translate(bytes.ToArray(), 0);

                foreach (var replyProperty in reply.GetType().GetProperties())
                {
                    switch (replyProperty.Name)
                    {
                    case "ACASMessage":                          Assert.IsTrue(TestUtilities.SequenceEqual(expectedValue.GetBytes("MV"), reply.ACASMessage)); break;

                    case "Altitude":                             Assert.AreEqual(expectedValue.GetNInt("AC"), reply.Altitude); break;

                    case "AltitudeIsMetric":                     Assert.AreEqual(expectedValue.GetNBool("AC:M"), reply.AltitudeIsMetric); break;

                    case "ApplicationField":                     Assert.AreEqual(expectedValue.GetEnum <ApplicationField>("AF"), reply.ApplicationField); break;

                    case "Capability":                           Assert.AreEqual(expectedValue.GetEnum <Capability>("CA"), reply.Capability); break;

                    case "CommBMessage":                         Assert.IsTrue(TestUtilities.SequenceEqual(expectedValue.GetBytes("MB"), reply.CommBMessage)); break;

                    case "CommDMessage":                         Assert.IsTrue(TestUtilities.SequenceEqual(expectedValue.GetBytes("MD"), reply.CommDMessage)); break;

                    case "ControlField":                         Assert.AreEqual(expectedValue.GetEnum <ControlField>("CF"), reply.ControlField); break;

                    case "CrossLinkCapability":                  Assert.AreEqual(expectedValue.GetNBool("CC"), reply.CrossLinkCapability); break;

                    case "DownlinkFormat":                       Assert.AreEqual(worksheet.ParseEnum <DownlinkFormat>("DownlinkFormat"), reply.DownlinkFormat); break;

                    case "DownlinkRequest":                      Assert.AreEqual(expectedValue.GetNByte("DR", true), reply.DownlinkRequest); break;

                    case "DSegmentNumber":                       Assert.AreEqual(expectedValue.GetNByte("ND", true), reply.DSegmentNumber); break;

                    case "ElmControl":                           Assert.AreEqual(expectedValue.GetEnum <ElmControl>("KE"), reply.ElmControl); break;

                    case "ExtendedSquitterMessage":              Assert.IsTrue(TestUtilities.SequenceEqual(expectedValue.GetBytes("ME"), reply.ExtendedSquitterMessage)); break;

                    case "ExtendedSquitterSupplementaryMessage": Assert.IsTrue(TestUtilities.SequenceEqual(expectedValue.GetBytes("MEX"), reply.ExtendedSquitterSupplementaryMessage)); break;

                    case "FlightStatus":                         Assert.AreEqual(expectedValue.GetEnum <FlightStatus>("FS"), reply.FlightStatus); break;

                    case "FormattedIcao24":                      Assert.AreEqual(worksheet.String("Icao24"), reply.FormattedIcao24); break;

                    case "Icao24":                               Assert.AreEqual(Convert.ToInt32(worksheet.String("Icao24"), 16), reply.Icao24); break;

                    case "Identity":                             Assert.AreEqual(expectedValue.GetNShort("ID"), reply.Identity); break;

                    case "NonIcao24Address":                     Assert.AreEqual(expectedValue.GetNInt("AAX", true), reply.NonIcao24Address); break;

                    case "ParityInterrogatorIdentifier":         Assert.AreEqual(expectedValue.GetNInt("PI", true), reply.ParityInterrogatorIdentifier); break;

                    case "PossibleCallsign":                     Assert.AreEqual(expectedValue.GetString("PC"), reply.PossibleCallsign); break;

                    case "ReplyInformation":                     Assert.AreEqual(expectedValue.GetNByte("RI", true), reply.ReplyInformation); break;

                    case "SensitivityLevel":                     Assert.AreEqual(expectedValue.GetNByte("SL", true), reply.SensitivityLevel); break;

                    case "UtilityMessage":                       Assert.AreEqual(expectedValue.GetNByte("UM", true), reply.UtilityMessage); break;

                    case "VerticalStatus":                       Assert.AreEqual(expectedValue.GetEnum <VerticalStatus>("VS"), reply.VerticalStatus); break;

                    default:                                     throw new NotImplementedException();
                    }
                }
            }
        }