diff --git a/.github/workflows/CIBuild.yml b/.github/workflows/CIBuild.yml
index 1dd5a5d..0aea018 100644
--- a/.github/workflows/CIBuild.yml
+++ b/.github/workflows/CIBuild.yml
@@ -21,5 +21,5 @@ jobs:
- name: Build
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat"
- msbuild /restore /t:Build src/NmeaParser.sln /p:Configuration=Release
+ msbuild /restore /t:Build src/NmeaParser.sln /p:Configuration=Release /p:JavaSdkDirectory="$(JAVA_HOME_8_X64)"
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 8de345b..cec482c 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -7,7 +7,7 @@ trigger:
- master
pool:
- vmImage: 'windows-latest'
+ vmImage: 'windows-2019'
variables:
solution: '**/*.sln'
diff --git a/src/NmeaParser.sln b/src/NmeaParser.sln
index bd0b36f..2e70d94 100644
--- a/src/NmeaParser.sln
+++ b/src/NmeaParser.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2003
+# Visual Studio 16
+VisualStudioVersion = 16.0.0.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NmeaParser", "NmeaParser", "{1701F3BA-A09C-4706-A612-24FD9340FC18}"
EndProject
diff --git a/src/NmeaParser/BluetoothDevice.Android.cs b/src/NmeaParser/BluetoothDevice.Android.cs
index 46ff7b6..0f1d56a 100644
--- a/src/NmeaParser/BluetoothDevice.Android.cs
+++ b/src/NmeaParser/BluetoothDevice.Android.cs
@@ -29,7 +29,7 @@ namespace NmeaParser
{
private static Java.Util.UUID SERIAL_UUID = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
private Android.Bluetooth.BluetoothDevice m_device;
- private BluetoothSocket m_socket;
+ private BluetoothSocket? m_socket;
///
/// Gets a list of bluetooth devices that supports serial communication
@@ -51,7 +51,7 @@ namespace NmeaParser
/// The Android Bluetooth Device.
public BluetoothDevice(Android.Bluetooth.BluetoothDevice device)
{
- m_device = device;
+ m_device = device ?? throw new ArgumentNullException(nameof(device));
}
///
@@ -80,7 +80,7 @@ namespace NmeaParser
if (stream == null)
throw new ArgumentNullException("stream");
stream.Dispose();
- m_socket.Dispose();
+ m_socket?.Dispose();
m_socket = null;
return Task.FromResult(true);
}
diff --git a/src/NmeaParser/BluetoothDevice.UWP.cs b/src/NmeaParser/BluetoothDevice.UWP.cs
index 13a2b9b..f4d6bff 100644
--- a/src/NmeaParser/BluetoothDevice.UWP.cs
+++ b/src/NmeaParser/BluetoothDevice.UWP.cs
@@ -33,9 +33,9 @@ namespace NmeaParser
///
public class BluetoothDevice : NmeaDevice
{
- private Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService m_deviceService;
- private Windows.Networking.Proximity.PeerInformation m_devicePeer;
- private StreamSocket m_socket;
+ private Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService? m_deviceService;
+ private Windows.Networking.Proximity.PeerInformation? m_devicePeer;
+ private StreamSocket? m_socket;
private bool m_disposeService;
private SemaphoreSlim m_semaphoreSlim = new SemaphoreSlim(1, 1);
@@ -60,7 +60,7 @@ namespace NmeaParser
/// Whether this devicee should also dispose the RfcommDeviceService provided when this device disposes.
public BluetoothDevice(RfcommDeviceService service, bool disposeService = false)
{
- m_deviceService = service;
+ m_deviceService = service ?? throw new ArgumentNullException(nameof(service));
m_disposeService = disposeService;
}
@@ -70,7 +70,7 @@ namespace NmeaParser
/// The peer information device.
public BluetoothDevice(Windows.Networking.Proximity.PeerInformation peer)
{
- m_devicePeer = peer;
+ m_devicePeer = peer ?? throw new ArgumentNullException(nameof(peer));
}
///
@@ -95,20 +95,37 @@ namespace NmeaParser
{
await socket.ConnectAsync(m_devicePeer.HostName, "1");
}
- else
+ else if (m_deviceService != null)
{
await socket.ConnectAsync(m_deviceService.ConnectionHostName, m_deviceService.ConnectionServiceName);
}
+ else
+ throw new InvalidOperationException();
m_socket = socket;
- return null; //We're going to use WinRT buffers instead and will handle read/write, so no reason to return a stream. This is mainly done to avoid locking issues reading and writing at the same time
+
+ return new DummyStream(); //We're going to use WinRT buffers instead and will handle read/write, so no reason to return a real stream. This is mainly done to avoid locking issues reading and writing at the same time
}
- ///
- /// Closes the stream the NmeaDevice is working on top off.
- ///
- /// The stream.
- ///
- protected override Task CloseStreamAsync(System.IO.Stream stream)
+ private class DummyStream : Stream
+ {
+ public override bool CanRead => false;
+ public override bool CanSeek => false;
+ public override bool CanWrite => false;
+ public override long Length => throw new NotSupportedException();
+ public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
+ public override void Flush() => throw new NotSupportedException();
+ public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException();
+ public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
+ public override void SetLength(long value) => throw new NotSupportedException();
+ public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
+ }
+
+ ///
+ /// Closes the stream the NmeaDevice is working on top off.
+ ///
+ /// The stream.
+ ///
+ protected override Task CloseStreamAsync(System.IO.Stream stream)
{
if(m_socket == null)
throw new InvalidOperationException("No connection to close");
@@ -124,6 +141,8 @@ namespace NmeaParser
// Reading and writing to the Bluetooth serial connection at the same time seems very unstable in UWP,
// so we use a semaphore to ensure we don't read and write at the same time
await m_semaphoreSlim.WaitAsync().ConfigureAwait(false);
+ if (m_socket == null)
+ throw new InvalidOperationException("Socket not initialized");
try
{
var r = await m_socket.InputStream.ReadAsync(buffer.AsBuffer(), (uint)count, Windows.Storage.Streams.InputStreamOptions.None);
diff --git a/src/NmeaParser/BufferedStreamDevice.cs b/src/NmeaParser/BufferedStreamDevice.cs
index f4e182f..3cd218a 100644
--- a/src/NmeaParser/BufferedStreamDevice.cs
+++ b/src/NmeaParser/BufferedStreamDevice.cs
@@ -27,7 +27,7 @@ namespace NmeaParser
///
public abstract class BufferedStreamDevice : NmeaDevice
{
- private BufferedStream m_stream;
+ private BufferedStream? m_stream;
private readonly int m_readSpeed;
///
@@ -71,7 +71,7 @@ namespace NmeaParser
///
protected override Task CloseStreamAsync(System.IO.Stream stream)
{
- m_stream.Dispose();
+ m_stream?.Dispose();
return Task.FromResult(true);
}
@@ -83,8 +83,8 @@ namespace NmeaParser
private byte[] m_buffer = new byte[0];
private readonly System.Threading.Timer m_timer;
private readonly object lockObj = new object();
- private string groupToken = null;
- private string lastLineRead = null;
+ private string? groupToken = null;
+ private string? lastLineRead = null;
///
/// Initializes a new instance of the class.
///
diff --git a/src/NmeaParser/Nmea/Bod.cs b/src/NmeaParser/Nmea/Bod.cs
index 551172d..ef906c1 100644
--- a/src/NmeaParser/Nmea/Bod.cs
+++ b/src/NmeaParser/Nmea/Bod.cs
@@ -63,11 +63,11 @@ namespace NmeaParser.Nmea
///
/// Name of origin
///
- public string OriginId { get; }
+ public string? OriginId { get; }
///
/// Name of destination
///
- public string DestinationId { get; }
+ public string? DestinationId { get; }
}
}
\ No newline at end of file
diff --git a/src/NmeaParser/Nmea/Gns.cs b/src/NmeaParser/Nmea/Gns.cs
index 50234a6..db70972 100644
--- a/src/NmeaParser/Nmea/Gns.cs
+++ b/src/NmeaParser/Nmea/Gns.cs
@@ -228,7 +228,7 @@ namespace NmeaParser.Nmea
///
/// eference station ID1, range 0000-4095 - Null if talker ID is GN, additional GNS messages follow with GP and/or GL Reference station ID
///
- public string DgpsStationId { get; }
+ public string? DgpsStationId { get; }
///
/// Navigational status
diff --git a/src/NmeaParser/NmeaDevice.cs b/src/NmeaParser/NmeaDevice.cs
index ec1567a..7ad7b77 100644
--- a/src/NmeaParser/NmeaDevice.cs
+++ b/src/NmeaParser/NmeaDevice.cs
@@ -29,10 +29,10 @@ namespace NmeaParser
{
private readonly object m_lockObject = new object();
private string m_message = "";
- private Stream m_stream;
- private CancellationTokenSource m_cts;
+ private Stream? m_stream;
+ private CancellationTokenSource? m_cts;
private bool m_isOpening;
- private Task m_ParserTask;
+ private Task? m_ParserTask;
///
/// Initializes a new instance of the class.
@@ -183,7 +183,9 @@ namespace NmeaParser
private void OnMessageReceived(Nmea.NmeaMessage msg)
{
- Nmea.NmeaMessage[] messageParts = null;
+ if (msg == null)
+ return;
+ Nmea.NmeaMessage[]? messageParts = null;
if (msg is IMultiPartMessage multi)
{
string messageType = msg.MessageType.Substring(2); //We don't care about the two first characters. Ie GPGSV, GLGSV, GAGSV etc are all part of the same multi-part message
@@ -221,7 +223,7 @@ namespace NmeaParser
///
/// Occurs when an NMEA message is received.
///
- public event EventHandler MessageReceived;
+ public event EventHandler? MessageReceived;
///
/// Releases unmanaged and - optionally - managed resources.
@@ -287,7 +289,7 @@ namespace NmeaParser
///
public sealed class NmeaMessageReceivedEventArgs : EventArgs
{
- internal NmeaMessageReceivedEventArgs(Nmea.NmeaMessage message, IReadOnlyList messageParts)
+ internal NmeaMessageReceivedEventArgs(Nmea.NmeaMessage message, IReadOnlyList? messageParts)
{
Message = message;
MessageParts = messageParts;
@@ -315,6 +317,6 @@ namespace NmeaParser
///
/// The message parts.
///
- public IReadOnlyList MessageParts { get; }
+ public IReadOnlyList? MessageParts { get; }
}
}
diff --git a/src/NmeaParser/NmeaFileDevice.cs b/src/NmeaParser/NmeaFileDevice.cs
index 395fa23..e7f7d13 100644
--- a/src/NmeaParser/NmeaFileDevice.cs
+++ b/src/NmeaParser/NmeaFileDevice.cs
@@ -27,7 +27,7 @@ namespace NmeaParser
public class NmeaFileDevice : BufferedStreamDevice
{
#if NETFX_CORE
- private Windows.Storage.IStorageFile m_storageFile;
+ private Windows.Storage.IStorageFile? m_storageFile;
#endif
private string m_filename;
@@ -44,8 +44,8 @@ namespace NmeaParser
///
/// Initializes a new instance of the class.
///
- ///
- public NmeaFileDevice(Windows.Storage.IStorageFile fileName) : this(fileName, 1000)
+ ///
+ public NmeaFileDevice(Windows.Storage.IStorageFile storageFile) : this(storageFile, 1000)
{
}
#endif
@@ -63,12 +63,13 @@ namespace NmeaParser
///
/// Initializes a new instance of the class.
///
- ///
+ ///
/// The time to wait between each group of lines being read in milliseconds
- public NmeaFileDevice(Windows.Storage.IStorageFile fileName, int readSpeed)
+ public NmeaFileDevice(Windows.Storage.IStorageFile storageFile, int readSpeed)
: base(readSpeed)
{
- m_storageFile = fileName;
+ m_storageFile = storageFile ?? throw new ArgumentNullException(nameof(storageFile));
+ m_filename = storageFile.Path;
}
#endif
@@ -79,10 +80,6 @@ namespace NmeaParser
{
get
{
-#if NETFX_CORE
- if (m_storageFile != null)
- return m_storageFile.Path;
-#endif
return m_filename;
}
}
diff --git a/src/NmeaParser/NmeaParser.csproj b/src/NmeaParser/NmeaParser.csproj
index 80dbe53..447244c 100644
--- a/src/NmeaParser/NmeaParser.csproj
+++ b/src/NmeaParser/NmeaParser.csproj
@@ -1,7 +1,7 @@
-
+
- netstandard1.4;net451;monoandroid50;monoandroid70;xamarinios10;uap10.0.14393
+ netstandard1.4;net451;monoandroid50;monoandroid70;xamarinios10;uap10.0.16299
true
true
Debug;Release
@@ -27,9 +27,10 @@ Updated license to Apache 2.0
true
true
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
- 7.3
+ 8.0
true
true
+ enable
@@ -41,11 +42,13 @@ Updated license to Apache 2.0
+ false
$(DefineConstants);XAMARIN;API_LEVEL_21
$(NoWarn);XA0113;XA0114
false
+ false
$(DefineConstants);XAMARIN;API_LEVEL_24
$(NoWarn);XA0113;XA0114
false
@@ -56,10 +59,10 @@ Updated license to Apache 2.0
$(NoWarn);VSX1000
-
+
-
+
diff --git a/src/NmeaParser/SerialPortDevice.Desktop.cs b/src/NmeaParser/SerialPortDevice.Desktop.cs
index 61522fc..7c84311 100644
--- a/src/NmeaParser/SerialPortDevice.Desktop.cs
+++ b/src/NmeaParser/SerialPortDevice.Desktop.cs
@@ -64,7 +64,7 @@ namespace NmeaParser
{
if (Port.IsOpen)
Port.Close();
- return Task.FromResult
true
diff --git a/src/UnitTests/NmeaParser.Tests.UWP/NmeaParser.Tests.UWP.csproj b/src/UnitTests/NmeaParser.Tests.UWP/NmeaParser.Tests.UWP.csproj
index 95e231d..a115610 100644
--- a/src/UnitTests/NmeaParser.Tests.UWP/NmeaParser.Tests.UWP.csproj
+++ b/src/UnitTests/NmeaParser.Tests.UWP/NmeaParser.Tests.UWP.csproj
@@ -13,12 +13,14 @@
UAP
10.0.17763.0
10.0.16299.0
- 14
+ 16
512
{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
NmeaParser.Tests.UWP_TemporaryKey.pfx
$(VisualStudioVersion)
D07B149B4E796AB0184B2E2FC9DDC1A2F5CA5A7E
+ 8.0
+ enable
true
diff --git a/src/UnitTests/NmeaParser.Tests.UWP/UnitTestApp.xaml.cs b/src/UnitTests/NmeaParser.Tests.UWP/UnitTestApp.xaml.cs
index bbcb58c..4d18550 100644
--- a/src/UnitTests/NmeaParser.Tests.UWP/UnitTestApp.xaml.cs
+++ b/src/UnitTests/NmeaParser.Tests.UWP/UnitTestApp.xaml.cs
@@ -47,7 +47,7 @@ namespace NmeaParser.Tests.UWP
}
#endif
- Frame rootFrame = Window.Current.Content as Frame;
+ Frame? rootFrame = Window.Current?.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
@@ -64,13 +64,15 @@ namespace NmeaParser.Tests.UWP
}
// Place the frame in the current Window
- Window.Current.Content = rootFrame;
+ if (Window.Current != null)
+ Window.Current.Content = rootFrame;
}
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();
// Ensure the current window is active
- Window.Current.Activate();
+ if (Window.Current != null)
+ Window.Current.Activate();
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.Run(e.Arguments);
}
diff --git a/src/UnitTests/NmeaParser.Tests/DeviceTests.cs b/src/UnitTests/NmeaParser.Tests/DeviceTests.cs
index d7702d3..ae045ea 100644
--- a/src/UnitTests/NmeaParser.Tests/DeviceTests.cs
+++ b/src/UnitTests/NmeaParser.Tests/DeviceTests.cs
@@ -13,6 +13,7 @@ namespace NmeaParser.Tests
{
[TestMethod]
[TestCategory("Device")]
+ [Timeout(2000)]
public async Task TestGpgsvGroupMessage()
{
var message = "$GPGSV,3,1,9,00,30,055,48,00,19,281,00,27,19,275,00,12,16,319,00*4C\n$GPGSV,3,2,9,00,30,055,48,00,19,281,00,27,19,275,00,12,16,319,00*4F\n$GPGSV,3,3,9,32,10,037,00,,,,,,,,,,,,*74";
@@ -26,7 +27,7 @@ namespace NmeaParser.Tests
{
Assert.IsTrue(e.IsMultipart, "IsMultiPart");
Assert.IsInstanceOfType(e.Message, typeof(NmeaParser.Nmea.Gsv));
- var msg = e.Message as NmeaParser.Nmea.Gsv;
+ var msg = (NmeaParser.Nmea.Gsv)e.Message;
if (msg.TotalMessages == msg.MessageNumber)
{
Assert.IsNotNull(e.MessageParts);
@@ -50,6 +51,7 @@ namespace NmeaParser.Tests
[TestMethod]
[TestCategory("Device")]
+ [Timeout(2000)]
public async Task TestMixedGsvGroupMessage()
{
// A group message can have multiple diffent GSV types.
@@ -67,7 +69,7 @@ $GAGSV,4,4,14,19,82,349,40,1,44,220,40,4,24,314,38*5F";
{
Assert.IsTrue(e.IsMultipart, "IsMultiPart");
Assert.IsInstanceOfType(e.Message, typeof(NmeaParser.Nmea.Gsv));
- var msg = e.Message as NmeaParser.Nmea.Gsv;
+ var msg = (NmeaParser.Nmea.Gsv)e.Message;
if (msg.TotalMessages == msg.MessageNumber)
{
Assert.IsNotNull(e.MessageParts);
@@ -100,7 +102,8 @@ $GAGSV,4,4,14,19,82,349,40,1,44,220,40,4,24,314,38*5F";
[TestMethod]
[TestCategory("Device")]
- public async Task TestInvalidGpgsvGroupMessage()
+ [Timeout(2000)]
+ public async Task TestInvalidGpgsvGroupMessage()
{
var message = "$GPGSV,3,2,9,00,30,055,48,00,19,281,00,27,19,275,00,12,16,319,00*4D\n$GPGSV,3,2,9,00,30,055,48,00,19,281,00,27,19,275,00,12,16,319,00*4F\n$GPGSV,3,3,9,32,10,037,00,,,,,,,,,,,,*74";
NmeaDevice dev = new BufferedStringDevice(message);