Asus sdk problem
Lumiond opened this issue · comments
As we know, asus sdk can be unstable in c#.
I post in discord these examples a few month ago:
working - https://pastebin.com/ARCJtWiN
non-working - https://pastebin.com/a66ZdGi0
I thought that problem is in asus aura sdk but after reading some articles I think problem is "how c# works with com objects" (and asus sdk is com object of course). Also I have found wrapper for unity from asus (it doesn't work in unity, he-he, but it doesn't matter) and have seen interesting thing: they use c# class AuraDevice. This class contain IAuraSyncDevice, array of IAuraRgbLight, device type and some device info like animation type, width. height etc. I try to use this idea in my synthetic example. And it works! Two days, 10 hours of stable work without any problem. Also, I have tried to cut array of IAuraRgbLight from my class and have got crash after 1 hour (as usual). Unfortunately, I don't understand architecture of RGB.NET at sufficient level so I can't implement a fix. But I provide my working example and hope that it's helpful and we get fully working stuff. I think that this implementation change time of object life so we get stable work. My code:
using System.Runtime;
using AuraServiceLib;
using System.Threading;
using System.Collections.Generic;
namespace SharpAuraTestImport5
{
class AuraDev
{
public uint devType;
public IAuraSyncDevice device;
public IAuraRgbLight[] lightArray;
}
class Program
{
static void Main(string[] args)
{
List<AuraDev> devList = new List<AuraDev>();
IAuraSdk2 sdk = (IAuraSdk2)new AuraSdk();
try
{
sdk.SwitchMode();
IAuraSyncDeviceCollection devices = sdk.Enumerate(0); // 0 means all
devList.Clear();
foreach (IAuraSyncDevice dev in devices)
{
if (dev.Name != "Termial 2")
{
AuraDev auraDev = new AuraDev()
{
devType = dev.Type,
device = dev,
lightArray = new IAuraRgbLight[dev.Lights.Count],
};
uint num = 0;
foreach (IAuraRgbLight light in dev.Lights)
auraDev.lightArray[(int)num++] = light;
devList.Add(auraDev);
}
}
int count = 0;
while (true)
{
foreach (AuraDev dev in devList)
{
foreach (IAuraRgbLight light in dev.lightArray)
{
if (count == 0)
{
light.Color = 0x00FF0000;
}
else if (count == 1)
{
light.Color = 0x0000FF00;
}
else
{
light.Color = 0x000000FF;
};
};
dev.device.Apply();
}
if (count != 2) count += 1;
else count = 0;
Thread.Sleep(33);
}
sdk.ReleaseControl(0);
}
catch
{
sdk.ReleaseControl(0);
}
}
}
}
So. I change AsusUpdateQueue class:
- Add IAuraRgbLight array
IAuraRgbLight[] lightArray
- Add this in constructor:
lightArray = new IAuraRgbLight[device.Lights.Count];
uint num = 0;
foreach (IAuraRgbLight light in device.Lights)
lightArray[(int)num++] = light;
- In update method I change this:
- IAuraRgbLight light = Device.Lights[index];
+ IAuraRgbLight light = lightArray[index];
Unfortunately, I don't know how to be with keyboard (and I don't have asus keyboard to test).
And after this changes Artemis works about 9 hours without crashes! Maybe we need add something else but I just wanted to test idea - add array of IAuraRgbLight and see what happens. And seems like I don't have memory leak.
@DarthAffe , good luck with fix and I hope that my help is useful.
@DarthAffe do you want to try these changes out in Artemis?
@DarthAffe , @SpoinkyNL , guys, any ETA for fix of this issue?
Hi, it's up to Darth but it might be useful if you put these changes in a PR. Then we can easily get a special build of the Artemis plugin to give people for testing
If you can't figure out how to do so, I can perhaps take a look this week
Unfortunately, I'm bad in c#. I can try, but I don't know if I can. I don't understand at all how to rewrite keyboard logic. And of course I think that good c# programmer can do this fix better.
My current code is like this (I have commented with "!!!" what I changed):
using System;
using AuraServiceLib;
using RGB.NET.Core;
namespace RGB.NET.Devices.Asus
{
/// <inheritdoc />
/// <summary>
/// Represents the update-queue performing updates for asus devices.
/// </summary>
public class AsusUpdateQueue : UpdateQueue
{
#region Properties & Fields
/// <summary>
/// The device to be updated.
/// </summary>
protected IAuraSyncDevice Device { get; }
protected IAuraRgbLight[] lightArray; //!!! add this array; this prevent from garbage collector deletion of links to com object
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="AsusUpdateQueue"/> class.
/// </summary>
/// <param name="updateTrigger">The update trigger used by this queue.</param>
public AsusUpdateQueue(IDeviceUpdateTrigger updateTrigger, IAuraSyncDevice device)
: base(updateTrigger)
{
this.Device = device;
// !!! this is for array init
lightArray = new IAuraRgbLight[device.Lights.Count];
uint num = 0;
foreach (IAuraRgbLight light in device.Lights)
lightArray[(int)num++] = light;
// !!!
}
#endregion
#region Methods
/// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{
try
{
if ((Device.Type == (uint)AsusDeviceType.KEYBOARD_RGB) || (Device.Type == (uint)AsusDeviceType.NB_KB_RGB))
{
if (Device is not IAuraSyncKeyboard keyboard)
return;
foreach ((object customData, Color value) in dataSet)
{
(AsusLedType ledType, int id) = (AsusKeyboardLedCustomData)customData;
if (ledType == AsusLedType.Key)
{
IAuraRgbLight light = keyboard.Key[(ushort)id];
(_, byte r, byte g, byte b) = value.GetRGBBytes();
light.Red = r;
light.Green = g;
light.Blue = b;
}
else
{
IAuraRgbLight light = keyboard.Lights[id];
(_, byte r, byte g, byte b) = value.GetRGBBytes();
light.Red = r;
light.Green = g;
light.Blue = b;
}
}
}
else
{
foreach ((object key, Color value) in dataSet)
{
int index = (int)key;
IAuraRgbLight light = lightArray[index]; // !!! and in update loop we must set lights from our array, not from device
(_, byte r, byte g, byte b) = value.GetRGBBytes();
light.Red = r;
light.Green = g;
light.Blue = b;
}
}
Device.Apply();
}
catch
{ /* "The server threw an exception." seems to be a thing here ... */
}
}
#endregion
}
}
I have been using my custom dll already one month and don't have any problem (I use ambilight profile for 4 strips on monitor - connected through aura terminal - and my own profile: "wave" effect + particles + static background for Maximus IX Hero + second aura terminal with 3 strips + RAM).
A quick test plugin for Artemis
Artemis.Plugins.Devices.Asus-c20e876f.zip