mirror of
https://github.com/DarthAffe/OBD.NET.git
synced 2025-12-12 16:58:30 +00:00
Added method to wait till all queued commands are processed;
Added method to request data by pid
This commit is contained in:
parent
38d80c0658
commit
b8b94ae554
@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using OBD.NET.Common.Commands;
|
using OBD.NET.Common.Commands;
|
||||||
using OBD.NET.Common.Communication;
|
using OBD.NET.Common.Communication;
|
||||||
@ -80,6 +82,7 @@ namespace OBD.NET.Common.Devices
|
|||||||
Logger?.WriteLine("Setting the Protocol to 'Auto' ...", OBDLogLevel.Debug);
|
Logger?.WriteLine("Setting the Protocol to 'Auto' ...", OBDLogLevel.Debug);
|
||||||
SendCommand(ATCommand.SetProtocolAuto);
|
SendCommand(ATCommand.SetProtocolAuto);
|
||||||
|
|
||||||
|
WaitQueue();
|
||||||
}
|
}
|
||||||
// DarthAffe 21.02.2017: This seems to happen sometimes, i don't know why - just retry.
|
// DarthAffe 21.02.2017: This seems to happen sometimes, i don't know why - just retry.
|
||||||
catch
|
catch
|
||||||
@ -108,7 +111,11 @@ namespace OBD.NET.Common.Devices
|
|||||||
RequestData(pid);
|
RequestData(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void RequestData(byte pid)
|
/// <summary>
|
||||||
|
/// Request data based on a pid
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pid">The pid of the requested data</param>
|
||||||
|
public virtual void RequestData(byte pid)
|
||||||
{
|
{
|
||||||
Logger?.WriteLine("Requesting PID " + pid.ToString("X2") + " ...", OBDLogLevel.Debug);
|
Logger?.WriteLine("Requesting PID " + pid.ToString("X2") + " ...", OBDLogLevel.Debug);
|
||||||
SendCommand(((byte)Mode).ToString("X2") + pid.ToString("X2"));
|
SendCommand(((byte)Mode).ToString("X2") + pid.ToString("X2"));
|
||||||
@ -124,11 +131,20 @@ namespace OBD.NET.Common.Devices
|
|||||||
{
|
{
|
||||||
Logger?.WriteLine("Requesting Type " + typeof(T).Name + " ...", OBDLogLevel.Debug);
|
Logger?.WriteLine("Requesting Type " + typeof(T).Name + " ...", OBDLogLevel.Debug);
|
||||||
byte pid = ResolvePid<T>();
|
byte pid = ResolvePid<T>();
|
||||||
|
return await RequestDataAsync(pid) as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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)
|
||||||
|
{
|
||||||
Logger?.WriteLine("Requesting PID " + pid.ToString("X2") + " ...", OBDLogLevel.Debug);
|
Logger?.WriteLine("Requesting PID " + pid.ToString("X2") + " ...", OBDLogLevel.Debug);
|
||||||
CommandResult result = SendCommand(((byte)Mode).ToString("X2") + pid.ToString("X2"));
|
CommandResult result = SendCommand(((byte)Mode).ToString("X2") + pid.ToString("X2"));
|
||||||
|
|
||||||
await result.WaitHandle.WaitAsync();
|
await result.WaitHandle.WaitAsync();
|
||||||
return result.Result as T;
|
return result.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override object ProcessMessage(string message)
|
protected override object ProcessMessage(string message)
|
||||||
@ -168,16 +184,42 @@ namespace OBD.NET.Common.Devices
|
|||||||
where T : class, IOBDData, new()
|
where T : class, IOBDData, new()
|
||||||
{
|
{
|
||||||
if (!PidCache.TryGetValue(typeof(T), out byte pid))
|
if (!PidCache.TryGetValue(typeof(T), out byte pid))
|
||||||
{
|
pid = AddToPidCache<T>();
|
||||||
T data = Activator.CreateInstance<T>();
|
|
||||||
pid = data.PID;
|
|
||||||
PidCache.Add(typeof(T), pid);
|
|
||||||
DataTypeCache.Add(pid, typeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual byte AddToPidCache<T>()
|
||||||
|
where T : class, IOBDData, new() => AddToPidCache(typeof(T));
|
||||||
|
|
||||||
|
protected virtual byte AddToPidCache(Type obdDataType)
|
||||||
|
{
|
||||||
|
IOBDData data = (IOBDData)Activator.CreateInstance(obdDataType);
|
||||||
|
if (data == null) throw new ArgumentException("Has to implement IOBDData", nameof(obdDataType));
|
||||||
|
|
||||||
|
byte pid = data.PID;
|
||||||
|
|
||||||
|
PidCache.Add(obdDataType, pid);
|
||||||
|
DataTypeCache.Add(pid, obdDataType);
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// YOU SHOULDN'T NEED THIS METHOD!
|
||||||
|
///
|
||||||
|
/// You should only use this method if you're requesting data by pid instead of the <see cref="RequestData{T}"/>-method.
|
||||||
|
///
|
||||||
|
/// Initializes the PID-Cache with all IOBDData-Types contained in OBD.NET.
|
||||||
|
/// You can add additional ones with <see cref="AddToPidCache{T}"/>.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void InitializePidCache()
|
||||||
|
{
|
||||||
|
TypeInfo iobdDataInfo = typeof(IOBDData).GetTypeInfo();
|
||||||
|
foreach (TypeInfo obdDataType in iobdDataInfo.Assembly.DefinedTypes.Where(t => t.IsClass && !t.IsAbstract && iobdDataInfo.IsAssignableFrom(t)))
|
||||||
|
AddToPidCache(obdDataType.AsType());
|
||||||
|
}
|
||||||
|
|
||||||
public override void Dispose() => Dispose(true);
|
public override void Dispose() => Dispose(true);
|
||||||
|
|
||||||
public void Dispose(bool sendCloseProtocol)
|
public void Dispose(bool sendCloseProtocol)
|
||||||
|
|||||||
@ -23,6 +23,11 @@ namespace OBD.NET.Common.Devices
|
|||||||
private Task _commandWorkerTask;
|
private Task _commandWorkerTask;
|
||||||
private CancellationTokenSource _commandCancellationToken;
|
private CancellationTokenSource _commandCancellationToken;
|
||||||
|
|
||||||
|
private volatile int _queueSize = 0;
|
||||||
|
private readonly ManualResetEvent _queueEmptyEvent = new ManualResetEvent(true);
|
||||||
|
|
||||||
|
public int QueueSize => _queueSize;
|
||||||
|
|
||||||
protected QueuedCommand CurrentCommand;
|
protected QueuedCommand CurrentCommand;
|
||||||
protected IOBDLogger Logger { get; }
|
protected IOBDLogger Logger { get; }
|
||||||
protected ISerialConnection Connection { get; }
|
protected ISerialConnection Connection { get; }
|
||||||
@ -102,6 +107,8 @@ namespace OBD.NET.Common.Devices
|
|||||||
Logger?.WriteLine("Queuing Command: '" + command.Replace('\r', '\'') + "'", OBDLogLevel.Verbose);
|
Logger?.WriteLine("Queuing Command: '" + command.Replace('\r', '\'') + "'", OBDLogLevel.Verbose);
|
||||||
|
|
||||||
QueuedCommand cmd = new QueuedCommand(command);
|
QueuedCommand cmd = new QueuedCommand(command);
|
||||||
|
_queueEmptyEvent.Reset();
|
||||||
|
_queueSize++;
|
||||||
_commandQueue.Add(cmd);
|
_commandQueue.Add(cmd);
|
||||||
|
|
||||||
return cmd.CommandResult;
|
return cmd.CommandResult;
|
||||||
@ -193,8 +200,14 @@ namespace OBD.NET.Common.Devices
|
|||||||
while (!_commandCancellationToken.IsCancellationRequested)
|
while (!_commandCancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
CurrentCommand = null;
|
CurrentCommand = null;
|
||||||
if (_commandQueue.TryTake(out CurrentCommand, Timeout.Infinite, _commandCancellationToken.Token))
|
|
||||||
|
if (_queueSize == 0)
|
||||||
|
_queueEmptyEvent.Set();
|
||||||
|
|
||||||
|
if (_commandQueue.TryTake(out CurrentCommand, 10, _commandCancellationToken.Token))
|
||||||
{
|
{
|
||||||
|
_queueSize--;
|
||||||
|
|
||||||
Logger?.WriteLine("Writing Command: '" + CurrentCommand.CommandText.Replace('\r', '\'') + "'", OBDLogLevel.Verbose);
|
Logger?.WriteLine("Writing Command: '" + CurrentCommand.CommandText.Replace('\r', '\'') + "'", OBDLogLevel.Verbose);
|
||||||
|
|
||||||
if (Connection.IsAsync)
|
if (Connection.IsAsync)
|
||||||
@ -208,6 +221,10 @@ namespace OBD.NET.Common.Devices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WaitQueue() => _queueEmptyEvent.WaitOne();
|
||||||
|
|
||||||
|
public async Task WaitQueueAsync() => await Task.Run(() => WaitQueue());
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace OBD.NET.Common.Logging
|
namespace OBD.NET.Common.Logging
|
||||||
{
|
{
|
||||||
@ -8,9 +9,31 @@ namespace OBD.NET.Common.Logging
|
|||||||
/// <seealso cref="IOBDLogger" />
|
/// <seealso cref="IOBDLogger" />
|
||||||
public class OBDDebugLogger : IOBDLogger
|
public class OBDDebugLogger : IOBDLogger
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
public OBDLogLevel LogLevel { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public OBDDebugLogger(OBDLogLevel level = OBDLogLevel.None)
|
||||||
|
{
|
||||||
|
this.LogLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
public void WriteLine(string text, OBDLogLevel level) => Debug.WriteLine($"{level}: {text}");
|
public void WriteLine(string text, OBDLogLevel level)
|
||||||
|
{
|
||||||
|
if (LogLevel == OBDLogLevel.None) return;
|
||||||
|
|
||||||
|
if ((int)level <= (int)LogLevel)
|
||||||
|
Debug.WriteLine($"{DateTime.Now:G} - {level} - {text}");
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using OBD.NET.Common.Devices;
|
using OBD.NET.Common.Devices;
|
||||||
|
using OBD.NET.Common.Extensions;
|
||||||
using OBD.NET.Common.Logging;
|
using OBD.NET.Common.Logging;
|
||||||
using OBD.NET.Common.OBDData;
|
using OBD.NET.Common.OBDData;
|
||||||
using ODB.NET.Desktop.Communication;
|
using ODB.NET.Desktop.Communication;
|
||||||
@ -25,9 +26,10 @@ namespace ODB.NET.ConsoleClient
|
|||||||
using (ELM327 dev = new ELM327(connection, new OBDConsoleLogger(OBDLogLevel.Debug)))
|
using (ELM327 dev = new ELM327(connection, new OBDConsoleLogger(OBDLogLevel.Debug)))
|
||||||
{
|
{
|
||||||
dev.SubscribeDataReceived<EngineRPM>((sender, data) => Console.WriteLine("EngineRPM: " + data.Data.Rpm));
|
dev.SubscribeDataReceived<EngineRPM>((sender, data) => Console.WriteLine("EngineRPM: " + data.Data.Rpm));
|
||||||
|
|
||||||
dev.SubscribeDataReceived<VehicleSpeed>((sender, data) => Console.WriteLine("VehicleSpeed: " + data.Data.Speed));
|
dev.SubscribeDataReceived<VehicleSpeed>((sender, data) => Console.WriteLine("VehicleSpeed: " + data.Data.Speed));
|
||||||
|
|
||||||
|
dev.SubscribeDataReceived<IOBDData>((sender, data) => Console.WriteLine($"PID {data.Data.PID.ToHexString()}: {data.Data}"));
|
||||||
|
|
||||||
dev.Initialize();
|
dev.Initialize();
|
||||||
dev.RequestData<FuelType>();
|
dev.RequestData<FuelType>();
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
@ -40,9 +42,9 @@ namespace ODB.NET.ConsoleClient
|
|||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
|
|
||||||
//Async example
|
//Async example
|
||||||
MainAsync(comPort).Wait();
|
//MainAsync(comPort).Wait();
|
||||||
|
|
||||||
Console.ReadLine();
|
//Console.ReadLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -30,7 +30,7 @@ namespace ODB.NET.Desktop.Logging
|
|||||||
{
|
{
|
||||||
if (LogLevel == OBDLogLevel.None) return;
|
if (LogLevel == OBDLogLevel.None) return;
|
||||||
|
|
||||||
if ((int)level >= (int)LogLevel)
|
if ((int)level <= (int)LogLevel)
|
||||||
Console.WriteLine($"{DateTime.Now:G} - {level} - {text}");
|
Console.WriteLine($"{DateTime.Now:G} - {level} - {text}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user