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

Readded EnhanvedSerialPort for .NET-Framework support

This commit is contained in:
Darth Affe 2022-05-21 13:35:11 +02:00
parent 163f5eb3a3
commit 2136aaf0ca
25 changed files with 372 additions and 89 deletions

View File

@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFramework>net4.8</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>

View File

@ -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<string> availablePorts = SerialConnection.GetAvailablePorts();
// IEnumerable<string> 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];

View File

@ -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

View File

@ -1,4 +1,6 @@
using OBD.NET.Communication.EventArgs;
using System;
using System.Threading.Tasks;
using OBD.NET.Communication.EventArgs;
namespace OBD.NET.Communication;

View File

@ -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,11 +47,78 @@ public class SerialConnection : ISerialConnection
#region Methods
public static IEnumerable<string> GetAvailablePorts()
public static IEnumerable<string> GetAvailablePorts() => SerialPort.GetPortNames();
public void Connect() => _serialPort.Open();
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
return SerialPort.GetPortNames();
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
}
#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<DataReceivedEventArgs>? 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<string> GetAvailablePorts() => SerialPort.GetPortNames();
public void Connect() => _serialPort.Open();
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)

View File

@ -1,4 +1,6 @@
namespace OBD.NET.DataTypes;
using System;
namespace OBD.NET.DataTypes;
public abstract class GenericData
{

View File

@ -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;

View File

@ -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;

View File

@ -1,4 +1,5 @@
using OBD.NET.OBDData;
using System;
using OBD.NET.OBDData;
namespace OBD.NET.Events.EventArgs;

View File

@ -1,4 +1,6 @@
namespace OBD.NET.Events.EventArgs;
using System;
namespace OBD.NET.Events.EventArgs;
public class RawDataReceivedEventArgs
{

View File

@ -1,4 +1,5 @@
using OBD.NET.Devices;
using System;
using OBD.NET.Devices;
using OBD.NET.Events.EventArgs;
using OBD.NET.OBDData;

View File

@ -1,4 +1,5 @@
using OBD.NET.OBDData;
using System;
using OBD.NET.OBDData;
namespace OBD.NET.Events;

View File

@ -1,4 +1,6 @@
namespace OBD.NET.Exceptions;
using System;
namespace OBD.NET.Exceptions;
public class SerialException : Exception
{

View File

@ -1,4 +1,6 @@
namespace OBD.NET.Exceptions;
using System;
namespace OBD.NET.Exceptions;
public class UnexpectedResultException : Exception
{

View File

@ -1,4 +1,7 @@
namespace OBD.NET.Extensions;
using System;
using System.Linq;
namespace OBD.NET.Extensions;
public static class HexExtension
{

View File

@ -1,3 +1,5 @@
using System;
namespace OBD.NET.Logging;
/// <summary>

View File

@ -1,4 +1,5 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
namespace OBD.NET.Logging;

View File

@ -1,9 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFrameworks>net6.0;net5.0;netstandard1.4</TargetFrameworks>
<TargetFrameworks>net6.0;net5.0;net4.8</TargetFrameworks>
<LangVersion>10</LangVersion>
<Authors>Darth Affe / Roman Lumetsberger</Authors>
@ -49,10 +48,10 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
<DebugType>portable</DebugType>
<Optimize>true</Optimize>
<NoWarn>$(NoWarn);CS1591;CS1572;CS1573</NoWarn>
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">

View File

@ -1,4 +1,6 @@
namespace OBD.NET.OBDData._00_1F;
using System;
namespace OBD.NET.OBDData._00_1F;
public class CommandedSecondaryAirStatus : AbstractOBDData
{

View File

@ -1,4 +1,6 @@
namespace OBD.NET.OBDData._00_1F;
using System;
namespace OBD.NET.OBDData._00_1F;
public class FuelSystemStatus : AbstractOBDData
{

View File

@ -1,4 +1,6 @@
namespace OBD.NET.OBDData._00_1F;
using System;
namespace OBD.NET.OBDData._00_1F;
public class OxygenSensorPresent : AbstractOBDData
{

View File

@ -1,4 +1,6 @@
namespace OBD.NET.OBDData._00_1F;
using System;
namespace OBD.NET.OBDData._00_1F;
public class OxygenSensorPresent2 : AbstractOBDData
{

View File

@ -1,4 +1,5 @@
using OBD.NET.Extensions;
using System;
using OBD.NET.Extensions;
namespace OBD.NET.OBDData;

View File

@ -1,4 +1,5 @@
using System.Collections;
using System.Collections.Generic;
namespace OBD.NET.OBDData;

View File

@ -1,4 +1,7 @@
namespace OBD.NET.Util;
using System.Threading;
using System.Threading.Tasks;
namespace OBD.NET.Util;
/// <summary>
/// Notifies one or more waiting awaiters that an event has occurred