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..accb039 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 @@ -212,8 +214,8 @@ namespace NmeaParser } } } - - MessageReceived?.Invoke(this, new NmeaMessageReceivedEventArgs(msg, messageParts)); + if (messageParts != null) + MessageReceived?.Invoke(this, new NmeaMessageReceivedEventArgs(msg, messageParts)); } private readonly Dictionary> MultiPartMessageCache = new Dictionary>(); 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..064f64f 100644 --- a/src/NmeaParser/NmeaParser.csproj +++ b/src/NmeaParser/NmeaParser.csproj @@ -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 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(null); + return Task.FromResult(null); } /// @@ -90,7 +90,7 @@ namespace NmeaParser throw new InvalidOperationException("Device not open"); Port.Write(buffer, offset, length); - return Task.FromResult(null); + return Task.FromResult(null); } } } diff --git a/src/NmeaParser/StreamDevice.cs b/src/NmeaParser/StreamDevice.cs index d84d6f7..f92cbef 100644 --- a/src/NmeaParser/StreamDevice.cs +++ b/src/NmeaParser/StreamDevice.cs @@ -33,7 +33,7 @@ namespace NmeaParser /// The stream. public StreamDevice(Stream stream) : base() { - m_stream = stream; + m_stream = stream ?? throw new ArgumentNullException(nameof(stream)); } /// @@ -64,7 +64,6 @@ namespace NmeaParser base.Dispose(disposing); if (m_stream != null) m_stream.Dispose(); - m_stream = null; } /// diff --git a/src/NmeaParser/SystemNmeaDevice.Android.cs b/src/NmeaParser/SystemNmeaDevice.Android.cs index 6f14bf0..7cbc380 100644 --- a/src/NmeaParser/SystemNmeaDevice.Android.cs +++ b/src/NmeaParser/SystemNmeaDevice.Android.cs @@ -32,16 +32,18 @@ namespace NmeaParser /// public class SystemNmeaDevice : NmeaDevice { - private StringStream stream; - private Listener listener; + private StringStream? stream; + private Listener? listener; private LocationManager manager; /// /// Initializes a new instance of the class. /// - public SystemNmeaDevice() + public SystemNmeaDevice(Context context) { - manager = Application.Context.GetSystemService(Context.LocationService) as LocationManager; + if (context == null) + throw new ArgumentNullException(nameof(context)); + manager = context.GetSystemService(Context.LocationService) as LocationManager ?? throw new InvalidOperationException("Cannot acces the Location Service"); } /// @@ -76,10 +78,10 @@ namespace NmeaParser { manager.RemoveUpdates(listener); manager.RemoveNmeaListener(listener); - listener.Dispose(); + listener?.Dispose(); listener = null; stream.Dispose(); - return Task.FromResult(null); + return Task.CompletedTask; } private class Listener : Java.Lang.Object, diff --git a/src/SampleApp.Droid/MainActivity.cs b/src/SampleApp.Droid/MainActivity.cs index 444e64e..f584d7e 100644 --- a/src/SampleApp.Droid/MainActivity.cs +++ b/src/SampleApp.Droid/MainActivity.cs @@ -96,7 +96,7 @@ namespace SampleApp.Droid return; launched = true; - listener = new NmeaParser.SystemNmeaDevice(); + listener = new NmeaParser.SystemNmeaDevice(ApplicationContext); } else //Bluetooth {