/// <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; } } } }
public void ModeSTranslator_Translate_Throws_If_Statistics_Is_Not_Initialised() { _Translator.Statistics = null; _Translator.Translate(new byte[0], 0, null, false); }
/// <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; } } } }
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(); } } } }