1
0
mirror of https://github.com/DarthAffe/OBD.NET.git synced 2025-12-12 08:48:30 +00:00

Fixed uses of nullable reference types

This commit is contained in:
Darth Affe 2022-05-02 21:59:20 +02:00
parent 18b0fec0f2
commit 163f5eb3a3
19 changed files with 63 additions and 73 deletions

View File

@ -21,9 +21,7 @@ public class Program
Console.WriteLine("\nAvailable ports:");
foreach (string port in availablePorts)
{
Console.WriteLine(port);
}
return;
}
@ -33,10 +31,10 @@ public class Program
using SerialConnection connection = new(comPort);
using ELM327 dev = new(connection, new OBDConsoleLogger(OBDLogLevel.Debug));
dev.SubscribeDataReceived<EngineRPM>((sender, data) => Console.WriteLine("EngineRPM: " + data.Data.Rpm));
dev.SubscribeDataReceived<EngineFuelRate>((sender, data) => Console.WriteLine("VehicleSpeed: " + data.Data));
dev.SubscribeDataReceived<EngineRPM>((_, data) => Console.WriteLine("EngineRPM: " + data.Data.Rpm));
dev.SubscribeDataReceived<EngineFuelRate>((_, data) => Console.WriteLine("VehicleSpeed: " + data.Data));
dev.SubscribeDataReceived<IOBDData>((sender, data) => Console.WriteLine($"PID {data.Data.PID.ToHexString()}: {data.Data}"));
dev.SubscribeDataReceived<IOBDData>((_, data) => Console.WriteLine($"PID {data.Data.PID.ToHexString()}: {data.Data}"));
dev.Initialize();
dev.RequestData<FuelType>();
@ -66,18 +64,18 @@ public class Program
using SerialConnection connection = new(comPort);
using ELM327 dev = new(connection, new OBDConsoleLogger(OBDLogLevel.Debug));
dev.Initialize();
await dev.InitializeAsync();
EngineRPM engineRpm = await dev.RequestDataAsync<EngineRPM>();
Console.WriteLine("Data: " + engineRpm.Rpm);
EngineRPM? engineRpm = await dev.RequestDataAsync<EngineRPM>();
Console.WriteLine("Data: " + (engineRpm?.Rpm.ToString() ?? "-"));
engineRpm = await dev.RequestDataAsync<EngineRPM>();
Console.WriteLine("Data: " + engineRpm.Rpm);
Console.WriteLine("Data: " + (engineRpm?.Rpm.ToString() ?? "-"));
VehicleSpeed vehicleSpeed = await dev.RequestDataAsync<VehicleSpeed>();
Console.WriteLine("Data: " + vehicleSpeed.Speed);
VehicleSpeed? vehicleSpeed = await dev.RequestDataAsync<VehicleSpeed>();
Console.WriteLine("Data: " + (vehicleSpeed?.Speed.ToString() ?? "-"));
engineRpm = await dev.RequestDataAsync<EngineRPM>();
Console.WriteLine("Data: " + engineRpm.Rpm);
Console.WriteLine("Data: " + (engineRpm?.Rpm.ToString() ?? "-"));
}
}

View File

