How DeviceStatusProvider Collects Windows Host Metadata and Process Information in openclaw-windows-node
The DeviceStatusProvider class in openclaw-windows-node gathers Windows host metadata and process information by combining .NET base class library APIs, Win32 P/Invoke, and WinRT battery contracts to produce serialized snapshots of OS, CPU, memory, disk, and power state.
The DeviceStatusProvider is the Windows-specific implementation of the IDeviceStatusProvider contract in the openclaw-windows-node repository. It lives in src/OpenClaw.Tray.WinUI/Services/DeviceStatusProvider.cs and is designed to supply the OpenClaw tray UI with an on-board, self-contained diagnostics snapshot without relying on any external services. Every query method returns a plain C# anonymous type that the application serializes to JSON for local or remote reporting.
Operating System and Host Identity
The GetOsInfo method (DeviceStatusProvider.cs, lines 59–68) collects core platform data using standard .NET environment properties. It reads Environment.OSVersion to capture the Windows build, RuntimeInformation.OSArchitecture for the processor architecture, Environment.MachineName for the device name, and Environment.TickCount64 to compute system uptime. Because these values are in-process memory lookups, the method completes synchronously and returns immediately.
CPU Detection and Dynamic Utilization
Processor Name and Core Count
The provider discovers the CPU model by reading the registry key HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\ProcessorNameString. The logical core count is taken from Environment.ProcessorCount. This logic lives in GetCpuInfoAsync at DeviceStatusProvider.cs lines 72–88.
Background Sampling of CPU Load
To track host-level process load, the class maintains a background System.Timers.Timer that samples a PerformanceCounter targeting Processor\% Processor Time\_Total. The StartCpuSampling method (DeviceStatusProvider.cs, lines 35–52) primes the counter with an initial read of 0, then refreshes _lastCpuUsage every two seconds from the timer callback at lines 44–49. Callers who invoke GetCpuInfoAsync receive the most recent sampled value, which may be null during the first warm-up window.
Memory Metrics via Win32 P/Invoke
Memory statistics are gathered through GlobalMemoryStatusEx from kernel32.dll, declared in the P/Invoke block inside DeviceStatusProvider.cs (lines 29–48). The GetMemoryInfo method (lines 94–112) populates a MEMORYSTATUSEX structure and derives the usage percentage from total and available physical memory. This approach avoids shelling out to external tools and keeps all memory calculations inside the process.
Disk Enumeration and Capacity Metrics
The GetDiskInfo method (DeviceStatusProvider.cs, lines 14–41) iterates over DriveInfo.GetDrives(), filters for ready fixed drives, and reads TotalSize, AvailableFreeSpace, VolumeLabel, and DriveFormat. Usage percent is calculated directly from total versus free space for each eligible volume.
Battery State Through WinRT
Battery data is collected via the Windows.Devices.Power.Battery WinRT API. Inside GetBatteryInfo (DeviceStatusProvider.cs, lines 44–95), the provider requests an aggregate battery report through GetReport(), capturing presence, charge capacity, status (Charging, Discharging, NotPresent), charge rate, and remaining capacity. From these fields it derives the charge percentage and, when the system is discharging, an estimated minutes-remaining value. This API path is only available on Windows 10 and later hosts.
Lifecycle Management and Cleanup
The provider implements IDisposable. The Dispose method (DeviceStatusProvider.cs, lines 110–127) drains the background timer, disposes the PerformanceCounter, and clears the timer reference to prevent race conditions during application shutdown.
Usage Examples
The following pattern shows how to initialize the provider, start background sampling, query host metadata, and dispose of resources cleanly.
// Startup: create the provider and begin CPU sampling
var logger = serviceProvider.GetRequiredService<IOpenClawLogger>();
var statusProvider = new DeviceStatusProvider(logger);
statusProvider.StartCpuSampling();
// Querying snapshots (CPU may be null during warm-up)
var osInfo = statusProvider.GetOsInfo();
var cpuInfo = await statusProvider.GetCpuInfoAsync();
var memInfo = statusProvider.GetMemoryInfo();
var diskInfo = statusProvider.GetDiskInfo();
var battInfo = statusProvider.GetBatteryInfo();
// Shutdown: release the PerformanceCounter and timer
statusProvider.Dispose();
Summary
DeviceStatusProviderimplementsIDeviceStatusProviderentirely on-device, using no external services.- OS metadata is sourced from
Environmentproperties inGetOsInfo. - CPU name comes from the registry, while CPU usage is sampled by a background
Timerdriving aPerformanceCounter. - Memory is queried through the Win32
GlobalMemoryStatusExP/Invoke path inGetMemoryInfo. - Disk layout is enumerated with
DriveInfo.GetDrives()insideGetDiskInfo. - Battery state is read from the WinRT
Windows.Devices.Power.BatteryAPI inGetBatteryInfo. - All errors are logged via
IOpenClawLoggerand returned as fallback objects to keep the tray UI stable.
Frequently Asked Questions
What API does DeviceStatusProvider use to sample CPU usage?
The provider creates a PerformanceCounter for Processor\% Processor Time\_Total and samples it every two seconds via a background System.Timers.Timer. The latest value is stored in _lastCpuUsage and returned asynchronously by GetCpuInfoAsync.
How does DeviceStatusProvider read total and available memory?
It calls the Win32 GlobalMemoryStatusEx function through a P/Invoke declaration to kernel32.dll. The GetMemoryInfo method uses the returned MEMORYSTATUSEX structure to calculate total, available, and percentage-used physical memory.
Does DeviceStatusProvider require an external service to collect data?
No. According to the openclaw-windows-node source code, all data collection happens locally on the Windows host through .NET BCL APIs, registry reads, Win32 P/Invoke, and WinRT contracts.
What happens if the device has no battery or the registry query fails?
Errors are caught internally and forwarded to the injected IOpenClawLogger. The provider returns a safe fallback payload instead of throwing, ensuring the tray UI continues to function even when individual sensors are unavailable.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →