1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-31 17:53:39 +00:00

Compare commits

...

5 Commits

Author SHA1 Message Date
4675349621
Merge pull request #304 from DarthAffe/DeviceExceptionHandling
Device exception handling
2023-03-05 18:10:12 +01:00
4a9bbb64dc Added missing doc comment 2023-03-05 18:06:08 +01:00
30ccfdcd85 (MAJOR) Added success-indication to device updates and forced flushes after nonsuccessful ones.
Added exception handling the last missing queues.
2023-03-05 18:04:50 +01:00
1b4b92b44c
Merge pull request #303 from DarthAffe/DeviceExceptionHandling
Added exception-handling to all UpdateQueues
2023-03-05 16:38:32 +01:00
37e4954583 Added exception-handling to all UpdateQueues 2023-03-05 16:34:01 +01:00
24 changed files with 355 additions and 128 deletions

View File

@ -111,7 +111,7 @@ public abstract class AbstractRGBDevice<TDeviceInfo> : Placeable, IRGBDevice<TDe
/// </summary> /// </summary>
/// <param name="flushLeds">Forces all LEDs to be treated as dirty.</param> /// <param name="flushLeds">Forces all LEDs to be treated as dirty.</param>
/// <returns>The collection LEDs to update.</returns> /// <returns>The collection LEDs to update.</returns>
protected virtual IEnumerable<Led> GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)).Where(led => led.RequestedColor?.A > 0); protected virtual IEnumerable<Led> GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds || UpdateQueue.RequiresFlush) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)).Where(led => led.RequestedColor?.A > 0);
/// <summary> /// <summary>
/// Gets an enumerable of a custom data and color tuple for the specified leds. /// Gets an enumerable of a custom data and color tuple for the specified leds.

View File

@ -178,7 +178,7 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
/// </summary> /// </summary>
/// <param name="ex">The exception to throw.</param> /// <param name="ex">The exception to throw.</param>
/// <param name="isCritical">Indicates if the exception is critical for device provider to work correctly.</param> /// <param name="isCritical">Indicates if the exception is critical for device provider to work correctly.</param>
protected virtual void Throw(Exception ex, bool isCritical = false) public virtual void Throw(Exception ex, bool isCritical = false)
{ {
ExceptionEventArgs args = new(ex, isCritical, ThrowsExceptions); ExceptionEventArgs args = new(ex, isCritical, ThrowsExceptions);
try { OnException(args); } catch { /* we don't want to throw due to bad event handlers */ } try { OnException(args); } catch { /* we don't want to throw due to bad event handlers */ }

View File

@ -20,6 +20,10 @@ public interface IRGBDeviceProvider : IDisposable
/// <summary> /// <summary>
/// Indicates if exceptions in the device provider are thrown or silently ignored. /// Indicates if exceptions in the device provider are thrown or silently ignored.
/// </summary> /// </summary>
/// <remarks>
/// This should only be set to <c>true</c> for debugging/development purposes.
/// Production code should use the <see cref="Exception"/>-Event to handle exceptions.
/// </remarks>
bool ThrowsExceptions { get; } bool ThrowsExceptions { get; }
/// <summary> /// <summary>

View File

@ -11,6 +11,11 @@ namespace RGB.NET.Core;
public interface IUpdateQueue<TIdentifier, TData> : IDisposable public interface IUpdateQueue<TIdentifier, TData> : IDisposable
where TIdentifier : notnull where TIdentifier : notnull
{ {
/// <summary>
/// Gets a bool indicating if the queue requires a flush of all data due to an internal error.
/// </summary>
bool RequiresFlush { get; }
/// <summary> /// <summary>
/// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available. /// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available.
/// </summary> /// </summary>

View File

@ -19,6 +19,9 @@ public abstract class UpdateQueue<TIdentifier, TData> : IUpdateQueue<TIdentifier
private readonly IDeviceUpdateTrigger _updateTrigger; private readonly IDeviceUpdateTrigger _updateTrigger;
private readonly Dictionary<TIdentifier, TData> _currentDataSet = new(); private readonly Dictionary<TIdentifier, TData> _currentDataSet = new();
/// <inheritdoc />
public bool RequiresFlush { get; private set; }
#endregion #endregion
#region Constructors #region Constructors
@ -62,7 +65,7 @@ public abstract class UpdateQueue<TIdentifier, TData> : IUpdateQueue<TIdentifier
_currentDataSet.Clear(); _currentDataSet.Clear();
} }
Update(data); RequiresFlush = !Update(data);
ArrayPool<(TIdentifier, TData)>.Shared.Return(dataSet); ArrayPool<(TIdentifier, TData)>.Shared.Return(dataSet);
} }
@ -78,7 +81,7 @@ public abstract class UpdateQueue<TIdentifier, TData> : IUpdateQueue<TIdentifier
/// Performs the update this queue is responsible for. /// Performs the update this queue is responsible for.
/// </summary> /// </summary>
/// <param name="dataSet">The set of data that needs to be updated.</param> /// <param name="dataSet">The set of data that needs to be updated.</param>
protected abstract void Update(in ReadOnlySpan<(TIdentifier key, TData color)> dataSet); protected abstract bool Update(in ReadOnlySpan<(TIdentifier key, TData color)> dataSet);
/// <summary> /// <summary>
/// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available. /// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available.

View File

@ -43,14 +43,14 @@ public class AsusUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
try try
{ {
if ((Device.Type == (uint)AsusDeviceType.KEYBOARD_RGB) || (Device.Type == (uint)AsusDeviceType.NB_KB_RGB)) if ((Device.Type == (uint)AsusDeviceType.KEYBOARD_RGB) || (Device.Type == (uint)AsusDeviceType.NB_KB_RGB))
{ {
if (Device is not IAuraSyncKeyboard keyboard) if (Device is not IAuraSyncKeyboard keyboard)
return; return true;
foreach ((object customData, Color value) in dataSet) foreach ((object customData, Color value) in dataSet)
{ {
@ -88,11 +88,16 @@ public class AsusUpdateQueue : UpdateQueue
} }
Device.Apply(); Device.Apply();
}
catch
{ /* "The server threw an exception." seems to be a thing here ... */
}
}
return true;
}
catch (Exception ex)
{
AsusDeviceProvider.Instance.Throw(ex);
}
return false;
}
#endregion #endregion
} }

View File

@ -37,15 +37,26 @@ public class CoolerMasterUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
foreach ((object key, Color color) in dataSet) try
{ {
(int row, int column) = ((int, int))key; foreach ((object key, Color color) in dataSet)
_deviceMatrix.KeyColor[row, column] = new _CoolerMasterKeyColor(color.GetR(), color.GetG(), color.GetB()); {
(int row, int column) = ((int, int))key;
_deviceMatrix.KeyColor[row, column] = new _CoolerMasterKeyColor(color.GetR(), color.GetG(), color.GetB());
}
_CoolerMasterSDK.SetAllLedColor(_deviceMatrix, _deviceIndex);
return true;
}
catch (Exception ex)
{
CoolerMasterDeviceProvider.Instance.Throw(ex);
} }
_CoolerMasterSDK.SetAllLedColor(_deviceMatrix, _deviceIndex); return false;
} }
#endregion #endregion

View File

