From 2136aaf0ca297e9c511fb7642b1daf99d5a752b4 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sat, 21 May 2022 13:35:11 +0200 Subject: [PATCH] Readded EnhanvedSerialPort for .NET-Framework support --- OBD.NET/ConsoleClient/ConsoleClient.csproj | 6 +- OBD.NET/ConsoleClient/Program.cs | 23 ++- .../Communication/EnhancedSerialPort.cs | 172 ++++++++++++++++++ .../Communication/ISerialConnection.cs | 4 +- .../OBD.NET/Communication/SerialConnection.cs | 80 +++++++- OBD.NET/OBD.NET/DataTypes/GenericData.cs | 4 +- OBD.NET/OBD.NET/Devices/ELM327.cs | 6 +- OBD.NET/OBD.NET/Devices/SerialDevice.cs | 5 +- .../Events/EventArgs/DataReceivedEventArgs.cs | 3 +- .../EventArgs/RawDataReceivedEventArgs.cs | 4 +- .../OBD.NET/Events/GenericDataEventManager.cs | 3 +- OBD.NET/OBD.NET/Events/IDataEventManager.cs | 3 +- OBD.NET/OBD.NET/Exceptions/SerialException.cs | 4 +- .../Exceptions/UnexpectedResultException.cs | 4 +- OBD.NET/OBD.NET/Extensions/HexExtension.cs | 5 +- OBD.NET/OBD.NET/Logging/OBDConsoleLogger.cs | 2 + OBD.NET/OBD.NET/Logging/OBDDebugLogger.cs | 3 +- OBD.NET/OBD.NET/OBD.NET.csproj | 105 ++++++----- .../00-1F/CommandedSecondaryAirStatus.cs | 4 +- .../OBD.NET/OBDData/00-1F/FuelSystemStatus.cs | 4 +- .../OBDData/00-1F/OxygenSensorPresent.cs | 4 +- .../OBDData/00-1F/OxygenSensorsPresent2.cs | 4 +- OBD.NET/OBD.NET/OBDData/AbstractOBDData.cs | 3 +- .../OBD.NET/OBDData/AbstractPidsSupported.cs | 1 + OBD.NET/OBD.NET/Util/AsyncManulResetEvent.cs | 5 +- 25 files changed, 372 insertions(+), 89 deletions(-) create mode 100644 OBD.NET/OBD.NET/Communication/EnhancedSerialPort.cs diff --git a/OBD.NET/ConsoleClient/ConsoleClient.csproj b/OBD.NET/ConsoleClient/ConsoleClient.csproj index ed1d504..749ab70 100644 --- a/OBD.NET/ConsoleClient/ConsoleClient.csproj +++ b/OBD.NET/ConsoleClient/ConsoleClient.csproj @@ -1,10 +1,10 @@ - + Exe - net6.0 - enable + net4.8 enable + latest diff --git a/OBD.NET/ConsoleClient/Program.cs b/OBD.NET/ConsoleClient/Program.cs index 5142569..ee49a53 100644 --- a/OBD.NET/ConsoleClient/Program.cs +++ b/OBD.NET/ConsoleClient/Program.cs @@ -1,4 +1,7 @@ -using OBD.NET.Communication; +using System; +using System.Threading; +using System.Threading.Tasks; +using OBD.NET.Communication; using OBD.NET.Devices; using OBD.NET.Extensions; using OBD.NET.Logging; @@ -12,19 +15,19 @@ public class Program { public static void Main(string[] args) { - if (args.Length < 1) - { - Console.WriteLine("Parameter ComPort needed."); + //if (args.Length < 1) + //{ + // Console.WriteLine("Parameter ComPort needed."); - IEnumerable availablePorts = SerialConnection.GetAvailablePorts(); + // IEnumerable availablePorts = SerialConnection.GetAvailablePorts(); - Console.WriteLine("\nAvailable ports:"); + // Console.WriteLine("\nAvailable ports:"); - foreach (string port in availablePorts) - Console.WriteLine(port); + // foreach (string port in availablePorts) + // Console.WriteLine(port); - return; - } + // return; + //} string comPort = args[0]; diff --git a/OBD.NET/OBD.NET/Communication/EnhancedSerialPort.cs b/OBD.NET/OBD.NET/Communication/EnhancedSerialPort.cs new file mode 100644 index 0000000..76ed8c1 --- /dev/null +++ b/OBD.NET/OBD.NET/Communication/EnhancedSerialPort.cs @@ -0,0 +1,172 @@ +#if !NET5_0_OR_GREATER + +// Copyright 2013 Antanas Veiverys www.veiverys.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.ComponentModel; +using System.IO; +using System.IO.Ports; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +// Source: http://antanas.veiverys.com/mono-serialport-datareceived-event-workaround-using-a-derived-class/ +namespace OBD.NET.Communication; + +[DesignerCategory("Code")] +public class EnhancedSerialPort : SerialPort +{ + #region Properties & Fields + + // private member access via reflection + private int _fd; + private FieldInfo? _disposedFieldInfo; + private object? _dataReceived; + private Thread? _thread; + + #endregion + + #region DLLImports + + [DllImport("MonoPosixHelper", SetLastError = true)] + private static extern bool poll_serial(int fd, out int error, int timeout); + + [DllImport("libc")] + private static extern IntPtr strerror(int errnum); + + #endregion + + #region Constructors + + public EnhancedSerialPort() + : base() + { } + + public EnhancedSerialPort(IContainer container) + : base(container) + { } + + public EnhancedSerialPort(string portName) + : base(portName) + { } + + public EnhancedSerialPort(string portName, int baudRate) + : base(portName, baudRate) + { } + + public EnhancedSerialPort(string portName, int baudRate, Parity parity) + : base(portName, baudRate, parity) + { } + + public EnhancedSerialPort(string portName, int baudRate, Parity parity, int dataBits) + : base(portName, baudRate, parity, dataBits) + { } + + public EnhancedSerialPort(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) + : base(portName, baudRate, parity, dataBits, stopBits) + { } + + #endregion + + #region Methods + + public new void Open() + { + base.Open(); + + if (!IsWindows) + { + FieldInfo? fieldInfo = BaseStream.GetType().GetField("fd", BindingFlags.Instance | BindingFlags.NonPublic); + if (fieldInfo == null) throw new NotSupportedException("Unable to initialize SerialPort - 'fd'-field is missing."); + _fd = (int)fieldInfo.GetValue(BaseStream)!; + + _disposedFieldInfo = BaseStream.GetType().GetField("disposed", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new NotSupportedException("Unable to initialize SerialPort - 'disposed'-field is missing."); + + fieldInfo = typeof(SerialPort).GetField("data_received", BindingFlags.Instance | BindingFlags.NonPublic); + if (fieldInfo == null) throw new NotSupportedException("Unable to initialize SerialPort - 'data_received'-field is missing."); + _dataReceived = fieldInfo.GetValue(this); + + _thread = new Thread(EventThreadFunction); + _thread.Start(); + } + } + + private static bool IsWindows + { + get + { + PlatformID id = Environment.OSVersion.Platform; + return (id == PlatformID.Win32Windows) || (id == PlatformID.Win32NT); // WinCE not supported + } + } + + private void EventThreadFunction() + { + do + { + try + { + Stream? stream = BaseStream; + if (stream == null) + return; + + if (Poll(stream, ReadTimeout)) + OnDataReceived(null!); + } + catch + { + return; + } + } while (IsOpen); + } + + private void OnDataReceived(SerialDataReceivedEventArgs args) + { + SerialDataReceivedEventHandler? handler = Events[_dataReceived!] as SerialDataReceivedEventHandler; + handler?.Invoke(this, args); + } + + private bool Poll(Stream stream, int timeout) + { + CheckDisposed(stream); + if (IsOpen == false) + throw new Exception("port is closed"); + + bool pollResult = poll_serial(_fd, out int error, ReadTimeout); + if (error == -1) + ThrowIOException(); + + return pollResult; + } + + private static void ThrowIOException() + { + int errnum = Marshal.GetLastWin32Error(); + string errorMessage = Marshal.PtrToStringAnsi(strerror(errnum))!; + + throw new IOException(errorMessage); + } + + private void CheckDisposed(Stream stream) + { + bool disposed = (bool)_disposedFieldInfo!.GetValue(stream)!; + if (disposed) + throw new ObjectDisposedException(stream.GetType().FullName); + } + + #endregion +} + +#endif \ No newline at end of file diff --git a/OBD.NET/OBD.NET/Communication/ISerialConnection.cs b/OBD.NET/OBD.NET/Communication/ISerialConnection.cs index 0f509b5..2203137 100644 --- a/OBD.NET/OBD.NET/Communication/ISerialConnection.cs +++ b/OBD.NET/OBD.NET/Communication/ISerialConnection.cs @@ -1,4 +1,6 @@ -using OBD.NET.Communication.EventArgs; +using System; +using System.Threading.Tasks; +using OBD.NET.Communication.EventArgs; namespace OBD.NET.Communication; diff --git a/OBD.NET/OBD.NET/Communication/SerialConnection.cs b/OBD.NET/OBD.NET/Communication/SerialConnection.cs index 8f0c8e1..4e8a238 100644 --- a/OBD.NET/OBD.NET/Communication/SerialConnection.cs +++ b/OBD.NET/OBD.NET/Communication/SerialConnection.cs @@ -1,6 +1,9 @@ #if NET5_0_OR_GREATER +using System; +using System.Collections.Generic; using System.IO.Ports; +using System.Threading.Tasks; using OBD.NET.Communication.EventArgs; namespace OBD.NET.Communication; @@ -44,10 +47,7 @@ public class SerialConnection : ISerialConnection #region Methods - public static IEnumerable GetAvailablePorts() - { - return SerialPort.GetPortNames(); - } + public static IEnumerable GetAvailablePorts() => SerialPort.GetPortNames(); public void Connect() => _serialPort.Open(); @@ -68,4 +68,74 @@ public class SerialConnection : ISerialConnection #endregion } -#endif \ No newline at end of file +#else + +using System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Threading.Tasks; +using OBD.NET.Communication.EventArgs; + +namespace OBD.NET.Communication; + +public class SerialConnection : ISerialConnection +{ + #region Properties & Fields + + private readonly EnhancedSerialPort _serialPort; + + public bool IsOpen => _serialPort?.IsOpen ?? false; + public bool IsAsync => false; + + private readonly byte[] _readBuffer = new byte[1024]; + + #endregion + + #region Events + + public event EventHandler? DataReceived; + + #endregion + + #region Constructors + + public SerialConnection(string port, int baudRate = 38400, Parity parity = Parity.None, StopBits stopBits = StopBits.One, + Handshake handshake = Handshake.None, int timeout = 5000) + { + _serialPort = new EnhancedSerialPort(port, baudRate, parity) + { + StopBits = stopBits, + Handshake = handshake, + ReadTimeout = timeout, + WriteTimeout = timeout + }; + + _serialPort.DataReceived += SerialPortOnDataReceived; + } + + #endregion + + #region Methods + + public static IEnumerable GetAvailablePorts() => SerialPort.GetPortNames(); + + public void Connect() => _serialPort.Open(); + + private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs) + { + int count = _serialPort.Read(_readBuffer, 0, _serialPort.BytesToRead); + DataReceived?.Invoke(this, new DataReceivedEventArgs(count, _readBuffer)); + } + + public void Dispose() => _serialPort.Dispose(); + + public Task ConnectAsync() => throw new NotSupportedException("Asynchronous operations not supported"); + + public Task WriteAsync(byte[] data) => throw new NotSupportedException("Asynchronous operations not supported"); + + public void Write(byte[] data) => _serialPort.Write(data, 0, data.Length); + + #endregion +} + +#endif diff --git a/OBD.NET/OBD.NET/DataTypes/GenericData.cs b/OBD.NET/OBD.NET/DataTypes/GenericData.cs index e04191b..a3f19cb 100644 --- a/OBD.NET/OBD.NET/DataTypes/GenericData.cs +++ b/OBD.NET/OBD.NET/DataTypes/GenericData.cs @@ -1,4 +1,6 @@ -namespace OBD.NET.DataTypes; +using System; + +namespace OBD.NET.DataTypes; public abstract class GenericData { diff --git a/OBD.NET/OBD.NET/Devices/ELM327.cs b/OBD.NET/OBD.NET/Devices/ELM327.cs index ba9733f..b62184e 100644 --- a/OBD.NET/OBD.NET/Devices/ELM327.cs +++ b/OBD.NET/OBD.NET/Devices/ELM327.cs @@ -1,4 +1,8 @@ -using System.Reflection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; using OBD.NET.Commands; using OBD.NET.Communication; using OBD.NET.Enums; diff --git a/OBD.NET/OBD.NET/Devices/SerialDevice.cs b/OBD.NET/OBD.NET/Devices/SerialDevice.cs index 0735a7b..19ebb27 100644 --- a/OBD.NET/OBD.NET/Devices/SerialDevice.cs +++ b/OBD.NET/OBD.NET/Devices/SerialDevice.cs @@ -1,5 +1,8 @@ -using System.Collections.Concurrent; +using System; +using System.Collections.Concurrent; using System.Text; +using System.Threading; +using System.Threading.Tasks; using OBD.NET.Communication; using OBD.NET.Communication.EventArgs; using OBD.NET.Exceptions; diff --git a/OBD.NET/OBD.NET/Events/EventArgs/DataReceivedEventArgs.cs b/OBD.NET/OBD.NET/Events/EventArgs/DataReceivedEventArgs.cs index b369e38..f8ce5a7 100644 --- a/OBD.NET/OBD.NET/Events/EventArgs/DataReceivedEventArgs.cs +++ b/OBD.NET/OBD.NET/Events/EventArgs/DataReceivedEventArgs.cs @@ -1,4 +1,5 @@ -using OBD.NET.OBDData; +using System; +using OBD.NET.OBDData; namespace OBD.NET.Events.EventArgs; diff --git a/OBD.NET/OBD.NET/Events/EventArgs/RawDataReceivedEventArgs.cs b/OBD.NET/OBD.NET/Events/EventArgs/RawDataReceivedEventArgs.cs index 40a1eaf..e9a6577 100644 --- a/OBD.NET/OBD.NET/Events/EventArgs/RawDataReceivedEventArgs.cs +++ b/OBD.NET/OBD.NET/Events/EventArgs/RawDataReceivedEventArgs.cs @@ -1,4 +1,6 @@ -namespace OBD.NET.Events.EventArgs; +using System; + +namespace OBD.NET.Events.EventArgs; public class RawDataReceivedEventArgs { diff --git a/OBD.NET/OBD.NET/Events/GenericDataEventManager.cs b/OBD.NET/OBD.NET/Events/GenericDataEventManager.cs index 1fc0eab..2f52a23 100644 --- a/OBD.NET/OBD.NET/Events/GenericDataEventManager.cs +++ b/OBD.NET/OBD.NET/Events/GenericDataEventManager.cs @@ -1,4 +1,5 @@ -using OBD.NET.Devices; +using System; +using OBD.NET.Devices; using OBD.NET.Events.EventArgs; using OBD.NET.OBDData; diff --git a/OBD.NET/OBD.NET/Events/IDataEventManager.cs b/OBD.NET/OBD.NET/Events/IDataEventManager.cs index e2e150e..1a348f2 100644 --- a/OBD.NET/OBD.NET/Events/IDataEventManager.cs +++ b/OBD.NET/OBD.NET/Events/IDataEventManager.cs @@ -1,4 +1,5 @@ -using OBD.NET.OBDData; +using System; +using OBD.NET.OBDData; namespace OBD.NET.Events; diff --git a/OBD.NET/OBD.NET/Exceptions/SerialException.cs b/OBD.NET/OBD.NET/Exceptions/SerialException.cs index 29a8a34..cd05440 100644 --- a/OBD.NET/OBD.NET/Exceptions/SerialException.cs +++ b/OBD.NET/OBD.NET/Exceptions/SerialException.cs @@ -1,4 +1,6 @@ -namespace OBD.NET.Exceptions; +using System; + +namespace OBD.NET.Exceptions; public class SerialException : Exception { diff --git a/OBD.NET/OBD.NET/Exceptions/UnexpectedResultException.cs b/OBD.NET/OBD.NET/Exceptions/UnexpectedResultException.cs index e0fb2f4..8cbd24b 100644 --- a/OBD.NET/OBD.NET/Exceptions/UnexpectedResultException.cs +++ b/OBD.NET/OBD.NET/Exceptions/UnexpectedResultException.cs @@ -1,4 +1,6 @@ -namespace OBD.NET.Exceptions; +using System; + +namespace OBD.NET.Exceptions; public class UnexpectedResultException : Exception { diff --git a/OBD.NET/OBD.NET/Extensions/HexExtension.cs b/OBD.NET/OBD.NET/Extensions/HexExtension.cs index 12930fa..f138c7d 100644 --- a/OBD.NET/OBD.NET/Extensions/HexExtension.cs +++ b/OBD.NET/OBD.NET/Extensions/HexExtension.cs @@ -1,4 +1,7 @@ -namespace OBD.NET.Extensions; +using System; +using System.Linq; + +namespace OBD.NET.Extensions; public static class HexExtension { diff --git a/OBD.NET/OBD.NET/Logging/OBDConsoleLogger.cs b/OBD.NET/OBD.NET/Logging/OBDConsoleLogger.cs index ed1dcc7..c25ce4d 100644 --- a/OBD.NET/OBD.NET/Logging/OBDConsoleLogger.cs +++ b/OBD.NET/OBD.NET/Logging/OBDConsoleLogger.cs @@ -1,3 +1,5 @@ +using System; + namespace OBD.NET.Logging; /// diff --git a/OBD.NET/OBD.NET/Logging/OBDDebugLogger.cs b/OBD.NET/OBD.NET/Logging/OBDDebugLogger.cs index 9b1fb78..ce7a19f 100644 --- a/OBD.NET/OBD.NET/Logging/OBDDebugLogger.cs +++ b/OBD.NET/OBD.NET/Logging/OBDDebugLogger.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; namespace OBD.NET.Logging; diff --git a/OBD.NET/OBD.NET/OBD.NET.csproj b/OBD.NET/OBD.NET/OBD.NET.csproj index d8788c4..a88d2cd 100644 --- a/OBD.NET/OBD.NET/OBD.NET.csproj +++ b/OBD.NET/OBD.NET/OBD.NET.csproj @@ -1,66 +1,65 @@  - - enable - enable - net6.0;net5.0;netstandard1.4 - 10 + + enable + net6.0;net5.0;net4.8 + 10 - Darth Affe / Roman Lumetsberger - - - OBD.NET - C#-Library to read/write data from/to a car through an ELM327-/STN1170-Adapter - 1.2.0 + Darth Affe / Roman Lumetsberger + - + OBD.NET + C#-Library to read/write data from/to a car through an ELM327-/STN1170-Adapter + 1.2.0 - True - Github - https://github.com/DarthAffe/OBD.NET - https://github.com/DarthAffe/OBD.NET - GPL-2.0-only + True + Github + https://github.com/DarthAffe/OBD.NET + https://github.com/DarthAffe/OBD.NET + GPL-2.0-only - ..\bin\ - true - True - True - snupkg - OBD.NET - OBD.NET - OBD.NET - - + ..\bin\ + true + True + True + snupkg + OBD.NET + OBD.NET + OBD.NET + - - NET5_0;NETFULL - - - NET6_0;NETFULL - + + NET5_0;NETFULL + - - NETCORE;NETSTANDARD;NETSTANDARD1_4 - - - - $(DefineConstants);TRACE;DEBUG - true - full - false - + + NET6_0;NETFULL + - - portable - true - $(NoWarn);CS1591;CS1572;CS1573 - $(DefineConstants);RELEASE - + + NETCORE;NETSTANDARD;NETSTANDARD1_4 + - - - + + $(DefineConstants);TRACE;DEBUG + true + full + false + - - - + + $(DefineConstants);RELEASE + portable + true + $(NoWarn);CS1591;CS1572;CS1573 + + + + + + + + + diff --git a/OBD.NET/OBD.NET/OBDData/00-1F/CommandedSecondaryAirStatus.cs b/OBD.NET/OBD.NET/OBDData/00-1F/CommandedSecondaryAirStatus.cs index 27aecbc..2775906 100644 --- a/OBD.NET/OBD.NET/OBDData/00-1F/CommandedSecondaryAirStatus.cs +++ b/OBD.NET/OBD.NET/OBDData/00-1F/CommandedSecondaryAirStatus.cs @@ -1,4 +1,6 @@ -namespace OBD.NET.OBDData._00_1F; +using System; + +namespace OBD.NET.OBDData._00_1F; public class CommandedSecondaryAirStatus : AbstractOBDData { diff --git a/OBD.NET/OBD.NET/OBDData/00-1F/FuelSystemStatus.cs b/OBD.NET/OBD.NET/OBDData/00-1F/FuelSystemStatus.cs index a90fd69..de2b869 100644 --- a/OBD.NET/OBD.NET/OBDData/00-1F/FuelSystemStatus.cs +++ b/OBD.NET/OBD.NET/OBDData/00-1F/FuelSystemStatus.cs @@ -1,4 +1,6 @@ -namespace OBD.NET.OBDData._00_1F; +using System; + +namespace OBD.NET.OBDData._00_1F; public class FuelSystemStatus : AbstractOBDData { diff --git a/OBD.NET/OBD.NET/OBDData/00-1F/OxygenSensorPresent.cs b/OBD.NET/OBD.NET/OBDData/00-1F/OxygenSensorPresent.cs index c40276f..71edf3a 100644 --- a/OBD.NET/OBD.NET/OBDData/00-1F/OxygenSensorPresent.cs +++ b/OBD.NET/OBD.NET/OBDData/00-1F/OxygenSensorPresent.cs @@ -1,4 +1,6 @@ -namespace OBD.NET.OBDData._00_1F; +using System; + +namespace OBD.NET.OBDData._00_1F; public class OxygenSensorPresent : AbstractOBDData { diff --git a/OBD.NET/OBD.NET/OBDData/00-1F/OxygenSensorsPresent2.cs b/OBD.NET/OBD.NET/OBDData/00-1F/OxygenSensorsPresent2.cs index 52ad864..547895d 100644 --- a/OBD.NET/OBD.NET/OBDData/00-1F/OxygenSensorsPresent2.cs +++ b/OBD.NET/OBD.NET/OBDData/00-1F/OxygenSensorsPresent2.cs @@ -1,4 +1,6 @@ -namespace OBD.NET.OBDData._00_1F; +using System; + +namespace OBD.NET.OBDData._00_1F; public class OxygenSensorPresent2 : AbstractOBDData { diff --git a/OBD.NET/OBD.NET/OBDData/AbstractOBDData.cs b/OBD.NET/OBD.NET/OBDData/AbstractOBDData.cs index 0cd51e8..f32069e 100644 --- a/OBD.NET/OBD.NET/OBDData/AbstractOBDData.cs +++ b/OBD.NET/OBD.NET/OBDData/AbstractOBDData.cs @@ -1,4 +1,5 @@ -using OBD.NET.Extensions; +using System; +using OBD.NET.Extensions; namespace OBD.NET.OBDData; diff --git a/OBD.NET/OBD.NET/OBDData/AbstractPidsSupported.cs b/OBD.NET/OBD.NET/OBDData/AbstractPidsSupported.cs index ad1b596..b699446 100644 --- a/OBD.NET/OBD.NET/OBDData/AbstractPidsSupported.cs +++ b/OBD.NET/OBD.NET/OBDData/AbstractPidsSupported.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Collections.Generic; namespace OBD.NET.OBDData; diff --git a/OBD.NET/OBD.NET/Util/AsyncManulResetEvent.cs b/OBD.NET/OBD.NET/Util/AsyncManulResetEvent.cs index 4a93fe5..515f063 100644 --- a/OBD.NET/OBD.NET/Util/AsyncManulResetEvent.cs +++ b/OBD.NET/OBD.NET/Util/AsyncManulResetEvent.cs @@ -1,4 +1,7 @@ -namespace OBD.NET.Util; +using System.Threading; +using System.Threading.Tasks; + +namespace OBD.NET.Util; /// /// Notifies one or more waiting awaiters that an event has occurred