@ -46,7 +46,6 @@ namespace OBD.NET.Communication
/// Initializes a new instance of the <see cref="BluetoothSerialConnection"/> class.
/// </summary>
/// <param name="deviceName">Name of the _device.</param>
/// <param name="logger">The logger.</param>
public BluetoothSerialConnection(string deviceName)
{
this._device = deviceName;

View File

@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following

View File

@ -28,13 +28,13 @@ public class ATCommand
#region Properties & Fields
public string Command { get; }
public string ExpectedResult { get; }
public string? ExpectedResult { get; }
#endregion
#region Constructors
private ATCommand(string command, string expectedResult = null)
private ATCommand(string command, string? expectedResult = null)
{
this.Command = command;
this.ExpectedResult = expectedResult;

View File

@ -1,7 +1,6 @@
#if NET5_0_OR_GREATER
using System.IO.Ports;
using System.Text;
using OBD.NET.Communication.EventArgs;
namespace OBD.NET.Communication;
@ -12,19 +11,16 @@ public class SerialConnection : ISerialConnection
private readonly SerialPort _serialPort;
public bool IsOpen => _serialPort?.IsOpen ?? false;
public bool IsOpen => _serialPort.IsOpen;
public bool IsAsync => false;
private readonly byte[] _readBuffer = new byte[1024];
private readonly StringBuilder _lineBuffer = new();
private readonly AutoResetEvent _hasPrompt = new(true);
#endregion
#region Events
public event EventHandler<DataReceivedEventArgs> DataReceived = delegate { };
public event EventHandler<DataReceivedEventArgs>? DataReceived = delegate { };
#endregion
@ -61,7 +57,7 @@ public class SerialConnection : ISerialConnection
DataReceived?.Invoke(this, new DataReceivedEventArgs(count, _readBuffer));
}
public void Dispose() => _serialPort?.Dispose();
public void Dispose() => _serialPort.Dispose();
public Task ConnectAsync() => throw new NotSupportedException("Asynchronous operations not supported");

View File

@ -4,7 +4,7 @@ public class Count : GenericData
{
#region Properties & Fields
protected override string Unit => null;
protected override string? Unit => null;
#endregion

View File

@ -22,7 +22,7 @@ public class Degree : GenericData
#region Methods
public override string ToString() => (IsFloatingPointValue ? Value.ToString("0.00") : Value.ToString()) + (Unit ?? string.Empty);
public override string ToString() => (IsFloatingPointValue ? Value.ToString("0.00") : Value.ToString()) + Unit;
#endregion
}

View File

@ -22,7 +22,7 @@ public class DegreeCelsius : GenericData
#region Methods
public override string ToString() => (IsFloatingPointValue ? Value.ToString("0.00") : Value.ToString()) + (Unit ?? string.Empty);
public override string ToString() => (IsFloatingPointValue ? Value.ToString("0.00") : Value.ToString()) + Unit;
#endregion
}

View File

@ -9,7 +9,7 @@ public abstract class GenericData
public double MaxValue { get; }
public bool IsFloatingPointValue { get; }
protected abstract string Unit { get; }
protected abstract string? Unit { get; }
#endregion

View File