@ -50,6 +50,26 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider
/// </summary> /// </summary>
public CorsairSessionDetails SessionDetails { get; private set; } = new(); public CorsairSessionDetails SessionDetails { get; private set; } = new();
private CorsairSessionState _sessionState = CorsairSessionState.Invalid;
public CorsairSessionState SessionState
{
get => _sessionState;
private set
{
_sessionState = value;
try { SessionStateChanged?.Invoke(this, SessionState); }
catch { /* catch faulty event-handlers*/ }
}
}
#endregion
#region Events
// ReSharper disable once UnassignedField.Global
public EventHandler<CorsairSessionState>? SessionStateChanged;
#endregion #endregion
#region Constructors #region Constructors
@ -74,7 +94,7 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider
using ManualResetEventSlim waitEvent = new(false); using ManualResetEventSlim waitEvent = new(false);
void OnSessionStateChanged(object? sender, CorsairSessionState state) void OnInitializeSessionStateChanged(object? sender, CorsairSessionState state)
{ {
if (state == CorsairSessionState.Connected) if (state == CorsairSessionState.Connected)
// ReSharper disable once AccessToDisposedClosure // ReSharper disable once AccessToDisposedClosure
@ -84,6 +104,7 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider
try try
{ {
_CUESDK.SessionStateChanged += OnSessionStateChanged; _CUESDK.SessionStateChanged += OnSessionStateChanged;
_CUESDK.SessionStateChanged += OnInitializeSessionStateChanged;
CorsairError errorCode = _CUESDK.CorsairConnect(); CorsairError errorCode = _CUESDK.CorsairConnect();
if (errorCode != CorsairError.Success) if (errorCode != CorsairError.Success)
@ -100,10 +121,12 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider
} }
finally finally
{ {
_CUESDK.SessionStateChanged -= OnSessionStateChanged; _CUESDK.SessionStateChanged -= OnInitializeSessionStateChanged;
} }
} }
private void OnSessionStateChanged(object? sender, CorsairSessionState state) => SessionState = state;
/// <inheritdoc /> /// <inheritdoc />
protected override IEnumerable<IRGBDevice> LoadDevices() protected override IEnumerable<IRGBDevice> LoadDevices()
{ {
@ -129,7 +152,7 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider
Throw(new RGBDeviceException($"Failed to take control of device '{device.id}'. (ErrorCode: {error})")); Throw(new RGBDeviceException($"Failed to take control of device '{device.id}'. (ErrorCode: {error})"));
CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), device); CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), device);
int channelLedCount = 0; int channelLedCount = 0;
for (int i = 0; i < device.channelCount; i++) for (int i = 0; i < device.channelCount; i++)
{ {

View File

@ -38,19 +38,32 @@ public class CorsairDeviceUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override unsafe void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override unsafe bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
Span<_CorsairLedColor> colors = new((void*)_colorPtr, dataSet.Length); try
for (int i = 0; i < colors.Length; i++)
{ {
(object id, Color color) = dataSet[i]; if (!_CUESDK.IsConnected) return false;
(byte a, byte r, byte g, byte b) = color.GetRGBBytes();
colors[i] = new _CorsairLedColor((CorsairLedId)id, r, g, b, a); Span<_CorsairLedColor> colors = new((void*)_colorPtr, dataSet.Length);
for (int i = 0; i < colors.Length; i++)
{
(object id, Color color) = dataSet[i];
(byte a, byte r, byte g, byte b) = color.GetRGBBytes();
colors[i] = new _CorsairLedColor((CorsairLedId)id, r, g, b, a);
}
CorsairError error = _CUESDK.CorsairSetLedColors(_device.id!, dataSet.Length, _colorPtr);
if (error != CorsairError.Success)
throw new RGBDeviceException($"Failed to update device '{_device.id}'. (ErrorCode: {error})");
return true;
}
catch (Exception ex)
{
CorsairDeviceProvider.Instance.Throw(ex);
} }
CorsairError error = _CUESDK.CorsairSetLedColors(_device.id!, dataSet.Length, _colorPtr); return false;
if (error != CorsairError.Success)
throw new RGBDeviceException($"Failed to update device '{_device.id}'. (ErrorCode: {error})");
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -59,18 +59,29 @@ public class E131UpdateQueue : UpdateQueue
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
DataPacket.SetSequenceNumber(GetNextSequenceNumber()); try
foreach ((object key, Color color) in dataSet)
{ {
LedChannelMapping mapping = (LedChannelMapping)key; DataPacket.SetSequenceNumber(GetNextSequenceNumber());
foreach ((int channel, Func<Color, byte> getValue) in mapping)
DataPacket.SetChannel(channel, getValue(color)); foreach ((object key, Color color) in dataSet)
{
LedChannelMapping mapping = (LedChannelMapping)key;
foreach ((int channel, Func<Color, byte> getValue) in mapping)
DataPacket.SetChannel(channel, getValue(color));
}
_socket.Send(DataPacket, DataPacket.Length);
return true;
}
catch (Exception ex)
{
DMXDeviceProvider.Instance.Throw(ex);
} }
_socket.Send(DataPacket, DataPacket.Length); return false;
} }
/// <summary> /// <summary>

View File

