Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 50 additions & 21 deletions src/APRSsharp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AprsSharp.AprsIsClient;
using AprsSharp.AprsParser;
Expand Down Expand Up @@ -131,17 +132,16 @@ public static void Main(string[] args)
aliases: new string[] { "--filter", "-f" },
getDefaultValue: () => AprsIsClient.AprsIsConstants.DefaultFilter,
description: "A user filter parsed as a string. Should not include the word 'filter', just the logic string."),
new Option<LogLevel>(
aliases: new string[] { "--verbosity", "-v" },
getDefaultValue: () => LogLevel.Warning,
description: "Set the verbosity of console logging."),
new Option(
aliases: new string[] { "--display-unsupported" },
description: "If specified, includes output of unknown or unsupported info types values. If not, such packets are not displayed."),
new Option<string?>(
aliases: new string[] { "--serialPort" },
getDefaultValue: () => null,
description: "A serial port for use with serial TNCs."),
new Option(
aliases: new string[] { "--display-parse-failures" },
description: "If specified, prints packets that failed to parse. Helpful for development."),
};
#pragma warning restore CA1861 // Avoid constant arrays as arguments
rootCommand.Name = "APRSsharp";
Expand All @@ -152,19 +152,38 @@ public static void Main(string[] args)

// The parameters of the handler method are matched according to the names of the options
rootCommand.Handler = CommandHandler
.Create(async (Mode mode, string callsign, string password, string server, int port, string filter, LogLevel verbosity, bool displayUnsupported, string? serialPort)
=> await Execute(mode, callsign, password, server, port, filter, verbosity, displayUnsupported, serialPort));
.Create(async (Mode mode, string callsign, string password, string server, int port, string filter, bool displayUnsupported, string? serialPort, bool displayParseFailures)
=> await Execute(mode, callsign, password, server, port, filter, displayUnsupported, serialPort, displayParseFailures));

rootCommand.Invoke(args);
}

private static void RunTncMode(Tnc tnc, string callsign)
/// <summary>
/// Executes the logic for running in TNC mode.
/// </summary>
/// <param name="tnc">A <see cref="Tnc"/> with which to interface.</param>
/// <param name="callsign">The callsign to use for sent messages.</param>
/// <param name="displayParseFailures">Whether or not to print message parse failures to the command line.</param>
private static void RunTncMode(Tnc tnc, string callsign, bool displayParseFailures)
{
tnc.FrameReceivedEvent += (sender, args) =>
{
var byteArray = args.Data.ToArray();
var packet = new Packet(byteArray);
PrintPacket(packet);

#pragma warning disable CA1031 // Do not catch general exception types
try
{
var packet = new Packet(byteArray);
PrintPacket(packet);
}
catch (Exception ex)
{
if (displayParseFailures)
{
PrintParseFailure(ex, Encoding.ASCII.GetString(byteArray));
}
}
#pragma warning restore CA1031 // Do not catch general exception types
};

tnc.SetTxDelay(50);
Expand Down Expand Up @@ -192,6 +211,18 @@ private static void RunTncMode(Tnc tnc, string callsign)
while (true);
}

/// <summary>
/// Prints a parse failure to the user.
/// </summary>
/// <param name="ex">The <see cref="Exception"/> that occurred.</param>
/// <param name="attempted">The <see cref="string"/> that failed to decode.</param>
private static void PrintParseFailure(Exception ex, string attempted)
{
Console.WriteLine("Failed to decode.");
Console.WriteLine($" Packet: {attempted}");
Console.WriteLine($" Exception: {ex}");
}

/// <summary>
/// Executes functionality using the provided command line arguments.
/// </summary>
Expand All @@ -202,9 +233,9 @@ private static void RunTncMode(Tnc tnc, string callsign)
/// <param name="port">A port to use for connection to a TNC via TCP.</param>
/// <param name="filter">The filter that will be used for receiving the packets.
/// This parameter shouldn't include the `filter` at the start, just the logic string itself.</param>
/// <param name="verbosity">The minimum level for an event to be logged to the console.</param>
/// <param name="displayUnsupported">If true, display packets with unsupported info field types. If false, such packets are not displayed.</param>
/// <param name="serialPort">A serial port to use for connection to a TNC via serial connection.</param>
/// <param name="displayParseFailures">Whether to print parse failures.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
private static async Task Execute(
Mode mode,
Expand All @@ -213,17 +244,10 @@ private static async Task Execute(
string server,
int port,
string filter,
LogLevel verbosity,
bool displayUnsupported,
string? serialPort)
string? serialPort,
bool displayParseFailures)
{
using ILoggerFactory loggerFactory = LoggerFactory.Create(config =>
{
config.ClearProviders()
.AddConsole()
.SetMinimumLevel(verbosity);
});

Program.displayUnsupported = displayUnsupported;

switch (mode)
Expand All @@ -235,6 +259,11 @@ private static async Task Execute(
using AprsIsClient n = new AprsIsClient();
n.ReceivedPacket += PrintPacket;

if (displayParseFailures)
{
n.DecodeFailed += PrintParseFailure;
}

Task receive = n.Receive(callsign, password, server, filter);

while (true)
Expand All @@ -260,7 +289,7 @@ private static async Task Execute(
tcp.Connect(server, port);
using Tnc tnc = new TcpTnc(tcp, 0);

RunTncMode(tnc, callsign);
RunTncMode(tnc, callsign, displayParseFailures);

break;
}
Expand All @@ -278,7 +307,7 @@ private static async Task Execute(
using SerialConnection serial = new SerialConnection(serialPort);
using Tnc tnc = new SerialTnc(serial, 0);

RunTncMode(tnc, callsign);
RunTncMode(tnc, callsign, displayParseFailures);

break;
}
Expand Down