This guide explains how to integrate real vendor SDKs (Corsair iCUE, Logitech G HUB) and hardware monitoring libraries into OmenCore.
OmenCore uses interface-driven abstraction layers for all vendor integrations:
┌─────────────────────────────────────────┐
│ MainViewModel (MVVM) │
└────────────────┬────────────────────────┘
│
┌──────────┴──────────┐
│ │
┌─────▼──────┐ ┌────────▼─────────┐
│ Enhanced │ │ Enhanced │
│ Corsair │ │ Logitech │
│ Service │ │ Service │
└─────┬──────┘ └────────┬─────────┘
│ │
┌─────▼──────────┐ ┌─────▼──────────┐
│ ICorsairSdk │ │ ILogitechSdk │
│ Provider │ │ Provider │
└─────┬──────────┘ └─────┬──────────┘
│ │
┌──┴───┐ ┌───┴────┐
│ Stub │ Real │ Stub │ Real
│ Impl │ iCUE SDK │ Impl │ G HUB
└──────┘ └────────┘
Benefits:
- ✅ Swap implementations without touching UI code
- ✅ Test without real hardware
- ✅ Graceful fallback on SDK failures
- ✅ Easy to add new vendors
Install-Package CUE.NET
# Or
dotnet add package CUE.NETEdit Services/Corsair/ICorsairSdkProvider.cs:
public class CorsairICueSdk : ICorsairSdkProvider
{
public async Task<bool> InitializeAsync()
{
try
{
// UNCOMMENT THIS:
var result = CueSDK.Initialize();
if (result.HasError)
{
_logging.Error($"Failed to initialize iCUE SDK: {result.Error}");
return false;
}
_logging.Info("Corsair iCUE SDK initialized successfully");
_initialized = true;
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logging.Error("iCUE SDK initialization failed", ex);
return false;
}
}
public async Task<IEnumerable<CorsairDevice>> DiscoverDevicesAsync()
{
var devices = new List<CorsairDevice>();
// UNCOMMENT THIS:
var deviceCount = CueSDK.DeviceCount;
for (int i = 0; i < deviceCount; i++)
{
var cueDevice = CueSDK.GetDeviceInfo(i);
var device = new CorsairDevice
{
DeviceId = cueDevice.DeviceId.ToString(),
Name = cueDevice.Model,
DeviceType = MapCorsairDeviceType(cueDevice.Type),
Zones = ExtractZones(cueDevice),
Status = await GetDeviceStatusAsync(null)
};
devices.Add(device);
}
return await Task.FromResult<IEnumerable<CorsairDevice>>(devices);
}
// Helper methods
private CorsairDeviceType MapCorsairDeviceType(CorsairDeviceType cueType)
{
return cueType switch
{
CueDeviceType.Keyboard => CorsairDeviceType.Keyboard,
CueDeviceType.Mouse => CorsairDeviceType.Mouse,
CueDeviceType.Headset => CorsairDeviceType.Headset,
CueDeviceType.MouseMat => CorsairDeviceType.MouseMat,
_ => CorsairDeviceType.Accessory
};
}
private List<string> ExtractZones(CorsairDeviceInfo deviceInfo)
{
var zones = new List<string>();
// Extract LED zones from device capabilities
foreach (var led in deviceInfo.LEDs)
{
if (!zones.Contains(led.Zone))
zones.Add(led.Zone);
}
return zones;
}
}public async Task ApplyLightingAsync(CorsairDevice device, CorsairLightingPreset preset)
{
var cueDevice = CueSDK.GetDeviceInfo(device.DeviceId);
var color = ColorTranslator.FromHtml(preset.PrimaryColor);
switch (preset.Effect)
{
case LightingEffectType.Static:
cueDevice.Brush = new SolidColorBrush(new CorsairColor(color.R, color.G, color.B));
break;
case LightingEffectType.Wave:
var gradient = new RainbowGradient();
cueDevice.Brush = new LinearGradientBrush(gradient);
break;
case LightingEffectType.Breathing:
var breathe = new BreathingGradient(new CorsairColor(color.R, color.G, color.B), 2000);
cueDevice.Brush = new LinearGradientBrush(breathe);
break;
}
await Task.CompletedTask;
}// In MainViewModel.cs constructor
var corsairService = await EnhancedCorsairDeviceService.CreateAsync(_logging);
// Automatically detects and uses real SDK if available- Download from Logitech Developer Portal
- Add
LogitechLedEnginesWrapper.dllto project - Set Copy to Output Directory: Always
Edit Services/Logitech/ILogitechSdkProvider.cs:
public class LogitechGHubSdk : ILogitechSdkProvider
{
public async Task<bool> InitializeAsync()
{
try
{
// UNCOMMENT THIS:
var result = LogitechGSDK.LogiLedInit();
if (!result)
{
_logging.Error("Failed to initialize Logitech LED SDK");
return false;
}
_logging.Info("Logitech G HUB SDK initialized");
_initialized = true;
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logging.Error("G HUB SDK initialization failed", ex);
return false;
}
}
public async Task ApplyStaticColorAsync(LogitechDevice device, string hexColor, int brightness)
{
// UNCOMMENT THIS:
var color = ColorTranslator.FromHtml(hexColor);
var r = (int)(color.R * brightness / 100.0);
var g = (int)(color.G * brightness / 100.0);
var b = (int)(color.B * brightness / 100.0);
// Per-device targeting (if supported)
LogitechGSDK.LogiLedSetLightingForTargetZone(
DeviceType.All,
0,
(byte)Math.Clamp(r, 0, 100),
(byte)Math.Clamp(g, 0, 100),
(byte)Math.Clamp(b, 0, 100)
);
_logging.Info($"Applied color {hexColor} to {device.Name}");
await Task.CompletedTask;
}
}For advanced control (DPI, macros), use HID protocol:
using HidSharp;
public async Task<IEnumerable<LogitechDevice>> DiscoverDevicesAsync()
{
var devices = new List<LogitechDevice>();
var deviceList = DeviceList.Local;
var hidDevices = deviceList.GetHidDevices();
foreach (var hidDevice in hidDevices)
{
// Logitech VID: 0x046D
if (hidDevice.VendorID == 0x046D)
{
var device = new LogitechDevice
{
DeviceId = hidDevice.DevicePath,
Name = hidDevice.GetProductName(),
DeviceType = DetermineDeviceType(hidDevice.ProductID)
};
devices.Add(device);
}
}
return await Task.FromResult<IEnumerable<LogitechDevice>>(devices);
}Install-Package LibreHardwareMonitorLib
# Or
dotnet add package LibreHardwareMonitorLibEdit Hardware/LibreHardwareMonitorImpl.cs:
public class LibreHardwareMonitorImpl : IHardwareMonitorBridge, IDisposable
{
private readonly Computer _computer; // UNCOMMENT
public LibreHardwareMonitorImpl()
{
// UNCOMMENT THIS BLOCK:
_computer = new Computer
{
IsCpuEnabled = true,
IsGpuEnabled = true,
IsMemoryEnabled = true,
IsStorageEnabled = true,
IsControllerEnabled = true,
IsNetworkEnabled = false
};
_computer.Open();
_initialized = true;
}
private void UpdateHardwareReadings()
{
// UNCOMMENT THIS BLOCK:
lock (_lock)
{
_computer.Accept(new UpdateVisitor());
foreach (var hardware in _computer.Hardware)
{
hardware.Update();
switch (hardware.HardwareType)
{
case HardwareType.Cpu:
_cachedCpuTemp = GetSensor(hardware, SensorType.Temperature, "CPU Package")?.Value ?? 0;
_cachedCpuLoad = GetSensor(hardware, SensorType.Load, "CPU Total")?.Value ?? 0;
_cachedCoreClocks.Clear();
for (int i = 0; i < 16; i++) // Up to 16 cores
{
var clockSensor = GetSensor(hardware, SensorType.Clock, $"Core #{i + 1}");
if (clockSensor != null && clockSensor.Value.HasValue)
{
_cachedCoreClocks.Add(clockSensor.Value.Value);
}
}
break;
case HardwareType.GpuNvidia:
case HardwareType.GpuAmd:
case HardwareType.GpuIntel:
_cachedGpuTemp = GetSensor(hardware, SensorType.Temperature, "GPU Core")?.Value ?? 0;
_cachedGpuLoad = GetSensor(hardware, SensorType.Load, "GPU Core")?.Value ?? 0;
_cachedVramUsage = GetSensor(hardware, SensorType.SmallData, "GPU Memory Used")?.Value ?? 0;
break;
case HardwareType.Memory:
_cachedRamUsage = GetSensor(hardware, SensorType.Data, "Memory Used")?.Value ?? 0;
_cachedRamTotal = GetSensor(hardware, SensorType.Data, "Memory Available")?.Value ?? 16;
break;
case HardwareType.Storage:
if (hardware.Name.Contains("NVMe") || hardware.Name.Contains("SSD"))
{
_cachedSsdTemp = GetSensor(hardware, SensorType.Temperature)?.Value ?? 0;
_cachedDiskUsage = GetSensor(hardware, SensorType.Load)?.Value ?? 0;
}
break;
}
}
}
}
// Helper method (UNCOMMENT):
private ISensor GetSensor(IHardware hardware, SensorType type, string namePattern = null)
{
var sensors = hardware.Sensors.Where(s => s.SensorType == type);
if (!string.IsNullOrEmpty(namePattern))
{
sensors = sensors.Where(s => s.Name.Contains(namePattern));
}
return sensors.FirstOrDefault();
}
public void Dispose()
{
_computer?.Close(); // UNCOMMENT
}
}Edit ViewModels/MainViewModel.cs:
// Replace LibreHardwareMonitorBridge with LibreHardwareMonitorImpl
var monitorBridge = new LibreHardwareMonitorImpl(); // Real hardware
_hardwareMonitoringService = new OptimizedHardwareMonitoringService(
monitorBridge,
_logging,
_config.Monitoring ?? new MonitoringPreferences()
);internal class UpdateVisitor : IVisitor
{
public void VisitComputer(IComputer computer)
{
computer.Traverse(this);
}
public void VisitHardware(IHardware hardware)
{
hardware.Update();
foreach (var subHardware in hardware.SubHardware)
subHardware.Accept(this);
}
public void VisitSensor(ISensor sensor) { }
public void VisitParameter(IParameter parameter) { }
}Replace old services with enhanced versions:
// OLD:
_corsairDeviceService = new CorsairDeviceService(_logging);
_logitechDeviceService = new LogitechDeviceService(_logging);
// NEW:
_corsairDeviceService = await EnhancedCorsairDeviceService.CreateAsync(_logging);
_logitechDeviceService = await EnhancedLogitechDeviceService.CreateAsync(_logging);Update async initialization:
public static async Task<MainViewModel> CreateAsync()
{
var vm = new MainViewModel();
await vm.InitializeServicesAsync();
return vm;
}
private async Task InitializeServicesAsync()
{
_corsairDeviceService = await EnhancedCorsairDeviceService.CreateAsync(_logging);
_logitechDeviceService = await EnhancedLogitechDeviceService.CreateAsync(_logging);
await _corsairDeviceService.DiscoverAsync();
await _logitechDeviceService.DiscoverAsync();
}All services work with stub implementations by default:
// Stub mode (no SDK required)
var corsairStub = new CorsairSdkStub(_logging);
var corsairService = new EnhancedCorsairDeviceService(corsairStub, _logging);
// Discover fake devices for testing
await corsairService.DiscoverAsync();| SDK | Init Time | Memory | CPU Overhead |
|---|---|---|---|
| Corsair iCUE | ~300ms | +10 MB | +0.2% |
| Logitech LED | ~150ms | +5 MB | +0.1% |
| LibreHardwareMonitor | ~800ms | +20 MB | +0.5% |
Error: "SDK not available"
- Ensure iCUE software is installed and running
- Check Windows Service: "Corsair Service"
- Verify DLL is in output directory
Error: "Device not found"
- Reconnect devices
- Restart iCUE software
- Check USB connection
Error: "LogitechLedEnginesWrapper.dll not found"
- Copy DLL to bin folder
- Set "Copy to Output Directory" = Always
Error: "LED control not working"
- Ensure G HUB is running
- Check device has RGB support
- Try closing competing software (OpenRGB, SignalRGB)
Error: "Access denied"
- Run as Administrator (required for some sensors)
- Disable antivirus temporarily
No sensors detected:
- Update chipset drivers
- Check BIOS settings (some sensors can be disabled)
<!-- OmenCoreApp.csproj -->
<ItemGroup>
<!-- Real hardware monitoring -->
<PackageReference Include="LibreHardwareMonitorLib" Version="0.9.2" />
<!-- Corsair support -->
<PackageReference Include="CUE.NET" Version="3.0.0" />
<!-- Logitech support (manual DLL) -->
<Reference Include="LogitechLedEnginesWrapper">
<HintPath>libs\LogitechLedEnginesWrapper.dll</HintPath>
</Reference>
<!-- HID protocol (optional, for advanced control) -->
<PackageReference Include="HidSharp" Version="2.1.0" />
</ItemGroup>After integration, verify:
- ✅ Service initializes without errors
- ✅ Devices are discovered
- ✅ Real sensor data appears (not random)
- ✅ Lighting control works
- ✅ No memory leaks (check Task Manager after 1 hour)
- ✅ Graceful fallback on SDK failure
- Install required NuGet packages
- Uncomment real implementations
- Test with your hardware
- Fine-tune polling intervals
- Add vendor-specific features
Happy integrating! 🎉