@ -15,7 +15,7 @@ internal class DebugDeviceUpdateQueue : UpdateQueue
#region Methods #region Methods
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { } protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet) => true;
#endregion #endregion
} }

View File

@ -25,14 +25,25 @@ public class LogitechPerDeviceUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
Color color = dataSet[0].color; try
{
Color color = dataSet[0].color;
_LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.DeviceRGB); _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.DeviceRGB);
_LogitechGSDK.LogiLedSetLighting((int)Math.Round(color.R * 100), _LogitechGSDK.LogiLedSetLighting((int)Math.Round(color.R * 100),
(int)Math.Round(color.G * 100), (int)Math.Round(color.G * 100),
(int)Math.Round(color.B * 100)); (int)Math.Round(color.B * 100));
return true;
}
catch (Exception ex)
{
LogitechDeviceProvider.Instance.Throw(ex);
}
return false;
} }
#endregion #endregion

View File

@ -25,19 +25,30 @@ public class LogitechPerKeyUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
_LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.PerKeyRGB); try
foreach ((object key, Color color) in dataSet)
{ {
// These will be LogitechLedId but the SDK expects an int and doesn't care about invalid values _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.PerKeyRGB);
int keyName = (int)key;
_LogitechGSDK.LogiLedSetLightingForKeyWithKeyName(keyName, foreach ((object key, Color color) in dataSet)
(int)MathF.Round(color.R * 100), {
(int)MathF.Round(color.G * 100), // These will be LogitechLedId but the SDK expects an int and doesn't care about invalid values
(int)MathF.Round(color.B * 100)); int keyName = (int)key;
_LogitechGSDK.LogiLedSetLightingForKeyWithKeyName(keyName,
(int)MathF.Round(color.R * 100),
(int)MathF.Round(color.G * 100),
(int)MathF.Round(color.B * 100));
}
return true;
} }
catch (Exception ex)
{
LogitechDeviceProvider.Instance.Throw(ex);
}
return false;
} }
#endregion #endregion

View File

@ -33,18 +33,29 @@ public class LogitechZoneUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
_LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.All); try
foreach ((object key, Color color) in dataSet)
{ {
int zone = (int)key; _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.All);
_LogitechGSDK.LogiLedSetLightingForTargetZone(_deviceType, zone,
(int)MathF.Round(color.R * 100), foreach ((object key, Color color) in dataSet)
(int)MathF.Round(color.G * 100), {
(int)MathF.Round(color.B * 100)); int zone = (int)key;
_LogitechGSDK.LogiLedSetLightingForTargetZone(_deviceType, zone,
(int)MathF.Round(color.R * 100),
(int)MathF.Round(color.G * 100),
(int)MathF.Round(color.B * 100));
}
return true;
} }
catch (Exception ex)
{
LogitechDeviceProvider.Instance.Throw(ex);
}
return false;
} }
#endregion #endregion

View File

@ -34,10 +34,21 @@ public class MsiDeviceUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
foreach ((object key, Color color) in dataSet) try
_MsiSDK.SetLedColor(_deviceType, (int)key, color.GetR(), color.GetG(), color.GetB()); {
foreach ((object key, Color color) in dataSet)
_MsiSDK.SetLedColor(_deviceType, (int)key, color.GetR(), color.GetG(), color.GetB());
return true;
}
catch (Exception ex)
{
MsiDeviceProvider.Instance.Throw(ex);
}
return false;
} }
#endregion #endregion

View File

@ -35,10 +35,21 @@ public abstract class MidiUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
foreach ((object key, Color color) in dataSet) try
SendMessage(CreateMessage(key, color)); {
foreach ((object key, Color color) in dataSet)
SendMessage(CreateMessage(key, color));
return true;
}
catch (Exception ex)
{
NovationDeviceProvider.Instance.Throw(ex);
}
return false;
} }
/// <summary> /// <summary>

View File

