mirror of
https://github.com/DarthAffe/OBD.NET.git
synced 2025-12-12 16:58:30 +00:00
Added DTC support
(this will most likely only work for up to 3 trouble codes)
This commit is contained in:
parent
43dd6968d9
commit
59e8580e8d
@ -7,6 +7,7 @@ namespace OBD.NET.Common.Devices
|
|||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
public object Result { get; set; }
|
public object Result { get; set; }
|
||||||
|
public string RawResult { get; set; }
|
||||||
public AsyncManualResetEvent WaitHandle { get; }
|
public AsyncManualResetEvent WaitHandle { get; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -11,6 +11,7 @@ using OBD.NET.Common.Events.EventArgs;
|
|||||||
using OBD.NET.Common.Extensions;
|
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 OBD.NET.Common.OBDData.DTC;
|
||||||
|
|
||||||
namespace OBD.NET.Common.Devices
|
namespace OBD.NET.Common.Devices
|
||||||
{
|
{
|
||||||
@ -147,33 +148,63 @@ namespace OBD.NET.Common.Devices
|
|||||||
return result.Result;
|
return result.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual TroubleCode[] RequestDTCs() => RequestDTCsAsync().Result;
|
||||||
|
|
||||||
|
public virtual async Task<TroubleCode[]> RequestDTCsAsync()
|
||||||
|
{
|
||||||
|
Logger?.WriteLine("Requesting DTCs ...", OBDLogLevel.Debug);
|
||||||
|
MonitorStatusSinceDTCsClreared dtcStatus = await RequestDataAsync<MonitorStatusSinceDTCsClreared>();
|
||||||
|
|
||||||
|
CommandResult result = SendCommand(((int)Mode.ShowStoredDiagnosticTroubleCodes).ToString());
|
||||||
|
await result.WaitHandle.WaitAsync();
|
||||||
|
|
||||||
|
if (!(result.Result is List<TroubleCode> resultCodes)) return new TroubleCode[0];
|
||||||
|
|
||||||
|
int count = Math.Min(dtcStatus.DTCCount, resultCodes.Count);
|
||||||
|
return resultCodes.Take(count).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
protected override object ProcessMessage(string message)
|
protected override object ProcessMessage(string message)
|
||||||
{
|
{
|
||||||
DateTime timestamp = DateTime.Now;
|
DateTime timestamp = DateTime.Now;
|
||||||
|
|
||||||
RawDataReceived?.Invoke(this, new RawDataReceivedEventArgs(message, timestamp));
|
RawDataReceived?.Invoke(this, new RawDataReceivedEventArgs(message, timestamp));
|
||||||
|
|
||||||
if (message.Length > 4)
|
if (message.Length >= 4)
|
||||||
{
|
{
|
||||||
if (message[0] == '4')
|
if (message[0] == '4')
|
||||||
{
|
{
|
||||||
byte mode = (byte)message[1].GetHexVal();
|
byte mode = (byte)message[1].GetHexVal();
|
||||||
if (mode == (byte)Mode)
|
switch ((Mode)mode)
|
||||||
{
|
{
|
||||||
byte pid = (byte)message.Substring(2, 2).GetHexVal();
|
case Mode.ShowCurrentData:
|
||||||
if (DataTypeCache.TryGetValue(pid, out Type dataType))
|
byte pid = (byte)message.Substring(2, 2).GetHexVal();
|
||||||
{
|
if (DataTypeCache.TryGetValue(pid, out Type dataType))
|
||||||
IOBDData obdData = (IOBDData)Activator.CreateInstance(dataType);
|
{
|
||||||
obdData.Load(message.Substring(4, message.Length - 4));
|
IOBDData obdData = (IOBDData)Activator.CreateInstance(dataType);
|
||||||
|
obdData.Load(message.Substring(4));
|
||||||
|
|
||||||
if (DataReceivedEventHandlers.TryGetValue(dataType, out IDataEventManager dataEventManager))
|
if (DataReceivedEventHandlers.TryGetValue(dataType, out IDataEventManager dataEventManager))
|
||||||
dataEventManager.RaiseEvent(this, obdData, timestamp);
|
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);
|
genericDataEventManager.RaiseEvent(this, obdData, timestamp);
|
||||||
|
|
||||||
return obdData;
|
return obdData;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode.ShowStoredDiagnosticTroubleCodes:
|
||||||
|
//TODO DarthAffe 14.09.2017: I think multiple frames (as stated in the documentation for dtcs) aren't supported right now - how to handle them?
|
||||||
|
List<TroubleCode> troubleCodes = new List<TroubleCode>();
|
||||||
|
for (int i = 2; (i + 3) < message.Length; i += 4)
|
||||||
|
{
|
||||||
|
string dtc = message.Substring(i, 4);
|
||||||
|
TroubleCode troubleCode = new TroubleCode();
|
||||||
|
troubleCode.Load(dtc);
|
||||||
|
troubleCodes.Add(troubleCode);
|
||||||
|
}
|
||||||
|
return troubleCodes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -183,6 +183,7 @@ namespace OBD.NET.Common.Devices
|
|||||||
{
|
{
|
||||||
object data = ProcessMessage(message);
|
object data = ProcessMessage(message);
|
||||||
CurrentCommand.CommandResult.Result = data;
|
CurrentCommand.CommandResult.Result = data;
|
||||||
|
CurrentCommand.CommandResult.RawResult = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
namespace OBD.NET.Common.OBDData
|
||||||
|
{
|
||||||
|
public class MonitorStatusSinceDTCsClreared : AbstractOBDData
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
public bool IsMilOn => (A & (1 << 7)) != 0;
|
||||||
|
|
||||||
|
public int DTCCount => A & ~(1 << 7);
|
||||||
|
|
||||||
|
//TODO DarthAffe 26.08.2017: Implement Test-Bits https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_1_PID_01
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public MonitorStatusSinceDTCsClreared()
|
||||||
|
: base(0x01, 4)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public override string ToString() => IsMilOn.ToString();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
122
OBD.NET/OBD.NET.Common/OBDData/DTC/TroubleCode.cs
Normal file
122
OBD.NET/OBD.NET.Common/OBDData/DTC/TroubleCode.cs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OBD.NET.Common.Extensions;
|
||||||
|
|
||||||
|
namespace OBD.NET.Common.OBDData.DTC
|
||||||
|
{
|
||||||
|
public class TroubleCode : AbstractOBDData
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private static readonly Dictionary<TroublePart, string> PART_DESCRIPTION = new Dictionary<TroublePart, string>
|
||||||
|
{
|
||||||
|
|
||||||
|
{ TroublePart.Powertrain, "P" },
|
||||||
|
{ TroublePart.Chassis, "C" },
|
||||||
|
{ TroublePart.Body, "B" },
|
||||||
|
{ TroublePart.Network, "U" },
|
||||||
|
};
|
||||||
|
|
||||||
|
public TroublePart TroublePart
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
byte data = (byte)(A & 0b11000000);
|
||||||
|
switch (data)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return TroublePart.Powertrain;
|
||||||
|
case 0b01000000:
|
||||||
|
return TroublePart.Chassis;
|
||||||
|
case 0b10000000:
|
||||||
|
return TroublePart.Body;
|
||||||
|
case 0b11000000:
|
||||||
|
return TroublePart.Network;
|
||||||
|
default:
|
||||||
|
throw new IndexOutOfRangeException($"Can't parse TroublePart with data {data}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Definition Definition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
byte data = (byte)(A & 0b00110000);
|
||||||
|
switch (data)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return Definition.SAEJ2012;
|
||||||
|
case 0b01000000:
|
||||||
|
return Definition.Custom;
|
||||||
|
case 0b10000000:
|
||||||
|
return Definition.Undefined;
|
||||||
|
case 0b11000000:
|
||||||
|
return Definition.Undefined2;
|
||||||
|
default:
|
||||||
|
throw new IndexOutOfRangeException($"Can't parse Definition with data {data}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpecificPart SpecificPart => (SpecificPart)(A & 0b00001111);
|
||||||
|
|
||||||
|
public string FaultCode => B.ToHexString();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public TroubleCode()
|
||||||
|
: base(byte.MaxValue, 2) // DarthAffe 14.09.2017: Trouble-Codes don't have a pid
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public override string ToString() => $"{PART_DESCRIPTION[TroublePart]}{(int)Definition}{((byte)SpecificPart).ToHexString()[1]}{FaultCode}";
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Data
|
||||||
|
|
||||||
|
public enum TroublePart
|
||||||
|
{
|
||||||
|
Powertrain = 0,
|
||||||
|
Chassis = 1,
|
||||||
|
Body = 2,
|
||||||
|
Network = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Definition
|
||||||
|
{
|
||||||
|
SAEJ2012 = 0,
|
||||||
|
Custom = 1,
|
||||||
|
Undefined = 2,
|
||||||
|
Undefined2 = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SpecificPart
|
||||||
|
{
|
||||||
|
Undefined = 0,
|
||||||
|
FuelAndAirMetering = 1,
|
||||||
|
FuelAndAirMeteringInjectorCircuit = 2,
|
||||||
|
IgnitionSystemOfMisfire = 3,
|
||||||
|
AuxiliaryEmissionControls = 4,
|
||||||
|
VehicleSpeedControlAndIdleControlSystem = 5,
|
||||||
|
ComputerOutputCircuit = 6,
|
||||||
|
Transmission = 7,
|
||||||
|
Transmission2 = 8,
|
||||||
|
Undefined2 = 9,
|
||||||
|
Undefined3 = 10,
|
||||||
|
Undefined4 = 11,
|
||||||
|
Undefined5 = 12,
|
||||||
|
Undefined6 = 13,
|
||||||
|
Undefined7 = 14,
|
||||||
|
Undefined8 = 15,
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user