@ -4,7 +4,7 @@ public class Ratio : GenericData
{
#region Properties & Fields
protected override string Unit => null;
protected override string? Unit => null;
#endregion

View File

@ -6,7 +6,7 @@ public class CommandResult
{
#region Properties & Fields
public object Result { get; set; }
public object? Result { get; set; }
public AsyncManualResetEvent WaitHandle { get; }
#endregion

View File

@ -21,7 +21,7 @@ public class ELM327 : SerialDevice
protected Mode Mode { get; set; } = Mode.ShowCurrentData; //TODO DarthAffe 26.06.2016: Implement different modes
protected string MessageChunk { get; set; }
protected string MessageChunk { get; set; } = string.Empty;
#endregion
@ -30,13 +30,13 @@ public class ELM327 : SerialDevice
public delegate void DataReceivedEventHandler<T>(object sender, DataReceivedEventArgs<T> args) where T : IOBDData;
public delegate void RawDataReceivedEventHandler(object sender, RawDataReceivedEventArgs args);
public event RawDataReceivedEventHandler RawDataReceived;
public event RawDataReceivedEventHandler? RawDataReceived;
#endregion
#region Constructors
public ELM327(ISerialConnection connection, IOBDLogger logger = null)
public ELM327(ISerialConnection connection, IOBDLogger? logger = null)
: base(connection, logger: logger)
{ }
@ -124,7 +124,7 @@ public class ELM327 : SerialDevice
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public virtual async Task<T> RequestDataAsync<T>()
public virtual async Task<T?> RequestDataAsync<T>()
where T : class, IOBDData, new()
{
Logger?.WriteLine("Requesting Type " + typeof(T).Name + " ...", OBDLogLevel.Debug);
@ -135,9 +135,8 @@ public class ELM327 : SerialDevice
/// <summary>
/// Requests the data asynchronous and return the data when available
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public virtual async Task<IOBDData> RequestDataAsync(Type type)
public virtual async Task<IOBDData?> RequestDataAsync(Type type)
{
Logger?.WriteLine("Requesting Type " + type.Name + " ...", OBDLogLevel.Debug);
byte pid = ResolvePid(type);
@ -148,7 +147,7 @@ public class ELM327 : SerialDevice
/// Request data based on a pid
/// </summary>
/// <param name="pid">The pid of the requested data</param>
public virtual async Task<object> RequestDataAsync(byte pid)
public virtual async Task<object?> RequestDataAsync(byte pid)
{
Logger?.WriteLine("Requesting PID " + pid.ToString("X2") + " ...", OBDLogLevel.Debug);
CommandResult result = SendCommand(((byte)Mode).ToString("X2") + pid.ToString("X2"));
@ -157,10 +156,8 @@ public class ELM327 : SerialDevice
return result.Result;
}
protected override object ProcessMessage(string message)
protected override object? ProcessMessage(string message)
{
if (message == null) return null;
DateTime timestamp = DateTime.Now;
RawDataReceived?.Invoke(this, new RawDataReceivedEventArgs(message, timestamp));
@ -177,7 +174,7 @@ public class ELM327 : SerialDevice
else if (message[0] == '1')
{
string fullMessage = MessageChunk + message.Substring(2, message.Length - 2);
MessageChunk = null;
MessageChunk = string.Empty;
return ProcessMessage(fullMessage);
}
}
@ -187,15 +184,15 @@ public class ELM327 : SerialDevice
if (mode == (byte)Mode)
{
byte pid = (byte)message.Substring(2, 2).GetHexVal();
if (DataTypeCache.TryGetValue(pid, out Type dataType))
if (DataTypeCache.TryGetValue(pid, out Type? dataType))
{
IOBDData obdData = (IOBDData)Activator.CreateInstance(dataType);
IOBDData obdData = (IOBDData)Activator.CreateInstance(dataType)!;
obdData.Load(message.Substring(4, message.Length - 4));
if (DataReceivedEventHandlers.TryGetValue(dataType, out IDataEventManager dataEventManager))
if (DataReceivedEventHandlers.TryGetValue(dataType, out IDataEventManager? dataEventManager))
dataEventManager.RaiseEvent(this, obdData, timestamp);
if (DataReceivedEventHandlers.TryGetValue(typeof(IOBDData), out IDataEventManager genericDataEventManager))
if (DataReceivedEventHandlers.TryGetValue(typeof(IOBDData), out IDataEventManager? genericDataEventManager))
genericDataEventManager.RaiseEvent(this, obdData, timestamp);
return obdData;
@ -223,8 +220,7 @@ public class ELM327 : SerialDevice
protected virtual byte AddToPidCache(Type obdDataType)
{
IOBDData data = (IOBDData)Activator.CreateInstance(obdDataType);
if (data == null) throw new ArgumentException("Has to implement IOBDData", nameof(obdDataType));
if (Activator.CreateInstance(obdDataType) is not IOBDData data) throw new ArgumentException("Has to implement IOBDData", nameof(obdDataType));
byte pid = data.PID;
@ -267,7 +263,7 @@ public class ELM327 : SerialDevice
public void SubscribeDataReceived<T>(DataReceivedEventHandler<T> eventHandler) where T : IOBDData
{
if (!DataReceivedEventHandlers.TryGetValue(typeof(T), out IDataEventManager eventManager))
if (!DataReceivedEventHandlers.TryGetValue(typeof(T), out IDataEventManager? eventManager))
DataReceivedEventHandlers.Add(typeof(T), (eventManager = new GenericDataEventManager<T>()));
((GenericDataEventManager<T>)eventManager).DataReceived += eventHandler;
@ -275,7 +271,7 @@ public class ELM327 : SerialDevice
public void UnsubscribeDataReceived<T>(DataReceivedEventHandler<T> eventHandler) where T : IOBDData
{
if (DataReceivedEventHandlers.TryGetValue(typeof(T), out IDataEventManager eventManager))
if (DataReceivedEventHandlers.TryGetValue(typeof(T), out IDataEventManager? eventManager))
((GenericDataEventManager<T>)eventManager).DataReceived -= eventHandler;
}

View File

@ -8,7 +8,7 @@ public class STN1170 : ELM327 // Fully compatible device
{
#region Constructors
public STN1170(ISerialConnection connection, IOBDLogger logger = null)
public STN1170(ISerialConnection connection, IOBDLogger? logger = null)
: base(connection, logger)
{ }

View File

@ -17,16 +17,16 @@ public abstract class SerialDevice : IDisposable
private readonly BlockingCollection<QueuedCommand> _commandQueue = new();
private readonly StringBuilder _lineBuffer = new();
private readonly AutoResetEvent _commandFinishedEvent = new(false);
private Task _commandWorkerTask;
private CancellationTokenSource _commandCancellationToken;
private Task? _commandWorkerTask;
private CancellationTokenSource? _commandCancellationToken;
private volatile int _queueSize = 0;
private readonly ManualResetEvent _queueEmptyEvent = new(true);
public int QueueSize => _queueSize;
protected QueuedCommand CurrentCommand;
protected IOBDLogger Logger { get; }
protected QueuedCommand? CurrentCommand;
protected IOBDLogger? Logger { get; }
protected ISerialConnection Connection { get; }
protected char Terminator { get; set; }
@ -40,7 +40,7 @@ public abstract class SerialDevice : IDisposable
/// <param name="connection">connection.</param>
/// <param name="terminator">terminator used for terminating the command message</param>
/// <param name="logger">logger instance</param>
protected SerialDevice(ISerialConnection connection, char terminator = '\r', IOBDLogger logger = null)
protected SerialDevice(ISerialConnection connection, char terminator = '\r', IOBDLogger? logger = null)
{
this.Connection = connection;
this.Terminator = terminator;
@ -88,8 +88,7 @@ public abstract class SerialDevice : IDisposable
_commandCancellationToken = new CancellationTokenSource();
_commandWorkerTask = Task.Factory.StartNew(CommandWorker);
}
/// <summary>
/// Sends the command.
/// </summary>
@ -105,7 +104,7 @@ public abstract class SerialDevice : IDisposable
QueuedCommand cmd = new(command);
_queueEmptyEvent.Reset();
_queueSize++;
Interlocked.Increment(ref _queueSize);
_commandQueue.Add(cmd);
return cmd.CommandResult;
@ -131,7 +130,7 @@ public abstract class SerialDevice : IDisposable
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="DataReceivedEventArgs"/> instance containing the event data.</param>
private void OnDataReceived(object sender, DataReceivedEventArgs e)
private void OnDataReceived(object? sender, DataReceivedEventArgs e)
{
for (int i = 0; i < e.Count; i++)
{
@ -143,7 +142,7 @@ public abstract class SerialDevice : IDisposable
break;
case '>':
CurrentCommand.CommandResult.WaitHandle.Set();
CurrentCommand?.CommandResult.WaitHandle.Set();
_commandFinishedEvent.Set();
break;
@ -178,8 +177,9 @@ public abstract class SerialDevice : IDisposable
/// <param name="message">The message.</param>
private void InternalProcessMessage(string message)
{
object data = ProcessMessage(message);
CurrentCommand.CommandResult.Result = data;
object? data = ProcessMessage(message);
if (CurrentCommand != null)
CurrentCommand.CommandResult.Result = data;
}
/// <summary>
@ -187,13 +187,15 @@ public abstract class SerialDevice : IDisposable
/// </summary>
/// <param name="message">message received</param>
/// <returns>result data</returns>
protected abstract object ProcessMessage(string message);
protected abstract object? ProcessMessage(string message);
/// <summary>
/// Worker method for sending commands
/// </summary>
private async void CommandWorker()
{
if (_commandCancellationToken == null) return;
CancellationToken cancellationToken = _commandCancellationToken.Token;
while (!_commandCancellationToken.IsCancellationRequested)
@ -207,13 +209,14 @@ public abstract class SerialDevice : IDisposable
{
if (_commandQueue.TryTake(out CurrentCommand, 10, cancellationToken))
{
_queueSize--;
Interlocked.Decrement(ref _queueSize);
Logger?.WriteLine("Writing Command: '" + CurrentCommand.CommandText.Replace('\r', '\'') + "'", OBDLogLevel.Verbose);
if (Connection.IsAsync)
await Connection.WriteAsync(Encoding.ASCII.GetBytes(CurrentCommand.CommandText));
else
// ReSharper disable once MethodHasAsyncOverload
Connection.Write(Encoding.ASCII.GetBytes(CurrentCommand.CommandText));
// wait for command to finish or command canceled
@ -233,7 +236,7 @@ public abstract class SerialDevice : IDisposable
public void WaitQueue() => _queueEmptyEvent.WaitOne();
public async Task WaitQueueAsync() => await Task.Run(() => WaitQueue());
public async Task WaitQueueAsync() => await Task.Run(WaitQueue);
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
@ -243,7 +246,7 @@ public abstract class SerialDevice : IDisposable
_commandQueue.CompleteAdding();
_commandCancellationToken?.Cancel();
_commandWorkerTask?.Wait();
Connection?.Dispose();
Connection.Dispose();
}
#endregion

View File

@ -9,7 +9,7 @@ public class GenericDataEventManager<T> : IDataEventManager
{
#region Events
internal event ELM327.DataReceivedEventHandler<T> DataReceived;
internal event ELM327.DataReceivedEventHandler<T>? DataReceived;
#endregion

View File

@ -6,7 +6,7 @@ public class CalculatedEngineLoad : AbstractOBDData
{
#region Properties & Fields
public Percent Load => new(A / 2.55, 0, 100);
public new Percent Load => new(A / 2.55, 0, 100);
#endregion

View File

@ -6,7 +6,7 @@ public class AbsoluteLoadValue : AbstractOBDData
{
#region Properties & Fields
public Percent Load => new(((256 * A) + B) / 2.55, 0, 25700);
public new Percent Load => new(((256 * A) + B) / 2.55, 0, 25700);
#endregion

View File

@ -9,7 +9,7 @@ public abstract class AbstractOBDData : IOBDData
public byte PID { get; }
private readonly int _length;
private byte[] _rawData;
private byte[] _rawData = Array.Empty<byte>();
public byte[] RawData
{
get => _rawData;

View File

@ -26,8 +26,8 @@ public class AsyncManualResetEvent
public void Set()
{
TaskCompletionSource<bool> tcs = _tcs;
Task.Factory.StartNew(s => ((TaskCompletionSource<bool>)s).TrySetResult(true),
tcs, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default);
Task.Factory.StartNew(s => ((TaskCompletionSource<bool>)s!).TrySetResult(true),
tcs, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default);
tcs.Task.Wait();
}
@ -40,8 +40,7 @@ public class AsyncManualResetEvent
while (true)
{
TaskCompletionSource<bool> tcs = _tcs;
if (!tcs.Task.IsCompleted ||
(Interlocked.CompareExchange(ref _tcs, new TaskCompletionSource<bool>(), tcs) == tcs))
if (!tcs.Task.IsCompleted || (Interlocked.CompareExchange(ref _tcs, new TaskCompletionSource<bool>(), tcs) == tcs))
return;
}
}