@ -49,12 +49,23 @@ public class OpenRGBUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
foreach ((object key, Color color) in dataSet) try
_colors[(int)key] = new OpenRGBColor(color.GetR(), color.GetG(), color.GetB()); {
foreach ((object key, Color color) in dataSet)
_colors[(int)key] = new OpenRGBColor(color.GetR(), color.GetG(), color.GetB());
_openRGB.UpdateLeds(_deviceid, _colors); _openRGB.UpdateLeds(_deviceid, _colors);
return true;
}
catch (Exception ex)
{
OpenRGBDeviceProvider.Instance.Throw(ex);
}
return false;
} }
#endregion #endregion

View File

@ -44,22 +44,33 @@ public class PicoPiBulkUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
Span<byte> buffer = _dataBuffer; try
foreach ((object key, Color color) in dataSet)
{ {
int index = key as int? ?? -1; Span<byte> buffer = _dataBuffer;
if (index < 0) continue; foreach ((object key, Color color) in dataSet)
{
int index = key as int? ?? -1;
if (index < 0) continue;
(byte _, byte r, byte g, byte b) = color.GetRGBBytes(); (byte _, byte r, byte g, byte b) = color.GetRGBBytes();
int offset = index * 3; int offset = index * 3;
buffer[offset] = r; buffer[offset] = r;
buffer[offset + 1] = g; buffer[offset + 1] = g;
buffer[offset + 2] = b; buffer[offset + 2] = b;
}
_sdk.SendBulkUpdate(buffer, _channel);
return true;
}
catch (Exception ex)
{
PicoPiDeviceProvider.Instance.Throw(ex);
} }
_sdk.SendBulkUpdate(buffer, _channel); return false;
} }
#endregion #endregion

View File

@ -41,22 +41,33 @@ public class PicoPiHIDUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
Span<byte> buffer = _dataBuffer; try
foreach ((object key, Color color) in dataSet)
{ {
int index = key as int? ?? -1; Span<byte> buffer = _dataBuffer;
if (index < 0) continue; foreach ((object key, Color color) in dataSet)
{
int index = key as int? ?? -1;
if (index < 0) continue;
(byte _, byte r, byte g, byte b) = color.GetRGBBytes(); (byte _, byte r, byte g, byte b) = color.GetRGBBytes();
int offset = index * 3; int offset = index * 3;
buffer[offset] = r; buffer[offset] = r;
buffer[offset + 1] = g; buffer[offset + 1] = g;
buffer[offset + 2] = b; buffer[offset + 2] = b;
}
_sdk.SendHidUpdate(buffer, _channel);
return true;
}
catch (Exception ex)
{
PicoPiDeviceProvider.Instance.Throw(ex);
} }
_sdk.SendHidUpdate(buffer, _channel); return false;
} }
#endregion #endregion

View File

