Add battery remaining time sensor (#660)

This commit is contained in:
EMN-CSharp
2022-02-11 19:41:56 +01:00
committed by GitHub
parent d69e5c00e0
commit 8d8d84af22
3 changed files with 56 additions and 5 deletions
@@ -23,6 +23,7 @@ namespace LibreHardwareMonitor.Hardware.Battery
private readonly Sensor _designedCapacity;
private readonly Sensor _fullChargedCapacity;
private readonly Sensor _remainingCapacity;
private readonly Sensor _remainingTime;
private readonly Sensor _voltage;
public Battery
@@ -98,6 +99,9 @@ namespace LibreHardwareMonitor.Hardware.Battery
_degradationPercentage = new Sensor("Degradation Level", 0, SensorType.Level, this, settings);
ActivateSensor(_degradationPercentage);
_remainingTime = new Sensor("Remaining Time (Estimated)", 0, SensorType.TimeSpan, this, settings);
ActivateSensor(_remainingTime);
}
public float ChargeDischargeCurrent { get; private set; }
@@ -120,6 +124,8 @@ namespace LibreHardwareMonitor.Hardware.Battery
public float RemainingCapacity { get; private set; }
public uint RemainingTime { get; private set; }
public float Voltage { get; private set; }
public override void Update()
@@ -184,6 +190,31 @@ namespace LibreHardwareMonitor.Hardware.Battery
_degradationPercentage.Value = 100f - (_fullChargedCapacity.Value * 100f / _designedCapacity.Value);
}
uint estimatedRunTime = 0;
Kernel32.BATTERY_QUERY_INFORMATION bqi = default;
bqi.BatteryTag = _batteryTag;
bqi.InformationLevel = Kernel32.BATTERY_QUERY_INFORMATION_LEVEL.BatteryEstimatedTime;
if (Kernel32.DeviceIoControl(_batteryHandle,
Kernel32.IOCTL.IOCTL_BATTERY_QUERY_INFORMATION,
ref bqi,
Marshal.SizeOf(bqi),
ref estimatedRunTime,
Marshal.SizeOf<uint>(),
out _,
IntPtr.Zero))
{
RemainingTime = estimatedRunTime;
if (estimatedRunTime != Kernel32.BATTERY_UNKNOWN_TIME)
{
ActivateSensor(_remainingTime);
_remainingTime.Value = estimatedRunTime;
}
else
{
DeactivateSensor(_remainingTime);
}
}
}
public override void Close()
@@ -26,7 +26,7 @@ namespace LibreHardwareMonitor.Hardware.Battery
IntPtr hdev = SetupApi.SetupDiGetClassDevs(ref SetupApi.GUID_DEVICE_BATTERY, IntPtr.Zero, IntPtr.Zero, SetupApi.DIGCF_PRESENT | SetupApi.DIGCF_DEVICEINTERFACE);
if (hdev != SetupApi.INVALID_HANDLE_VALUE)
{
for (uint i = 0;; i++)
for (uint i = 0; ; i++)
{
SetupApi.SP_DEVICE_INTERFACE_DATA did = default;
did.cbSize = (uint)Marshal.SizeOf(typeof(SetupApi.SP_DEVICE_INTERFACE_DATA));
@@ -198,6 +198,11 @@ namespace LibreHardwareMonitor.Hardware.Battery
.Append(" Charge Level: ").AppendFormat("{0:F2}", bat.RemainingCapacity * 100f / bat.FullChargedCapacity).AppendLine(" %")
.Append(" Voltage: ").AppendFormat("{0:F3}", bat.Voltage).AppendLine(" V");
if (bat.RemainingTime != Kernel32.BATTERY_UNKNOWN_TIME)
{
reportBuilder.Append(" Remaining Time (Estimated): ").AppendFormat("{0:g}", TimeSpan.FromSeconds(bat.RemainingTime)).AppendLine();
}
switch (bat.ChargeDischargeRate)
{
case > 0:
+19 -4
View File
@@ -29,6 +29,8 @@ namespace LibreHardwareMonitor.Interop
internal const uint LPTR = 0x0000 | 0x0040;
internal const uint BATTERY_UNKNOWN_TIME = 0xFFFFFFFF;
private const string DllName = "kernel32.dll";
[Flags]
@@ -258,6 +260,19 @@ namespace LibreHardwareMonitor.Interop
out uint lpBytesReturned,
IntPtr lpOverlapped);
[DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeviceIoControl
(
SafeFileHandle hDevice,
IOCTL dwIoControlCode,
ref BATTERY_QUERY_INFORMATION lpInBuffer,
int nInBufferSize,
ref uint lpOutBuffer,
int nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped);
[DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
internal static extern IntPtr LocalAlloc(uint uFlags, ulong uBytes);
@@ -275,7 +290,7 @@ namespace LibreHardwareMonitor.Interop
[DllImport(DllName, ExactSpelling = true)]
internal static extern IntPtr GetProcAddress(IntPtr module, string methodName);
[DllImport(DllName)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool FreeLibrary(IntPtr module);
@@ -285,7 +300,7 @@ namespace LibreHardwareMonitor.Interop
[DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
internal static extern IntPtr GetCurrentThread();
[DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
public static extern ushort GetActiveProcessorGroupCount();
@@ -303,9 +318,9 @@ namespace LibreHardwareMonitor.Interop
(
SafeFileHandle device,
IOControlCode ioControlCode,
[MarshalAs(UnmanagedType.AsAny)] [In] object inBuffer,
[MarshalAs(UnmanagedType.AsAny)][In] object inBuffer,
uint inBufferSize,
[MarshalAs(UnmanagedType.AsAny)] [Out] object outBuffer,
[MarshalAs(UnmanagedType.AsAny)][Out] object outBuffer,
uint nOutBufferSize,
out uint bytesReturned,
IntPtr overlapped);