diff --git a/packages/ui/index.d.ts b/packages/ui/index.d.ts index 7d43d85..9fac545 100644 --- a/packages/ui/index.d.ts +++ b/packages/ui/index.d.ts @@ -126,6 +126,13 @@ declare global { name: string } + battery?: { + capacity: Sensor[] + level: Sensor[] + remainingTime?: Sensor + cycleCount: string + } + monitor: { monitors: Monitor[] } diff --git a/packages/ui/pages/home.svelte b/packages/ui/pages/home.svelte index 3797239..3cac72f 100644 --- a/packages/ui/pages/home.svelte +++ b/packages/ui/pages/home.svelte @@ -453,21 +453,57 @@ -
-
-
- + {#if $hardwareInfo.system.battery?.capacity.length ?? 0 > 0} +
+
+
+ +
+

Battery

-

Monitors

-
- {#each $hardwareInfo.system.monitor.monitors as { name, refreshRate, resolution }} +
-

Name: {name}

-

Resolution: {resolution}

-

Refresh rate: {refreshRate} Hz

+

Charge level: {Math.round($hardwareInfo.system.battery.level[1].value)}%

+

Health: {Math.round(100 - $hardwareInfo.system.battery.level[0].value)}%

+

Cycle count: {$hardwareInfo.system.battery.cycleCount}

+

+ Capacity: {Math.round($hardwareInfo.system.battery.capacity[2].value / 1000)}/{Math.round( + $hardwareInfo.system.battery.capacity[1].value / 1000, + )} Wh +

+

+ Remaining time: {#if $hardwareInfo.system.battery.remainingTime.value !== null} + {`${Math.floor($hardwareInfo.system.battery.remainingTime.value / 60)}:${( + $hardwareInfo.system.battery.remainingTime.value % 60 + ) + .toString() + .padStart(2, "0")}`} + {:else} + N/A + {/if} +

- {/each} -
+
+ {/if} + + {#if $hardwareInfo.system.monitor.monitors.length > 0} +
+
+
+ +
+

Monitors

+
+ + {#each $hardwareInfo.system.monitor.monitors as { name, refreshRate, resolution }} +
+

Name: {name}

+

Resolution: {resolution}

+

Refresh rate: {refreshRate} Hz

+
+ {/each} +
+ {/if}
@@ -512,7 +548,7 @@ import { hardwareInfo } from "ui/stores/hardwareInfo.ts" import GaugeChart from "ui/charts/gaugeChart.svelte" import MeterChart from "ui/charts/meterChart.svelte" - import { Gauge, CircuitBoard, Clock, Fan, HardDrive, Monitor, Network, Plug, Thermometer, Zap, Cpu } from "lucide-svelte" + import { Gauge, CircuitBoard, Clock, Fan, HardDrive, Monitor, Network, Plug, Thermometer, Zap, Cpu, Battery } from "lucide-svelte" import { GpuCard, Memory, PcDisplay } from "svelte-bootstrap-icons" import Progress from "ui/components/progress.svelte" diff --git a/platforms/windows/lib/Commands.cs b/platforms/windows/lib/Commands.cs index 67273c3..e4c433d 100644 --- a/platforms/windows/lib/Commands.cs +++ b/platforms/windows/lib/Commands.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using Serilog; +using System.Diagnostics; using System.Text.Json; namespace lib; @@ -56,4 +57,33 @@ public static string GetGPUInfo() { return foramttedDate; } + + public class CycleCountInfo { + public int? CycleCount { get; set; } + } + + public static string GetCycleCount() { + try { + var command = ExecuteCommand("Get-WmiObject -Class MSBatteryClass -Namespace ROOT/WMI | Select-Object CycleCount | ConvertTo-Json"); + + var cycles = JsonSerializer.Deserialize>(command); + var c = 0; + + if (cycles?.Count > 0) { + foreach (var cycle in cycles) { + c += cycle.CycleCount ?? 0; + } + } + + if (c == 0) { + return "N/A"; + } else { + return c.ToString(); + } + } + catch (Exception) { + Log.Error("Failed to get cycle count"); + return "N/A"; + } + } } diff --git a/platforms/windows/lib/HardwareInfo.cs b/platforms/windows/lib/HardwareInfo.cs index 1027b47..8ddcbf9 100644 --- a/platforms/windows/lib/HardwareInfo.cs +++ b/platforms/windows/lib/HardwareInfo.cs @@ -16,6 +16,7 @@ public class HardwareInfo { IsMotherboardEnabled = true, IsStorageEnabled = true, IsNetworkEnabled = true, + IsBatteryEnabled = true, }; public API API { @@ -594,6 +595,64 @@ public void GetInfo() { } } } + + // Battery + if (hardware.HardwareType == HardwareType.Battery) { + var energySensors = hardware.Sensors.Where(x => x.SensorType == SensorType.Energy).ToArray(); + var levelSensors = hardware.Sensors.Where(x => x.SensorType == SensorType.Level).ToArray(); + var timeSpanSensors = hardware.Sensors.Where(x => x.SensorType == SensorType.TimeSpan).ToArray(); + + // Energy capacity + for (int j = 0; j < energySensors.Length; j++) { + var data = new Sensor { + Name = energySensors[j].Name, + Value = energySensors[j].Value ?? 0, + Min = energySensors[j].Min ?? 0, + Max = energySensors[j].Max ?? 0, + }; + + if (firstRun) { + API.System.Battery.Capacity.Add(data); + } else { + API.System.Battery.Capacity[j] = data; + } + } + + // Charge level + for (int j = 0; j < levelSensors.Length; j++) { + var data = new Sensor { + Name = levelSensors[j].Name, + Value = levelSensors[j].Value ?? 0, + Min = levelSensors[j].Min ?? 0, + Max = levelSensors[j].Max ?? 0, + }; + + if (firstRun) { + API.System.Battery.Level.Add(data); + } else { + API.System.Battery.Level[j] = data; + } + } + + // Remaining time + for (int j = 0; j < timeSpanSensors.Length; j++) { + var data = new Sensor { + Name = timeSpanSensors[j].Name, + Value = timeSpanSensors[j].Value ?? 0, + Min = timeSpanSensors[j].Min ?? 0, + Max = timeSpanSensors[j].Max ?? 0, + }; + + API.System.Battery.RemainingTime = data; + } + + // Cycle count + if (firstRun) { + var cycles = Commands.GetCycleCount(); + + API.System.Battery.CycleCount = cycles; + } + } } // HWInfo, monitors, network interfaces diff --git a/platforms/windows/lib/Interfaces.cs b/platforms/windows/lib/Interfaces.cs index 0a17490..facaddf 100644 --- a/platforms/windows/lib/Interfaces.cs +++ b/platforms/windows/lib/Interfaces.cs @@ -293,6 +293,17 @@ public List Interfaces { } = new(); } +public class BatteryInfo { + public List Capacity { + get; set; + } = new(); + public List Level { + get; set; + } = new(); + public Sensor RemainingTime { get; set; } + public string CycleCount { get; set; } +} + public class SystemAPI { public OSInfo OS { get; set; @@ -306,6 +317,10 @@ public MotherboardInfo Motherboard { get; set; } = new(); + public BatteryInfo Battery { + get; set; + } = new(); + public MonitorInfo Monitor { get; set; } = new();