-
-
Notifications
You must be signed in to change notification settings - Fork 120
Expand file tree
/
Copy pathDeviceBase.cs
More file actions
144 lines (123 loc) · 5.02 KB
/
DeviceBase.cs
File metadata and controls
144 lines (123 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Device.Net
{
/// <summary>
/// Base class for all devices
/// </summary>
public abstract class DeviceBase : IDisposable
{
#region Fields
private readonly SemaphoreSlim _WriteAndReadLock = new(1, 1);
private bool disposed;
#endregion
#region Protected Properties
protected ILogger Logger { get; }
protected ILoggerFactory LoggerFactory { get; }
#endregion
#region Public Properties
public string DeviceId { get; }
#endregion
#region Constructor
protected DeviceBase(
string deviceId,
ILoggerFactory loggerFactory = null,
ILogger logger = null)
{
DeviceId = deviceId ?? throw new ArgumentNullException(nameof(deviceId));
Logger = logger ?? NullLogger.Instance;
LoggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
}
#endregion
#region Public Abstract Methods
//TODO: Why are these here?
public abstract Task<TransferResult> ReadAsync(CancellationToken cancellationToken = default);
public abstract Task<uint> WriteAsync(byte[] data, CancellationToken cancellationToken = default);
#endregion
#region Public Methods
public virtual Task Flush(CancellationToken cancellationToken = default) => throw new NotImplementedException(Messages.ErrorMessageFlushNotImplemented);
public async Task<TransferResult> WriteAndReadAsync(byte[] writeBuffer, CancellationToken cancellationToken = default)
{
if (writeBuffer == null) throw new ArgumentNullException(nameof(writeBuffer));
await _WriteAndReadLock.WaitAsync(cancellationToken).ConfigureAwait(false);
using var logScope = Logger.BeginScope("DeviceId: {deviceId} Call: {call} Write Buffer Length: {writeBufferLength}", DeviceId, nameof(WriteAndReadAsync), writeBuffer.Length);
try
{
_ = await WriteAsync(writeBuffer, cancellationToken).ConfigureAwait(false);
var retVal = await ReadAsync(cancellationToken).ConfigureAwait(false);
Logger.LogInformation(Messages.SuccessMessageWriteAndReadCalled);
return retVal;
}
catch (Exception ex)
{
Logger.LogError(ex, Messages.ErrorMessageReadWrite);
throw;
}
finally
{
_ = _WriteAndReadLock.Release();
}
}
public virtual void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool dispose)
{
if (disposed)
{
Logger.LogWarning(Messages.WarningMessageAlreadyDisposed, DeviceId);
return;
}
disposed = true;
Logger.LogInformation($"{nameof(DeviceBase)}: {Messages.InformationMessageDisposingDevice}", DeviceId);
_WriteAndReadLock.Dispose();
GC.SuppressFinalize(this);
}
#endregion
#region Public Static Methods
public static ConnectedDeviceDefinition GetDeviceDefinitionFromWindowsDeviceId(
string deviceId,
DeviceType deviceType,
ILogger logger,
Guid? classGuid = null)
{
uint? vid = null;
uint? pid = null;
try
{
vid = GetNumberFromDeviceId(deviceId, "vid_");
pid = GetNumberFromDeviceId(deviceId, "pid_");
}
#pragma warning disable CA1031
catch (Exception ex)
#pragma warning restore CA1031
{
//If anything goes wrong here, log it and move on.
(logger ?? NullLogger.Instance).LogError(ex, "Error {errorMessage} Area: {area}", ex.Message, nameof(GetDeviceDefinitionFromWindowsDeviceId));
}
return new ConnectedDeviceDefinition(deviceId, deviceType, vid, pid, classGuid: classGuid);
}
#endregion
#region Private Static Methods
private static uint GetNumberFromDeviceId(string deviceId, string searchString)
{
if (deviceId == null) throw new ArgumentNullException(nameof(deviceId));
var indexOfSearchString = deviceId.IndexOf(searchString, StringComparison.OrdinalIgnoreCase);
string hexString = null;
if (indexOfSearchString > -1)
{
hexString = deviceId.Substring(indexOfSearchString + searchString.Length, 4);
}
#pragma warning disable CA1305 // Specify IFormatProvider
var numberAsInteger = uint.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
#pragma warning restore CA1305 // Specify IFormatProvider
return numberAsInteger;
}
#endregion
}
}