1
0
mirror of https://github.com/DarthAffe/OBD.NET.git synced 2025-12-12 08:48: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:
Darth Affe 2017-08-26 17:42:45 +02:00
parent 38d80c0658
commit b8b94ae554
5 changed files with 99 additions and 15 deletions

View File

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using OBD.NET.Common.Commands;
using OBD.NET.Common.Communication;
@ -80,6 +82,7 @@ namespace OBD.NET.Common.Devices
Logger?.WriteLine("Setting the Protocol to 'Auto' ...", OBDLogLevel.Debug);
SendCommand(ATCommand.SetProtocolAuto);
WaitQueue();
}
// DarthAffe 21.02.2017: This seems to happen sometimes, i don't know why - just retry.
catch
@ -108,7 +111,11 @@ namespace OBD.NET.Common.Devices
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);
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);
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);
CommandResult result = SendCommand(((byte)Mode).ToString("X2") + pid.ToString("X2"));
await result.WaitHandle.WaitAsync();
return result.Result as T;
return result.Result;
}
protected override object ProcessMessage(string message)
@ -168,16 +184,42 @@ namespace OBD.NET.Common.Devices
where T : class, IOBDData, new()
{
if (!PidCache.TryGetValue(typeof(T), out byte pid))
{
T data = Activator.CreateInstance<T>();
pid = data.PID;
PidCache.Add(typeof(T), pid);
DataTypeCache.Add(pid, typeof(T));
}
pid = AddToPidCache<T>();
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 void Dispose(bool sendCloseProtocol)

View File

@ -23,6 +23,11 @@ namespace OBD.NET.Common.Devices
private Task _commandWorkerTask;
private CancellationTokenSource _commandCancellationToken;
private volatile int _queueSize = 0;
private readonly ManualResetEvent _queueEmptyEvent = new ManualResetEvent(true);
public int QueueSize => _queueSize;
protected QueuedCommand CurrentCommand;
protected IOBDLogger Logger { get; }
protected ISerialConnection Connection { get; }
@ -102,6 +107,8 @@ namespace OBD.NET.Common.Devices
Logger?.WriteLine("Queuing Command: '" + command.Replace('\r', '\'') + "'", OBDLogLevel.Verbose);
QueuedCommand cmd = new QueuedCommand(command);
_queueEmptyEvent.Reset();
_queueSize++;
_commandQueue.Add(cmd);
return cmd.CommandResult;
@ -193,8 +200,14 @@ namespace OBD.NET.Common.Devices
while (!_commandCancellationToken.IsCancellationRequested)
{
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);
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>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>

View File

@ -1,4 +1,5 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
namespace OBD.NET.Common.Logging
{
@ -8,9 +9,31 @@ namespace OBD.NET.Common.Logging
/// <seealso cref="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
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
}

View File

@ -2,6 +2,7 @@
using System.Threading;
using System.Threading.Tasks;
using OBD.NET.Common.Devices;
using OBD.NET.Common.Extensions;
using OBD.NET.Common.Logging;
using OBD.NET.Common.OBDData;
using ODB.NET.Desktop.Communication;
@ -25,9 +26,10 @@ namespace ODB.NET.ConsoleClient
using (ELM327 dev = new ELM327(connection, new OBDConsoleLogger(OBDLogLevel.Debug)))
{
dev.SubscribeDataReceived<EngineRPM>((sender, data) => Console.WriteLine("EngineRPM: " + data.Data.Rpm));
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.RequestData<FuelType>();
for (int i = 0; i < 5; i++)
@ -40,9 +42,9 @@ namespace ODB.NET.ConsoleClient
Console.ReadLine();
//Async example
MainAsync(comPort).Wait();
//MainAsync(comPort).Wait();
Console.ReadLine();
//Console.ReadLine();
}
/// <summary>

View File

@ -30,7 +30,7 @@ namespace ODB.NET.Desktop.Logging
{
if (LogLevel == OBDLogLevel.None) return;
if ((int)level >= (int)LogLevel)
if ((int)level <= (int)LogLevel)
Console.WriteLine($"{DateTime.Now:G} - {level} - {text}");
}