@ -10,7 +10,7 @@ namespace RGB.NET.Devices.Razer;
public abstract class RazerUpdateQueue : UpdateQueue public abstract class RazerUpdateQueue : UpdateQueue
{ {
#region Properties & Fields #region Properties & Fields
private Guid? _lastEffect; private Guid? _lastEffect;
#endregion #endregion
@ -23,26 +23,36 @@ public abstract class RazerUpdateQueue : UpdateQueue
/// <param name="updateTrigger">The update trigger used to update this queue.</param> /// <param name="updateTrigger">The update trigger used to update this queue.</param>
protected RazerUpdateQueue(IDeviceUpdateTrigger updateTrigger) protected RazerUpdateQueue(IDeviceUpdateTrigger updateTrigger)
: base(updateTrigger) : base(updateTrigger)
{ { }
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
IntPtr effectParams = CreateEffectParams(dataSet); try
Guid effectId = Guid.NewGuid(); {
CreateEffect(effectParams, ref effectId); IntPtr effectParams = CreateEffectParams(dataSet);
Guid effectId = Guid.NewGuid();
CreateEffect(effectParams, ref effectId);
_RazerSDK.SetEffect(effectId); _RazerSDK.SetEffect(effectId);
if (_lastEffect.HasValue) if (_lastEffect.HasValue)
_RazerSDK.DeleteEffect(_lastEffect.Value); _RazerSDK.DeleteEffect(_lastEffect.Value);
_lastEffect = effectId; _lastEffect = effectId;
return true;
}
catch (Exception ex)
{
RazerDeviceProvider.Instance.Throw(ex);
}
return false;
} }
/// <summary> /// <summary>

View File

@ -37,15 +37,35 @@ internal class SteelSeriesDeviceUpdateQueue : UpdateQueue
protected override void OnUpdate(object? sender, CustomUpdateData customData) protected override void OnUpdate(object? sender, CustomUpdateData customData)
{ {
if (customData[CustomUpdateDataIndex.HEARTBEAT] as bool? ?? false) try
SteelSeriesSDK.SendHeartbeat(); {
else if (customData[CustomUpdateDataIndex.HEARTBEAT] as bool? ?? false)
base.OnUpdate(sender, customData); SteelSeriesSDK.SendHeartbeat();
else
base.OnUpdate(sender, customData);
}
catch (Exception ex)
{
SteelSeriesDeviceProvider.Instance.Throw(ex);
}
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
=> SteelSeriesSDK.UpdateLeds(_deviceType, dataSet.ToArray().Select(x => (((SteelSeriesLedId)x.key).GetAPIName(), x.color.ToIntArray())).Where(x => x.Item1 != null).ToList()!); {
try
{
SteelSeriesSDK.UpdateLeds(_deviceType, dataSet.ToArray().Select(x => (((SteelSeriesLedId)x.key).GetAPIName(), x.color.ToIntArray())).Where(x => x.Item1 != null).ToList()!);
return true;
}
catch (Exception ex)
{
SteelSeriesDeviceProvider.Instance.Throw(ex);
}
return false;
}
#endregion #endregion
} }

View File

@ -56,13 +56,24 @@ public abstract class SerialConnectionUpdateQueue<TData> : UpdateQueue
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
foreach (TData command in GetCommands(dataSet.ToArray())) try
{ {
SerialConnection.ReadTo(Prompt); foreach (TData command in GetCommands(dataSet.ToArray()))
SendCommand(command); {
SerialConnection.ReadTo(Prompt);
SendCommand(command);
}
return true;
} }
catch (Exception ex)
{
WS281XDeviceProvider.Instance.Throw(ex);
}
return false;
} }
/// <summary> /// <summary>

View File

@ -77,13 +77,25 @@ public class NodeMCUWS2812USBUpdateQueue : UpdateQueue
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
foreach (IGrouping<int, ((int channel, int key), Color color)> channelData in dataSet.ToArray().Select(x => (((int channel, int key))x.key, x.color)).GroupBy(x => x.Item1.channel)) try
{ {
byte[] buffer = GetBuffer(channelData); foreach (IGrouping<int, ((int channel, int key), Color color)> channelData in dataSet.ToArray()
_sendDataAction(buffer); .Select(x => (((int channel, int key))x.key, x.color)).GroupBy(x => x.Item1.channel))
{
byte[] buffer = GetBuffer(channelData);
_sendDataAction(buffer);
}
return true;
} }
catch (Exception ex)
{
WS281XDeviceProvider.Instance.Throw(ex);
}
return false;
} }
private void SendHttp(byte[] buffer) private void SendHttp(byte[] buffer)

View File

@ -13,7 +13,7 @@ public class WootingUpdateQueue : UpdateQueue
#region Properties & Fields #region Properties & Fields
private readonly byte _deviceid; private readonly byte _deviceid;
#endregion #endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
@ -31,20 +31,31 @@ public class WootingUpdateQueue : UpdateQueue
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
lock (_WootingSDK.SdkLock) try
{ {
_WootingSDK.SelectDevice(_deviceid); lock (_WootingSDK.SdkLock)
foreach ((object key, Color color) in dataSet)
{ {
(int row, int column) = ((int, int))key; _WootingSDK.SelectDevice(_deviceid);
_WootingSDK.ArraySetSingle((byte)row, (byte)column, color.GetR(), color.GetG(), color.GetB());
foreach ((object key, Color color) in dataSet)
{
(int row, int column) = ((int, int))key;
_WootingSDK.ArraySetSingle((byte)row, (byte)column, color.GetR(), color.GetG(), color.GetB());
}
_WootingSDK.ArrayUpdateKeyboard();
} }
_WootingSDK.ArrayUpdateKeyboard(); return true;
} }
catch (Exception ex)
{
WootingDeviceProvider.Instance.Throw(ex);
}
return false;
} }
#endregion #endregion